└文章标题┐:Ardamax Keylogger 2.71破解分析
└破文作者┐:-=>大菜<=-
└破解对象┐:Ardamax Keylogger 2.71
└下载地址┐:网上搜..
└对象大小┐:不知..
└加壳方式┐:没有
└保护方式┐:普通算法
└编写语言┐:peid说"啥也没找到" - -!
└使用工具┐:OD
└破解平台┐:D版XP
└破解声明┐:
Crack真帅``哦呵呵呵
不过想想软件作者还真可怜,不过是国外的,我想偶在Crack时他大概在打喷嚏吧!我连软件怎么用有啥用都不清楚哇~~~
----------------------------------------------------------------------------------
└破解过程┐:
所有messagebox都设置断点,一共27个!
输入"jiangwu55"->"121212"
断在:
00405E53 |. 6A 30 push 30
00405E55 |. 68 082D4600 push 00462D08 ; UNICODE "Ardamax Keylogger"
00405E5A |. 68 D03A4600 push 00463AD0 ; UNICODE "No registration name entered."
00405E5F |> FF77 04 push dword ptr [edi+4] ; |hOwner
00405E62 |. FF15 30B54500 call dword ptr [<&USER32.MessageBoxW>>; \MessageBoxW ;断在这
00405E68 |. E9 84000000 jmp 00405EF1
00405E6D |> 51 push ecx
00405E6E |. 8D8D F0FBFFFF lea ecx, dword ptr [ebp-410]
00405E74 |. 8BC4 mov eax, esp
00405E76 |. 51 push ecx
00405E77 |. E8 B84C0100 call 0041AB34
00405E7C |. 51 push ecx
00405E7D |. 8D8D F8FDFFFF lea ecx, dword ptr [ebp-208]
00405E83 |. 8BC4 mov eax, esp
00405E85 |. 51 push ecx
00405E86 |. E8 A94C0100 call 0041AB34
00405E8B |. E8 A1FEFFFF call 00405D31
00405E90 |. 85C0 test eax, eax
00405E92 |. 74 65 je short 00405EF9
00405E94 |. 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00405E96 |. 68 082D4600 push 00462D08 ; |Title = "Ardamax Keylogger"
00405E9B |. 68 103B4600 push 00463B10 ; |Text = "Registration code is accepted. Thank you for registration!"
00405EA0 |. FF77 04 push dword ptr [edi+4] ; |hOwner
00405EA3 |. FF15 30B54500 call dword ptr [<&USER32.MessageBoxW>>; \MessageBoxW ;注册成功
可以看到字符串了,向上看可以看到GetDlgItemText这个函数(不知为啥直接断这个函数不行),取消所有断点,重新断在405dfd处:
00405DFD /$ 55 push ebp ;F2重新载入后断在这
00405DFE |. 8BEC mov ebp, esp
00405E00 |. 81EC 10040000 sub esp, 410
00405E06 |. 66:837D 08 01 cmp word ptr [ebp+8], 1
00405E0B |. 53 push ebx
00405E0C |. 56 push esi
00405E0D |. 0F85 B1000000 jnz 00405EC4
00405E13 |. 8B35 64B54500 mov esi, dword ptr [<&USER32.GetDlgI>; USER32.GetDlgItemTextW
00405E19 |. BB 04010000 mov ebx, 104
00405E1E |. 53 push ebx ; /Count => 104 (260.)
00405E1F |. 8D85 F0FBFFFF lea eax, dword ptr [ebp-410] ; |
00405E25 |. 50 push eax ; |Buffer
00405E26 |. 68 07040000 push 407 ; |ControlID = 407 (1031.)
00405E2B |. FF77 04 push dword ptr [edi+4] ; |hWnd
00405E2E |. FFD6 call esi ; \GetDlgItemTextW ;取注册码
00405E30 |. 53 push ebx ; /Count => 104 (260.)
00405E31 |. 8D85 F8FDFFFF lea eax, dword ptr [ebp-208] ; |
00405E37 |. 50 push eax ; |Buffer
00405E38 |. 68 F7030000 push 3F7 ; |ControlID = 3F7 (1015.)
00405E3D |. FF77 04 push dword ptr [edi+4] ; |hWnd
00405E40 |. FFD6 call esi ; \GetDlgItemTextW ;取注册名
00405E42 |. 8D85 F8FDFFFF lea eax, dword ptr [ebp-208]
00405E48 |. 50 push eax ; /String
00405E49 |. FF15 00B14500 call dword ptr [<&KERNEL32.lstrlenW>] ; \lstrlenW ;取注册名长度
00405E4F |. 85C0 test eax, eax
00405E51 |. 75 1A jnz short 00405E6D ;为空出错
***************************************************************************************************************
00405E6D |> \51 push ecx ;上面不为空就跳到这
00405E6E |. 8D8D F0FBFFFF lea ecx, dword ptr [ebp-410]
00405E74 |. 8BC4 mov eax, esp
00405E76 |. 51 push ecx
00405E77 |. E8 B84C0100 call 0041AB34
00405E7C |. 51 push ecx
00405E7D |. 8D8D F8FDFFFF lea ecx, dword ptr [ebp-208]
00405E83 |. 8BC4 mov eax, esp
00405E85 |. 51 push ecx
00405E86 |. E8 A94C0100 call 0041AB34
00405E8B |. E8 A1FEFFFF call 00405D31 ;经典关键,下面有注册成功信息
00405E90 |. 85C0 test eax, eax
00405E92 |. 74 65 je short 00405EF9
***************************************************************************************************************
关键call:(节省篇幅,省略n条代码...)^-^
00405D31 /$ 55 push ebp ;跟进后的第一条句语
F8一直走....
00405D8D |. FF75 EC push dword ptr [ebp-14] ; /Arg1 = 0012EAFC ASCII "jiangwu55" ;注册名
00405D90 |. 8D9D 64FEFFFF lea ebx, dword ptr [ebp-19C] ; |
00405D96 |. E8 1DFFFFFF call 00405CB8 ; \IWM.00405CB8 ;关键call
因为步过之后可以看到注册码了&_&
***************************************************************************************************************
跟进后:
00405CB9 |. 8BEC mov ebp, esp
00405CBB |. 83EC 0C sub esp, 0C
00405CBE |. 56 push esi
00405CBF |. 8B35 38B14500 mov esi, dword ptr [<&KERNEL32.lstrl>; kernel32.lstrlenA
00405CC5 |. 57 push edi
00405CC6 |. BF 0C594600 mov edi, 0046590C ; ASCII "207144FA6AD570E" ;一串字符(下面说为字符串a)
00405CCB |. 57 push edi ; /String => "207144FA6AD570E"
00405CCC |. FFD6 call esi ; \lstrlenA ;取其长度
00405CCE |. FF75 08 push dword ptr [ebp+8] ; /String ;注册名
00405CD1 |. 8945 F8 mov dword ptr [ebp-8], eax; |
00405CD4 |. FFD6 call esi ; \lstrlenA ;取注册名长度
00405CD6 |. 8BF0 mov esi, eax
00405CD8 |. 85F6 test esi, esi
00405CDA |. 8975 F4 mov dword ptr [ebp-C], esi
00405CDD |. 75 04 jnz short 00405CE3
00405CDF |. 8803 mov byte ptr [ebx], al
00405CE1 |. EB 48 jmp short 00405D2B
00405CE3 |> 57 push edi ; /String2 ;字符串a
00405CE4 |. 53 push ebx ; |String1 ;一个内存地址
00405CE5 |. FF15 4CB14500 call dword ptr [<&KERNEL32.lstrcpyA>] ; \lstrcpyA ;复制
00405CEB |. 8B45 F8 mov eax, dword ptr [ebp-8] ;字符串a长度到eax
00405CEE |. 3BF0 cmp esi, eax ;和注册名长度比较
00405CF0 |. 8975 FC mov dword ptr [ebp-4], esi ;注册名长度传到ebp-4
00405CF3 |. 7F 03 jg short 00405CF8 ;大于就跳
00405CF5 |. 8945 FC mov dword ptr [ebp-4], eax ;小于的话ebp-4就是字符串a长度
00405CF8 |> 33F6 xor esi, esi ;字符串a长度大于注册名长度就清零
00405CFA |. 3975 FC cmp dword ptr [ebp-4], esi ;esi作为计数器
ebp-4现在是注册名长度
00405CFD |. 7E 2C jle short 00405D2B
00405CFF |> 8BC6 /mov eax, esi ;本次循环计数器值到eax
00405D01 |. 99 |cdq ;双字扩展,没啥路用
00405D02 |. F77D F8 |idiv dword ptr [ebp-8] ;本次循环计数器值除以字符串a长度
00405D05 |. 8BC6 |mov eax, esi ;本次循环计数器值到eax
00405D07 |. 6A 19 |push 19 ;19进栈
00405D09 |. 5F |pop edi ;弹出来
00405D0A |. 8D0C1A |lea ecx, dword ptr [edx+ebx] ;edx是余数,ebx是字符串a的地址
第一次当然是整个字符串地址到ecx了
00405D0D |. 99 |cdq
00405D0E |. F77D F4 |idiv dword ptr [ebp-C] ;本次循环计数器值除以注册名长度
00405D11 |. 8B45 08 |mov eax, dword ptr [ebp+8] ;注册名到eax
00405D14 |. 0FB60402 |movzx eax, byte ptr [edx+eax] ;每次循环取注册名各个字符
00405D18 |. 0FB611 |movzx edx, byte ptr [ecx] ;每次循环取字符串a各个字符
00405D1B |. 33C2 |xor eax, edx ;xor异或
00405D1D |. 99 |cdq
00405D1E |. F7FF |idiv edi ;除以19
00405D20 |. 80C2 41 |add dl, 41 ;余数加上41
00405D23 |. 46 |inc esi ;计数器加一
00405D24 |. 3B75 FC |cmp esi, dword ptr [ebp-4] ;比看看算完没有
00405D27 |. 8811 |mov byte ptr [ecx], dl ;结果传回字符串a对应的位置
00405D29 |.^ 7C D4 \jl short 00405CFF ;没完跳上去
00405D2B |> 5F pop edi
00405D2C |. 5E pop esi
00405D2D |. C9 leave
00405D2E \. C2 0400 retn 4
算法总结:
根据比较字符串a和注册名的长度循环,前者大则循环15次,后者大则循环后者长度次
在405cff到405d02处代码和405d18处是有联系的`
比如说注册名长度大于字符串a长度:
循环超过15次
到15次时原[ecx]值已经是新算出来的字符串了,而在405d22处的idiv,则为0xf%0xf为0
405d0a处又重新从新字符串第一个字符开始取了,而且还是一样传回原来的位置,刚开始偶还以为接在后面,我汗了```
注册机可以算到注册名30位(我限制了^0^)
下面是WinSDK注册机的WM_COMMAND消息代码:
case WM_COMMAND:
if(IDOK==LOWORD(wParam))
{
char name[100],str[100]="207144FA6AD570E",key[100];
int i,len=0;
GetDlgItemText(hwndDlg,IDC_EDIT_NAME,name,sizeof(name));//取name
memset(key,0,sizeof(key));//全归0,免乱码
if(name[0] != NULL)//没输入的别点确定
{
len=strlen(name);
if(len<=15)//注册名长度小于字符串a长度的部分
{
for(i=len;i<15;i++)
name[i]=name[i-len];
for(i=0;i<15;i++)
{
key[i]=((name[i]^str[i])%0x19)+0x41;
}
SetDlgItemText(hwndDlg,IDC_EDIT_SERIAL,key);
}
else //字符串a长度小于注册名长度的部分
{
for(i=0;i<len;i++)
{
if(i>14)
str[i-15]=((name[i]^str[i-15])%0x19)+0x41;
else
str[i]=((name[i]^str[i])%0x19)+0x41;
}
SetDlgItemText(hwndDlg,IDC_EDIT_SERIAL,str);
}
}
else
{
SetDlgItemText(hwndDlg,IDC_EDIT_SERIAL,"Your Name???");
}
}
return TRUE;
----------------------------------------------------------------------------------
└经验总结┐:Crack一个软件也不难吧,呵呵``至少这个不难->^-^
----------------------------------------------------------------------------------
└版权声明┐ 本文原创于看雪软件安全论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年4月26日 20:1:7
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)