【文章标题】: MD2CrackMe算法分析
【文章作者】: dttom
【作者邮箱】: dttom2006@126.com
【软件名称】: MD2CrackMe
【软件大小】: 48Kb
【下载地址】: http://bbs.pediy.com/attachment.php?attachmentid=6635&d=1183881201
【保护方式】: 无
【编写语言】: Delphi
【使用工具】: Ollydbg,RadASM,Peid
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
首先我们先来了解一下什么是MD2算法,MD2是一种单向散列加密算法,根据RFC1319可以查得MD2算法的描述,基本算法流程如下:
(1)用i字节对消息进行填充,使填充后消息长度为(N=N+i)为16字节的整数倍。
(2)在256字节的随机打乱的数表中,通过XOR运算,获得一个16字节的附加检查和,附加到步骤一的结尾。N'=N+16
(3)初始化48字节的分组。将x的前16字节置为0,接下去的16字节对应消息的前16字节,第三个16字节是x的前16字节
与x的第二个16字节XOR结果。
(4)通过一段加密函数块实现加密。
t = 0;
for (i = 0; i < 18; i++)
{
for (j = 0; j < 48; j++)
t = x[j] ^= S[t];
t = (t + i) & 0xff;
}
(5)将消息块填入x的第二个16字节,x第三个16字节x是第一个16字节与第二个16字节XOR结果。重复这一过程,重复
次数为N'/16-1次。即最后16字节校验和不参与加密运算。
(6)最后输出x的前16字节为加密结果。
了解了上面的流程,我们可以来调试了,下面我说说我的操作过程,不一定正确,欢迎批评指正。我们来打开od,载入MD2CrackMe,F9运行,输入用户名dttom和试练码55556666,接着摆在我们面前
的就是下断,下bp GetDlgItemTextA断点。点注册认证,接着断在下面的代码处。
77D6AE36 > 8BFF mov edi, edi //断在这里
77D6AE38 55 push ebp
77D6AE39 8BEC mov ebp, esp
77D6AE3B FF75 0C push dword ptr [ebp+C]
77D6AE3E FF75 08 push dword ptr [ebp+8]
77D6AE41 E8 888FFBFF call GetDlgItem //获得控件的handle,为取数做准备
77D6AE46 85C0 test eax, eax
77D6AE48 74 0E je short 77D6AE58
77D6AE4A FF75 14 push dword ptr [ebp+14]
77D6AE4D FF75 10 push dword ptr [ebp+10]
77D6AE50 50 push eax
77D6AE51 E8 D572FCFF call GetWindowTextA //取控件内的字符串
77D6AE56 EB 0E jmp short 77D6AE66
77D6AE58 837D 14 00 cmp dword ptr [ebp+14], 0
77D6AE5C 74 06 je short 77D6AE64
77D6AE5E 8B45 10 mov eax, dword ptr [ebp+10]
77D6AE61 C600 00 mov byte ptr [eax], 0
77D6AE64 33C0 xor eax, eax
77D6AE66 5D pop ebp
77D6AE67 C2 1000 retn 10
......
ctrl+F9来到下面的代码处:
00408A2A . 8D45 B4 lea eax, dword ptr [ebp-4C]
00408A2D . BA AC934000 mov edx, 004093AC ; ASCII "dttom"
00408A32 . B9 FF000000 mov ecx, 0FF
00408A37 . E8 3CAEFFFF call 00403878 ; 计算用户名长度
00408A3C . 837D B4 00 cmp dword ptr [ebp-4C], 0
00408A40 . 75 1C jnz short 00408A5E
00408A42 . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408A44 . 68 788C4000 push 00408C78 ; |Title = ""D7,"",A2,"",B2,"崽崾?
00408A49 . 68 848C4000 push 00408C84 ; |Text = "用",BB,"?,B2,"",BB,"能为空请输入?,A1,""
00408A4E . 8B45 08 mov eax, dword ptr [ebp+8] ; |
00408A51 . 50 push eax ; |hOwner
00408A52 . E8 3DBDFFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00408A57 . 33DB xor ebx, ebx
00408A59 . E9 A2010000 jmp 00408C00
00408A5E > 68 FF000000 push 0FF ; /Count = FF (255.)
00408A63 . 68 AC944000 push 004094AC ; |Buffer = MD2Crack.004094AC
00408A68 . 68 F3030000 push 3F3 ; |ControlID = 3F3 (1011.)
00408A6D . 8B45 08 mov eax, dword ptr [ebp+8] ; |
00408A70 . 50 push eax ; |hWnd
00408A71 . E8 E6BCFFFF call <jmp.&user32.GetDlgItemTextA> ; \GetDlgItemTextA
00408A76 . 8D45 B0 lea eax, dword ptr [ebp-50]
00408A79 . BA AC944000 mov edx, 004094AC ; ASCII "55556666"
00408A7E . B9 FF000000 mov ecx, 0FF
00408A83 . E8 F0ADFFFF call 00403878 ; 计算假注册码长度
00408A88 . 837D B0 00 cmp dword ptr [ebp-50], 0
00408A8C . 75 1C jnz short 00408AAA
00408A8E . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408A90 . 68 788C4000 push 00408C78 ; |Title = ""D7,"",A2,"",B2,"崽崾?
00408A95 . 68 9C8C4000 push 00408C9C ; |Text = ""D7,"",A2,"",B2,"崧?,B2,"",BB,"能为空请输入?,A1,""
00408A9A . 8B45 08 mov eax, dword ptr [ebp+8] ; |
00408A9D . 50 push eax ; |hOwner
00408A9E . E8 F1BCFFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00408AA3 . 33DB xor ebx, ebx
00408AA5 . E9 56010000 jmp 00408C00
00408AAA > 33C0 xor eax, eax
00408AAC . 55 push ebp
00408AAD . 68 2C8B4000 push 00408B2C
00408AB2 . 64:FF30 push dword ptr fs:[eax]
00408AB5 . 64:8920 mov dword ptr fs:[eax], esp
00408AB8 . 8D45 A8 lea eax, dword ptr [ebp-58]
00408ABB . BA AC934000 mov edx, 004093AC ; ASCII "dttom"
00408AC0 . B9 FF000000 mov ecx, 0FF
00408AC5 . E8 AEADFFFF call 00403878 ;计算用户名长度
00408ACA . 8B45 A8 mov eax, dword ptr [ebp-58]
00408ACD . 8D55 AC lea edx, dword ptr [ebp-54]
00408AD0 . E8 EBFCFFFF call 004087C0 ;关键CALL,注册码的计算子过程
00408AD5 . 8B45 AC mov eax, dword ptr [ebp-54]
00408AD8 . 50 push eax
00408AD9 . 8D45 A4 lea eax, dword ptr [ebp-5C]
00408ADC . BA AC944000 mov edx, 004094AC ; ASCII "55556666"
00408AE1 . B9 FF000000 mov ecx, 0FF
00408AE6 . E8 8DADFFFF call 00403878
00408AEB . 8B55 A4 mov edx, dword ptr [ebp-5C]
00408AEE . 58 pop eax
00408AEF . E8 FCAEFFFF call 004039F0
00408AF4 . 75 17 jnz short 00408B0D
......
00408AD0 处点F7跟进分析,省掉一些字符长度检查,结构化异常安装等代码,找到关键计算408840,F7跟进
0040883E . 8BD3 mov edx, ebx
00408840 . E8 03FBFFFF call 00408348 ; 注册计算函数 F7跟进
00408845 . 8B55 F8 mov edx, dword ptr [ebp-8]
.......
来到下面一段函数
......
00408371 |. 8B55 08 mov edx, dword ptr [ebp+8]
00408374 |. 8D45 F0 lea eax, dword ptr [ebp-10]
00408377 |. E8 50FFFFFF call 004082CC ; call后出现注册码 F7跟进
.........
004082FD |. 8D55 FC lea edx, dword ptr [ebp-4]
00408300 |. 8B03 mov eax, dword ptr [ebx]
00408302 |. E8 6DFEFFFF call 00408174 ; 计算出注册码 F7跟进
来到下面一段函数,这一块函数到了我们的加密函数的核地带
00408174 /$ 55 push ebp
00408175 |. 8BEC mov ebp, esp
00408177 |. 83C4 F8 add esp, -8
0040817A |. 53 push ebx
0040817B |. 56 push esi
0040817C |. 57 push edi
0040817D |. 33C9 xor ecx, ecx
0040817F |. 894D F8 mov dword ptr [ebp-8], ecx
00408182 |. 8BFA mov edi, edx
00408184 |. 8BF0 mov esi, eax
00408186 |. 33C0 xor eax, eax
00408188 |. 55 push ebp
00408189 |. 68 07824000 push 00408207 ; 安装结构化异常处理程序
0040818E |. 64:FF30 push dword ptr fs:[eax]
00408191 |. 64:8920 mov dword ptr fs:[eax], esp
00408194 |. 33C0 xor eax, eax
00408196 |. 8A46 40 mov al, byte ptr [esi+40] ; 将用户名长度传入al
00408199 |. BA 10000000 mov edx, 10
0040819E |. 2BD0 sub edx, eax ; 计算出需要附加字符长度(padLen)
004081A0 |. 8955 FC mov dword ptr [ebp-4], edx
004081A3 |. 8B5D FC mov ebx, dword ptr [ebp-4]
004081A6 |. 4B dec ebx
004081A7 |. 85DB test ebx, ebx
004081A9 |. 72 0E jb short 004081B9
004081AB |. 43 inc ebx
004081AC |> 8A55 FC /mov dl, byte ptr [ebp-4]
004081AF |. 8BC6 |mov eax, esi
004081B1 |. E8 A2FEFFFF |call 00408058 ; 输入数据内存copy及附加字符串,保证字串MOD 16=0
004081B6 |. 4B |dec ebx
004081B7 |.^ 75 F3 \jnz short 004081AC
004081B9 |> 33DB xor ebx, ebx
004081BB |> 8A541E 30 /mov dl, byte ptr [esi+ebx+30]
004081BF |. 8BC6 |mov eax, esi
004081C1 |. E8 92FEFFFF |call 00408058 ; 附加checksum处理
004081C6 |. 43 |inc ebx
004081C7 |. 83FB 10 |cmp ebx, 10
004081CA |.^ 75 EF \jnz short 004081BB
004081CC |. 33DB xor ebx, ebx
004081CE |> 33C0 /xor eax, eax
004081D0 |. 8A041E |mov al, byte ptr [esi+ebx]
004081D3 |. 33D2 |xor edx, edx
004081D5 |. 52 |push edx
004081D6 |. 50 |push eax
004081D7 |. 8D55 F8 |lea edx, dword ptr [ebp-8]
004081DA |. B0 02 |mov al, 2
004081DC |. E8 BFFDFFFF |call 00407FA0 ; 更新checksum
004081E1 |. 8B55 F8 |mov edx, dword ptr [ebp-8]
004081E4 |. 8BC7 |mov eax, edi
......
在4081B1处F7可以来到下面一段加密块计算过程如下,在加密块前有载入静态表的一些准备工作,代码不贴了大家自己跟吧
004080D5 |. 33C0 xor eax, eax
004080D7 |. C64424 04 00 mov byte ptr [esp+4], 0
004080DC |> 8B1424 /mov edx, dword ptr [esp] ; 加密块计算过程
004080DF |. B1 08 |mov cl, 8
004080E1 |> 25 FF000000 |/and eax, 0FF
004080E6 |. 8A0406 ||mov al, byte ptr [esi+eax]
004080E9 |. 3002 ||xor byte ptr [edx], al
004080EB |. 8A02 ||mov al, byte ptr [edx]
004080ED |. 42 ||inc edx
004080EE |. 25 FF000000 ||and eax, 0FF
004080F3 |. 8A0406 ||mov al, byte ptr [esi+eax]
004080F6 |. 3002 ||xor byte ptr [edx], al
004080F8 |. 8A02 ||mov al, byte ptr [edx]
004080FA |. 42 ||inc edx
004080FB |. 25 FF000000 ||and eax, 0FF
00408100 |. 8A0406 ||mov al, byte ptr [esi+eax]
00408103 |. 3002 ||xor byte ptr [edx], al
00408105 |. 8A02 ||mov al, byte ptr [edx]
00408107 |. 42 ||inc edx
00408108 |. 25 FF000000 ||and eax, 0FF
0040810D |. 8A0406 ||mov al, byte ptr [esi+eax]
00408110 |. 3002 ||xor byte ptr [edx], al
00408112 |. 8A02 ||mov al, byte ptr [edx]
00408114 |. 42 ||inc edx
00408115 |. 25 FF000000 ||and eax, 0FF
0040811A |. 8A0406 ||mov al, byte ptr [esi+eax]
0040811D |. 3002 ||xor byte ptr [edx], al
0040811F |. 8A02 ||mov al, byte ptr [edx]
00408121 |. 42 ||inc edx
00408122 |. 25 FF000000 ||and eax, 0FF
00408127 |. 8A0406 ||mov al, byte ptr [esi+eax]
0040812A |. 3002 ||xor byte ptr [edx], al
0040812C |. 8A02 ||mov al, byte ptr [edx]
0040812E |. 42 ||inc edx
0040812F |. FEC9 ||dec cl
00408131 |.^ 75 AE |\jnz short 004080E1
00408133 |. 024424 04 |add al, byte ptr [esp+4]
00408137 |. FE4424 04 |inc byte ptr [esp+4]
0040813B |. 807C24 04 12 |cmp byte ptr [esp+4], 12
00408140 |.^ 75 9A \jnz short 004080DC
对应c语言如下:
t = 0;
for (i = 0; i < 18; i++) {
for (j = 0; j < 48; j++)
t = x[j] ^= PI_SUBST[t];
t = (t + i) & 0xff;
}
其它则是一些收尾工作,具体代码就不贴出来了。
下面就是写汇编注册机,最近工作比较忙,这个等我有时间学会了再写,现在256个数的数组在汇编里怎么设置还不会,等学会了再写,先把算法
分析发上。
--------------------------------------------------------------------------------
【经验总结】
汇编带码里函数的嵌套比较多,但是对着C语言代码来看相对要容易多了。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年02月20日 上午 09:35:00
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!