且行且远
分类: 逆向手札 由 ssfighter 于 2006年5月6日 发表

【破文标题】对一个KeyFile的CrackMe的分析
【破文作者】ssfighter
【作者邮箱】ssfighter@gmail.com
【作者主页】
【破解工具】OllyICE、FileMon7.01、FileInfo4.01
【破解平台】WinXP
【软件名称】
【软件大小】
【原版下载】
【保护方式】
【软件简介】
【破解声明】第一次玩KeyFile的CrackMe,不是很难,但是算法设计的比较有意思
————————————————————————
这个CrackMe挺有意思的,提示给的很全:-P,不错的练手的教材。高手就不要看了

先用FileInfo侦壳,发现是UPX加的壳,OllyICE载入后停在这里:
004460F0 >  60              pushad
004460F1    BE 00104300     mov     esi, CrackMe.00431000
004460F6    8DBE 0000FDFF   lea     edi, ds:[esi+FFFD0000]
004460FC    57              push    edi
004460FD    83CD FF         or      ebp, FFFFFFFF
00446100    EB 10           jmp     short CrackMe.00446112

用ESP定律,直接到这里:
0044623E    61              popad
0044623F  – E9 D405FEFF     jmp     CrackMe.00426818
00446244    5C              pop     esp

00426818    55              push    ebp    在这里Dump即可
00426819    8BEC            mov     ebp, esp
0042681B    83C4 F4         add     esp, -0C
0042681E    E8 41C9FDFF     call    CrackMe.00403164

脱壳后可以运行,侦壳发现是Delphi编写的,而且还是比较老的Delphi编的:)
用FileMon扫描一下,发现程序需要读取的KeyFile是ctm_cm02.key。新建一个这个文件,在OllyICE中下API断点CreateFileA。从系统领空中返回到这里:
00404166    8D43 48         lea     eax, ds:[ebx+48]
00404169    50              push    eax
0040416A    E8 9DD0FFFF     call    <jmp.&kernel32.CreateFileA>
0040416F    83F8 FF         cmp     eax, -1
00404172    74 29           je      short cr1.0040419D
00404174    8903            mov     ds:[ebx], eax
00404176    5F              pop     edi
00404177    5E              pop     esi
00404178    5B              pop     ebx
00404179    C3              retn
0040417A    33C0            xor     eax, eax
0040417C    C3              retn

再返回到这里:
0042658D    E8 1EDCFDFF     call    cr1.004041B0                     ; 读取文件ctm_cm02.key
00426592    E8 4DC1FDFF     call    cr1.004026E4
00426597    85C0            test    eax, eax
00426599    0F85 66010000   jnz     cr1.00426705
0042659F    8D85 A8FEFEFF   lea     eax, ss:[ebp+FFFEFEA8]
004265A5    E8 5AD9FDFF     call    cr1.00403F04                     ; 判断文件大小
004265AA    E8 F9C0FDFF     call    cr1.004026A8
004265AF    8945 FC         mov     ss:[ebp-4], eax
004265B2    837D FC 00      cmp     dword ptr ss:[ebp-4], 0
004265B6    75 15           jnz     short cr1.004265CD004265B8    BA 64674200     mov     edx, cr1.00426764                ; key file is empty!
004265BD    8B83 B0010000   mov     eax, ds:[ebx+1B0]
004265C3    E8 CCB6FEFF     call    cr1.00411C94
004265C8    E9 28010000     jmp     cr1.004266F5
004265CD    817D FC 0000010>cmp     dword ptr ss:[ebp-4], 10000      ; UNICODE “=::=::\”
004265D4    7E 07           jle     short cr1.004265DD
004265D6    C745 FC 0000010>mov     dword ptr ss:[ebp-4], 10000      ; UNICODE “=::=::\”
004265DD    6A 00           push    0
004265DF    8D95 FCFFFEFF   lea     edx, ss:[ebp+FFFEFFFC]
004265E5    8B4D FC         mov     ecx, ss:[ebp-4]
004265E8    8D85 A8FEFEFF   lea     eax, ss:[ebp+FFFEFEA8]
004265EE    E8 71D8FDFF     call    cr1.00403E64                     ; 读取文件
004265F3    E8 B0C0FDFF     call    cr1.004026A8
004265F8    53              push    ebx
004265F9    57              push    edi
004265FA    56              push    esi
004265FB    8D75 FC         lea     esi, ss:[ebp-4]
004265FE    8B0E            mov     ecx, ds:[esi]
00426600    8DB5 FCFFFEFF   lea     esi, ss:[ebp+FFFEFFFC]
00426606    8DBD FBFFFEFF   lea     edi, ss:[ebp+FFFEFFFB]
0042660C    31C0            xor     eax, eax
0042660E    83CA FF         or      edx, FFFFFFFF
00426611    31DB            xor     ebx, ebx
00426613    40              inc     eax
00426614    F7D2            not     edx

下面就是判断序列号的地方了
00426616    8A1C16          mov     bl, ds:[esi+edx]                 ; 取序列号各位
00426619    84DB            test    bl, bl                           ; 注意这里,只有是0才可以
0042661B    74 29           je      short cr1.00426646
0042661D    E8 16000000     call    cr1.00426638
00426622    52              push    edx
00426623    F7E3            mul     ebx
00426625    5A              pop     edx
00426626    35 326D5463     xor     eax, 63546D32
0042662B    FEC2            inc     dl
0042662D    39CA            cmp     edx, ecx                         ; ecx是文件的大小
0042662F    74 42           je      short cr1.00426673
00426631    80FA FF         cmp     dl, 0FF
00426634    74 3D           je      short cr1.00426673
00426636  ^ EB DE           jmp     short cr1.00426616
可是这里的计算大概上就是去序列号的第一位乘以1,然后和63546D32异或,之后再乘以序列号第二位,然后再和63546D32异或,依次这样进行下去。

再往下看,注意刚才test bl, bl的地方,如果那里没有跳,就会跳到这里,但是只要到这里必然会到Invalid的地方。因此必须让bl=0,这也就是说明在序列号文件某处应该是00 (注意不一定是结尾,一开始我就以为是在结尾,结果把自己绕了进去)只要是00就会从上面那个循环的地方正确地跳出,不会出现Invalid的情况。

00426673    B8 02000000     mov     eax, 2
00426678    8907            mov     ds:[edi], eax
0042667A    5E              pop     esi
0042667B    5F              pop     edi
0042667C    5B              pop     ebx
0042667D    8A85 FBFFFEFF   mov     al, ss:[ebp+FFFEFFFB]
00426683    2C 01           sub     al, 1
00426685    72 08           jb      short cr1.0042668F
00426687    74 4A           je      short cr1.004266D3
00426689    FEC8            dec     al
0042668B    74 58           je      short cr1.004266E5
0042668D    EB 66           jmp     short cr1.004266F5
0042668F    BA 80674200     mov     edx, cr1.00426780                ; valid key file found!
00426694    8B83 B0010000   mov     eax, ds:[ebx+1B0]
0042669A    E8 F5B5FEFF     call    cr1.00411C94
0042669F    BA A0674200     mov     edx, cr1.004267A0                ; registered to:
004266A4    8D85 A4FEFEFF   lea     eax, ss:[ebp+FFFEFEA4]
004266AA    E8 05CCFDFF     call    cr1.004032B4
004266AF    8D85 A4FEFEFF   lea     eax, ss:[ebp+FFFEFEA4]
004266B5    8B95 F4FFFEFF   mov     edx, ss:[ebp+FFFEFFF4]
004266BB    E8 DCCCFDFF     call    cr1.0040339C
004266C0    8B95 A4FEFEFF   mov     edx, ss:[ebp+FFFEFEA4]
004266C6    8B83 C0010000   mov     eax, ds:[ebx+1C0]
004266CC    E8 C3B5FEFF     call    cr1.00411C94
004266D1    EB 22           jmp     short cr1.004266F5
004266D3    BA B8674200     mov     edx, cr1.004267B8                ; key file contains wrong serial!
004266D8    8B83 B0010000   mov     eax, ds:[ebx+1B0]
004266DE    E8 B1B5FEFF     call    cr1.00411C94
004266E3    EB 10           jmp     short cr1.004266F5
004266E5    BA E0674200     mov     edx, cr1.004267E0                ; key file is not valid!
004266EA    8B83 B0010000   mov     eax, ds:[ebx+1B0]
004266F0    E8 9FB5FEFF     call    cr1.00411C94
004266F5    8D85 A8FEFEFF   lea     eax, ss:[ebp+FFFEFEA8]
004266FB    E8 C8D7FDFF     call    cr1.00403EC8
00426700    E8 A3BFFDFF     call    cr1.004026A8

但是仅仅这样还没有完,如果从bl=0处跳转,会来到这里

0042664B    42              inc     edx
0042664C    83C2 04         add     edx, 4
0042664F    39D1            cmp     ecx, edx
这里,edx是序列号中00之前的部分,再加上4应该和ecx(也就是文件长度)相等,这说明在KeyFile中00之后还应该有4个字节,这4个字节很重要,后面将会看到。

00426651    75 20           jnz     short cr1.00426673
00426653    83EA 04         sub     edx, 4
00426656    85C0            test    eax, eax
00426658    76 02           jbe     short cr1.0042665C
0042665A    D1E8            shr     eax, 1
0042665C    3B0416          cmp     eax, ds:[esi+edx]
注意看这里,ESI指向的就是KeyFile中的内容,而ESI+EDX正好指向00之后的那四个字节,而eax是什么,前面异或算了很久的东西,再加上上一部的右移一位就是eax的内容,看到这里我们明白了,这个KeyFile实际上就是在检验00前面和00后面的东西能否对应上,前面的算法已经有了,因此只要把00后面的4个字节的东西加上就可以了。

0042665F    75 09           jnz     short cr1.0042666A
00426661    B8 00000000     mov     eax, 0
这里只有eax=0才能出现正确的提示。

00426666    8907            mov     ds:[edi], eax
00426668    EB 10           jmp     short cr1.0042667A
0042666A    B8 01000000     mov     eax, 1
0042666F    8907            mov     ds:[edi], eax
00426671    EB 07           jmp     short cr1.0042667A

好的,下面就可以自己写一个KeyFile了,计算过程比较简单,假设注册的ID是ssfighter@newsmth,写一个KeyFile如下:
73 73 66 69 67 68 74 65 72 40 6E 65 77 73 6D 74     // ssfighter@newsmt
68 00 51 30 AB 03                    // h…..

运行之后显示成功的信息。
————————————————————————
这是我第一次玩KeyFile的CrackMe,还好这个不是很难,在PYG上面看到的这个CrackMe,觉得有意思就拿来做了一下,PYG论坛上那个人写的破文分析的有点问题,我就自己写了一个破文。
————————————————————————
【版权声明】



发表评论

昵称:  (必须)
邮件:  (必须)
网址: 
评论: