【文章标题】: CRACKME破解分析
【文章作者】: 逍遥风
【软件名称】: CRC算法练习
【下载地址】: 本地下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
---------------------------------------------------------------------
【详细过程】
菜鸟偶得一点心得,与大家分享。
很不错的CRC32算法练习。
非明码比较。F(注册名)=G(注册码)才能注册成功
用OD载入这个CRACKME。根据错误提示很容易找到关键代码处:
004042EF |. E8 ACECFFFF call 00402FA0
004042F4 |. 50 push eax ; |Buffer
004042F5 |. A1 28654000 mov eax, [406528] ; |
004042FA |. 50 push eax ; |hWnd => 001603DC (class='Edit',parent=001B032C)
004042FB |. E8 DCF9FFFF call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
00404300 |. 83FE 05 cmp esi, 5 ; 取注册名的位数与5比较
00404303 |. 0F8C B1000000 jl 004043BA ; 小于5位就跳向失败
从这里可以得知,注册名的位数必须大于等于5位
00404309 |. 8D45 FC lea eax, [ebp-4]
0040430C |. 8B4D FC mov ecx, [ebp-4] ; [EBP-4]中存放的就是注册名
0040430F |. BA F8434000 mov edx, 004043F8 ; diken
00404314 |. E8 03ECFFFF call 00402F1C ; 将注册名与固定字符串DiKeN合并,组成新的字符串设为字符串A
00404319 |. 8B45 FC mov eax, [ebp-4] ; 使EAX等于字符串A
0040431C |. E8 AFEBFFFF call 00402ED0 ; 取字符串A的位数
00404321 |. 8BD0 mov edx, eax ; 使EDX等于字符串A的位数
00404323 |. 8D45 FC lea eax, [ebp-4] ; 使EAX等于字符串A
取输入的注册名,以lovetc为例,与固定字符串DiKeN合并。
组成字符串A:DiKeNlovetc
00404326 |. E8 C5FAFFFF call 00403DF0 ; 对字符串A进行CRC32计算
0040432B |. 8BF0 mov esi, eax ; 使ESI等于计算的结果
将字符串A进行CRC32计算。
即CRC32(DiKeNlovetc)= 0BE89C3C 这个计算结果设为设为结果1
0040432D |. 8D45 F8 lea eax, [ebp-8]
00404330 |. E8 B3EAFFFF call 00402DE8
00404335 |. A1 2C654000 mov eax, [40652C]
0040433A |. 50 push eax ; /hWnd => 001A0390 (class='Edit',parent=001B032C)
0040433B |. E8 A4F9FFFF call <jmp.&user32.GetWindowTextLengthA> ; \GetWindowTextLengthA
00404340 |. 8BD8 mov ebx, eax ; 取输入的注册码的位数
00404342 |. 85DB test ebx, ebx
00404344 |. 7E 10 jle short 00404356
00404346 |> 8D45 F8 /lea eax, [ebp-8]
00404349 |. BA EC434000 |mov edx, 004043EC
0040434E |. E8 85EBFFFF |call 00402ED8
00404353 |. 4B |dec ebx
00404354 |.^ 75 F0 \jnz short 00404346 ; 格式检验
00404356 |> 6A 20 push 20
00404358 |. 8B45 F8 mov eax, [ebp-8]
0040435B |. E8 40ECFFFF call 00402FA0
00404360 |. 50 push eax ; |Buffer
00404361 |. A1 2C654000 mov eax, [40652C] ; |
00404366 |. 50 push eax ; |hWnd => 001A0390 (class='Edit',parent=001B032C)
00404367 |. E8 70F9FFFF call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
0040436C |. 8D45 F8 lea eax, [ebp-8] ; 取输入的注册码
0040436F |. 8B4D F8 mov ecx, [ebp-8] ; 使ECX等于输入的注册码
00404372 |. BA 08444000 mov edx, 00404408 ; 0
00404377 |. E8 A0EBFFFF call 00402F1C ; 在输入的注册码前面补0,得到字符串B
0040437C |. 8B45 F8 mov eax, [ebp-8] ; 使EAX等于字符串B
这里取输入的注册码进行计算。
例如输入的注册码是123 。在这里就在123前补一个0
即:字符串B等于0123
0040437F |. E8 A0FEFFFF call 00404224 ; 对字符串B的计算。
这里是对输入的注册码进行的计算。跟进看看
来到这里:
00404224 /$ 55 push ebp ; 来到这里
00404225 |. 8BEC mov ebp, esp
省略一些代码。。。
0040424C |. 8B55 FC mov edx, [ebp-4]
0040424F |. E8 2CECFFFF call 00402E80 ; 取输入的注册码的位数
00404254 |. 8B45 F8 mov eax, [ebp-8] ; EAX等于注册码的位数
00404257 |. E8 74ECFFFF call 00402ED0 ; 取字符串B
0040425C |. 8BC8 mov ecx, eax ; 使EAX等于字符串B的位数
0040425E |. 41 inc ecx
0040425F |. 33D2 xor edx, edx ; EDX清零
00404261 |. B8 01000000 mov eax, 1 ; 使EAX等于1
00404266 |> 03D2 /add edx, edx ; Dn=Cn+Cn(即:Dn=Cn*2)
00404268 |. 8D1492 |lea edx, [edx+edx*4] ; En=Dn+Dn*4
0040426B |. 8B5D F8 |mov ebx, [ebp-8] ; 使EBX等于字符串B
0040426E |. 0FB65C03 FF |movzx ebx, byte ptr [ebx+eax-1] ; 依次取字符串B的每一位的HEX值
00404273 |. 03D3 |add edx, ebx ; 每一位的HEX值加上对应的En
00404275 |. 83EA 30 |sub edx, 30 ; 相加结果减去定值0x30,结果设为Cn
00404278 |. 40 |inc eax ; 每计算一次EAX加1
00404279 |. 3BC8 |cmp ecx, eax ; 计算完了吗
0040427B |.^ 75 E9 \jnz short 00404266 ; 循环计算
0040427D |. 8BDA mov ebx, edx ; 保存计算结果
0040427F |. 33C0 xor eax, eax
这里就是对注册码的计算过程:简单说明一下,以注册码123为例
例如:输入的注册码是123
那么进行计算时的字符串B就是:0123
此时
取字符串B每一位的HEX值
第一位:0 (D1=0 ,E1=0)
0x30+0=0x30
C1=0x30-0x30=0
则:
D2=0+0=0
E2=0+0*4=0
第二位:1
0x31+0=0x31
C2=0x31-0x30=1
则:
D3=1+1=2
E3=2+2*4=A
第三位:2
0x32+A=0x3C
C3=0x3C-0x30=C
D4=C+C=18
E4=18+18*4=78
第四位:3
0x33+78=AB
C4=0xAB-0x30=0x7B
得到的C4就是计算结果:这个结果设为结果2
00404384 |. 33F0 xor esi, eax ; 检验ESI与EAX中的值是否相等
即比较结果一与结果2是否相等
00404386 |. 85F6 test esi, esi
00404388 |. 74 19 je short 004043A3 ; 相等就注册成功
0040438A |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
0040438C |. 68 0C444000 push 0040440C ; |错误
00404391 |. 68 14444000 push 00404414 ; |错误的注册码
00404396 |. A1 04654000 mov eax, [406504] ; |
0040439B |. 50 push eax ; |hOwner => 001B032C ('Crackme only CRC32 - DiKeN',class='MyWindowClass')
0040439C |. E8 6BF9FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004043A1 |. EB 17 jmp short 004043BA
004043A3 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
004043A5 |. 68 24444000 push 00404424 ; |恭喜
004043AA |. 68 2C444000 push 0040442C ; |正确的注册码
算法总结:
1)将注册名与固定字符串DiKeN合并。
2)将得到的新字符串进行CRC32计算。得到结果1
3)将输入的注册码补0后进行累加计算。得到结果2
4)将结果1与结果2比较。相等就注册成功
----------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月24日 16:42:14
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!