首页
论坛
课程
招聘
[原创][2020][KCTF] 第七题 杯弓蛇影 wp
2020-4-28 11:10 2669

[原创][2020][KCTF] 第七题 杯弓蛇影 wp

ccfer 活跃值
15
2020-4-28 11:10
2669

一 壳部分
有些anti,最主要的是GetThreadContext,会检查drx是否为0:

        0044F244   FFD1             CALL ECX                            //GetThreadContext
        0044F246   C745 F8 00000000 MOV DWORD PTR SS:[EBP-8],0
        0044F24D   83BD 30FDFFFF 00 CMP DWORD PTR SS:[EBP-2D0],0        //dr0 == 0 ?
        0044F254   75 1B            JNZ SHORT CrackMe.0044F271
        0044F256   83BD 34FDFFFF 00 CMP DWORD PTR SS:[EBP-2CC],0        //dr1 == 0 ?
        0044F25D   75 12            JNZ SHORT CrackMe.0044F271
        0044F25F   83BD 38FDFFFF 00 CMP DWORD PTR SS:[EBP-2C8],0        //dr2 == 0 ?
        0044F266   75 09            JNZ SHORT CrackMe.0044F271
        0044F268   83BD 3CFDFFFF 00 CMP DWORD PTR SS:[EBP-2C4],0        //dr3 == 0 ?
        0044F26F   74 07            JE SHORT CrackMe.0044F278

        00450E97   E8 24FDFFFF      CALL CrackMe.00450BC0               //处理输入表,可以在这里dump
        00450E9C   83C4 10          ADD ESP,10
        00450E9F   8945 D0          MOV DWORD PTR SS:[EBP-30],EAX
        00450EA2   837D D0 00       CMP DWORD PTR SS:[EBP-30],0
        00450EA6   75 04            JNZ SHORT CrackMe.00450EAC
        00450EA8   33C0             XOR EAX,EAX
        00450EAA   EB 1E            JMP SHORT CrackMe.00450ECA
        00450EAC   8B4D 08          MOV ECX,DWORD PTR SS:[EBP+8]
        00450EAF   51               PUSH ECX
        00450EB0   E8 4BE3FFFF      CALL CrackMe.0044F200
        00450EB5   83C4 04          ADD ESP,4
        00450EB8   83F8 01          CMP EAX,1
        00450EBB   75 05            JNZ SHORT CrackMe.00450EC2
        00450EBD   E8 1EE3FFFF      CALL CrackMe.0044F1E0
        00450EC2   FF55 F0          CALL DWORD PTR SS:[EBP-10]          //to oep : 0x417E83

        00450CE3   8B55 08          MOV EDX,DWORD PTR SS:[EBP+8]
        00450CE6   52               PUSH EDX
        00450CE7   8B45 F0          MOV EAX,DWORD PTR SS:[EBP-10]
        00450CEA   50               PUSH EAX
        00450CEB   E8 60F3FFFF      CALL CrackMe.00450050               //可以nop掉,阻止函数入口抽取
        00450CF0   83C4 08          ADD ESP,8
        00450CF3   8945 EC          MOV DWORD PTR SS:[EBP-14],EAX

二 验证流程:

        004011A7   68 685A4300      PUSH CrackMe.00435A68               //"Please input Serial:"
        004011AC   E8 BFFEFFFF      CALL CrackMe.00401070
        004011B1   83C4 04          ADD ESP,4
        004011B4   8D8424 E00C0000  LEA EAX,DWORD PTR SS:[ESP+CE0]
        004011BB   68 E8030000      PUSH 3E8
        004011C0   50               PUSH EAX
        004011C1   68 645A4300      PUSH CrackMe.00435A64
        004011C6   E8 E5FEFFFF      CALL CrackMe.004010B0               //读取sn
        。。。
        0040157A   8B4424 18        MOV EAX,DWORD PTR SS:[ESP+18]
        0040157E   8D4C24 60        LEA ECX,DWORD PTR SS:[ESP+60]
        00401582   898424 D0000000  MOV DWORD PTR SS:[ESP+D0],EAX       //0044B258,大端转换后的sn
        00401589   8B4424 14        MOV EAX,DWORD PTR SS:[ESP+14]
        0040158D   898424 D4000000  MOV DWORD PTR SS:[ESP+D4],EAX
        00401594   8B4424 10        MOV EAX,DWORD PTR SS:[ESP+10]
        00401598   898424 D8000000  MOV DWORD PTR SS:[ESP+D8],EAX       //0044BE58,输入参数
        0040159F   8B4424 1C        MOV EAX,DWORD PTR SS:[ESP+1C]
        004015A3   898424 DC000000  MOV DWORD PTR SS:[ESP+DC],EAX
        004015AA   8B4424 20        MOV EAX,DWORD PTR SS:[ESP+20]
        004015AE   898424 E0000000  MOV DWORD PTR SS:[ESP+E0],EAX       //00448358,输入参数
        004015B5   8B4424 24        MOV EAX,DWORD PTR SS:[ESP+24]
        004015B9   898424 E4000000  MOV DWORD PTR SS:[ESP+E4],EAX
        004015C0   8B4424 28        MOV EAX,DWORD PTR SS:[ESP+28]
        004015C4   898424 E8000000  MOV DWORD PTR SS:[ESP+E8],EAX       //0044B658,输出5个DWORD
        004015CB   8B4424 2C        MOV EAX,DWORD PTR SS:[ESP+2C]
        004015CF   898424 EC000000  MOV DWORD PTR SS:[ESP+EC],EAX
        004015D6   8B4424 30        MOV EAX,DWORD PTR SS:[ESP+30]
        004015DA   898424 F8000000  MOV DWORD PTR SS:[ESP+F8],EAX       //00448338,输出8个DWORD
        004015E1   8B4424 34        MOV EAX,DWORD PTR SS:[ESP+34]
        004015E5   898424 FC000000  MOV DWORD PTR SS:[ESP+FC],EAX
        004015EC   E8 3FCB0000      CALL CrackMe.0040E130               //应该是个虚拟机
        。。。

    经过一番调试观察,找到下面几个关键的运算位置:
        0040F47C   E8 CFF20100      CALL CrackMe.0042E750               //vm_mul
        0040F512   E8 790D0000      CALL CrackMe.00410290               //vm_div,这里面有anti
        0040F3C0   E8 1B0D0000      CALL CrackMe.004100E0               //vm_add,这里面有anti
        0040F6BD   3144D3 68        XOR DWORD PTR DS:[EBX+EDX*8+68],EAX //vm_xor
    输入公开的一组用户名和序列号,利用上面4个断点观察数值的变化:
        s = 0
        m = 0xFFFFFFFB
        b = 1
        s = (0x45CEB196 * b % m + s) % m = 0x45CEB196
        b = b * 0x158EA2A9 % m = 0x158EA2A9
        s = (0xA20DD51E * b % m + s) % m = 0xF2AC7FFF
        b = b * 0x158EA2A9 % m = 0x9DE9E259
        s = (0xEAADB7F2 * b % m + s) % m = 0x8E85CE47
        b = b * 0x158EA2A9 % m = 0x5D7D98F0
        0x4B82D0BC ^ 0x8E85CE47 = 0xC5071EFB
    从虚拟机出来以后,观察输入输出可以得出:
        0x158EA2A9是输入参数[44BE58]的第一个DWORD
        0x4B82D0BC是输入参数[448358]的第一个DWORD
        0x45CEB196,0xA20DD51E,0xEAADB7F2刚好是输入sn即[44B258]的前三个DWORD
        [44B658]输出了5个DWORD,[448338]输出8个DWORD,加起来13个DWORD,输入sn三个一组的话刚好也是13组
        0xC5071EFB是输出[44B658]的第一个DWORD
    单从一个输出可以猜测出:
        out[i] = (sn[3*i+0] + sn[3*i+1] * DWORD_44BE58[i] + sn[3*i+2] * DWORD_44BE58[i] * DWORD_44BE58[i]) % m ^ DWORD_448358[i]
    经验证验证后面12组也符合此规律,至此vm里的算法就算猜出来了

    后续验证流程:
        00401600   8BC8             MOV ECX,EAX
        00401602   83E1 07          AND ECX,7
        00401605   8B148D 38834400  MOV EDX,DWORD PTR DS:[ECX*4+448338] //输出后8个DWORD
        0040160C   331485 58B64400  XOR EDX,DWORD PTR DS:[EAX*4+44B658] //输出前5个DWORD
        00401613   8BCA             MOV ECX,EDX
        00401615   891485 78BE4400  MOV DWORD PTR DS:[EAX*4+44BE78],EDX
        0040161C   C1E9 08          SHR ECX,8
        0040161F   880C85 7AC24400  MOV BYTE PTR DS:[EAX*4+44C27A],CL
        00401626   8BCA             MOV ECX,EDX
        00401628   881485 7BC24400  MOV BYTE PTR DS:[EAX*4+44C27B],DL
        0040162F   C1E9 10          SHR ECX,10
        00401632   C1EA 18          SHR EDX,18
        00401635   880C85 79C24400  MOV BYTE PTR DS:[EAX*4+44C279],CL
        0040163C   881485 78C24400  MOV BYTE PTR DS:[EAX*4+44C278],DL   //xor后再大小端转换,得到一个人为设定的字符串,三轮的结果不同
        00401643   40               INC EAX
        00401644   3BC6             CMP EAX,ESI
        00401646  ^7C B8            JL SHORT CrackMe.00401600
        00401648   FF7424 38        PUSH DWORD PTR SS:[ESP+38]
        0040164C   BA 38B24400      MOV EDX,CrackMe.0044B238            //hash输出
        00401651   B9 78C24400      MOV ECX,CrackMe.0044C278            //设定的字符串
        00401656   FF7424 40        PUSH DWORD PTR SS:[ESP+40]
        0040165A   E8 11C00000      CALL CrackMe.0040D670               //感觉是个hash,也不知道哪种hash,还带vm,咱就不和它较劲了,直接看输出结果
        0040165F   83C4 08          ADD ESP,8
        00401662   33C9             XOR ECX,ECX
        00401670   8B81 38834400    MOV EAX,DWORD PTR DS:[ECX+448338]   //输出后8个DWORD
        00401676   3B81 38B24400    CMP EAX,DWORD PTR DS:[ECX+44B238]   //hash
        0040167C   75 3F            JNZ SHORT CrackMe.004016BD          //输出前5个DWORD与后8个DWORD异或得到字符串的hash == 输出后8个DWORD ?
        0040167E   83C1 04          ADD ECX,4
        00401681   83F9 20          CMP ECX,20
        00401684  ^7C EA            JL SHORT CrackMe.00401670
        00401686   8B4424 7C        MOV EAX,DWORD PTR SS:[ESP+7C]
        0040168A   85C0             TEST EAX,EAX
        0040168C   74 09            JE SHORT CrackMe.00401697
        0040168E   50               PUSH EAX
        0040168F   E8 9A650100      CALL CrackMe.00417C2E
        00401694   83C4 04          ADD ESP,4
        00401697   8B4424 08        MOV EAX,DWORD PTR SS:[ESP+8]
        0040169B   83C7 04          ADD EDI,4
        0040169E   05 00010000      ADD EAX,100
        004016A3   894424 08        MOV DWORD PTR SS:[ESP+8],EAX
        004016A7   81FF 64BA4400    CMP EDI,CrackMe.0044BA64            //循环三轮
        004016AD  ^0F8C FDFDFFFF    JL CrackMe.004014B0
        004016B3   68 A45A4300      PUSH CrackMe.00435AA4                    ; ASCII "Congratulations! The Serial is Correct!"
        004016B8  ^E9 59FCFFFF      JMP CrackMe.00401316
    只要使vm输出的[44B658]和[448338]一共13个DWORD和公开那组用户名/序列号的结果一样,后面hash就都会自然通过验证
    DWORD_448358内容是和用户名相关的,DWORD_44BE58是和用户名和轮次相关的
    vm跑了三轮,vm前面分析出的算法可以建立一个三元一次同余方程组:
        out[i] = (sn[3*i+0] + sn[3*i+1] * DWORD_44BE58[i] + sn[3*i+2] * DWORD_44BE58[i] * DWORD_44BE58[i]) % m ^ DWORD_448358[i]
    输入用户名KCTF把每轮的[448358]和[44BE58]都抓取出来得到系数矩阵,解13个方程组,得到全部13个DWORD即可

三 解方程的sage代码:

base_44BE58_pub = [
    [0x158EA2A9,0x0119F92D,0xA8E297DF,0x114EFFC3,0x3D192BAC,0xD1354A27,0xBE4D0722,0x365DF0C9],
    [0xBCB9C89C,0x1AC6837F,0xB72DD1BF,0xC41AFC16,0xE1C33972,0x3998A0AE,0xBBDE5E70,0xA09E23E0],
    [0xF1E0C866,0xC69DE660,0x4CB62BA8,0x4E0DCD2F,0xA1DC0564,0xE8DB2CCF,0xD10A0F17,0xCDD12459]
]

key_448358_pub = [0x4B82D0BC,0xF8B8853D,0x049D762A,0x362AD93C,0xB49B3DE9,0xE2D166BC,0xCF1EE01B,0xD4E36847,0xB40A13BE,0xE536D6B8,0xDECBDD5E,0xBDE27342,0xD2EF4FBD]

base_44BE58_KCTF = [
    [0x835904E1,0xC834944B,0x027A19E0,0xFEB308A3,0x621FF195,0x4B705C5C,0x3EB5D9D0,0x9A5C73F4],
    [0xCCFFA00F,0x490C46ED,0xF78BE5A1,0x81A56274,0x165DEB5C,0xF6F46796,0x44DE5146,0x00E4984C],
    [0xDF77DFA8,0xAE0ED8D8,0x064DA354,0x4C8B95CC,0xF934CA39,0xC4E9DE04,0x18EE2793,0x945AC9C2],
]

key_448358_KCTF = [0xD9C3E463,0x11C9AF78,0x6485BF9E,0xFF4BD05D,0x65769726,0xF5C38988,0xBF3A2423,0x4B718CC0,0xC70D8F49,0xDFC73315,0x74470070,0x94B89F71,0x0E60F6B1]

sn_pub = [0x45CEB196,0xA20DD51E,0xEAADB7F2,0x17A4AABF,0x036D8FE4,0x81DAFC12,0x6C310213,0x7691C395,0x27444D11,0x0E0D1071,0x99703FD6,0xAAA510DF,0xE8433E09,0x702603E8,0x10A68ED0,0x06082EF6,0xF2793580,0x2B2CE24F,0x105F91CA,0xDF697948,0x92B4F088,0x4DADF6A7,0x0A1F25BD,0x23A2D4D2,0xE36D836F,0xE9946B9F,0x559D26C6,0x3237E615,0xE218F66B,0x6A572CF3,0xBDA45BD8,0x8D0E7E59,0xB9C93D8F,0xA55B218D,0x3643F639,0x0C6AA85F,0x2B8EB982,0x18F4C6C9,0x4E17CC73]
t = []
p = 0xFFFFFFFB
for i in range(13):
    c = []
    for j in range(3):
        a = []
        b = 1
        a.append(b)
        b = b * base_44BE58_pub[j][i%8] % p
        a.append(b)
        b = (b * base_44BE58_pub[j][i%8]) % p
        a.append(b)
        y = (a[0] * sn_pub[i*3+0] + a[1] * sn_pub[i*3+1] + a[2] * sn_pub[i*3+2]) % p
        a.append(y ^^ key_448358_pub[i])

        b = 1
        a[0] = b
        b = b * base_44BE58_KCTF[j][i%8] % p
        a[1] = b
        b = (b * base_44BE58_KCTF[j][i%8]) % p
        a[2] = b
        a[3] ^^= key_448358_KCTF[i]
        c += a
    t.append(c)

A = matrix(Zmod(p), 3, 3)
for i in range(13):
    for j in range(3):
        A[j] = [t[i][j*4+0],t[i][j*4+1],t[i][j*4+2]]
    B = vector(Zmod(p),[t[i][0*4+3],t[i][1*4+3],t[i][2*4+3]])
    x = A\B
    print('%08X%08X%08X' % (x[0],x[1],x[2]))

运行后得到结果:E84DE727B4C7223FC4C8B34F9D4E4221225DD4A26A95E624E5EB45269DE64C0A9ED50B44BBA723F9878E4B4DD8841263453DC5157B401D6B5AF4F1401193FAA1433ADA48145A358ABCE1B8439C7F5D390C31987E39BB056E1A21B92B8DE2358ECEC1FF6C206CF8C17C46C89144BA8DA0EC4834389FFA54B32C8D3174E97AC3C2024783D0DFDC2BC9524B9C81B40F78F2E184A49B2292B4D79A58EF0B


[公告]第4届看雪技术峰会2020年10月23日上海浦东喜来登由由大酒店召开!

最后于 2020-4-28 16:19 被ccfer编辑 ,原因:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回