系统 : Windows xp
程序 : Bxm_CrackMe1
程序下载地址 :http://pan.baidu.com/s/1pK0a0xt
要求 : 分析算法
使用工具 :OD
可在看雪论坛中查找关于此程序的讨论:传送门
OD载入程序,利用插件查看字串表,双击“破解成功”的字串进入关键算法:
00402406 |. 50 push eax ; /src
00402407 |. 8D45 D0 lea eax, dword ptr [ebp-30] ; |
0040240A |. 50 push eax ; |dest
0040240B |. E8 24EDFFFF call <jmp.&MSVCRTD.strcpy> ; strcpy
00402410 |. 83C4 08 add esp, 8
00402413 |. 8D4D D0 lea ecx, dword ptr [ebp-30] ; 取出字串地址
00402416 |. 51 push ecx ; /s
00402417 |. E8 1EEDFFFF call <jmp.&MSVCRTD.strlen> ; strlen
0040241C |. 83C4 04 add esp, 4
0040241F |. 8945 E8 mov dword ptr [ebp-18], eax ; 保存长度
00402422 |. C745 EC 00000>mov dword ptr [ebp-14], 0 ; 取出一段内存置零
00402429 |. EB 09 jmp short 00402434
0040242B |> 8B55 EC /mov edx, dword ptr [ebp-14]
0040242E |. 83C2 01 |add edx, 1
00402431 |. 8955 EC |mov dword ptr [ebp-14], edx ; 循环变量自增
00402434 |> 8B45 EC mov eax, dword ptr [ebp-14]
00402437 |. 3B45 E8 |cmp eax, dword ptr [ebp-18] ; 迭代字串完毕则跳转
0040243A |. 7D 12 |jge short 0040244E
0040243C |. 8B4D EC |mov ecx, dword ptr [ebp-14]
0040243F |. 0FBE540D D0 |movsx edx, byte ptr [ebp+ecx-30] ; 取出字符
00402444 |. 8B45 F8 |mov eax, dword ptr [ebp-8]
00402447 |. 03C2 |add eax, edx ; 累加
00402449 |. 8945 F8 |mov dword ptr [ebp-8], eax ; 保存结果
0040244C |.^ EB DD jmp short 0040242B
0040244E |> 8B4D F8 mov ecx, dword ptr [ebp-8]
00402451 |. F7D9 neg ecx ; 对结果进行求补运算
00402453 |. 8B55 F8 mov edx, dword ptr [ebp-8]
00402456 |. 0355 E8 add edx, dword ptr [ebp-18] ; 结果加上用户名字串的长度
00402459 |. 0FAFCA imul ecx, edx ; 相乘
0040245C |. 894D F4 mov dword ptr [ebp-C], ecx ; 保存结果
0040245F |. 8B4D FC mov ecx, dword ptr [ebp-4]
00402462 |. 83C1 64 add ecx, 64
00402465 |. E8 2AFBFFFF call <jmp.&MFC42D.#880>
0040246A |. 50 push eax ; /src
0040246B |. 8D45 B8 lea eax, dword ptr [ebp-48] ; |
0040246E |. 50 push eax ; |dest
0040246F |. E8 C0ECFFFF call <jmp.&MSVCRTD.strcpy> ; strcpy
00402474 |. 83C4 08 add esp, 8
00402477 |. C745 B0 01000>mov dword ptr [ebp-50], 1
0040247E |. 8D4D B8 lea ecx, dword ptr [ebp-48]
00402481 |. 51 push ecx ; /s
00402482 |. E8 B3ECFFFF call <jmp.&MSVCRTD.strlen> ; strlen
00402487 |. 83C4 04 add esp, 4
0040248A |. 83E8 01 sub eax, 1 ; 长度-1
0040248D |. 8945 B4 mov dword ptr [ebp-4C], eax ; 保存
00402490 |. EB 09 jmp short 0040249B
00402492 |> 8B55 B4 /mov edx, dword ptr [ebp-4C]
00402495 |. 83EA 01 |sub edx, 1 ; 循环变量自减
00402498 |. 8955 B4 |mov dword ptr [ebp-4C], edx
0040249B |> 837D B4 00 cmp dword ptr [ebp-4C], 0 ; 迭代完毕则跳转
0040249F |. 7C 22 |jl short 004024C3
004024A1 |. 8B45 B4 |mov eax, dword ptr [ebp-4C]
004024A4 |. 0FBE4C05 B8 |movsx ecx, byte ptr [ebp+eax-48] ; 倒序取字符
004024A9 |. 83E9 30 |sub ecx, 30 ; 转化为十进制
004024AC |. 0FAF4D B0 |imul ecx, dword ptr [ebp-50] ; 相乘
004024B0 |. 8B55 F0 |mov edx, dword ptr [ebp-10]
004024B3 |. 03D1 |add edx, ecx
004024B5 |. 8955 F0 |mov dword ptr [ebp-10], edx ; 保存累加结果
004024B8 |. 8B45 B0 |mov eax, dword ptr [ebp-50]
004024BB |. 6BC0 0A |imul eax, eax, 0A ; eax * 0A
004024BE |. 8945 B0 |mov dword ptr [ebp-50], eax ; 再存回去
004024C1 |.^ EB CF jmp short 00402492
004024C3 |> 8B4D F0 mov ecx, dword ptr [ebp-10] ; 取结果
004024C6 |. 6BC9 FF imul ecx, ecx, -1 ; 取相反数
004024C9 |. 894D F0 mov dword ptr [ebp-10], ecx ; 再存回去
004024CC |. 837D E8 00 cmp dword ptr [ebp-18], 0 ; 用户名长度为0?
004024D0 |. 74 2F je short 00402501 ; 为0则破解失败
004024D2 |. 8B55 F0 mov edx, dword ptr [ebp-10]
004024D5 |. 0FAF55 F0 imul edx, dword ptr [ebp-10] ; 相反数 * 相反数
004024D9 |. 8B45 F0 mov eax, dword ptr [ebp-10] ; 取出结果
004024DC |. 0FAF45 E8 imul eax, dword ptr [ebp-18] ; 结果乘以用户名长度
004024E0 |. 8B4D F4 mov ecx, dword ptr [ebp-C] ; 取F(用户名)
004024E3 |. 03CA add ecx, edx ; 累加之前的结果
004024E5 |. 03C1 add eax, ecx
004024E7 |. 85C0 test eax, eax ; eax为0?
004024E9 |. 75 16 jnz short 00402501 ; 不为0则破解失败
004024EB |. 6A 00 push 0
004024ED |. 68 20514100 push 00415120 ; 恭喜你
004024F2 |. 68 14514100 push 00415114 ; 破解成功!
004024F7 |. 8B4D FC mov ecx, dword ptr [ebp-4]
004024FA |. E8 71ECFFFF call <jmp.&MFC42D.#3517>
004024FF |. EB 14 jmp short 00402515
00402501 |> 6A 00 push 0
00402503 |. 68 08514100 push 00415108 ; 破解失败
00402508 |. 68 58504100 push 00415058 ; 重试?
0040250D |. 8B4D FC mov ecx, dword ptr [ebp-4]
00402510 |. E8 5BECFFFF call <jmp.&MFC42D.#3517>
算法比较简单,就不一一说明了,直接修改4024E9处的跳转指令就可以完成爆破。
有兴趣的朋友可以尝试写出注册机。
-------------------------------------------------------------------------------------------------------------------
既然算法简单,那就尝试着把注册机写出来吧。该cm采用了二元函数加密,检测F(用户名,密钥)==0来判断是否是正确的注册码。
我们直接打开之前搭建的框架,并修改OnBtnDecrypt函数如下:
void CKengen_TemplateDlg::OnBtnDecrypt()
{
// TODO: Add your control notification handler code here
CString str;
GetDlgItemText( IDC_EDIT_NAME,str ); //获取用户名字串基本信息。
int len = str.GetLength();
if ( len != 0 ){ //格式控制。
SetDlgItemText( IDC_EDIT_PASSWORD,str );
unsigned int sum = 0;
int FUserName;
for ( int i = 0 ; i != len ; i++ )
sum += str[i];
FUserName = (~sum + 1) * (sum + 5);
/*
//模拟F(Serial)
CString Serial = "12345";
int product = 1;
int SerialLen = Serial.GetLength() - 1;
sum = 0;
for ( ; SerialLen != -1 ; SerialLen-- ){
sum += (Serial[SerialLen] - 0x30 ) * product; //把字符串转化成对应的数值
product *= 10;
}
//取相反数
sum *= -1;
//X^2+bx+c = 0
if ( sum * sum + sum * len + FUserName == 0 )
MessageBox( "注册成功!" );
*/
int delt = len*len-4*1*FUserName;
if ( delt < 0 ) //方程是否无根?
{
SetDlgItemText( IDC_EDIT_PASSWORD,"方程无解!无法找出注册码!" );
return ;
}
//解方程
int x = ((double)-len-sqrt(delt))/(double)(2*1);
x = -x;
CString PassWord;
PassWord.Format( "%d",x );
SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
}
else
MessageBox( "用户名格式错误!" );
}
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("bxm-firstcm_Keygen"));
运行效果: