系统 : Windows xp
程序 : RegKiller-crackme
程序下载地址 :http://pan.baidu.com/s/1cC1CeU
要求 : 编写注册机
使用工具 :OD
可在看雪论坛中查找关于此程序的破文,标题为“CrackMe 6 算法分析+注册机”。
OD载入程序,找出关键子串“right code”,向上翻找出关键算法:
004417B8 /. 55 push ebp
004417B9 |. 8BEC mov ebp, esp
004417BB |. 6A 00 push 0
004417BD |. 6A 00 push 0
004417BF |. 6A 00 push 0
004417C1 |. 53 push ebx
004417C2 |. 8BD8 mov ebx, eax
004417C4 |. 33C0 xor eax, eax
004417C6 |. 55 push ebp
004417C7 |. 68 60184400 push 00441860
004417CC |. 64:FF30 push dword ptr fs:[eax]
004417CF |. 64:8920 mov dword ptr fs:[eax], esp
004417D2 |. 8D55 FC lea edx, dword ptr [ebp-4]
004417D5 |. 8B83 C8020000 mov eax, dword ptr [ebx+2C8]
004417DB |. E8 C419FEFF call 004231A4
004417E0 |. 8B45 FC mov eax, dword ptr [ebp-4] ; 取出密钥
004417E3 |. 50 push eax ; 密钥入栈
004417E4 |. 8D55 F4 lea edx, dword ptr [ebp-C]
004417E7 |. 8B83 C4020000 mov eax, dword ptr [ebx+2C4]
004417ED |. E8 B219FEFF call 004231A4
004417F2 |. 8B45 F4 mov eax, dword ptr [ebp-C] ; 取出用户名
004417F5 |. 8D55 F8 lea edx, dword ptr [ebp-8]
004417F8 |. E8 FBFEFFFF call 004416F8 ; 算出序列号
004417FD |. 8B55 F8 mov edx, dword ptr [ebp-8]
00441800 |. 58 pop eax ; 密钥弹栈
00441801 |. E8 3E23FCFF call 00403B44 ; 是否相同?
00441806 |. 75 1A jnz short 00441822
00441808 |. 6A 40 push 40
0044180A |. B9 6C184400 mov ecx, 0044186C ; u made it
0044180F |. BA 78184400 mov edx, 00441878 ; right code
00441814 |. A1 302C4400 mov eax, dword ptr [442C30]
00441819 |. 8B00 mov eax, dword ptr [eax]
0044181B |. E8 D4D6FFFF call 0043EEF4
00441820 |. EB 18 jmp short 0044183A
00441822 |> 6A 10 push 10
00441824 |. B9 84184400 mov ecx, 00441884 ; error
00441829 |. BA 8C184400 mov edx, 0044188C ; wrong code
0044182E |. A1 302C4400 mov eax, dword ptr [442C30]
00441833 |. 8B00 mov eax, dword ptr [eax]
00441835 |. E8 BAD6FFFF call 0043EEF4
跟入4416F8算法CALL:
004416F8 /$ 53 push ebx
004416F9 |. 56 push esi
004416FA |. 57 push edi
004416FB |. 83C4 DC add esp, -24
004416FE |. 891424 mov dword ptr [esp], edx
00441701 |. 8BF8 mov edi, eax
00441703 |. BB 05033949 mov ebx, 49390305 ; 赋值给寄存器两个常量
00441708 |. BE 20126348 mov esi, 48631220
0044170D |. 8BC7 mov eax, edi
0044170F |. E8 2023FCFF call 00403A34 ; 计算用户名长度
00441714 |. 85C0 test eax, eax ; 长度是否为0?
00441716 |. 7E 2E jle short 00441746
00441718 |. BA 01000000 mov edx, 1
0044171D |> 33C9 /xor ecx, ecx
0044171F |. 8A4C17 FF |mov cl, byte ptr [edi+edx-1] ; 循环迭代用户名子串
00441723 |. 33D9 |xor ebx, ecx ; 和两个常量进行异或
00441725 |. 33F3 |xor esi, ebx
00441727 |. F6C3 01 |test bl, 1 ; 异或操作结果等于1?
0044172A |. 74 0F |je short 0044173B
0044172C |. D1FB |sar ebx, 1 ; 算数右移一位
0044172E |. 79 03 |jns short 00441733 ; 符号为正?
00441730 |. 83D3 00 |adc ebx, 0 ; 不为正则ebx += ebx+0+1
00441733 |> 81F3 11032001 |xor ebx, 1200311 ; 与一个固定值异或
00441739 |. EB 07 |jmp short 00441742
0044173B |> D1FB |sar ebx, 1 ; 算数右移一位
0044173D |. 79 03 |jns short 00441742 ; 符号为正?
0044173F |. 83D3 00 |adc ebx, 0 ; 不为正则ebx += ebx+0+1
00441742 |> 42 |inc edx ; 循环变量自增
00441743 |. 48 |dec eax ; 长度-1
00441744 |.^ 75 D7 jnz short 0044171D
00441746 |> 8B0424 mov eax, dword ptr [esp]
00441749 |. 50 push eax
0044174A |. 8BC3 mov eax, ebx ; 循环得出的结果给eax
0044174C |. 25 FFFF0000 and eax, 0FFFF ; 按位与
00441751 |. 894424 08 mov dword ptr [esp+8], eax
00441755 |. C64424 0C 00 mov byte ptr [esp+C], 0
0044175A |. C1EB 10 shr ebx, 10 ; 逻辑右移
0044175D |. 895C24 10 mov dword ptr [esp+10], ebx ; 保存结果
00441761 |. C64424 14 00 mov byte ptr [esp+14], 0
00441766 |. 8BC6 mov eax, esi ; 之前循环异或的值
00441768 |. 25 FFFF0000 and eax, 0FFFF ; 按位与
0044176D |. 894424 18 mov dword ptr [esp+18], eax ; 保存
00441771 |. C64424 1C 00 mov byte ptr [esp+1C], 0
00441776 |. C1EE 10 shr esi, 10 ; 逻辑右移
00441779 |. 897424 20 mov dword ptr [esp+20], esi ; 保存
0044177D |. C64424 24 00 mov byte ptr [esp+24], 0
00441782 |. 8D5424 08 lea edx, dword ptr [esp+8]
00441786 |. B9 03000000 mov ecx, 3
0044178B |. B8 A4174400 mov eax, 004417A4 ; %.4x-%.4x-%.4x-%.4x
00441790 |. E8 6F68FCFF call 00408004
00441795 |. 83C4 24 add esp, 24
00441798 |. 5F pop edi
00441799 |. 5E pop esi
0044179A |. 5B pop ebx
0044179B . C3 retn
这个cm采用了F(用户名)=密钥的形式。很简单的一个cm,小心将算法部分转化成高级语言即可破解。
我们直接打开之前搭建的框架,并修改OnBtnDecrypt函数如下:
void CKengen_TemplateDlg::OnBtnDecrypt()
{
// TODO: Add your control notification handler code here
CString str;
GetDlgItemText( IDC_EDIT_NAME,str ); //获取用户名字串基本信息。
int len = str.GetLength();
unsigned int XorRes1 = 0x49390305,XorRes2 = 0x48631220;
unsigned int AndRes1,AndRes2,ShrRes1,ShrRes2;
if ( len != 0 ){ //格式控制。
for ( int i = 0 ; i != len ; i++ ){
XorRes1 ^= str[i];
XorRes2 ^= XorRes1;
if ( XRLowIsOne( XorRes1 ) )
XorRes1 = CallAsm( XorRes1 );
else{
XorRes1 = CallAsm( XorRes1 );
XorRes1 ^= 0x1200311;
}
}
AndRes1 = XorRes1 & 0x0FFFF; //And结果1
__asm{ //Shr结果1
push ebx
mov ebx,XorRes1
shr ebx,0x10
mov ShrRes1,ebx
pop ebx
}
AndRes2 = XorRes2 & 0x0FFFF; //And结果2
__asm{ //Shr结果2
push ebx
mov ebx,XorRes2
shr ebx,0x10
mov ShrRes2,ebx
pop ebx
}
CString PassWord;
PassWord.Format( "%.4X-%.4X-%.4X-%.4X",AndRes1,ShrRes1,AndRes2,ShrRes2 ); //格式改成大写
SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
}
else
MessageBox( "用户名格式错误!" );
}
并添加如下类成员函数:
inline unsigned int CallAsm( unsigned int XorRes )
{
unsigned int temp;
__asm{
push ebx
mov ebx,XorRes
sar ebx,1
jns end
adc ebx,0
end: mov temp,ebx
pop ebx
}
return temp;
}
inline bool XRLowIsOne( unsigned int xr )
{
bool flag = true;
__asm{
push eax
mov eax,xr
test al,1 //低位是否为1?
je end //为1直接结束
mov flag,0
end: pop eax
}
return flag;
}
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("RegKiller-crackme_Keygen"));
运行效果: