Happytown第33个CrackMe(KeyGenMe)分析,在HappyTown发贴的那个页面,出现人身攻击,所以稍稍跟踪了一下,那个贴子出现人身攻击,我不便跟贴,只好重新开贴了。这是个简单的Crackme,大家不必如此。
00401170 8B3D A4504000 mov edi,dword ptr ds:[<&USER32.GetDlgI>; USER32.GetDlgItemTextA
00401176 33C0 xor eax,eax
00401178 8D8C24 98000000 lea ecx,dword ptr ss:[esp+98]
0040117F 894424 14 mov dword ptr ss:[esp+14],eax
00401183 6A 65 push 65
00401185 51 push ecx
00401186 894424 20 mov dword ptr ss:[esp+20],eax
0040118A 68 E8030000 push 3E8 ; 0x3E8是注册名Edit的控件ID
0040118F 56 push esi
00401190 C74424 20 00000000 mov dword ptr ss:[esp+20],0 ; 栈区某处清零
00401198 894424 2C mov dword ptr ss:[esp+2C],eax ; 栈区某处清零
0040119C C74424 34 FD7129BB mov dword ptr ss:[esp+34],BB2971FD ; 从此以下,初始化四组常数
004011A4 C74424 38 705338A1 mov dword ptr ss:[esp+38],A1385370
004011AC C74424 3C 1D23D6A6 mov dword ptr ss:[esp+3C],A6D6231D
004011B4 C74424 40 C8DAE1BD mov dword ptr ss:[esp+40],BDE1DAC8
004011BC FFD7 call edi ; 调用GetDlgItemTextA函数,获取注册名
004011BE 8BD8 mov ebx,eax ; 函数返回注册名的长度
004011C0 83FB 03 cmp ebx,3 ; HappyTown要求注册名长度不能少于3
004011C3 73 0C jnb short CrackMe_.004011D1
004011C5 5F pop edi
004011C6 5E pop esi
004011C7 33C0 xor eax,eax
004011C9 5B pop ebx
004011CA 81C4 F0000000 add esp,0F0
004011D0 C3 retn
004011D1 8D5424 34 lea edx,dword ptr ss:[esp+34]
004011D5 6A 65 push 65
004011D7 52 push edx
004011D8 68 E9030000 push 3E9 ; 0x3E9是注册码Edit控件ID
004011DD 56 push esi
004011DE FFD7 call edi ; 调用GetDlgItemTextA函数,获取注册码
004011E0 83F8 20 cmp eax,20 ; 返回注册码长度,应该等于0x20
004011E3 74 0C je short CrackMe_.004011F1
004011E5 5F pop edi
004011E6 5E pop esi
004011E7 33C0 xor eax,eax
004011E9 5B pop ebx
004011EA 81C4 F0000000 add esp,0F0
004011F0 C3 retn
004011F1 33F6 xor esi,esi ; 对ESI寄存器清零
004011F3 833D E0624000 01 cmp dword ptr ds:[4062E0],1
004011FA 7E 16 jle short CrackMe_.00401212
004011FC 33C0 xor eax,eax
004011FE 68 80000000 push 80
00401203 8A4434 38 mov al,byte ptr ss:[esp+esi+38]
00401207 50 push eax
00401208 E8 33010000 call CrackMe_.00401340
0040120D 83C4 08 add esp,8
00401210 EB 14 jmp short CrackMe_.00401226
00401212 8B15 D4604000 mov edx,dword ptr ds:[4060D4] ; 好长的一个字串,包括了该Crackme的文件名,系统目录……
00401218 33C9 xor ecx,ecx
0040121A 8A4C34 34 mov cl,byte ptr ss:[esp+esi+34] ; 开始处理注册码,注册码逐位送CL
0040121E 8A044A mov al,byte ptr ds:[edx+ecx*2]
00401221 25 80000000 and eax,80
00401226 85C0 test eax,eax
00401228 ^ 74 BB je short CrackMe_.004011E5
0040122A 46 inc esi
0040122B 83FE 20 cmp esi,20 ; 循环0x20次
0040122E ^ 72 C3 jb short CrackMe_.004011F3
00401230 83FB 10 cmp ebx,10 ; 注册名长度如果不够0x10位,则需要填充,填充的数据是就是注册名长度+0x21,不断自增1,并加上0x21
00401233 73 14 jnb short CrackMe_.00401249
00401235 8BC3 mov eax,ebx
00401237 8AC8 mov cl,al
00401239 80C1 21 add cl,21
0040123C 888C04 98000000 mov byte ptr ss:[esp+eax+98],cl ; 新生数据,附在原注册名后面
00401243 40 inc eax
00401244 83F8 10 cmp eax,10 ; 真到生成16位注册名
00401247 ^ 72 EE jb short CrackMe_.00401237
00401249 8BB424 98000000 mov esi,dword ptr ss:[esp+98] ; 第一组注册名
00401250 8B8424 9C000000 mov eax,dword ptr ss:[esp+9C] ; 第二组注册名
00401257 8B8C24 A0000000 mov ecx,dword ptr ss:[esp+A0] ; 第三组注册名
0040125E 8B9424 A4000000 mov edx,dword ptr ss:[esp+A4] ; 第四组注册名
00401265 55 push ebp
00401266 8D7C24 28 lea edi,dword ptr ss:[esp+28] ; 前面初始化的常数的首地址,送EDI备用
0040126A C74424 10 04000000 mov dword ptr ss:[esp+10],4 ; 4,将要进行四次循环,处理16位的注册名
00401272 56 push esi
00401273 8BE8 mov ebp,eax
00401275 8BD9 mov ebx,ecx
00401277 895424 28 mov dword ptr ss:[esp+28],edx
0040127B E8 A0000000 call CrackMe_.00401320 ; 一个子程序:@特别注明@,处理注册名,顺序是1,4,3,2
00401280 8B0F mov ecx,dword ptr ds:[edi]
00401282 8B7424 28 mov esi,dword ptr ss:[esp+28]
00401286 8BD3 mov edx,ebx
00401288 8B5C24 14 mov ebx,dword ptr ss:[esp+14]
0040128C 83C4 04 add esp,4
0040128F 03C1 add eax,ecx
00401291 83C7 04 add edi,4 ; 指向下一组常数
00401294 4B dec ebx ; 循环次数,dec(ebx)
00401295 8BCD mov ecx,ebp
00401297 895C24 10 mov dword ptr ss:[esp+10],ebx
0040129B ^ 75 D5 jnz short CrackMe_.00401272
0040129D 897424 14 mov dword ptr ss:[esp+14],esi ; 将生成的注册码存放
004012A1 895424 20 mov dword ptr ss:[esp+20],edx
004012A5 894C24 1C mov dword ptr ss:[esp+1C],ecx
004012A9 894424 18 mov dword ptr ss:[esp+18],eax
004012AD 33D2 xor edx,edx
004012AF 8D7424 39 lea esi,dword ptr ss:[esp+39] ; 假注册码的首地址送ESI
004012B3 5D pop ebp
004012B4 8A46 FF mov al,byte ptr ds:[esi-1] ; 逐位送AL,如果是数字,非数字……进行相应的加减处理
004012B7 3C 30 cmp al,30
004012B9 72 08 jb short CrackMe_.004012C3
004012BB 3C 39 cmp al,39
004012BD 77 04 ja short CrackMe_.004012C3
004012BF 2C 30 sub al,30
004012C1 EB 02 jmp short CrackMe_.004012C5
004012C3 2C 37 sub al,37
004012C5 8AD8 mov bl,al
004012C7 884414 34 mov byte ptr ss:[esp+edx+34],al
004012CB C0E3 04 shl bl,4
004012CE 885C14 34 mov byte ptr ss:[esp+edx+34],bl
004012D2 8A06 mov al,byte ptr ds:[esi]
004012D4 3C 30 cmp al,30
004012D6 8ACB mov cl,bl
004012D8 72 08 jb short CrackMe_.004012E2
004012DA 3C 39 cmp al,39
004012DC 77 04 ja short CrackMe_.004012E2
004012DE 2C 30 sub al,30
004012E0 EB 02 jmp short CrackMe_.004012E4
004012E2 2C 37 sub al,37
004012E4 0AC1 or al,cl
004012E6 83C6 02 add esi,2
004012E9 884414 34 mov byte ptr ss:[esp+edx+34],al
004012ED 42 inc edx
004012EE 83FA 10 cmp edx,10 ; 在这个循环里对假注册码进行32变16的处理,实际上就是两位一组,当作某字符的ASCII码
004012F1 ^ 72 C1 jb short CrackMe_.004012B4
004012F3 33C0 xor eax,eax
004012F5 8B5404 10 mov edx,dword ptr ss:[esp+eax+10] ; 开始比较真假注册码,这里是真注册码
004012F9 8B4C04 34 mov ecx,dword ptr ss:[esp+eax+34] ; 这里是假注册码
004012FD 33D1 xor edx,ecx ; 异或结果为零,说明两数相等,OK
004012FF ^ 0F85 E0FEFFFF jnz CrackMe_.004011E5 ; 否则Good bye
00401305 83C0 04 add eax,4 ; 加4
00401308 83F8 10 cmp eax,10 ; 直到等于16
0040130B ^ 7C E8 jl short CrackMe_.004012F5
0040130D 5F pop edi
0040130E 5E pop esi
0040130F B8 01000000 mov eax,1 ; 如果正情形发展正常的话,就给注册标志EAX赋值1,
00401314 5B pop ebx
00401315 81C4 F0000000 add esp,0F0
0040131B C3 retn
@特别注明@子过程:
===========================================================================
00401320 8B4424 04 mov eax,dword ptr ss:[esp+4]------分组后的注册名,我称它为:reg
00401324 56 push esi
00401325 8DB0 DC23B19D lea esi,dword ptr ds:[eax+9DB123DC]--加上0x9DB123DC,我称它为:sum
0040132B 8BCE mov ecx,esi
0040132D 33C8 xor ecx,eax--------------再与自身,即reg异或,我称它为:xor
0040132F 8BD1 mov edx,ecx
00401331 F7D2 not edx----------------然后再取反,我称它为not
00401333 03D6 add edx,esi--------------加上sum
00401335 40 inc eax----------------inc(reg)
00401336 0FAFC2 imul eax,edx--------------然后imul not
00401339 03C1 add eax,ecx--------------加上 xor
0040133B 03C6 add eax,esi--------------加上 sum
0040133D 5E pop esi
0040133E C3 retn------------------返回处理结果在EAX中
============================================================================= 给出一组有效注册码:
name:wofan
code:04D1321D41615ED9BEA2DDAF958839DB
19:23 2006-12-1
by wofan[OCN]
QQ:339171218
快调试玩的时候,突然停电,靠!多亏我因为注册码长度不够时,重新载入过一回!
凭记忆,填充了一些注释。
本Crackme属于超级简单的一类,不知这是HappyTown 的那一个系列。怎么就排到了33??
33对我来说是个吉祥数,所以就玩一下了。
如果确实需要,改日补写注册机。
看到有人关注这个Crackme,还是补上注册机源码吧。
//=============================================================//
//=====做一个给自已使用的 Delphi版本的注册机模板 ==============//
//========= wofan[OCN][PYG][DCG] 2006-10-28 ==================//
//=============================================================//
program Keygen;
uses
windows,
SysUtils,//用来支持:File_Dir:=ExtractFilePath(paramStr(0)); //提取程序所在目录
ShellAPI, //仅仅是用它来支持链接
Messages;
{$R KeygenRc.RES}
var
Cap_Rect:TRECT; //标题栏RECT,需要保存备用(移动Form),定义为全局变量
h_BRUSH:HBRUSH; //画刷标题栏的画刷
h_BRUSH_2:HBRUSH; //画边框的画刷
File_Dir:String; //该程序所在目录
h_Cur:HCURSOR; //动画光标句柄
L_Cur:HCURSOR; //链接用的光标
h_Icon:HICON; //图标句柄
mName:array[0..255] of byte; //注册名
mCode:array[0..31] of byte; //注册码
//===============================================================
Const
//===============================================================
IDD_MAIN=101; //主对话框控件
IDB_BMP=102; //位图资源ID-看雪学院
IDI_ICON=103; //图标资源ID-[OCN]
IDC_Cur=104; //链接用的光标
//----------------------------------------------
IDC_ICON=1000; //装载图标的图像控件
IDC_N =1001; //注册名Label
IDC_Name =1002; //注册名 Edit
IDC_C=1003; //注册码Label
IDC_Code=1004; //注册码 Edit
IDC_wofan=1005; //破解人 Label
IDC_Time=1006; //破解时间 Label
IDC_OK=1007; //确定按钮
IDC_About=1008; //关于按钮
IDC_Cancel=1009; //取消按钮
IDC_Close=1010; //标题栏上的关闭按扭
IDC_BMP= -1; //装载位图的控件
//===============================================================
//=======================以下资源在发布时即时修改========================
//------------------------------------------------------------------------
AboutText='本Keygen模板由wofan[OCN]制作'+#13+'这是HappyTown系列Crackme的注册机之33'; //关于Messagebox的Text
AboutTitle='wofan[OCN]'; //MessageBox的Title
MainCaption='kgme.HT.vc.0033'; //主对话框的Caption
Time='2006-10-29'; //发布时间
Author='wofan[OCN]'; //发布者名号
//------------------------------------------------------------------------
//=======================================================================
//-----------------------------------------------------------------------
//============= 函数,过程,回调函数 ==================================
//=======================================================================
//=======================================================================
procedure child; //处理注册名的子过程,是一个完全独立的过程,所以,抄过来得了
begin
asm
push esi //esi,和ecx 的值要用,压栈保护一下
push ecx
lea esi,dword ptr ds:[eax+9DB123DCh]
mov ecx,esi
xor ecx,eax
mov edx,ecx
not edx
add edx,esi
inc eax
imul eax,edx
add eax,ecx
add eax,esi
pop ecx
pop esi
end;
end;
procedure sort;
begin
asm
mov eax,dword ptr ds:[esi+4]
mov ebx,dword ptr ds:[esi+8]
mov edx,dword ptr ds:[esi+12]
mov dword ptr ds:[esi+4],edx
mov dword ptr ds:[esi+8],ebx
mov dword ptr ds:[esi+12],eax
end;
end;
procedure wofanKeygen(hdlg:HWND);
var
Title,text:string;
var
tmp:array[0..3] of dword;
Begin
Title:='提示';
Text:='注册名至少3位!';
ZeroMemory(@mName,sizeof(mName));
zeroMemory(@mCode,sizeof(mCode));
GetDlgItemText(hDlg,IDC_Name,@mName,sizeof(mName));
asm
LEA ESI,mName //把注册名的地址传到ESI
cmp eax,3 //EAX 是GetDlgItemText函数返回值,它是字串实际长度
Jl @Err //注册名长度至少3位
cmp eax,16
jnb @next
@patch: //如果注册名长度不够16位,则补充为16位。注册名只处理前16位。
mov cl,al
add cl,21h
mov byte ptr ds:[esi+eax],cl
inc eax
cmp eax,16
jb @patch
@next:
call sort //调整注册名字符的位置,先分成四组,然后按1,4,3,2的顺序放置
xor ecx,ecx //==============循环四次处理注册名
lea edi,tmp //常数,以下是对常数进行初始化存放
mov dword ptr ds:[edi],0BB2971FDh
mov dword ptr ds:[edi+4],0A1385370h
mov dword ptr ds:[edi+8],0A6D6231Dh
mov dword ptr ds:[edi+12],0BDE1DAC8h
@cal:
mov eax,dword ptr ds:[esi+ecx*4] //注册名
call child //计算分组后的注册名
mov edx,dword ptr ds:[edi+ecx*4] //取出对应常数
add edx,eax //加起相应注册名算出的结果
mov dword ptr ds:[edi+ecx*4],edx //保存相应结果
inc ecx
cmp ecx,4 //======循环四次处理注册名
jb @cal
mov esi,edi
call sort //再次重排注册码
lea edi,mCode //=======注册码存放的地址 ,开始生成注册码的字符
mov ecx,16
@rrep:
mov al,byte ptr ds:[esi]
mov bl,al
shr bl,4
cmp bl,9
jbe @num
add bl,37h //如果是字符,加上37H
jmp @result
@num:
add bl,30h //是纯数字0..9之间,加上30H
@result:
mov byte ptr ds:[edi],bl
and al,0fh
cmp al,9
jbe @num2
add al,37h
jmp @result2
@num2:
add al,30h
@result2:
mov byte ptr ds:[edi+1],al
inc esi
add edi,2
dec ecx
jnz @rrep //=====================================
jmp @End
@Err:
push 0
MOV EAX,DWORD PTR SS:[Title]
PUSH EAX
MOV EAX,DWORD PTR SS:[Text]
PUSH EAX
PUSH MB_OK
Call MessageBox //提示:注册名长度至少要3位
@End:
End; //End ASM
End;
//=======================================================================
//=======================================================================
//=======================================================================
Function LinkProc(LinkCtl:HWND;uMsg,wParam,lParam:DWORD):LRESULT;stdcall;
Begin
Result:=0;
Case uMsg of
WM_SETCURSOR:
Begin
SetCursor(L_Cur);
End;
WM_NCHITTEST:
Begin
Result:=1;
End;
WM_LBUTTONUP:
Begin
ShellExecute(0,nil,'http://www.pediy.com',nil,nil,0);//链接到:看雪学院
End
else
Begin
CallWindowProc(Pointer(GetWindowLong(LinkCtl,GWL_USERDATA)),LinkCtl,uMsg,wParam,lParam);
End;
end;
End; procedure MoveToCentre(hDlg:HWND); //窗口启动中在屏幕中心显示
Var
D_Rect:TRECT; //本程序的RECT
S_Rect:Trect; //DeskTop 的RECT,实际上就是SCREEN了。
S_Hwnd:HWND; //DeskTop 的句柄
Begin
GetWindowRECT(hDlg,D_Rect);
S_Hwnd:=GetDesktopwindow;
GetWindowRect(s_Hwnd,S_Rect);
moveWindow(hDlg,(S_Rect.right-D_Rect.Right)div 2 ,(S_Rect.Bottom-D_Rect.Bottom ) div 2,D_Rect.Right ,D_Rect.Bottom,true);
End;
Function GetOS:string;
var
OS: OSVERSIONINFO;
OS_Str:string;
begin
ZeroMemory(@OS,sizeof(OS));
OS.dwOSVersionInfoSize :=sizeof(OSVERSIONINFO);
GetVerSionEx(OS);
OS_Str:='你使用非Windows操作系统';
if (OS.dwPlatformId = VER_PLATFORM_WIN32_NT) and
(OS.dwMajorVersion = 5) and (OS.dwMinorVersion =1)
then OS_str:='你使用WinXP'+' '+OS.szCSDVersion;
if (OS.dwPlatformId = VER_PLATFORM_WIN32_NT) and
(OS.dwMajorVersion = 5) and
(OS.dwMinorVersion =0)
then OS_str:='你使用Win2K'+' '+OS.szCSDVersion;
if (OS.dwPlatformId = VER_PLATFORM_WIN32_NT) and
(OS.dwMajorVersion = 4)
then OS_str:='你使用WinNT'+' '+OS.szCSDVersion;
if (OS.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS)
then OS_str:='你使用Win9X'+' '+OS.szCSDVersion;
Result:=OS_str;
end;
Procedure DialogInit(hDlg:HWND);
Begin
SetWindowText(hDlg,mainCaption);
SetDlgItemText(hDlg,IDC_Time,Time);
SetDlgItemText(hDlg,IDC_wofan,Author);
SetDlgItemText(hDlg,IDC_Name,Pchar('wofan[OCN][PYG][DCG]'));
if h_Cur<>0 then
Begin
SetClassLong(hDlg,GCL_HCURSOR,h_Cur); //设置动画光标
SetClassLong(GetDlgItem(hDlg,IDC_Name),GCL_HCURSOR,h_Cur); //各个控件有同样的光标
SetClassLong(GetDlgItem(hDlg,IDC_Code),GCL_HCURSOR,h_Cur);
SetClassLong(GetDlgItem(hDlg,IDC_OK),GCL_HCURSOR,h_Cur);
SetClassLong(GetDlgItem(hDlg,IDC_About),GCL_HCURSOR,h_Cur);
SetClassLong(GetDlgItem(hDlg,IDC_Cancel),GCL_HCURSOR,h_Cur);
End;
SendMessage(hDlg,WM_SETICON,ICON_SMALL,h_Icon);//设置图标 ,ICON_SMALL=0 ICON_Big=1, ICON_Small2=2
setfocus(getDlgItem(hDlg,IDC_Name)); //使注册名的Edit控件获得焦点
End;
Function MainProc(hDlg:HWND;uMsg,wParam,lParam:DWORD):LRESULT;stdcall; //加上stdcall 这是回调函数
var
sPaint:PaintStruct; //用来获取DC
Cap_PT:TPOINT; //点结构,用来保存鼠标点击位置,确定是否可以移动Form
DC:HDC; //场景句柄
LinkHwnd:HWND; //链接
SetLongRet:LONGINT; //链接
Begin
Result:=0; //初始化函数返回值,返回零
Case uMsg of
WM_INITDIALOG:
Begin
DialogInit(hDlg);
MoveToCentre(hDlg);
LinkHwnd:=GetDlgItem(hDlg,IDC_BMP);
SetLongRet:=SetWindowLong(LinkHWND,GWL_WNDPROC,Longword(@LinkProc));
SetWindowLong(LinkHWND,GWL_USERDATA,SetLongRet);
End;
WM_LBUTTONDOWN:
Begin
Cap_PT.X:=lParam and $FFFF;
Cap_PT.Y:=lParam SHR 16;
if PTInRect(Cap_Rect,Cap_PT) then
Begin
PostMessage(hDlg,WM_NCLBUTTONDOWN,HTCAPTION,0); //转换消息,单击Form如同单击标题栏
End;
End;
WM_Paint:
Begin
GetClientRect(hDlg,Cap_Rect);
DC:=BeginPaint(hDlg,sPaint);
FrameRect(DC,Cap_Rect,h_Brush_2); //画外框
Cap_Rect.Bottom:=Cap_Rect.Top+25;
Cap_Rect.Left:=Cap_Rect.Left+2;
Cap_Rect.Top:=Cap_Rect.Top+2;
Cap_Rect.Right :=Cap_Rect.Right -2;
FillRect(DC,Cap_Rect,h_Brush); //填充标题栏
if h_Icon<>0 Then
Begin
DrawIconEx(DC,4,4,h_Icon,$10,$10,0,0,3);
End;
SetBKMode(DC,TRANSPARENT); //设置背景透明,标题栏的画出的文字背景色不再是难看的白色
DrawText(DC,MainCaption,-1,Cap_Rect,DT_CENTER OR DT_SINGLELINE OR DT_VCENTER); //居中单行绘制文本
EndPaint(hDlg,sPaint);
End;
WM_COMMAND:
Begin
Case wParam and $FFFF of
IDC_OK:
Begin
wofanKeygen(hDlg);
SetDlgItemText(hdlg,IDC_Code,@mCode);
End;
IDC_About:
Begin
MessageBox(hDlg,pchar(AboutText+#13+GetOS),AboutTitle,MB_OK or MB_ICONINFORMATION);
End;
IDC_Cancel:
Begin
EndDialog(hDlg,0);
End;
IDC_Close:
Begin
EndDialog(hDlg,0);
End;
IDC_Name:
Begin
Case wParam shr 16 of
EN_CHANGE:
Begin
wofanKeygen(hDlg);
SetDlgItemText(hdlg,IDC_Code,@mCode);
End;
End; //end---wParam shr 16 of---- case
End; //End ----IDC_Name ----Begin
End; //End----WM_Command----Case
End; //End ----WM_Command---- Begin
End; //End ---Umsg----case
End; //End -----Function
Begin
h_Brush:=CreateSolidBrush($C0C0D0); //这里可以设置画刷
h_Brush_2:=CreateSolidBrush($1F1F1F);
File_Dir:=ExtractFilePath(paramStr(0)); //提取程序所在目录
h_Cur:=loadCursorFromFile(pchar(file_Dir+'[OCN]Mouse.ani'));
L_Cur:=LoadCursor(hInstance,MakeintResource(IDC_Cur));
h_Icon:=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON));
DialogBox(hInstance,LPCTSTR(IDD_MAIN),0,@MainProc);
DeleteObject(h_Brush);
DeleteObject(h_Brush_2);
ExitProcess(0);
End.
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: