
系统 : Windows xp
程序 : Rith's CrackMe #1
程序下载地址 :http://pan.baidu.com/s/1gecW9Qr
要求 : 注册机编写
使用工具 : IDA Pro & OD
可在“PEDIY CrackMe 2007”中查找关于此程序的破文,标题为“WAKU的第二个破文----Rith's CrackMe #1(非常简单)”。
使用IDA载入程序,在字串表中找出正确注册的提示“Well done cracker!”,并双击交叉参考来到关键代码处:
. B81B4000 push 00401BB8 ; SE handler installation
. :A1 >mov eax, dword ptr fs:[]
0040158D . push eax
0040158E . : >mov dword ptr fs:[], esp
. 83EC 0C sub esp, 0C
. push ebx
. push ebp
0040159A . push esi
0040159B . 8BF1 mov esi, ecx
0040159D . push edi
0040159E . push ; ASCII "31415926535897932384"
004015A3 . 8D4C24 lea ecx, dword ptr [esp+]
004015A7 . 1C mov dword ptr [esp+1C], esi
004015AB . E8 FA020000 call <jmp.&MFC42.#>
004015B0 . 6A push
004015B2 . 8BCE mov ecx, esi
004015B4 . C74424 >mov dword ptr [esp+],
004015BC . E8 E3020000 call <jmp.&MFC42.#> ; MFC函数,此时,函数正在获取对话框的数据
004015C1 . 8B7E mov edi, dword ptr [esi+] ; 执行完此指令,edi存着用户名地址
004015C4 . 8B5F F8 mov ebx, dword ptr [edi-] ; 用户名长度
004015C7 . 83FB cmp ebx, ; 长度不能小于5
004015CA . 7C 7E jl short 0040164A
004015CC . 8B46 mov eax, dword ptr [esi+] ; eax存着序列号地址
004015CF . mov dword ptr [esp+], eax
004015D3 . F8 cmp dword ptr [eax-], ebx ; 用户名序列号长度是否相同?
004015D6 . jnz short 0040164A
004015D8 . 83FB cmp ebx, ; 用户名长度大于0x14?
004015DB . 7F 6D jg short 0040164A
004015DD . 33C9 xor ecx, ecx
004015DF . 85DB test ebx, ebx ; 长度为0,则跳转。并没有用的一条指令
004015E1 . 7E jle short
004015E3 . 8B7424 mov esi, dword ptr [esp+] ; 取密钥
004015E7 > 8A040F mov al, byte ptr [edi+ecx] ; 迭代用户名字串
004015EA . 0FBE2C31 movsx ebp, byte ptr [ecx+esi] ; 迭代密钥
004015EE . 0FBEC0 movsx eax, al
004015F1 . cdq ; 扩展指令
004015F2 . F7FD idiv ebp ; 用户名字符除以密钥字符
004015F4 . 8BC2 mov eax, edx ; 保留余数
004015F6 . D1E0 shl eax, ; 左移1位
004015F8 . 83F8 7B cmp eax, 7B ; 小于等于7B?
004015FB . 7E jle short
004015FD . 83E8 1A sub eax, 1A ; 大于7B则减去-1A
> 83F8 cmp eax, ; 大于等于41?
. 7D jge short 0040160E ; 是则进入下一cmp
. BA mov edx,
0040160A . 2BD0 sub edx, eax ; edx-=eax
0040160C . 8BC2 mov eax, edx ; 保留edx
0040160E > 83F8 5B cmp eax, 5B ; 小于等于5B?
. 7E jle short ; 是则直接去序列号进行对比
. 83F8 cmp eax, ; 大于等于61?
. 7D 0D jge short ; 是则直接去序列号进行对比
. cdq ; 否则eax除以10
. BD 0A000000 mov ebp, 0A
0040161E . F7FD idiv ebp
. 83C2 add edx, ; 余数+30
. 8BC2 mov eax, edx ; 存入eax
> 8B5424 mov edx, dword ptr [esp+] ; 取序列号
. 38040A cmp byte ptr [edx+ecx], al ; 序列号与处理结果是否相同?
0040162C . 1C jnz short 0040164A
0040162E . inc ecx ; 循环变量自增
0040162F . 3BCB cmp ecx, ebx ; 迭代结束?
.^ 7C B4 jl short 004015E7
. 8B7424 mov esi, dword ptr [esp+]
> 6A push
. push ; ASCII "Congratulations!"
0040163E . push ; ASCII "Well done cracker!"
. 8BCE mov ecx, esi
. E8 call <jmp.&MFC42.#> ; MessageBox函数
以上就是注册的关键代码了,发现该程序调用了MFC函数,函数名并没有在OD中显示,不要紧,对比IDA中相同的地址就可以看到具体用了什么函数。快速破解这个程序需要对MFC有一定的了解。好了,仔细跟踪代码,发现程序采用了F(用户名)=序列号的判断形势,我们用高级语言实现F(用户名)即可。
打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,并修改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 >= && len <= 0x14 ){ //格式控制。
CString Serial = ""; //密钥
CString PassWord = str; //序列号 for ( int i = ; i != len ; i++ ){
PassWord.SetAt( i,( PassWord[i] % Serial[i] ) << );
if ( PassWord[i] > 0x7B )
PassWord.SetAt( i,PassWord[i] - 0x1A );
if ( PassWord[i] < 0x41 )
PassWord.SetAt( i,0x82 - PassWord[i] ); if ( PassWord[i] > 0x5B && PassWord[i] < 0x61 )
PassWord.SetAt( i,PassWord[i] % + 0x30 );
} SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
}
else
MessageBox( "用户名格式错误!" );
}
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("Rith's CrackMe #1_Keygen"));
运行效果: