【文章标题】: forgot's CRACKME 1994算法分析
【文章作者】: bxm
【作者邮箱】: bxm78@163.com
【软件名称】: forgot's CRACKME 1994
【下载地址】: http://bbs.pediy.com/showthread.php?t=46861
【加壳方式】: 无
【保护方式】: name,code
【编写语言】: E语言
【使用工具】: OD,E-Code Explorer,计算器
【操作平台】: wixp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
感谢forgot给我们提供了这么好CRACKME,更感谢monkeycz,没有他的E-Code Explorer软件,我也写不出这个破文。
用E-Code Explorer软件找到按钮“go”的处理入口,并适当反编译,然后在OD中调试。
输入name:bxm78
code:123-456-789
004096B9 55 push ebp
004096BA 8BEC mov ebp, esp
004096BC 81EC 0C000000 sub esp, 0C
004096C2 6A FF push -1
004096C4 6A 08 push 8
004096C6 68 2B000116 push 1601002B
004096CB 68 01000152 push 52010001
004096D0 E8 410A0000 call 0040A116
004096D5 83C4 10 add esp, 10
004096D8 8945 FC mov dword ptr [ebp-4], eax ; name地址入[ebp-4]
004096DB 6A FF push -1
004096DD 6A 08 push 8
004096DF 68 02000116 push 16010002
004096E4 68 01000152 push 52010001
004096E9 E8 280A0000 call 0040A116
004096EE 83C4 10 add esp, 10
004096F1 8945 F8 mov dword ptr [ebp-8], eax ; code地址入[ebp-8]
004096F4 8D45 F8 lea eax, dword ptr [ebp-8]
004096F7 50 push eax
004096F8 8D45 FC lea eax, dword ptr [ebp-4]
004096FB 50 push eax
004096FC E8 00010000 call 00409801 ; 关键call
00409701 8945 F4 mov dword ptr [ebp-C], eax ; 如验证通过,EAX返回1,否则返回0
00409704 8B5D FC mov ebx, dword ptr [ebp-4]
00409707 85DB test ebx, ebx
00409709 74 09 je short 00409714
0040970B 53 push ebx
0040970C E8 F3090000 call 0040A104
00409711 83C4 04 add esp, 4
00409714 8B5D F8 mov ebx, dword ptr [ebp-8]
00409717 85DB test ebx, ebx
00409719 74 09 je short 00409724
0040971B 53 push ebx
0040971C E8 E3090000 call 0040A104
00409721 83C4 04 add esp, 4
00409724 837D F4 00 cmp dword ptr [ebp-C], 0 ; 验证通过了吗?
00409728 0F84 35000000 je 00409763 ; 通过,显示“good job!”
0040972E 6A 00 push 0
00409730 6A 00 push 0
00409732 6A 00 push 0
00409734 68 01030080 push 80000301
00409739 6A 00 push 0
0040973B 68 00000000 push 0
00409740 68 04000080 push 80000004
00409745 6A 00 push 0
00409747 68 CB904000 push 004090CB ; ASCII "good job!"
0040974C 68 03000000 push 3
00409751 BB 00030000 mov ebx, 300
00409756 E8 AF090000 call 0040A10A
===============================================================
跟入关键Call
00409801 55 push ebp
00409802 8BEC mov ebp, esp
00409804 81EC 50000000 sub esp, 50
0040980A C745 FC 0000000>mov dword ptr [ebp-4], 0
00409811 68 08000000 push 8
00409816 E8 F5080000 call 0040A110 ; 从堆上分配内存空间
0040981B 83C4 04 add esp, 4
0040981E 8945 F8 mov dword ptr [ebp-8], eax
00409821 8BF8 mov edi, eax
00409823 BE F6904000 mov esi, 004090F6
00409828 AD lods dword ptr [esi]
00409829 AB stos dword ptr es:[edi]
0040982A AD lods dword ptr [esi]
0040982B AB stos dword ptr es:[edi]
0040982C C745 F4 0000000>mov dword ptr [ebp-C], 0
00409833 68 08000000 push 8
00409838 E8 D3080000 call 0040A110 ; 从堆上分配内存空间
0040983D 83C4 04 add esp, 4
00409840 8945 F0 mov dword ptr [ebp-10], eax
00409843 8BF8 mov edi, eax
00409845 BE F6904000 mov esi, 004090F6
0040984A AD lods dword ptr [esi]
0040984B AB stos dword ptr es:[edi]
0040984C AD lods dword ptr [esi]
0040984D AB stos dword ptr es:[edi]
0040984E C745 EC 0000000>mov dword ptr [ebp-14], 0
00409855 C745 E8 0000000>mov dword ptr [ebp-18], 0
0040985C FF75 08 push dword ptr [ebp+8] ; name入栈
0040985F E8 B0030000 call 00409C14 ; name的每个字符与0x4B23566异或,但只返回最后一个字符异或的结果
00409864 8945 FC mov dword ptr [ebp-4], eax ; 保存最后一个结果
00409867 6A 00 push 0
00409869 6A 00 push 0
0040986B 6A 00 push 0
0040986D 68 04000080 push 80000004
00409872 6A 00 push 0
00409874 68 DB904000 push 004090DB
00409879 68 04000080 push 80000004
0040987E 6A 00 push 0
00409880 8B5D 0C mov ebx, dword ptr [ebp+C]
00409883 8B03 mov eax, dword ptr [ebx]
00409885 85C0 test eax, eax
00409887 75 05 jnz short 0040988E
00409889 B8 DD904000 mov eax, 004090DD
0040988E 50 push eax
0040988F 68 03000000 push 3
00409894 BB 90010000 mov ebx, 190
00409899 E8 6C080000 call 0040A10A ; 以"-"字符分割文本
0040989E 83C4 28 add esp, 28
004098A1 8945 E4 mov dword ptr [ebp-1C], eax
004098A4 8B45 E4 mov eax, dword ptr [ebp-1C]
004098A7 50 push eax
004098A8 8B5D F8 mov ebx, dword ptr [ebp-8]
004098AB 53 push ebx
004098AC 8B0B mov ecx, dword ptr [ebx]
004098AE 83C3 04 add ebx, 4
004098B1 85C9 test ecx, ecx
004098B3 74 11 je short 004098C6
004098B5 8B03 mov eax, dword ptr [ebx]
004098B7 83C3 04 add ebx, 4
004098BA 49 dec ecx
004098BB 74 05 je short 004098C2
004098BD 0FAF03 imul eax, dword ptr [ebx]
004098C0 ^ EB F5 jmp short 004098B7
004098C2 8BC8 mov ecx, eax
004098C4 85C9 test ecx, ecx
004098C6 0F84 19000000 je 004098E5
004098CC 51 push ecx
004098CD 8B03 mov eax, dword ptr [ebx]
004098CF 85C0 test eax, eax
004098D1 74 0B je short 004098DE
004098D3 53 push ebx
004098D4 50 push eax
004098D5 E8 2A080000 call 0040A104 ; 销毁从堆上分配到的内存
004098DA 83C4 04 add esp, 4
004098DD 5B pop ebx
004098DE 83C3 04 add ebx, 4
004098E1 59 pop ecx
004098E2 49 dec ecx
004098E3 ^ 75 E7 jnz short 004098CC
004098E5 E8 1A080000 call 0040A104 ; 销毁从堆上分配到的内存
004098EA 83C4 04 add esp, 4
004098ED 58 pop eax
004098EE 8945 F8 mov dword ptr [ebp-8], eax
004098F1 8B5D F8 mov ebx, dword ptr [ebp-8]
004098F4 E8 A8FEFFFF call 004097A1 ; EAX返回code分割后的个数
004098F9 8945 F4 mov dword ptr [ebp-C], eax ; 保存
省略一些代码……
0040997A 52 push edx
0040997B 51 push ecx
0040997C 53 push ebx
0040997D 890B mov dword ptr [ebx], ecx
0040997F 3BCA cmp ecx, edx
00409981 0F8F D8000000 jg 00409A5F
00409987 8B5D F0 mov ebx, dword ptr [ebp-10]
0040998A E8 2BFEFFFF call 004097BA
0040998F 53 push ebx
00409990 51 push ecx
00409991 8B45 EC mov eax, dword ptr [ebp-14]
00409994 48 dec eax
00409995 79 0D jns short 004099A4
00409997 68 04000000 push 4
0040999C E8 7B070000 call 0040A11C ; 调用Runtime内部异常处理
004099A1 83C4 04 add esp, 4
004099A4 59 pop ecx
004099A5 5B pop ebx
004099A6 3BC1 cmp eax, ecx
004099A8 7C 0D jl short 004099B7
004099AA 68 01000000 push 1
004099AF E8 68070000 call 0040A11C ; 调用Runtime内部异常处理
004099B4 83C4 04 add esp, 4
004099B7 C1E0 02 shl eax, 2
004099BA 03D8 add ebx, eax
004099BC 895D E4 mov dword ptr [ebp-1C], ebx
004099BF 8B5D F8 mov ebx, dword ptr [ebp-8]
004099C2 E8 F3FDFFFF call 004097BA
004099C7 53 push ebx
004099C8 51 push ecx
004099C9 8B45 EC mov eax, dword ptr [ebp-14]
004099CC 48 dec eax
004099CD 79 0D jns short 004099DC
004099CF 68 04000000 push 4
004099D4 E8 43070000 call 0040A11C
004099D9 83C4 04 add esp, 4
004099DC 59 pop ecx
004099DD 5B pop ebx
004099DE 3BC1 cmp eax, ecx
004099E0 7C 0D jl short 004099EF
004099E2 68 01000000 push 1
004099E7 E8 30070000 call 0040A11C
004099EC 83C4 04 add esp, 4
004099EF C1E0 02 shl eax, 2
004099F2 03D8 add ebx, eax
004099F4 895D E0 mov dword ptr [ebp-20], ebx
004099F7 68 04000080 push 80000004
004099FC 6A 00 push 0
004099FE 8B5D E0 mov ebx, dword ptr [ebp-20]
00409A01 8B03 mov eax, dword ptr [ebx]
00409A03 85C0 test eax, eax
00409A05 75 05 jnz short 00409A0C
00409A07 B8 DD904000 mov eax, 004090DD
00409A0C 50 push eax
00409A0D 68 01000000 push 1
00409A12 BB 64010000 mov ebx, 164
00409A17 E8 EE060000 call 0040A10A ; 把code分割后的每一段文本转成相应的十进制数
00409A1C 83C4 10 add esp, 10
00409A1F 8945 D8 mov dword ptr [ebp-28], eax
00409A22 8955 DC mov dword ptr [ebp-24], edx
00409A25 68 01030080 push 80000301
00409A2A 6A 00 push 0
00409A2C FF75 FC push dword ptr [ebp-4]
00409A2F DD45 D8 fld qword ptr [ebp-28]
00409A32 E8 A3FDFFFF call 004097DA ; 把浮点数转成十六进制数
00409A37 68 01030080 push 80000301
00409A3C 6A 00 push 0
00409A3E 50 push eax
00409A3F 68 02000000 push 2
00409A44 BB CC000000 mov ebx, 0CC
00409A49 E8 BC060000 call 0040A10A ; code的每一段与name运算后的返回值(我的为0x4B2355E)进行位异或,结果设为A
00409A4E 83C4 1C add esp, 1C
00409A51 8B5D E4 mov ebx, dword ptr [ebp-1C]
00409A54 8903 mov dword ptr [ebx], eax
00409A56 5B pop ebx
00409A57 59 pop ecx
00409A58 5A pop edx
00409A59 41 inc ecx
00409A5A ^ E9 1BFFFFFF jmp 0040997A
此段代码功能:把code分割后的文本转成相应的十进制数,然后分别与name运算后的返回值异或
=======================================================================
00409A5F 83C4 0C add esp, 0C
00409A62 817D F4 0004000>cmp dword ptr [ebp-C], 400 ; code分割后的个数与0x400比较
00409A69 0F8D 0A000000 jge 00409A79 ; 大于等于跳,否则完蛋,我这只好强行跳了
00409A6F B8 00000000 mov eax, 0
00409A74 E9 42010000 jmp 00409BBB
00409A79 8D45 EC lea eax, dword ptr [ebp-14]
00409A7C 8BD8 mov ebx, eax
00409A7E B9 01000000 mov ecx, 1
00409A83 51 push ecx ; ECX为循环计数器
00409A84 53 push ebx
00409A85 890B mov dword ptr [ebx], ecx
00409A87 81F9 00040000 cmp ecx, 400 ; ECX大于0x400?
00409A8D 0F8F 1B010000 jg 00409BAE ; 大于,跳
00409A93 8B5D F0 mov ebx, dword ptr [ebp-10]
00409A96 E8 1FFDFFFF call 004097BA ; 返回code分割后的长度
00409A9B 53 push ebx
00409A9C 51 push ecx
00409A9D 8B45 EC mov eax, dword ptr [ebp-14]
00409AA0 48 dec eax
00409AA1 79 0D jns short 00409AB0
00409AA3 68 04000000 push 4
00409AA8 E8 6F060000 call 0040A11C
00409AAD 83C4 04 add esp, 4
00409AB0 59 pop ecx
00409AB1 5B pop ebx
00409AB2 3BC1 cmp eax, ecx
00409AB4 7C 0D jl short 00409AC3
00409AB6 68 01000000 push 1
00409ABB E8 5C060000 call 0040A11C
00409AC0 83C4 04 add esp, 4
00409AC3 C1E0 02 shl eax, 2
00409AC6 03D8 add ebx, eax
00409AC8 895D E4 mov dword ptr [ebp-1C], ebx
00409ACB DB45 E8 fild dword ptr [ebp-18]
00409ACE DD5D DC fstp qword ptr [ebp-24]
00409AD1 DD45 DC fld qword ptr [ebp-24] ; A的分步累加结果入st0,初始值为0
00409AD4 8B5D E4 mov ebx, dword ptr [ebp-1C]
00409AD7 DB03 fild dword ptr [ebx] ; 异或后的结果装入st0
00409AD9 DD5D D4 fstp qword ptr [ebp-2C]
00409ADC DC45 D4 fadd qword ptr [ebp-2C] ; 相加
00409ADF DD5D CC fstp qword ptr [ebp-34]
00409AE2 DD45 CC fld qword ptr [ebp-34]
00409AE5 E8 F0FCFFFF call 004097DA ; 结果转换成十六制数
00409AEA 8945 E8 mov dword ptr [ebp-18], eax ; 保存
00409AED DB45 E8 fild dword ptr [ebp-18]
00409AF0 DD5D E0 fstp qword ptr [ebp-20]
00409AF3 DD45 E0 fld qword ptr [ebp-20]
00409AF6 DC0D DE904000 fmul qword ptr [4090DE] ; *2(固定数)
00409AFC DD5D D8 fstp qword ptr [ebp-28]
00409AFF 68 01060080 push 80000601
00409B04 FF75 DC push dword ptr [ebp-24]
00409B07 FF75 D8 push dword ptr [ebp-28]
00409B0A 68 01000000 push 1
00409B0F BB 70000000 mov ebx, 70
00409B14 E8 F1050000 call 0040A10A ; 求平方根
00409B19 83C4 10 add esp, 10
00409B1C 8945 D0 mov dword ptr [ebp-30], eax
00409B1F 8955 D4 mov dword ptr [ebp-2C], edx
00409B22 8B5D F0 mov ebx, dword ptr [ebp-10]
00409B25 E8 90FCFFFF call 004097BA
00409B2A 53 push ebx
00409B2B 51 push ecx
00409B2C 8B45 EC mov eax, dword ptr [ebp-14]
00409B2F 48 dec eax
00409B30 79 0D jns short 00409B3F
00409B32 68 04000000 push 4
00409B37 E8 E0050000 call 0040A11C
00409B3C 83C4 04 add esp, 4
00409B3F 59 pop ecx
00409B40 5B pop ebx
00409B41 3BC1 cmp eax, ecx
00409B43 7C 0D jl short 00409B52
00409B45 68 01000000 push 1
00409B4A E8 CD050000 call 0040A11C
00409B4F 83C4 04 add esp, 4
00409B52 C1E0 02 shl eax, 2
00409B55 03D8 add ebx, eax
00409B57 895D CC mov dword ptr [ebp-34], ebx
00409B5A 8B5D CC mov ebx, dword ptr [ebp-34]
00409B5D DB03 fild dword ptr [ebx]
00409B5F DD5D C4 fstp qword ptr [ebp-3C]
00409B62 DD45 C4 fld qword ptr [ebp-3C]
00409B65 DC05 DE904000 fadd qword ptr [4090DE] ; A+2
00409B6B DD5D BC fstp qword ptr [ebp-44]
00409B6E DD45 BC fld qword ptr [ebp-44]
00409B71 DC0D E6904000 fmul qword ptr [4090E6] ; *0.5=B
00409B77 DD5D B4 fstp qword ptr [ebp-4C]
00409B7A DD45 D0 fld qword ptr [ebp-30] ; 装入实数为上面开方后的结果
00409B7D DC65 B4 fsub qword ptr [ebp-4C] ; st0-B
00409B80 D9E4 ftst ; 0检测
00409B82 DFE0 fstsw ax ; 保存状态字
00409B84 F6C4 01 test ah, 1
00409B87 74 02 je short 00409B8B
00409B89 D9E0 fchs ; 改变符号位
00409B8B DC1D EE904000 fcomp qword ptr [4090EE] ; 与1.0E-7比较
00409B91 DFE0 fstsw ax
00409B93 F6C4 41 test ah, 41
00409B96 0F85 0A000000 jnz 00409BA6 ; 关键比较,不等完蛋,否则循环进行
00409B9C B8 00000000 mov eax, 0
00409BA1 E9 15000000 jmp 00409BBB
00409BA6 5B pop ebx
00409BA7 59 pop ecx
00409BA8 41 inc ecx
00409BA9 ^ E9 D5FEFFFF jmp 00409A83
00409BAE 83C4 08 add esp, 8
00409BB1 B8 01000000 mov eax, 1 ; 成功
00409BB6 E9 00000000 jmp 00409BBB ; 准备返回
此段代码功能分析:
设A为code的每一段与name运算后的返回值(我的为0x4B2355E)进行位异或后数组,temp3为A分步累加的结果(初始值为0),则
sqrt((temp3+A2)*2)-(A2+2)*0.5=0
解之得A=(4+sqrt(16.0-4.0*(4.0-8.0*temp3)))/2.0
然后A再与name运算后的返回值(我的为0x4B2355E)进行位异或,即得到code的每一段
循环此过程即得到注册码的每一段,然后用'-'进行连接即得完整的code.
具体的看上面的分析.
附:注册机源代码
#include "iostream.h"
#include "string.h"
#include "math.h"
void main()
{
unsigned long A;
double A2;
unsigned long temp1; //存放name与0x4B23566异或的结果
double temp3=0; //初始值为0
int i;
char name[30];
cout<<"Please input your name:"<<endl;
cin>>name;
cout<<endl;
temp1=0x4B23566^name[strlen(name)-1];
cout<<temp1<<endl;
temp3=0;
for(i=0;i<0x400;i++)
{
A2=(4+sqrt(16.0-4.0*(4.0-8.0*temp3)))/2.0;
A=temp1^ long(A2);
temp3=temp3+long(A2);
cout<<A<<"-";
}
A2=(4+sqrt(16.0-4.0*(4.0-8.0*temp3)))/2.0;
A=temp1^ long(A2);
cout<<A<<"-";
}
至于彩蛋部分我就不分析了,留给别人吧。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年06月26日 13:18:29
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课