-
-
[原创]HappytownCrackme006的分析及注册机源码
-
发表于: 2006-10-31 13:32 4357
-
下面是HappyTown的Crackme006 注册分析
这个Crackme有点意思,就把算法分析过程也贴上来了,呵!
不过这次认了一点真,把汇编码仔细检查了一下,自以为是最精炼的了。
没什么好东东,只是在做作业,就着这几天空闲时多,自娱自乐型。
ASM程序,用典型的断点:
GetDlgItemTextA----取文本函数
0040122A 68 04314000 push CrackMe_.00403104 ; ASCII "wofan"
0040122F 68 EC030000 push 3EC
00401234 FF75 08 push dword ptr ss:[ebp+8]
00401237 E8 FC000000 call <jmp.&user32.GetDlgItemTextA>
0040123C 8945 F4 mov dword ptr ss:[ebp-C],eax
0040123F 837D F4 04 cmp dword ptr ss:[ebp-C],4 ; 注册名不少于4位
00401243 73 04 jnb short CrackMe_.00401249
00401245 C9 leave
00401246 C2 1000 retn 10
00401249 68 04314000 push CrackMe_.00403104 ; ASCII "wofan"
0040124E E8 E3FDFFFF call CrackMe_.00401036 ; 计算
00401253 6A 01 push 1 ; 压栈一个数:1
00401255 50 push eax ; 计算值压栈
00401256 E8 26FEFFFF call CrackMe_.00401081 ; 把计算值ROL一次
0040125B 0B45 F0 or eax,dword ptr ss:[ebp-10] ; 加上一个数:44886452 ,得看看这个数是怎么来的,应该不会是个常数?
0040125E 25 FFFFFF0F and eax,0FFFFFFF ; 去掉最高位
00401263 8945 EC mov dword ptr ss:[ebp-14],eax ; 保存
00401266 33C9 xor ecx,ecx
00401268 33D2 xor edx,edx
0040126A 8D35 00304000 lea esi,dword ptr ds:[403000]
00401270 8B45 EC mov eax,dword ptr ss:[ebp-14]
00401273 8945 EC mov dword ptr ss:[ebp-14],eax
00401276 6A 10 push 10 ; 压一个数10
00401278 50 push eax ; 计算值
00401279 E8 82FDFFFF call CrackMe_.00401000 ; 原来是把计算值对10取余,保存余数
0040127E 8BC8 mov ecx,eax
00401280 8D3D 73204000 lea edi,dword ptr ds:[402073] ; 一个小小的字串:071362de9f8ab45c
00401286 8A0439 mov al,byte ptr ds:[ecx+edi] ; 凭那个余数,从字串中取得注册码
00401289 8806 mov byte ptr ds:[esi],al ; 保存注册码
0040128B 8B45 EC mov eax,dword ptr ss:[ebp-14] ; 计算值
0040128E 6A 04 push 4 ; 压一个数4
00401290 50 push eax
00401291 E8 86FDFFFF call CrackMe_.0040101C ; 对4取余,保存余数
00401296 8945 EC mov dword ptr ss:[ebp-14],eax
00401299 0BC0 or eax,eax ; 看看除4之后,是否已经除尽了,除尽了也就结束了
0040129B 74 04 je short CrackMe_.004012A1
0040129D 46 inc esi ; 移动注册码指针
0040129E 47 inc edi ; 这是那个字串,移动指针有什么用呀!这里应该是个错误。
0040129F ^ EB D2 jmp short CrackMe_.00401273 ; 循环处理注册名
004012A1 68 00010000 push 100
004012A6 8D85 ECFEFFFF lea eax,dword ptr ss:[ebp-114]
004012AC 50 push eax
004012AD 68 ED030000 push 3ED ; 3ED是控件ID号,这些已经很熟悉了
004012B2 FF75 08 push dword ptr ss:[ebp+8]
004012B5 E8 7E000000 call <jmp.&user32.GetDlgItemTextA>
004012BA 0BC0 or eax,eax ; 注册码不能为空
004012BC 75 04 jnz short CrackMe_.004012C2
004012BE C9 leave
004012BF C2 1000 retn 10
004012C2 68 00304000 push CrackMe_.00403000 ; ASCII "5cefd"
004012C7 8D85 ECFEFFFF lea eax,dword ptr ss:[ebp-114] ; 假注册码
004012CD 50 push eax
004012CE E8 53000000 call <jmp.&kernel32.lstrcmpA>
004012D3 0BC0 or eax,eax
004012D5 75 18 jnz short CrackMe_.004012EF
004012D7 6A 40 push 40
004012D9 68 08214000 push CrackMe_.00402108 ; ASCII "Congratulations"
004012DE 68 F9204000 push CrackMe_.004020F9 ; ASCII "GOOD JOB, MAN!"
============================计算==========================================================
00401039 8B75 08 mov esi,dword ptr ss:[ebp+8]
0040103C FC cld ; 清方向标志
0040103D 33D2 xor edx,edx
0040103F B8 01000000 mov eax,1 ; 累加器置初值1
00401044 0FB60E movzx ecx,byte ptr ds:[esi] ; 注册名ASCII码送ECX
00401047 46 inc esi ; 移动指针
00401048 0BC9 or ecx,ecx ; 不为零,表示有效,还不应该结束,因为:0 or 0=0
0040104A 74 06 je short CrackMe_.00401052
0040104C F7E1 mul ecx ; mul:注册名ASCII乘累加值
0040104E 03C2 add eax,edx ; 累加,如果产生高32位数,也得加上来
00401050 ^ EB F2 jmp short CrackMe_.00401044 ; 继续循环
00401052 C9 leave ; 结束
===========================================================================================
===========================================================================================
==========加上一个数:44886452 ,得看看这个数是怎么来的,应该不会是个常数?=================
===========================================================================================
向上可以找到:GetVolumeInformationA
莫非与它有关?
重新下断。
004010C2 55 push ebp
004010C3 8BEC mov ebp,esp
004010C5 81C4 F8FEFFFF add esp,-108
004010CB 53 push ebx
004010CC 57 push edi
004010CD 56 push esi
004010CE 68 80000000 push 80
004010D3 8D85 F8FEFFFF lea eax,dword ptr ss:[ebp-108]
004010D9 50 push eax
004010DA 8D85 78FFFFFF lea eax,dword ptr ss:[ebp-88]
004010E0 50 push eax
004010E1 68 FF000000 push 0FF
004010E6 8D85 7CFFFFFF lea eax,dword ptr ss:[ebp-84] ;需要的就是这个参数
004010EC 50 push eax
004010ED 68 80000000 push 80
004010F2 8D45 80 lea eax,dword ptr ss:[ebp-80]
004010F5 50 push eax
004010F6 FF75 08 push dword ptr ss:[ebp+8]
004010F9 E8 22020000 call <jmp.&kernel32.GetVolumeInformationA> ;这就是获取磁盘信息的函数。
004010FE 8B85 7CFFFFFF mov eax,dword ptr ss:[ebp-84]
----------------------------------------------
004011D0 68 43204000 push CrackMe_.00402043 ; ASCII "c:\"
004011D5 E8 E8FEFFFF call CrackMe_.004010C2 ; 取C盘信息
004011DA 8945 FC mov dword ptr ss:[ebp-4],eax
004011DD 6A 05 push 5 ; push 5
004011DF FF75 FC push dword ptr ss:[ebp-4] ; 参数
004011E2 E8 B1FEFFFF call CrackMe_.00401098 ; 对它进行移位SHL。移5次
004011E7 6A 0D push 0D ; push 0xD
004011E9 50 push eax
004011EA E8 92FEFFFF call CrackMe_.00401081 ; 再ROL 0xD次
004011EF 68 47204000 push CrackMe_.00402047 ; ASCII "d:\"
004011F4 E8 C9FEFFFF call CrackMe_.004010C2 ; 取D盘信息
004011F9 8945 F8 mov dword ptr ss:[ebp-8],eax ; 得取了返回值:44886452
004011FC FF75 F8 push dword ptr ss:[ebp-8]
004011FF FF75 FC push dword ptr ss:[ebp-4]
00401202 E8 A8FEFFFF call CrackMe_.004010AF ; 加1
00401207 6A 05 push 5
00401209 50 push eax
0040120A E8 89FEFFFF call CrackMe_.00401098 ; SHL 5
0040120F 6A 0D push 0D
00401211 50 push eax
00401212 E8 6AFEFFFF call CrackMe_.00401081 ; ROL 0xD
00401217 FF75 F8 push dword ptr ss:[ebp-8] ; 得到了原来的数:44886452,靠!!
0040121A FF75 FC push dword ptr ss:[ebp-4]
0040121D E8 34FEFFFF call CrackMe_.00401056 ; 这里还进进了浮点运算,靠,还是原数,不知在别的机器上是不是这样?
--------------------------------------------------
原来它是取本D盘的卷标信息。不知道,如果有只有一个分区时,会是怎样?
BOOL GetVolumeInformation(
LPCTSTR lpRootPathName, // address of root directory of the
// file system
LPTSTR lpVolumeNameBuffer, // address of name of the volume
DWORD nVolumeNameSize, // length of lpVolumeNameBuffer
LPDWORD lpVolumeSerialNumber, // address of volume serial number============>就是它了
LPDWORD lpMaximumComponentLength,
// address of system's maximum
// filename length
LPDWORD lpFileSystemFlags, // address of file system flags
LPTSTR lpFileSystemNameBuffer, // address of name of file system
DWORD nFileSystemNameSize // length of lpFileSystemNameBuffer
);
=====================================================================================================
Delphi内联汇编注册机关键部分源码:
//============= 函数,过程,回调函数 ==================================
//=======================================================================
Function Get_D_VolumeInfo:DWORD;
var
lpSerialNumber:DWORD; //序列号
lpFileSystemName:array[0..10] of char; //文件系统
lpMaximumComponentLength:DWORD;
lpFileSystemFlags:DWORD;
Begin
GetVolumeInformation(pchar('d:\'),
nil,
0,
@lpSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
lpFileSystemName,
sizeof(lpFileSysTemName)
);
result:=lpSerialNumber;
End;
procedure wofanKeygen(hdlg:HWND);
var
Title,text:string;
const
temp:array[0..15]of char=('0','7','1','3','6','2','d','e','9','f','8','a','b','4','5','c');
Begin
Title:='提示';
Text:='注册名至少4位!';
ZeroMemory(@mCode,sizeof(mCode));
ZeroMemory(@mName,sizeof(mName));
GetDlgItemText(hDlg,IDC_Name,@mName,sizeof(mName));
asm
LEA ESI,mName //把注册名的地址传到ESI
cmp eax,4 //EAX 是GetDlgItemText函数返回值,它是字串实际长度
JL @Err
mov eax,1 //累加器置初值
@CalBegin:
movzx ecx,byte ptr ds:[esi] //注册名ASCII码逐个送ECX
inc esi //移动指针
or ecx,ecx
je @EndCal
mul ecx
add eax,edx
jmp @CalBegin
@EndCal:
mov ecx,1
rol eax,cl
mov ecx,eax
call Get_D_VolumeInfo
or eax,ecx
and eax,0FFFFFFFH
lea esi,mCode //注册码地址
lea edi,temp //临时字串的地址
@loop:
push eax //压栈保存这个计算值
xor edx,edx
mov ecx,10H
idiv ecx
mov al,byte ptr ds:[edi+edx]
mov byte ptr ds:[esi],al
pop eax //计算值出栈
mov ecx,4
xor edx,edx
idiv ecx
or eax,eax
je @End
inc esi
jmp @loop
@Err:
push 0
MOV EAX,DWORD PTR SS:[Title]
PUSH EAX
MOV EAX,DWORD PTR SS:[Text]
PUSH EAX
PUSH MB_OK
Call MessageBox //提示:注册名长度至少要4位
@End:
End; //End ASM
End;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课