系统 : Windows xpphp
程序 : KeyGenMe-iNF1html
程序下载地址 :https://pan.baidu.com/s/1nvfLBIh
算法
要求 : 编写Keygen框架
使用工具 : OD函数
可在看雪论坛中查找关于此程序的破文:传送门工具
打开od,根据字符串“Serial is Correct!!!\nNow make a keygen”找到关键算法:spa
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(用户名):code
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
根据以上汇编代码,能够很容易地写出注册机。orm
直接打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,修改OnBtnDecrypt函数以下:htm
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"));
运行效果: