首页
社区
课程
招聘
[原创]看雪2016 第十一题 CrackMe逆向分析
发表于: 2016-11-24 16:58 6318

[原创]看雪2016 第十一题 CrackMe逆向分析

2016-11-24 16:58
6318

这个crackme坑比较多,绕了很久才找到真正的注册算法。说一下程序运行的大致流程。

程序启动会对下列数据进行解密,解密大小为0x34,DO不需要解密
003273A0  78 00 9E 5B 50 99 97 B6 9D 97 23 07 A9 34 7D 0B  x.瀃P櫁稘??}
003273B0  0F 77 04 EE CB 86 A5 13 AD 6A F2 B4 D5 E7 10 C1  w钏啣璲虼甄?
003273C0  22 6C D7 E0 0A 01 C0 71 9E 91 74 11 23 5F 4B 8B  "l奏.纐瀾t#_K?
003273D0  6E 03 E2 66 6E CF 20 1E 54 D4 67 92 00             n鈌n?T詆?...
其中  CF 20 1E 54 D4 67 92 00 为 变异MD5的值,后面会用到,设为h。

解密的算法为 t[i]^(FF-i),  解密的数据后为
00328420  78 FE 63 A7 AB 63 6E 4E 6A 61 D6 F3 5A C6 8C FB  xЙcnNja煮Z茖?
00328430  E0 99 E9 02 20 6C 4C FB 4A 8C 17 50 36 05 F1 21  鄼? lL鸍?P6?
00328440  FD B2 0A 3C D1 DB 19 A9 49 47 A1 C5 F0 8D 9A 5B  .<眼㊣G∨饙歔
00328450  A1 CD 2F AA A5                                   ⊥/..

注册码长度为56个字节,每当输入注册码时就会触发txtinput_Change事件,完成对t的解密
004057BD   .  0FB600        movzx   eax, byte ptr [eax]
004057C0   .  03C3          add     eax, ebx                         ;  sn[1]+i
004057C2   .  B9 00010000   mov     ecx, 100
004057C7   .  0F80 D3000000 jo      004058A0
004057CD   .  99            cdq
004057CE   .  F7F9          idiv    ecx
004057D0   .  53            push    ebx
004057D1   .  FF35 78E04000 push    dword ptr [40E078]
004057D7   .  8995 7CFFFFFF mov     dword ptr [ebp-84], edx
004057DD   .  E8 F0BDFFFF   call    <jmp.&MSVBVM60.__vbaDerefAry1>   ;  t[i]
004057E2   .  0FB600        movzx   eax, byte ptr [eax]
004057E5   .  8B8D 7CFFFFFF mov     ecx, dword ptr [ebp-84]
004057EB   .  33C8          xor     ecx, eax                         ;  t[i] xor (sn[1]+i)
004057ED   .  8B47 50       mov     eax, dword ptr [edi+50]
004057F0   .  8B40 04       mov     eax, dword ptr [eax+4]
004057F3   .  03C3          add     eax, ebx                         ;  xor (sn[1]+i)
004057F5   .  0F80 A5000000 jo      004058A0
004057FB   .  33C8          xor     ecx, eax
004057FD   .  E8 94BDFFFF   call    <jmp.&MSVBVM60.__vbaUI1I4>
00405802   .  FF75 E8       push    dword ptr [ebp-18]
00405805   .  8AD8          mov     bl, al

解密算法为 i = 1~0x34; t[i] = t[i] ^ (sn[1]+i) ^ i; txtinput_Change事件完成。

当点击注册按钮时触发cmdReg_Click事件,这里只有一件有意义的事 “禁用按钮”,其他的都是坑啊!!
纠结下面这段代码的,说明已入坑
00403DBF   .  E8 ECD8FFFF   call    <jmp.&MSVBVM60.__vbaVarCat>
00403DC4   .  50            push    eax
00403DC5   .  8D85 6CFFFFFF lea     eax, dword ptr [ebp-94]
00403DCB   .  50            push    eax
00403DCC   .  E8 91400000   call    00407E62
00403DD1   .  8D85 6CFFFFFF lea     eax, dword ptr [ebp-94]
00403DD7   .  C785 04FFFFFF>mov     dword ptr [ebp-FC], 0040284C               ;  UNICODE "033788636d9acb22"
00403DE1   .  50            push    eax                                        ; /var18
00403DE2   .  8D85 FCFEFFFF lea     eax, dword ptr [ebp-104]                   ; |
00403DE8   .  50            push    eax                                        ; |var28
00403DE9   .  8D85 5CFFFFFF lea     eax, dword ptr [ebp-A4]                    ; |
00403DEF   .  C785 FCFEFFFF>mov     dword ptr [ebp-104], 8008                  ; |
00403DF9   .  50            push    eax                                        ; |SaveTo8
00403DFA   .  E8 B7D8FFFF   call    <jmp.&MSVBVM60.__vbaVarCmpEq>              ; \__vbaVarCmpEq
00403DFF   .  8BD0          mov     edx, eax
00403E01   .  8D4D DC       lea     ecx, dword ptr [ebp-24]
00403E04   .  E8 B3D8FFFF   call    <jmp.&MSVBVM60.__vbaVarMove>

check_Timer是个计时器事件,当发现按钮被禁用后,开始验证序列号,真正的算法在这里。过程如下
00404CA1   .  8D45 DC       lea     eax, dword ptr [ebp-24]
00404CA4   .  50            push    eax
00404CA5   .  8D45 BC       lea     eax, dword ptr [ebp-44]
00404CA8   .  50            push    eax
00404CA9   .  E8 F70B0000   call    004058A5                         ;  check(out, sn)
00404CAE   .  8D45 BC       lea     eax, dword ptr [ebp-44]
00404CB1   .  50            push    eax
00404CB2   .  E8 BDC9FFFF   call    <jmp.&MSVBVM60.__vbaBoolVarNull>
00404CB7   .  8D4D BC       lea     ecx, dword ptr [ebp-44]
00404CBA   .  66:8BF8       mov     di, ax
00404CBD   .  E8 E2C9FFFF   call    <jmp.&MSVBVM60.__vbaFreeVar>
00404CC2   .  8B06          mov     eax, dword ptr [esi]
00404CC4   .  66:3BFB       cmp     di, bx
00404CC7   .  56            push    esi
00404CC8   .  0F84 3C030000 je      0040500A

check过程是输入序列号,输出bool结果,非0表示注册成功。check过程如下
调用zlib动态库压缩sn,输出t2
00405914   .  8B45 C4       mov     eax, dword ptr [ebp-3C]
00405917   .  8D95 54FFFFFF lea     edx, dword ptr [ebp-AC]
0040591D   .  52            push    edx
0040591E   .  8BD8          mov     ebx, eax
00405920   .  FF75 0C       push    dword ptr [ebp+C]
00405923   .  8B08          mov     ecx, dword ptr [eax]
00405925   .  50            push    eax
00405926   .  FF51 2C       call    dword ptr [ecx+2C]               ;  CompressString(strIn)
00405929   .  3BC6          cmp     eax, esi

处理压缩后的结果t2,3处修改,取余交换15和20位置,末尾(34)位置取余
00405991   .  6A 15         push    15
00405993   .  8818          mov     byte ptr [eax], bl               ;  t2[n] = t2[n]%21
00405995   .  FF75 CC       push    dword ptr [ebp-34]
00405998   .  E8 35BCFFFF   call    <jmp.&MSVBVM60.__vbaDerefAry1>
0040599D   .  0FB600        movzx   eax, byte ptr [eax]              ;  t2[15]
004059A0   .  6A 20         push    20
004059A2   .  8945 E4       mov     dword ptr [ebp-1C], eax
004059A5   .  FF75 CC       push    dword ptr [ebp-34]
004059A8   .  E8 25BCFFFF   call    <jmp.&MSVBVM60.__vbaDerefAry1>
004059AD   .  66:0FB600     movzx   ax, byte ptr [eax]               ;  t2[20]
004059B1   .  66:99         cwd
004059B3   .  66:B9 4200    mov     cx, 42
004059B7   .  66:F7F9       idiv    cx
004059BA   .  8BCA          mov     ecx, edx                         ;  t2[20]%42
004059BC   .  E8 13BDFFFF   call    <jmp.&MSVBVM60.__vbaUI1I2>
004059C1   .  6A 15         push    15
004059C3   .  8AD8          mov     bl, al
004059C5   .  FF75 CC       push    dword ptr [ebp-34]
004059C8   .  E8 05BCFFFF   call    <jmp.&MSVBVM60.__vbaDerefAry1>
004059CD   .  8818          mov     byte ptr [eax], bl               ;  t2[15]=t2[20]%42
004059CF   .  8B45 E4       mov     eax, dword ptr [ebp-1C]
004059D2   .  6A 63         push    63
004059D4   .  99            cdq
004059D5   .  59            pop     ecx
004059D6   .  F7F9          idiv    ecx
004059D8   .  8BCA          mov     ecx, edx                         ;  t2[15]%63
004059DA   .  E8 B7BBFFFF   call    <jmp.&MSVBVM60.__vbaUI1I4>
004059DF   .  6A 20         push    20
004059E1   .  8AD8          mov     bl, al
004059E3   .  FF75 CC       push    dword ptr [ebp-34]
004059E6   .  E8 E7BBFFFF   call    <jmp.&MSVBVM60.__vbaDerefAry1>   ;  t2[20]=t2[15]%63
004059EB   .  8818          mov     byte ptr [eax], bl

对sn进行md5,结果为h2
00405A7D   .  898D 68FFFFFF mov     dword ptr [ebp-98], ecx
00405A83   .  E8 DA230000   call    00407E62                         ;  hasn(sn)
00405A88   .  8D85 60FFFFFF lea     eax, dword ptr [ebp-A0]
00405A8E   .  50            push    eax
00405A8F   .  8D45 B0       lea     eax, dword ptr [ebp-50]
00405A92   .  50            push    eax
00405A93   .  8D45 A0       lea     eax, dword ptr [ebp-60]
00405A96   .  50            push    eax
00405A97   .  E8 14BCFFFF   call    <jmp.&MSVBVM60.__vbaVarCat>      ;  sn+hash(sn)
00405A9C   .  50            push    eax
00405A9D   .  8D45 90       lea     eax, dword ptr [ebp-70]
00405AA0   .  50            push    eax
00405AA1   .  E8 BC230000   call    00407E62                         ;  hash(sn+hash(sn))
00405AA6   .  8D45 90       lea     eax, dword ptr [ebp-70]
00405AA9   .  50            push    eax
00405AAA   .  8D45 80       lea     eax, dword ptr [ebp-80]
00405AAD   .  50            push    eax
00405AAE   .  E8 1BBCFFFF   call    <jmp.&MSVBVM60.#528>             ;  uper(y)
00405AB3   .  8D45 80       lea     eax, dword ptr [ebp-80]

对比结果 h == h2 && t == t2
00405B98   .  FF75 C0       push    dword ptr [ebp-40]
00405B9B   .  FF75 E8       push    dword ptr [ebp-18]
00405B9E   .  56            push    esi
00405B9F   .  E8 24BBFFFF   call    <jmp.&MSVBVM60.__vbaInStr>
00405BA4   .  48            dec     eax
00405BA5   .  6A 0B         push    0B
00405BA7   .  F7D8          neg     eax
00405BA9   .  1BC0          sbb     eax, eax
00405BAB   .  5F            pop     edi
00405BAC   .  40            inc     eax
00405BAD   .  8D95 60FFFFFF lea     edx, dword ptr [ebp-A0]
00405BB3   .  F7D8          neg     eax
00405BB5   .  8D4D D4       lea     ecx, dword ptr [ebp-2C]
00405BB8   .  66:8985 68FFF>mov     word ptr [ebp-98], ax            ;  ==
00405BBF   .  89BD 60FFFFFF mov     dword ptr [ebp-A0], edi
00405BC5   .  E8 F2BAFFFF   call    <jmp.&MSVBVM60.__vbaVarMove>
00405BCA   .  8D4D C0       lea     ecx, dword ptr [ebp-40]
00405BCD   .  E8 A8BAFFFF   call    <jmp.&MSVBVM60.__vbaFreeStr>
00405BD2   .  6A 01         push    1
00405BD4   .  FF75 C8       push    dword ptr [ebp-38]
00405BD7   .  FF75 D0       push    dword ptr [ebp-30]
00405BDA   .  56            push    esi
00405BDB   .  E8 E8BAFFFF   call    <jmp.&MSVBVM60.__vbaInStr>       ;  ==
00405BE0   .  48            dec     eax
00405BE1   .  89BD 70FFFFFF mov     dword ptr [ebp-90], edi

分析完成后,整理下表达式
t2 = mod(compress(sn)) = decode(t, sn[1])
h2 = hash(sn+hash(sn)) = "CF201E54D4679200"

由于存在 decode和取余操作,所以需要穷举一下,代码中借用了作者的zlib动态库

收藏
免费 1
支持
分享
最新回复 (4)
雪    币: 134
活跃值: (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
完全被带沟里去了
2016-11-24 17:27
0
雪    币: 13713
活跃值: (2851)
能力值: ( LV15,RANK:2663 )
在线值:
发帖
回帖
粉丝
3
h2 = hash(sn+hash(sn)) = "CF201E54D4679200"
如果hash指作者的变形md5加密过程,那这句不太对啊。应该是h2 = hash(sn+hash(sn+hash(sn)+c1)+c2)。
如果你这hash只是表示泛指的hash过程,算我没说
2016-11-25 00:39
0
雪    币: 3053
活跃值: (891)
能力值: ( LV13,RANK:1300 )
在线值:
发帖
回帖
粉丝
4
调用hash得地方大概有5处吧,坑那里就用到了3个,其结果与"033788636d9acb22"比较。我们说的好像不是一个地方。
另外,hash啥的根本不用管,也能算出sn。
2016-11-25 08:42
0
雪    币: 13713
活跃值: (2851)
能力值: ( LV15,RANK:2663 )
在线值:
发帖
回帖
粉丝
5
我错了。当时没看细,确实不是一个地方。
2016-12-6 21:34
0
游客
登录 | 注册 方可回帖
返回
//