【文章标题】: 加密解密习题破文
【文章作者】: kanghtta
【作者邮箱】: kanghtta@hotmail.com
【作者主页】: http://kanghtta.cublog.cn
【作者QQ号】: 18381291
【软件名称】: echap511
【软件大小】: 4kb
【下载地址】: 加密解密第二版光盘
【加壳方式】: 无
【编写语言】: masm32
【使用工具】: peid ollyICE
【软件介绍】: 系列号保护
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
大家好,这是我第一次写破文,(其实这样说蛮不好意思的,不过对于我这种菜鸟级的来说,也算是破文吧)
见习题上是中等难度,虽然有答案,但还是自己练练。嘿嘿,多动手比光看代码好吧!
首先,还是和通常一样,先运行下看看,点check ,嘿嘿,有字串,Bad Serial ,Sorry!“ 算是看到点希望了,毕竟
刚开始接触crack 。
1, 用peid 察看,无壳,汇编语言编写,(怪不得短小精炼),由于在学动态分析,就用OD载入了。
分析:
由于是用masm32汇编编写的,嘿嘿,一开始就看到了熟悉的函数,GetModuleHandle,刚开始打算用字串参考,
向下拉拉看,代码不长,就想自己来分析一下代码。
00401070 |> \83F8 10 cmp eax, 10
00401073 |. 75 0C jnz short 00401081
00401075 |. 6A 00 push 0 ; /Result = 0; Case 10 (WM_CLOSE) of switch 0040104F
00401077 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
0040107A |. E8 F7000000 call ; \EndDialog
0040107F |. EB 3F jmp short 004010C0
00401081 |> 3D 11010000 cmp eax, 111
00401086 |. 75 2F jnz short 004010B7
00401088 |. 8B45 10 mov eax, dword ptr [ebp+10] ; Case 111 (WM_COMMAND) of switch 0040104F
0040108B |. 66:3D B90B cmp ax, 0BB9
0040108F |. 75 2F jnz short 004010C0
00401091 |. C1E8 10 shr eax, 10
00401094 |. 66:0BC0 or ax, ax
00401097 |. 75 1C jnz short 004010B5
00401099 |. 6A 0A push 0A ; /Count = A (10.)
0040109B |. 68 44304000 push 00403044 ; |Buffer = echap511.00403044
004010A0 |. 68 B80B0000 push 0BB8 ; |ControlID = BB8 (3000.)
004010A5 |. FF35 54304000 push dword ptr [403054] ; |hWnd = 00330266 ('Pusillus Crackme 1.0',class='#32770')
004010AB |. E8 D2000000 call ; \GetDlgItemTextA
004010B0 |. E8 14000000 call 004010C9
004010B5 |> EB 09 jmp short 004010C0
004010B7 |> B8 00000000 mov eax, 0 ; Default case of switch 0040104F
004010BC |. C9 leave
004010BD |. C2 1000 retn 10
看004010AB处, GetDlgItemTextA函数,功能是获取和对话框关联的控件文本和标题。
004010B0 |. E8 14000000 call 004010C9 //猜测这个是关键,F7跟进,比较完了当然是验证了嘛。
004010C9 /$ 56 push esi
004010CA |. 57 push edi
004010CB |. 51 push ecx
004010CC |. 33F6 xor esi, esi
004010CE |. 33FF xor edi, edi
004010D0 |. B9 08000000 mov ecx, 8
004010D5 |. BE 44304000 mov esi, 00403044 ; ASCII "kanghtta"
004010DA |> 8036 32 /xor byte ptr [esi], 32
004010DD |. 46 |inc esi
004010DE |.^ E2 FA \loopd short 004010DA
004010E0 |. BE 44304000 mov esi, 00403044 ; 将输入和0x32异或运算 得ASCII "YS\UZFFS"
004010E5 |. B9 04000000 mov ecx, 4
004010EA |> 8A06 /mov al, byte ptr [esi]
004010EC |. 8A5E 01 |mov bl, byte ptr [esi+1]
004010EF |. 32C3 |xor al, bl
004010F1 |. 8887 4C304000 |mov byte ptr [edi+40304C], al
004010F7 |. 83C6 02 |add esi, 2
004010FA |. 47 |inc edi
004010FB |.^ E2 ED \loopd short 004010EA
004010FD |. BE 4C304000 mov esi, 0040304C ;将ASCII "YS\UZFFS"两两字符运算得4位存0040304C中
; 0040304C数据为 0A 09 1C 15
00401102 |. 8A06 mov al, byte ptr [esi]
00401104 |. 8A5E 01 mov bl, byte ptr [esi+1]
00401107 |. 32C3 xor al, bl
00401109 |. 8A5E 02 mov bl, byte ptr [esi+2]
0040110C |. 8A4E 03 mov cl, byte ptr [esi+3]
0040110F |. 32D9 xor bl, cl
00401111 |. 32C3 xor al, bl ;0A 09 1C 15两两异或后的结果在异或 存al =03
00401113 |. B9 08000000 mov ecx, 8
00401118 |. BE 44304000 mov esi, 00403044
0040111D |> 3006 /xor byte ptr [esi], al ;将ASCII "YS\UZFFS"和al异或后存入
0040111F |. 46 |inc esi
00401120 |.^ E2 FB \loopd short 0040111D
00401122 |. B9 08000000 mov ecx, 8
00401127 |. BE 44304000 mov esi, 00403044
0040112C |. BF 08304000 mov edi, 00403008 ;启0040303008的数据和运算后的比较
00401131 |> 8A06 /mov al, byte ptr [esi]
00401133 |. 3A07 |cmp al, byte ptr [edi]
00401135 75 1D jnz short 00401154 ;不等则完蛋
00401137 |. 46 |inc esi
00401138 |. 47 |inc edi
00401139 |.^ E2 F6 \loopd short 00401131
在这里的问题是如何知道00403008的数据呢? 很简单,信息窗口中:右键,数据窗口中跟随地址
可以看到 :00403008 71 18 59 1B 79 42 45 4C qYyBEL
可 这些数据是怎么来的呢?
现在有两种推断,这些数据是程序运行时动态产生的呢 还是程序一开始就有的呢?
ctrl+F2 重新载入
在数据窗口下内存写断点,不行,断不下来。猜测可能是静态数据。
在反汇编窗口中右键:转到 表达式 输入 :00403008
00403008 /71 18 jno short 00403022
0040300A |59 pop ecx
0040300B |1B79 42 sbb edi, dword ptr [ecx+42]
0040300E |45 inc ebp
0040300F |4C dec esp
有没有见到机器码中的数据很熟悉呢? 原来是启3008后的4字节作为比较参数!
嘿嘿。现在来看看这个注册的算法?
1)从对话框中的编辑框控件中提取用户输入的字符串。
2)将字符串中的每个字符和0x32作异或运算
3)将异或运算得到的结果在两两运算,得到4位的结果
4)将四位的结果两两异或,得到二位结果,
5)在将4运算的结果异或,结果存al
6)al和与0x32运算存入的字符串再次逐一异或运算。
7)将6运算的结果和00403008中的数据比较,不等则完蛋。
现在来算它的注册码: 由于00403008的数据固定,固写起来比较简单。
#include
void main()
{
char middle_1[4];
char middle_2[2];
char b[8]={0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C} ;
middle_1[0]=b[0]^b[1];
middle_1[1]=b[2]^b[3];
middle_1[2]=b[4]^b[5];
middle_1[3]=b[6]^b[7];
cout<<middle_1[0]<<middle_1[1]<<middle_1[2]<<middle_1[3]<<endl;
middle_2[0]=middle_1[0]^middle_1[1];
middle_2[1]=middle_1[2]^middle_1[3];
char al=middle_2[0]^middle_2[1];
cout<<al<<endl;
for(int i=0;i<=8;i++)
{
b[i]=b[i]^al;
b[i]=b[i]^0x32;
cout<<b[i]<<' ';
}
}
Z3r0Ring 运行程序将Z3r0Ring输入
Good work Cracker 哈哈。。。。成功!
--------------------------------------------------------------------------------
【经验总结】
虽然比较简单,但当
Good work Cracker 出来时,仍然按捺不住心中的那种激动,如果自己能破的,就不要看别人的答案,实在没思路了,
在参考,希望自己能在这条路上坚持下去。
感谢看雪,让我入门。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年03月27日 下午 04:42:42
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: