【破文标题】对一个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论坛上那个人写的破文分析的有点问题,我就自己写了一个破文。
------------------------------------------------------------------------
【版权声明】
评论