首页
社区
课程
招聘
[原创]对一个小软件e-PDF To HTML Converter的注册分析
发表于: 2012-3-25 15:15 7570

[原创]对一个小软件e-PDF To HTML Converter的注册分析

2012-3-25 15:15
7570

前几天在玩CrackMe 一直想找个共享软件练手
e-PDF To HTML Converter
看了这贴 就拿来分析一下 http://bbs.pediy.com/showthread.php?t=112427
见笑了。。。


此软件无壳 直接拉进OD
                     在GetWindowTextA断下 来到调用代码段
0043C169   .  68 C8000000   push    0C8                              ; /Count = C8 (200.)
0043C16E   .  68 3C3B4E00   push    004E3B3C                         ; |Buffer = pdf2html.004E3B3C
0043C173   .  68 FB030000   push    3FB                              ; |ControlID = 3FB (1019.)
0043C178   .  8B45 08       mov     eax, dword ptr [ebp+8]           ; |
0043C17B   .  50            push    eax                              ; |hWnd
0043C17C   .  FF15 0C654A00 call    dword ptr [<&USER32.GetDlgItemTe>; \GetDlgItemTextA
0043C182   .  68 3C3B4E00   push    004E3B3C                         ;  key压栈
0043C187   .  E8 EBF5FFFF   call    0043B777;   注册码验证CALL跟进

0043B777  /$  55            push    ebp
0043B778  |.  8BEC          mov     ebp, esp
0043B77A  |.  83EC 3C       sub     esp, 3C
0043B77D  |.  56            push    esi
0043B77E  |.  8B45 08       mov     eax, dword ptr [ebp+8]
0043B781  |.  8A08          mov     cl, byte ptr [eax]               ;  取第一个key 放入局部变量
0043B783  |.  884D F4       mov     byte ptr [ebp-C], cl
0043B786  |.  C645 F5 00    mov     byte ptr [ebp-B], 0              ;  后面一字节赋值为0 在后面的call中这个0很重要
0043B78A  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0043B78D  |.  8A42 01       mov     al, byte ptr [edx+1]             ;  取第二个key 放入局部变量
0043B790  |.  8845 E8       mov     byte ptr [ebp-18], al
0043B793  |.  C645 E9 00    mov     byte ptr [ebp-17], 0             ;  同上
0043B797  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]
0043B79A  |.  8A51 0E       mov     dl, byte ptr [ecx+E]             ;  取第15个key 放入局部变量
0043B79D  |.  8855 DC       mov     byte ptr [ebp-24], dl
0043B7A0  |.  C645 DD 00    mov     byte ptr [ebp-23], 0             ;  同上
0043B7A4  |.  8B45 08       mov     eax, dword ptr [ebp+8]
0043B7A7  |.  8A48 0F       mov     cl, byte ptr [eax+F]             ;  取第16个key 放入局部变量
0043B7AA  |.  884D D0       mov     byte ptr [ebp-30], cl
0043B7AD  |.  C645 D1 00    mov     byte ptr [ebp-2F], 0             ;  同上
0043B7B1  |.  8B55 08       mov     edx, dword ptr [ebp+8]
0043B7B4  |.  8A42 02       mov     al, byte ptr [edx+2]             ;  取第3个key 放入局部变量
0043B7B7  |.  8845 C4       mov     byte ptr [ebp-3C], al
0043B7BA  |.  C645 C5 00    mov     byte ptr [ebp-3B], 0             ;  同上
0043B7BE  |.  0FBE4D C4     movsx   ecx, byte ptr [ebp-3C]           ;  取出第三个key
0043B7C2  |.  83F9 24       cmp     ecx, 24                          ;  比较第三个key是否为 '$'
0043B7C5  |.  74 04         je      short 0043B7CB                   ;  相等的话进入关键验证段
0043B7C7  |.  33C0          xor     eax, eax                         ;  不相等返回0
0043B7C9  |.  EB 67         jmp     short 0043B832
0043B7CB  |>  8D55 F4       lea     edx, dword ptr [ebp-C]           ;  取出第一个key的地址
0043B7CE  |.  52            push    edx                              ;  压栈
0043B7CF  |.  E8 BCC80300   call    00478090                         ;  关键验证call跟入

00478090  /$  FF7424 04     push    dword ptr [esp+4];压入先前存放了key字符的局部变量地址
00478094  |.  E8 6CFFFFFF   call    00478005                         ;  傀儡函数  再次跟进
00478099  |.  59            pop     ecx
0047809A  \.  C3            retn

00478005  /$  53            push    ebx                              ;  先说明下 前面局部变量只是对连续两个字节赋值(key和0) 故这里一定最多只能得到第2个数0
00478006  |.  55            push    ebp
00478007  |.  56            push    esi
00478008  |.  57            push    edi
00478009  |.  8B7C24 14     mov     edi, dword ptr [esp+14]          ;  把原先存放key字符局部变量的地址取出
0047800D  |>  833D 481C4E00>/cmp     dword ptr [4E1C48], 1           ;  此比较的作用未知 [4E1C48]始终为1 对后面无影响
00478014  |.  7E 0F         |jle     short 00478025                  ;  跳
00478016  |.  0FB607        |movzx   eax, byte ptr [edi]
00478019  |.  6A 08         |push    8
0047801B  |.  50            |push    eax
0047801C  |.  E8 635B0000   |call    0047DB84                        ;  未知call 因为[4E1C48]始终为1 故此CALL并不会被调用
00478021  |.  59            |pop     ecx
00478022  |.  59            |pop     ecx
00478023  |.  EB 0F         |jmp     short 00478034
00478025  |>  0FB607        |movzx   eax, byte ptr [edi]             ;  取key字符
00478028  |.  8B0D 3C1A4E00 |mov     ecx, dword ptr [4E1A3C]         ;  取出一个数组的地址 数组内容见下面
0047802E  |.  8A0441        |mov     al, byte ptr [ecx+eax*2]        ;  取出数组中的内容 ecx[key * 2]
00478031  |.  83E0 08       |and     eax, 8                          ;  与8(1000)位与
00478034  |>  85C0          |test    eax, eax                        ;  测试0
00478036  |.  74 03         |je      short 0047803B                  ;  为0则跳出
00478038  |.  47            |inc     edi                             ;  地址偏移1字节
00478039  |.^ EB D2         \jmp     short 0047800D
0047803B  |>  0FB637        movzx   esi, byte ptr [edi]              ;  取key字符
0047803E  |.  47            inc     edi                              ;  见前面说明
0047803F  |.  83FE 2D       cmp     esi, 2D
00478042  |.  8BEE          mov     ebp, esi
00478044  |.  74 05         je      short 0047804B
00478046  |.  83FE 2B       cmp     esi, 2B
00478049  |.  75 04         jnz     short 0047804F
0047804B  |>  0FB637        movzx   esi, byte ptr [edi]
0047804E  |.  47            inc     edi                              ;  见前面说明
0047804F  |>  33DB          xor     ebx, ebx                         ;  前面比较如果与2D和2B不相等的话 则到这里 ebx清零
00478051  |>  833D 481C4E00>/cmp     dword ptr [4E1C48], 1           ;  相似代码段 同前面
00478058  |.  7E 0C         |jle     short 00478066
0047805A  |.  6A 04         |push    4
0047805C  |.  56            |push    esi
0047805D  |.  E8 225B0000   |call    0047DB84                        ;  相似代码段 同前面
00478062  |.  59            |pop     ecx
00478063  |.  59            |pop     ecx
00478064  |.  EB 0B         |jmp     short 00478071
00478066  |>  A1 3C1A4E00   |mov     eax, dword ptr [4E1A3C]         ;  相似代码段 同前面
0047806B  |.  8A0470        |mov     al, byte ptr [eax+esi*2]
0047806E  |.  83E0 04       |and     eax, 4                          ;  取出数组中的数与4(100)位与
00478071  |>  85C0          |test    eax, eax
00478073  |.  74 0D         |je      short 00478082                  ;  为0则跳出
00478075  |.  8D049B        |lea     eax, dword ptr [ebx+ebx*4]      ;  eax = ebx * 5
00478078  |.  8D5C46 D0     |lea     ebx, dword ptr [esi+eax*2-30]   ;  ebx = esi + ebx * 5 * 2 - 30h
0047807C  |.  0FB637        |movzx   esi, byte ptr [edi]
0047807F  |.  47            |inc     edi
00478080  |.^ EB CF         \jmp     short 00478051
00478082  |>  83FD 2D       cmp     ebp, 2D
00478085  |.  8BC3          mov     eax, ebx                         ;  ebx为返回值
00478087  |.  75 02         jnz     short 0047808B                   ;  如果ebp(前面ebp被esi赋值)不是2D则不对返回值neg
00478089  |.  F7D8          neg     eax
0047808B  |>  5F            pop     edi
0047808C  |.  5E            pop     esi
0047808D  |.  5D            pop     ebp
0047808E  |.  5B            pop     ebx
0047808F  \.  C3            retn

看到这里不懂也没关系 后面对返回值的处理会详细解释
上面代码用到的数组
仔细观察的话 如果不想让取出的数与4或8位与后不为0的话 只能找84h或48h
004E1A46  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
004E1A56  20 00 28 00 28 00 28 00 28 00 28 00 20 00 20 00   .(.(.(.(.(. . .
004E1A66  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
004E1A76  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
004E1A86  48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  H........
004E1A96  10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  ........
004E1AA6  84 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00  ????????
004E1AB6  84 00 84 00 10 00 10 00 10 00 10 00 10 00 10 00  ??......
004E1AC6  10 00 81 00 81 00 81 00 81 00 81 00 81 00 01 00  .??????.
004E1AD6  01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00  ........
004E1AE6  01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00  ........
004E1AF6  01 00 01 00 01 00 10 00 10 00 10 00 10 00 10 00  ........
004E1B06  10 00 82 00 82 00 82 00 82 00 82 00 82 00 02 00  .??????.
004E1B16  02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00  ........
004E1B26  02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00  ........
004E1B36  02 00 02 00 02 00 10 00 10 00 10 00 10 00 20 00  ....... .

出来后
0043B7D4  |.  83C4 04       add     esp, 4
0043B7D7  |.  8BF0          mov     esi, eax                         ;  把返回值放入esi
0043B7D9  |.  8D45 D0       lea     eax, dword ptr [ebp-30]          ;  取存了第16个key的局部变量地址
0043B7DC  |.  50            push    eax                              ;  压栈
0043B7DD  |.  E8 AEC80300   call    00478090                         ;  再次相同的CALL
0043B7E2  |.  83C4 04       add     esp, 4
0043B7E5  |.  03F0          add     esi, eax                         ;  这次把返回值和esi相加了。。
0043B7E7  |.  83FE 0A       cmp     esi, 0A                          ;  关键比较 两次返回值加起来要与0xA相等 这样的话结合上面的分析 我们必须构造出使两次返回值的和为0xA的字符
对数组的观察发现 里面大部分的数与4或8进行and操作的话 都会使返回值为零
故我第一次想让第一次的返回值为0 第二次的返回值为0xA 但是对前面几个操作进行反推发现并不能使返回值为0xA
要让返回值为0xA 那么ebx需为0xA
再对 [esi+eax*2-30] 反推得esi(esi为key字符)必须为0x3A(eax为0是因为前面的ebx被清零了 eax被ebx赋值为0)
但是如果esi为0x3A的话 就无法通过前面与取出的数组元素的比较(取出的数跟4或8 进行and操作后都为0) 那么就无法进行lea [esi+eax*2-30]
观察数组 结合计算:004E1A46(数组基地址)  + 0x3A * 2 = 004E1ABA 发现此地址旁边刚好就是0x84 这个数和4and操作不会为0
其实那么就不跳转 能lea [esi+eax*2-30]了
那么让esi再小一点  取出数组[eax+esi*2] 就能取到0x84了
我构造出了esi为0x35 即key字符'5' 这样取到0x84 让返回值也成了0x5 两次相加也就是0xA

0043B7EA  |.  75 23         jnz     short 0043B80F                   ;  不相等的话就验证失败
0043B7EC  |.  8D4D E8       lea     ecx, dword ptr [ebp-18]          ;  完全同上
0043B7EF  |.  51            push    ecx
0043B7F0  |.  E8 9BC80300   call    00478090                         ;  完全同上
0043B7F5  |.  83C4 04       add     esp, 4
0043B7F8  |.  8BF0          mov     esi, eax                         ;  完全同上
0043B7FA  |.  8D55 DC       lea     edx, dword ptr [ebp-24]
0043B7FD  |.  52            push    edx
0043B7FE  |.  E8 8DC80300   call    00478090                         ;  完全同上
0043B803  |.  83C4 04       add     esp, 4
0043B806  |.  03F0          add     esi, eax                         ;  完全同上
0043B808  |.  83FE 0A       cmp     esi, 0A
0043B80B  |.  75 02         jnz     short 0043B80F
0043B80D  |.  EB 04         jmp     short 0043B813
0043B80F  |>  33C0          xor     eax, eax
0043B811      EB 1F         jmp     short 0043B832
0043B813  |>  8B45 08       mov     eax, dword ptr [ebp+8]
0043B816  |.  8A48 03       mov     cl, byte ptr [eax+3]             ;  取第四个key
0043B819  |.  884D C4       mov     byte ptr [ebp-3C], cl
0043B81C  |.  C645 C5 00    mov     byte ptr [ebp-3B], 0
0043B820  |.  0FBE55 C4     movsx   edx, byte ptr [ebp-3C]
0043B824  |.  83FA 2F       cmp     edx, 2F                          ;  第四个key为0x2f
0043B827  |.  74 04         je      short 0043B82D
0043B829  |.  33C0          xor     eax, eax
0043B82B      EB 05         jmp     short 0043B832
0043B82D  |>  B8 01000000   mov     eax, 1                           ;  成功验证的返回值为1
0043B832  |>  5E            pop     esi
0043B833  |.  8BE5          mov     esp, ebp
0043B835  |.  5D            pop     ebp
0043B836  \.  C3            retn

这样的话这个key的第1, 2,15,16个key可以是'5'(ascii 0x35) 第四个key是'/'(ascii 0x2f)
第3个key是'$'(ascii 0x24)
例子: 55$/777777777755 这样就能过验证了

分析结束。我表达能力不好 有些东西很难说清 见笑了。。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 6
支持
分享
最新回复 (4)
雪    币: 162
活跃值: (63)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
不错,写得挺好的。
2012-3-26 11:20
0
雪    币: 517
活跃值: (35)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
不但是表达不清,还不知道程序到底在做什么。
告诉你吧,你那个数组其实是检测字符类型。如果是0123456789ABCDEF,则转化为整数。
且第1、16位之和以及2、15位之和必须为10。第3-4位必须是$/,其余随意。就这么简单。

你是不是说罗嗦了?*_^
2012-3-26 13:13
0
雪    币: 380
活跃值: (108)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
牛!大师不愧是大师,三言二语就能弄这么明白,强烈学习!
2012-3-28 20:50
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错,但是我看不懂
2012-4-2 18:40
0
游客
登录 | 注册 方可回帖
返回
//