系统 : Windows xp
程序 : KeyGenMe-iNF1
程序下载地址 :https://pan.baidu.com/s/1nvfLBIh
要求 : 编写Keygen
使用工具 : OD
可在看雪论坛中查找关于此程序的破文:传送门
打开od,根据字符串“Serial is Correct!!!\nNow make a keygen”找到关键算法:
00401530 /$ 8B4C24 04 mov ecx,dword ptr ss:[esp+0x4]
00401534 |. 8D4424 04 lea eax,dword ptr ss:[esp+0x4]
00401538 |. 50 push eax
00401539 |. 68 20304000 push KeyGenMe.00403020 ; |%x
0040153E |. 51 push ecx ; |s
0040153F |. FF15 A4214000 call dword ptr ds:[<&MSVCRT.sscanf>] ; \sscanf
00401545 |. 8B4424 10 mov eax,dword ptr ss:[esp+0x10] ; 将密码从字符串形式转换成十六进制
00401549 |. 83C4 0C add esp,0xC ; 平衡堆栈
0040154C \. C3 retn
0040154D 90 nop
0040154E 90 nop
0040154F 90 nop
00401550 . 83EC 2C sub esp,0x2C
00401553 . 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
00401557 . 53 push ebx
00401558 . 56 push esi
00401559 . 57 push edi
0040155A . 6A 1F push 0x1F
0040155C . 50 push eax
0040155D . 8BF9 mov edi,ecx
0040155F . 68 E8030000 push 0x3E8
00401564 . E8 29030000 call <jmp.&MFC42.#3098> ; 获取字符串
00401569 . 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
0040156D . 6A 0A push 0xA
0040156F . 51 push ecx
00401570 . 68 E9030000 push 0x3E9
00401575 . 8BCF mov ecx,edi
00401577 . E8 16030000 call <jmp.&MFC42.#3098> ; 获取字符串
0040157C . BE 3C314000 mov esi,KeyGenMe.0040313C
00401581 . 8D4424 18 lea eax,dword ptr ss:[esp+0x18]
00401585 > 8A10 mov dl,byte ptr ds:[eax] ; 存储用户名字符串首字符
00401587 . 8A1E mov bl,byte ptr ds:[esi]
00401589 . 8ACA mov cl,dl
0040158B . 3AD3 cmp dl,bl
0040158D . 75 1E jnz XKeyGenMe.004015AD ; 首字符不等于00则进行跳转
0040158F . 84C9 test cl,cl
00401591 . 74 16 je XKeyGenMe.004015A9
00401593 . 8A50 01 mov dl,byte ptr ds:[eax+0x1]
00401596 . 8A5E 01 mov bl,byte ptr ds:[esi+0x1]
00401599 . 8ACA mov cl,dl
0040159B . 3AD3 cmp dl,bl
0040159D . 75 0E jnz XKeyGenMe.004015AD
0040159F . 83C0 02 add eax,0x2
004015A2 . 83C6 02 add esi,0x2
004015A5 . 84C9 test cl,cl
004015A7 .^ 75 DC jnz XKeyGenMe.00401585
004015A9 > 33C0 xor eax,eax
004015AB . EB 05 jmp XKeyGenMe.004015B2
004015AD > 1BC0 sbb eax,eax
004015AF . 83D8 FF sbb eax,-0x1
004015B2 > 85C0 test eax,eax ; 如果eax等于 0,则跳转
004015B4 . 0F84 A1000000 je KeyGenMe.0040165B
004015BA . BE 3C314000 mov esi,KeyGenMe.0040313C
004015BF . 8D4424 0C lea eax,dword ptr ss:[esp+0xC] ; 取密码
004015C3 > 8A10 mov dl,byte ptr ds:[eax] ; 取密码首字符
004015C5 . 8A1E mov bl,byte ptr ds:[esi]
004015C7 . 8ACA mov cl,dl
004015C9 . 3AD3 cmp dl,bl
004015CB . 75 1E jnz XKeyGenMe.004015EB
004015CD . 84C9 test cl,cl
004015CF . 74 16 je XKeyGenMe.004015E7
004015D1 . 8A50 01 mov dl,byte ptr ds:[eax+0x1]
004015D4 . 8A5E 01 mov bl,byte ptr ds:[esi+0x1]
004015D7 . 8ACA mov cl,dl
004015D9 . 3AD3 cmp dl,bl
004015DB . 75 0E jnz XKeyGenMe.004015EB
004015DD . 83C0 02 add eax,0x2
004015E0 . 83C6 02 add esi,0x2
004015E3 . 84C9 test cl,cl
004015E5 .^ 75 DC jnz XKeyGenMe.004015C3
004015E7 > 33C0 xor eax,eax
004015E9 . EB 05 jmp XKeyGenMe.004015F0
004015EB > 1BC0 sbb eax,eax
004015ED . 83D8 FF sbb eax,-0x1
004015F0 > 85C0 test eax,eax ; 如果eax等于 0,则跳转
004015F2 . 74 67 je XKeyGenMe.0040165B
004015F4 . 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
004015F8 . 50 push eax ; 取密码
004015F9 . E8 B2FEFFFF call KeyGenMe.004014B0
004015FE . 83C4 04 add esp,0x4
00401601 . 85C0 test eax,eax
00401603 . 74 66 je XKeyGenMe.0040166B ; call结果为0则为不正确
00401605 . 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
00401609 . 51 push ecx
0040160A . E8 21FFFFFF call KeyGenMe.00401530
0040160F . 8D5424 1C lea edx,dword ptr ss:[esp+0x1C] ; 取用户名
00401613 . 8BF0 mov esi,eax
00401615 . 52 push edx ; 传入 密码、用户名
00401616 . E8 55FEFFFF call KeyGenMe.00401470 ; F(用户名)
0040161B . 05 8F020000 add eax,0x28F
00401620 . B9 34120000 mov ecx,0x1234
00401625 . 99 cdq
00401626 . F7F9 idiv ecx
00401628 . B9 01000100 mov ecx,0x10001
0040162D . 83C4 08 add esp,0x8
00401630 . 8BC2 mov eax,edx
00401632 . 0FAFC6 imul eax,esi ; eax * 密码 = 10002
00401635 . 99 cdq
00401636 . F7F9 idiv ecx
00401638 . B8 01000000 mov eax,0x1
0040163D . 2BC2 sub eax,edx ; 结果算出来edx等于1
0040163F . 75 2A jnz XKeyGenMe.0040166B
00401641 . 6A 00 push 0x0
00401643 . 68 60304000 push KeyGenMe.00403060 ; Good Work
00401648 . 68 38304000 push KeyGenMe.00403038 ; Serial is Correct!!!\nNow make a keygen
0040164D . 8BCF mov ecx,edi
0040164F . E8 38020000 call <jmp.&MFC42.#4224>
00401654 . 5F pop edi
00401655 . 5E pop esi
00401656 . 5B pop ebx
00401657 . 83C4 2C add esp,0x2C
0040165A . C3 retn
0040165B > 6A 00 push 0x0
0040165D . 6A 00 push 0x0
0040165F . 68 24304000 push KeyGenMe.00403024 ; Insufficient Info
00401664 . 8BCF mov ecx,edi
00401666 . E8 21020000 call <jmp.&MFC42.#4224>
0040166B > 5F pop edi
0040166C . 5E pop esi
0040166D . 5B pop ebx
0040166E . 83C4 2C add esp,0x2C
00401671 . C3 retn
跟入f(用户名):
00401470 /$ 8B5424 04 mov edx,dword ptr ss:[esp+0x4]
00401474 |. B8 9A020000 mov eax,0x29A
00401479 |. 8A0A mov cl,byte ptr ds:[edx] ; 取首字符
0040147B |. 84C9 test cl,cl
0040147D |. 74 2E je XKeyGenMe.004014AD ; 为空则直接退出call
0040147F |. 56 push esi
00401480 |> 0FBEC9 /movsx ecx,cl
00401483 |. 8BF1 |mov esi,ecx
00401485 |. 81F6 DADA0000 |xor esi,0xDADA ; 字符与固定值异或
0040148B |. 03F0 |add esi,eax ; 再加上固定值
0040148D |. 8BC1 |mov eax,ecx ; 再取用户名的字符
0040148F |. 35 BEBA0000 |xor eax,0xBABE
00401494 |. 81F1 01F00000 |xor ecx,0xF001
0040149A |. F7D0 |not eax
0040149C |. 8D04B0 |lea eax,dword ptr ds:[eax+esi*4]
0040149F |. C1F8 03 |sar eax,0x3 ; 算数右移
004014A2 |. 03C1 |add eax,ecx
004014A4 |. 8A4A 01 |mov cl,byte ptr ds:[edx+0x1] ; 取下一个
004014A7 |. 42 |inc edx
004014A8 |. 84C9 |test cl,cl ; 是否已经迭代完毕
004014AA |.^ 75 D4 \jnz XKeyGenMe.00401480
004014AC |. 5E pop esi
004014AD \> C3 retn
根据以上汇编代码,可以很容易地写出注册机。
直接打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,修改OnBtnDecrypt函数如下:
void CKeygenDlg::OnBtnDecrypt()
{
// TODO: Add your control notification handler code here
CString Name = "";
GetDlgItemText( IDC_EDIT_NAME,Name );
if ( Name.GetLength() == 0 ){
MessageBox( "用户名不能为空!" );
return ;
}
unsigned int ESI = 0;
unsigned int a = 0x29A;
unsigned int ECX = 0;
for ( int i = 0 ; i != Name.GetLength() ; i++ ){
ESI = (Name[i] ^ 0xDADA) + a;
a = (Name[i] ^ 0xBABE);
ECX = Name[i] ^ 0xF001;
__asm{
push eax
mov eax,a
not eax
mov a,eax
pop eax
}
a = a + ESI * 4;
a = a>>3;
a += ECX;
}
a = ( a + 0x28F ) % 0x1234;
for ( int j = 1 ; j != 1000000 ; j++ )
if ( (j*a) % 0x10001 == 1 )
break;
CString PassWord;
PassWord.Format( "%x",j );
SetDlgItemText( IDC_EDIT_SERIAL,PassWord );
}
再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("Keygen"));
运行效果:
我们一路奋战,不是为了改变世界,而是不让世界改变我们
——《熔炉》