―――――――――――――――――――――――――――――――――――――
【文章标题】: E KEYGEN ME NO.1—BY Z 的简单分析
【文章作者】: SZJOHN
【下载地址】: http://bbs.pediy.com/showthread.php?t=80122
【编写语言】: 易语言
【使用工具】: OD
【操作平台】: Windows XP 32 SP3
【作者声明】: 抛砖引玉,希望能得到大家赐教,谢谢
―――――――――――――――――――――――――――――――――――――
输入USER = pediy
废话少说,直接进入正题来到入口点00409953:
++++++++++++++++++++++++++++++++++
00409953 55 push ebp
00409954 8BEC mov ebp, esp //栈帧保护
00409956 81EC 14000000 sub esp, 14 //分配函数局部变量空间
0040995C C745 FC 0000000> mov dword ptr [ebp-4], 0 //第一个局部变量清0
00409963 C745 F8 0000000> mov dword ptr [ebp-8], 0 //第二个局部变量清0
0040996A C745 F4 0000000> mov dword ptr [ebp-C], 0//第三个局部变量清0
00409971 6A FF push -1 //为00409C77函数压入参数4
00409973 6A 08 push 8 //为00409C77函数压入参数3
00409975 68 04000116 push 16010004 //为00409C77函数压入参数3
0040997A 68 01000152 push 52010001//为00409C77函数压入参数2
0040997F E8 F3020000 call 00409C77 //CALL 函数00409C77
虽然我们现在还不指导函数00409C77的作用,没关系,再往下走一步发现:
寄存器VIEW里面显示了如下信息:
EAX 001541B8 ASCII “PEDIY”
很明显 00409C77函数是取到了USER 文本框中的用户名,接着往下看
00409984 83C4 10 add esp, 10 //恢复栈平衡
00409987 8945 F0 mov dword ptr [ebp-10], eax //user串首地址存储到函数局部空间【ebp-10】
0040998A 8B45 F0 mov eax, dword ptr [ebp-10]
0040998D 50 push eax //将USER串首地址压栈
0040998E 8B5D FC mov ebx, dword ptr [ebp-4]
00409991 85DB test ebx, ebx //判断是否
00409993 74 09 je short 0040999E
00409995 53 push ebx
00409996 E8 CA020000 call 00409C65
0040999B 83C4 04 add esp, 4
下面和上面取USER文本框代码类似:
0040999E 58 pop eax
0040999F 8945 FC mov dword ptr [ebp-4], eax //USER串首地址给局部变量1
004099A2 6A FF push -1
004099A4 6A 08 push 8
004099A6 68 05000116 push 16010005
004099AB 68 01000152 push 52010001
004099B0 E8 C2020000 call 00409C77
继续….
004099B5 83C4 10 add esp, 10 //恢复栈平衡
004099B8 8945 F0 mov dword ptr [ebp-10], eax //user串首地址存储到函数局部空间【ebp-10】
004099BB 8B45 F0 mov eax, dword ptr [ebp-10]
004099BE 50 push eax //将USER串首地址压栈
004099BF 8B5D F8 mov ebx, dword ptr [ebp-8]
004099C2 85DB test ebx, ebx
004099C4 74 09 je short 004099CF
004099C6 53 push ebx
004099C7 E8 99020000 call 00409C65
004099CC 83C4 04 add esp, 4
004099CF 58 pop eax
004099D0 8945 F8 mov dword ptr [ebp-8], eax//USER串首地址给局部变量2
004099D3 68 04000080 push 80000004
004099D8 6A 00 push 0
004099DA 8B45 FC mov eax, dword ptr [ebp-4] //取出USER串首地址给EAX
004099DD 85C0 test eax, eax //判断是否是空
004099DF 75 05 jnz short 004099E6 //不空跳入004099E6
004099E1 B8 02914000 mov eax, 00409102 //
004099E6 50 push eax //参数2USER入栈
004099E7 68 01000000 push 1 //参数1 1入栈
004099EC BB 00000000 mov ebx, 0 //EBX清0
004099F1 B8 01000000 mov eax, 1 //EAX 赋值1
004099F6 E8 76020000 call 00409C71 //如果要分析MD5,这里是关键
004099FB 83C4 10 add esp, 10 //恢复栈平衡
这里我们发现调用函数00409C71后 EAX返回 ASCII "4dd466d0e1e0cc123afbe504da2462ca"
EBX Md5.00C441E4 说明是用MD5对USER字符串进行了加密。
004099FE 8945 F0 mov dword ptr [ebp-10], eax //加密后USER串首地址EAX
00409A01 8B45 F0 mov eax, dword ptr [ebp-10]
00409A04 50 push eax //加密后USER串指针入栈
00409A05 8B5D FC mov ebx, dword ptr [ebp-4]//用户输入USER串首地址给BEX
00409A08 85DB test ebx, ebx //判断指针是否是空
00409A0A 74 09 je short 00409A15
00409A0C 53 push ebx//用户输入USER串首地址压栈
00409A0D E8 53020000 call 00409C65 //调用00409C65
00409A12 83C4 04 add esp, 4 //恢复栈平衡
00409A15 58 pop eax //将加密后的USER串首地址给EAX
00409A16 8945 FC mov dword ptr [ebp-4], eax //存入局部变量1
下面几个PUSH 给调用00409C6B函数准备参数
00409A19 68 01030080 push 80000301
00409A1E 6A 00 push 0
00409A20 68 08000000 push 8
00409A25 68 04000080 push 80000004
00409A2A 6A 00 push 0
00409A2C 8B45 F8 mov eax, dword ptr [ebp-8]//PASSWORD串首地址给EAX
00409A2F 85C0 test eax, eax //判断是否空
00409A31 75 05 jnz short 00409A38
00409A33 B8 02914000 mov eax, 00409102 //
00409A38 50 push eax //EAX入栈
00409A39 68 02000000 push 2
00409A3E BB 34010000 mov ebx, 134
00409A43 E8 23020000 call 00409C6B//函数取了MD5加密串前8个字符
00409A48 83C4 1C add esp, 1C //恢复栈平衡
00409A4B 8945 F0 mov dword ptr [ebp-10], eax//这时EAX返回的还是用户输入的PASSWORD
00409A4E 8B45 F0 mov eax, dword ptr [ebp-10]
00409A51 50 push eax //EA压栈
00409A52 8B5D F4 mov ebx, dword ptr [ebp-C]
00409A55 85DB test ebx, ebx //这个时候判断局部变量3是否为0
00409A57 74 09 je short 00409A62 //跳转到00409A62
00409A59 53 push ebx
00409A5A E8 06020000 call 00409C65
00409A5F 83C4 04 add esp, 4
00409A62 58 pop eax //用户输入的PASSWORD串首地址压栈
00409A63 8945 F4 mov dword ptr [ebp-C], eax//将其赋值给局部变量3
00409A66 68 01030080 push 80000301 //下面连续PUSH为00409C6B准备参数
00409A6B 6A 00 push 0
00409A6D 68 10000000 push 10
00409A72 68 01030080 push 80000301
00409A77 6A 00 push 0
00409A79 68 0A000000 push 0A
00409A7E 68 04000080 push 80000004
00409A83 6A 00 push 0
00409A85 8B45 F8 mov eax, dword ptr [ebp-8] //PASSWORD串首地址EAX
00409A88 85C0 test eax, eax//判断是否为空
00409A8A 75 05 jnz short 00409A91
00409A8C B8 02914000 mov eax, 00409102
00409A91 50 push eax //PASSWORD串首地址压栈
00409A92 68 03000000 push 3
00409A97 BB 3C010000 mov ebx, 13C
00409A9C E8 CA010000 call 00409C6B //取了MD5加密串第10位开始16个字符
00409AA1 83C4 28 add esp, 28 //恢复栈平衡
00409AA4 8945 F0 mov dword ptr [ebp-10], eax //这个时候EAX为0
00409AA7 FF75 F0 push dword ptr [ebp-10]
00409AAA FF75 F4 push dword ptr [ebp-C]
00409AAD B9 02000000 mov ecx, 2
00409AB2 E8 A3FDFFFF call 0040985A //直接CALL
00409AB7 83C4 08 add esp, 8//恢复栈平衡
00409ABA 8945 EC mov dword ptr [ebp-14], eax //EAX是用户输入的密码
00409ABD 8B5D F0 mov ebx, dword ptr [ebp-10]//EBX=0
00409AC0 85DB test ebx, ebx //跳转
00409AC2 74 09 je short 00409ACD
00409AC4 53 push ebx
00409AC5 E8 9B010000 call 00409C65
00409ACA 83C4 04 add esp, 4
00409ACD 8B45 EC mov eax, dword ptr [ebp-14] //AX是用户输入的密码
00409AD0 50 push eax //再压栈
00409AD1 8B5D F4 mov ebx, dword ptr [ebp-C] //EBX也似用户输入的密码
00409AD4 85DB test ebx, ebx //判断EBX是否为空
00409AD6 74 09 je short 00409AE1
00409AD8 53 push ebx //接着EBX入栈
00409AD9 E8 87010000 call 00409C65
00409ADE 83C4 04 add esp, 4 //恢复栈平衡
00409AE1 58 pop eax//EAX仍然为用户输入的密码
00409AE2 8945 F4 mov dword ptr [ebp-C], eax 保存到内部变量3
00409AE5 68 01030080 push 80000301 //压栈参数
00409AEA 6A 00 push 0
00409AEC 68 08000000 push 8
00409AF1 68 01030080 push 80000301
00409AF6 6A 00 push 0
00409AF8 68 1E000000 push 1E
00409AFD 68 04000080 push 80000004
00409B02 6A 00 push 0
00409B04 8B45 F8 mov eax, dword ptr [ebp-8] //仍然为用户输入的密码
00409B07 85C0 test eax, eax//判断是否空
00409B09 75 05 jnz short 00409B10
00409B0B B8 02914000 mov eax, 00409102
00409B10 50 push eax
00409B11 68 03000000 push 3
00409B16 BB 3C010000 mov ebx, 13C
00409B1B E8 4B010000 call 00409C6B//取30位开始MD5加密串最后8个字符
00409B20 83C4 28 add esp, 28
这里和00409AA4上面一样
00409B23 8945 F0 mov dword ptr [ebp-10], eax
00409B26 FF75 F0 push dword ptr [ebp-10]
00409B29 FF75 F4 push dword ptr [ebp-C]
00409B2C B9 02000000 mov ecx, 2
00409B31 E8 24FDFFFF call 0040985A
00409B36 83C4 08 add esp, 8
00409B39 8945 EC mov dword ptr [ebp-14], eax //仍然为用户输入的密码
00409B3C 8B5D F0 mov ebx, dword ptr [ebp-10]// 用户输入的密码
00409B3F 85DB test ebx, ebx
00409B41 74 09 je short 00409B4C
00409B43 53 push ebx
00409B44 E8 1C010000 call 00409C65
00409B49 83C4 04 add esp, 4
00409B4C 8B45 EC mov eax, dword ptr [ebp-14]// 用户输入的密码
00409B4F 50 push eax
00409B50 8B5D F4 mov ebx, dword ptr [ebp-C]//EBX也是用户输入的密码
00409B53 85DB test ebx, ebx
00409B55 74 09 je short 00409B60
00409B57 53 push ebx //入栈
00409B58 E8 08010000 call 00409C65
00409B5D 83C4 04 add esp, 4 //恢复栈平衡
00409B60 58 pop eax //没有POP前EAX=1,后为输入密码
00409B61 8945 F4 mov dword ptr [ebp-C], eax//存入局部变量3
00409B64 8B45 F4 mov eax, dword ptr [ebp-C]
00409B67 50 push eax//入栈
00409B68 FF75 FC push dword ptr [ebp-4]
//这里[ebp-4]是“4dd466d0e1e0cc123afbe504da2462ca”
//这里CALL 004098B6比较重要
00409B6B E8 46FDFFFF call 004098B6
00409B70 83C4 08 add esp, 8
00409B73 83F8 00 cmp eax, 0
00409B76 0F85 35000000 jnz 00409BB1//这里是爆破的关键
总结:该算法采用MD5对USER文本框的内容进行加密,最后将用户输入密码的前8位,第10位到26为,30到38拼起来与 MD5加密串进行对比判断用户输入密码合法性。
MD5算法由于不再分析。
抛砖引玉,希望能得到大牛赐教,谢谢
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!