Please Crack Me

闲着无聊,从以前的程序堆随便找了个 程序,“破解”一下,很简单,供大家把玩。
工具:windbg
破解方法:找出加密方法,算出注册码。
http://files.cnblogs.com/diggingdeeply/crackme.rar
要破解的程序界面如图:

打开注册时出现:

输入name和serial正确时:

输入错误时:


好,下面我们开始解密。打开windbg,load程序,一路F5.
程序界面出现,打开注册窗口,这时候kb,看一下callstack:
0 : 000 > kb
ChildEBP RetAddr  Args to Child              
0012fd94  7756 073f  77573c9f  001c0d68   00000001  ntdll!KiFastSystemCallRet
0012fd98  77573c9f  001c0d68   00000001   00000000  USER32!NtUserWaitMessage+0xc
0012fdcc  77572dc0  00080dbe   001c0d68   00000010  USER32!DialogBox2+0x202
0012fdf4  77572eec  00400000   004070dc   001c0d68  USER32!InternalDialogBox+0xd0
0012fe14  7758819e  00400000   004070dc   001c0d68  USER32!DialogBoxIndirectParamAorW+0x37
*** 
WARNING:  Unable to verify checksum for crackme.EXE
*** 
ERROR:  Symbol file could  not  be found.  Defaulted to export symbols for crackme.EXE - 
0012fe40   00401223   00400000   00402115   001c0d68  USER32!DialogBoxParamA+0x4c
WARNING:  Stack unwind information  not  available. Following frames may be wrong.
0012fe68  7755fd72  001c0d68   00000111   00000066  crackme!WndProc+0xfb
0012fe94  7755fe4a  00401128   001c0d68   00000111  USER32!InternalCallWinProc+0x23
0012ff0c  7756 018d   00000000   00401128   001c0d68  USER32!UserCallWinProcCheckWow+0x14b
0012ff70  77558b7c  00401128   00000001   0012ff94  USER32!DispatchMessageWorker+0x322
0012ff80   0040111b   00402048  777ad0e9 7ffdc000 USER32!DispatchMessageA+0xf
0012ff94  77c019bb 7ffdc000 75ec3dbf  00000000  crackme+0x111b
0012ffd4  77c0198e  00401000  7ffdc000  00000000  ntdll!__RtlUserThreadStart+0x23
0012ffec   00000000   00401000  7ffdc000  00000000  ntdll!_RtlUserThreadStart+0x1b

其中发现USER32!DialogBoxParamA比较可疑,下一个断点:
bp USER32!DialogBoxParamA,继续F5.
这时候cancle注册窗口,在打开就能击中断点了。
一路F10,打开汇编代码窗口(Alt+7),出现注册窗口,输入测试数据(aaa和bbb),这时候因为不知道加密规则,所以是随便输入的。
之后OK,断在了如下代码处:
 1  00401223  83f800           cmp      eax, 0
 2  00401226  74be             je       crackme!WndProc+0xbe ( 004011e6 )         [br= 0 ]
 3  00401228  688e214000       push     offset crackme!WndProc+0x1066 ( 0040218e )
 4  0040122d  e84c010000       call     crackme!WndProc+0x256 ( 0040137e )
 5  00401232   50                push     eax
 6  00401233  687e214000       push     offset crackme!WndProc+0x1056 ( 0040217e )
 7  00401238  e89b010000       call     crackme!WndProc+0x2b0 ( 004013d8 )
 8  0040123d  83c404           add      esp, 4
 9  00401240   58                pop      eax
10  00401241  3bc3             cmp      eax,ebx
11  00401243   7407              je       crackme!WndProc+0x124 ( 0040124c )
12  00401245  e818010000       call     crackme!WndProc+0x23a ( 00401362 )
13  0040124a  eb9a             jmp      crackme!WndProc+0xbe ( 004011e6 )
14  0040124c  e8fc000000       call     crackme!WndProc+0x225 ( 0040134d )
15 

因为14行call之后直接出现了错误提示窗口,所以12行应该是正确提示窗口。
那么3和4行,6行和7行则分别是两次数据判断的函数所在,则10行就是破解的关键,暴力破解的话就可以从这句入手。
从4行进入,代码如下:
 1  0040137e  8b742404         mov      esi,dword ptr [esp+ 4 ss: 0023 : 0012fe58 = 0040218e
 2  00401382   56                push     esi
 3  00401383  8a06             mov      al,byte ptr [esi]
 4  00401385  84c0             test     al,al
 5  00401387   7413              je       crackme!WndProc+0x274 ( 0040139c )
 6  00401389  3c41             cmp      al,41h
 7  0040138b  721f             jb       crackme!WndProc+0x284 ( 004013ac )
 8  0040138d  3c5a             cmp      al,5Ah
 9  0040138f   7303              jae      crackme!WndProc+0x26c ( 00401394 )
10  00401391   46                inc      esi
11  00401392  ebef             jmp      crackme!WndProc+0x25b ( 00401383 )
12  00401394  e839000000       call     crackme!WndProc+0x2aa ( 004013d2 )
13  00401399   46                inc      esi
14  0040139a  ebe7             jmp      crackme!WndProc+0x25b ( 00401383 )
15  0040139c  5e               pop      esi
16  0040139d  e820000000       call     crackme!WndProc+0x29a ( 004013c2 )
17  004013a2  81f778560000     xor      edi,5678h
18  004013a8  8bc7             mov      eax,edi
19  004013aa  eb15             jmp      crackme!WndProc+0x299 ( 004013c1 )
20  004013ac  5e               pop      esi
21  004013ad  6a30             push     30h
22  004013af   6860214000        push     offset crackme!WndProc+0x1038 ( 00402160 )
23  004013b4   6869214000        push     offset crackme!WndProc+0x1041 ( 00402169 )
24  004013b9  ff7508           push     dword ptr [ebp+ 8 ]
25  004013bc  e879000000       call     crackme!WndProc+0x312 ( 0040143a )
26  004013c1  c3               ret

刚开始就是将ESI的地址内容送入AL,看看ESI的内容是什么?打开寄存器窗口(Alt+4),看到ESI的值是40218e,
dd 40218e,数据为:
00616161 00000000 00000000 00000000
对照ascii表,知道61h是字符a,则就是刚才输入的name。可以看到将a送入AL后,分别和41h('A')和5Ah('Z')比较,
根据代码跟踪可以发现要求name的字符在A~Z之间, 不然就直接跳到错误的地方去了。
则变换数据,输入BBB,在继续跟踪将name 的地址pop到esi,在16行进入到另外一个地方:
1  04013c2  33ff             xor      edi,edi
2  004013c4  33db             xor      ebx,ebx
3  004013c6  8a1e             mov      bl,byte ptr [esi]
4  004013c8  84db             test     bl,bl
5  004013ca   7405              je       crackme!WndProc+0x2a9 ( 004013d1 )
6  004013cc   03fb              add      edi,ebx
7  004013ce   46                inc      esi
8  004013cf  ebf5             jmp      crackme!WndProc+0x29e ( 004013c6 )
9  004013d1  c3               ret
这段代码比较简单,就是将name的值相加,结果由edi传出,继续上一段代码,发现函数返回之后则和5678h进行了异或,结果放入了eax传回
则至此,name 的加密规则解密完毕,其伪代码如下:
循环name字符串
{
      if(字符<
' A ' 或是字符> ' Z ' ) return ;

      累加字符的和,返回。
}
之后和5678h异或

好了,name分析完了。下面接着是serial,F10进入:
 1  004013d8  33c0             xor      eax,eax
 2  004013da  33ff             xor      edi,edi
 3  004013dc  33db             xor      ebx,ebx
 4  004013de  8b742404         mov      esi,dword ptr [esp+ 4 ]
 5  004013e2  b00a             mov      al,0Ah
 6  004013e4  8a1e             mov      bl,byte ptr [esi]
 7  004013e6  84db             test     bl,bl
 8  004013e8  74 0b              je       crackme!WndProc+0x2cd ( 004013f5 )
 9  004013ea  8 0eb30            sub      bl,30h
10  004013ed   0faff8            imul     edi,eax
11  004013f0   03fb              add      edi,ebx
12  004013f2   46                inc      esi
13  004013f3  ebed             jmp      crackme!WndProc+0x2ba ( 004013e2 )
14  004013f5  81f734120000     xor      edi,1234h
15  004013fb  8bdf             mov      ebx,edi
16  004013fd  c3               ret

先是5行送个0ah到AL,然后将serial送入BL,9行减去30h,然后edi×eax+bl,依次循环。
一般减30h是将数字字符ascii码转为十进制数字,所以上面实际上就是
1  循环serial字符串
2  {
3       int  i=strtoint(字符);
4       sum=sum× 10 +i;
5      return sum;
6  }//其实就是inttostr(serial)
然后和1234h异或,结果由ebx
最后回到最最上面的代码
pop      eax
cmp      eax,ebx
则就是比较两个值,如果相等就显示正确的;反之就是错误的

我们name的值输入的是BBB,则name加密后的值是56BE;再则异或有交换的作用,
serial^1234h=name^5678h=56BE
则56BE^1234h=serial=448A,十进制是17546。
这时候输入BBB和17546,就能得到正确的消息了。


好了,这个程序分析完了。很简单吧?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值