Delphi逆向工程笔记[6]
先废话一会。本来这篇东西昨天晚上写好的,但是打算发时发现论坛上不去了。一直到刚才才打开。不知道是不是被dos了,还是检修什么的……
==================================================================
下面处理MainProc。规矩照旧。
0000:00404A44 sub_404A44 proc near
0000:00404A44
0000:00404A44 Paint = PAINTSTRUCT ptr -4Ch
0000:00404A44 wParam = dword ptr -0Ch
//这里看起来是个callback的参数,但实际上是一个HFONT。这从下面对
//WM_INITDIALOG的分析可以看到。
0000:00404A44 pt = POINT ptr -8
0000:00404A44 hWnd = dword ptr 8
0000:00404A44 arg_4 = dword ptr 0Ch
0000:00404A44 arg_8 = dword ptr 10h
0000:00404A44 arg_C = word ptr 14h
0000:00404A44
0000:00404A44 push ebp
0000:00404A45 mov ebp, esp
0000:00404A47 add esp, 0FFFFFFB4h
0000:00404A4A push ebx
0000:00404A4B push esi
0000:00404A4C push edi
0000:00404A4D mov esi, [ebp+hWnd]
0000:00404A50 xor ebx, ebx
0000:00404A52 mov eax, [ebp+arg_4]
0000:00404A55 cmp eax, 133h ; WM_CTLCOLOREDIT
0000:00404A5A jg short loc_404A87
0000:00404A5C jz loc_404CB3
0000:00404A62 sub eax, 0Fh ; WM_PAINT
0000:00404A65 jz loc_404BD6
0000:00404A6B sub eax, 1Ch ; WM_DRAWITEM
0000:00404A6E jz loc_404C86
0000:00404A74 sub eax, 0E5h ; WM_INITDIALOG
0000:00404A79 jz short loc_404AAB
0000:00404A7B dec eax ; WM_COMMAND
0000:00404A7C jz loc_404C0B
0000:00404A82 jmp loc_404CF5
0000:00404A87 loc_404A87:
0000:00404A87 sub eax, 136h ; WM_CTLCOLORDLG
0000:00404A8C jz loc_404C92
0000:00404A92 sub eax, 2 ; WM_CTLCOLORSTATIC
0000:00404A95 jz loc_404CD4
0000:00404A9B sub eax, 0C9h ; WM_LBUTTONDOWN
0000:00404AA0 jz loc_404B95
0000:00404AA6 jmp loc_404CF5
0000:00404CF5 loc_404CF5:
0000:00404CF5 xor ebx, ebx
0000:00404CF7 loc_404CF7:
0000:00404CF7 mov eax, ebx
0000:00404CF9 pop edi
0000:00404CFA pop esi
0000:00404CFB pop ebx
0000:00404CFC mov esp, ebp
0000:00404CFE pop ebp
0000:00404CFF retn 10h
0000:00404CFF sub_404A44 endp
于是有:
Function MainProc(hDlg:HWND;Msg,wParam,lParam:DWORD):LRESULT;stdcall;
Var
sPaint:PAINTSTRUCT;
sPoint:TPoint;
LFont:HFONT;
Begin
Result:=0;
Case Msg of
WM_COMMAND:
Begin
End;
WM_PAINT:
Begin
End;
WM_DRAWITEM:
Begin
End;
WM_INITDIALOG:
Begin
End;
WM_CTLCOLORDLG:
Begin
End;
WM_CTLCOLORSTATIC:
Begin
End;
WM_LBUTTONDOWN:
Begin
End;
WM_CTLCOLOREDIT:
Begin
End;
End;
End;
由于这里和LicenseProc总体差别不大,所以就把大致相同或比较简单的部分直
接给出,不一一分析了。
WM_CTLCOLOREDIT:
Begin
SetTextColor(wParam,$A0A0A0);
SetBkMode(wParam,TRANSPARENT);
Result:=h_Brush;
End;
WM_PAINT:
Begin
Paint(BeginPaint(hDlg,sPaint),h_Icon,szMainCaption,$767676,0,sRECTM);
EndPaint(hDlg,sPaint);
End;
WM_DRAWITEM:
Begin
ItemDraw(PDrawItemStruct(lParam));
Result:=0;
End;
WM_CTLCOLORDLG:
Begin
SetTextColor(wParam,$A0A0A0);
SetBkMode(wParam,TRANSPARENT);
Result:=h_Brush;
End;
WM_CTLCOLORSTATIC:
Begin
SetTextColor(wParam,$A0A0A0);
SetBkMode(wParam,TRANSPARENT);
Result:=h_Brush;
End;
WM_LBUTTONDOWN:
Begin
sPoint.x:=lParam AND $FFFF;
sPoint.y:=lParam SHR 16;
If PtInRect(sRectM,sPoint) Then
Begin
PostMessage(hDlg,WM_NCLBUTTONDOWN,2,0);
End;
End;
WM_COMMAND:
Begin
Case wParam of
MAIN_CALC:
Begin
GetDlgItemText(hDlg,$7DA,@RegName,255);
GetRegCode;
SetDlgItemText(hDlg,$7D9,@RegCode);
End;
MAIN_EXIT:
Begin
EndDialog(hDlg,0);
End;
MAIN_about :
Begin
MessageBeep(0);
DialogBox(h_Inst,LPCTSTR(IDD_ABOUTDLG),0,@AboutProc);
End;
MAIN_CLOSE:
Begin
EndDialog(hDlg,0);
End;
End;
End;
注意,MAIN_CALC的处理,特别是GetRegCode,肯定和原文不同(个人爱好)。原
文是带一个PChar参数的。
余下的部分就是WM_INITDIALOG和关于对话框部分了。
先反WM_INITDIALOG:
000:00404AAB loc_404AAB:
0000:00404AAB push offset stru_4060DC ; lpRect
//这里和LicenseProc一样,都用了全局的Rect。当时没有反到这里,所以名字取得
//不是很好。
0000:00404AB0 push esi ; hWnd
0000:00404AB1 call GetClientRect
0000:00404AB6 mov eax, ds:stru_4060DC.top
0000:00404ABB add eax, 14h
0000:00404ABE mov ds:stru_4060DC.bottom, eax
0000:00404AC3 push offset dword_404D04 ; lpString
0000:00404AC8 push 7DBh ; nIDDlgItem
0000:00404ACD push esi ; hDlg
0000:00404ACE call SetDlgItemTextA
//主页连接
0000:00404AD3 push offset loc_404D1C ; lpString
0000:00404AD8 push 7D8h ; nIDDlgItem
0000:00404ADD push esi ; hDlg
0000:00404ADE call SetDlgItemTextA
//时间
0000:00404AE3 push (offset loc_404D25+3) ; lpString
//这里的话,其实是IDA在发飚。因为所谓的loc_404D25根本不是什么代码,而是常
//量。误判。
0000:00404AE8 push 7D5h ; nIDDlgItem
0000:00404AED push esi ; hDlg
0000:00404AEE call SetDlgItemTextA
//软件名
0000:00404AF3 push offset dword_404D38 ; lpString
0000:00404AF8 push 7D6h ; nIDDlgItem
0000:00404AFD push esi ; hDlg
0000:00404AFE call SetDlgItemTextA
//开发者
0000:00404B03 push offset dword_404D4C ; lpString
0000:00404B08 push 7D7h ; nIDDlgItem
0000:00404B0D push esi ; hDlg
0000:00404B0E call SetDlgItemTextA
//解密者
0000:00404B13 push offset dword_404D5C ; lpString
0000:00404B18 push 7DCh ; nIDDlgItem
0000:00404B1D push esi ; hDlg
0000:00404B1E call SetDlgItemTextA
//KeyGen的版权所有者
0000:00404B23 push offset dword_404D84 ; lpString
0000:00404B28 push esi ; hWnd
0000:00404B29 call SetWindowTextA
//窗口的标题
0000:00404B2E push offset nullsub_4 ; LPCSTR
//发飚
0000:00404B33 push 0 ; DWORD
0000:00404B35 push 0 ; DWORD
0000:00404B37 push 0 ; DWORD
0000:00404B39 push 0 ; DWORD
0000:00404B3B push 1 ; DWORD
0000:00404B3D push 0 ; DWORD
0000:00404B3F push 1 ; DWORD
0000:00404B41 push 0 ; DWORD
0000:00404B43 push 2BCh ; int
0000:00404B48 push 0 ; int
0000:00404B4A push 0 ; int
0000:00404B4C push 0 ; int
0000:00404B4E push 0FFFFFFF4h ; int
0000:00404B50 call CreateFontA
0000:00404B55 mov [ebp+wParam], eax
//没什么说的
0000:00404B58 push 7DBh ; nIDDlgItem
0000:00404B5D push esi ; hDlg
0000:00404B5E call GetDlgItem
//这里是从ID得到HWND
0000:00404B63 mov edi, eax
0000:00404B65 push 0 ; lParam
0000:00404B67 mov eax, [ebp+wParam]
0000:00404B6A push eax ; wParam
0000:00404B6B push 30h ; Msg
0000:00404B6D push edi ; hWnd
0000:00404B6E call SendMessageA
//设置字体
0000:00404B73 push offset sub_4043FC ; dwNewLong
0000:00404B78 push 0FFFFFFFCh ; nIndex
0000:00404B7A push edi ; hWnd
0000:00404B7B call SetWindowLongA
0000:00404B80 push eax ; dwNewLong
0000:00404B81 push 0FFFFFFEBh ; nIndex
0000:00404B83 push edi ; hWnd
0000:00404B84 call SetWindowLongA
//设置超连接效果callback
0000:00404B89 mov eax, esi ; hWnd
0000:00404B8B call sub_404358
//其实就是LicenseProc最后的那个call
0000:00404B90 jmp loc_404CF7
超连接的callback:
0000:004043FC sub_4043FC proc near
0000:004043FC
0000:004043FC hWnd = dword ptr 8
0000:004043FC arg_4 = dword ptr 0Ch
0000:004043FC wParam = dword ptr 10h
0000:004043FC lParam = dword ptr 14h
0000:004043FC
0000:004043FC push ebp
0000:004043FD mov ebp, esp
0000:004043FF push ebx
0000:00404400 push esi
0000:00404401 mov ebx, [ebp+arg_4]
0000:00404404 mov esi, 1
//现在esi是返回值,下面可以看到
0000:00404409 mov eax, ebx
0000:0040440B sub eax, 20h
//WM_SETCURSOR
0000:0040440E jz short loc_404439
0000:00404410 sub eax, 64h
//WM_NCHITTEST
0000:00404413 jz short loc_404432
0000:00404415 sub eax, 17Eh
//WM_LBUTTONUP
0000:0040441A jnz short loc_404446
//还不是就去缺省处理
0000:0040441C push 0 ; nShowCmd
0000:0040441E push 0 ; lpDirectory
0000:00404420 push 0 ; lpParameters
0000:00404422 push offset dword_40446C ; lpFile
0000:00404427 push 0 ; lpOperation
0000:00404429 push 0 ; hwnd
0000:0040442B call ShellExecuteA
0000:00404430 jmp short loc_404464
0000:00404432
0000:00404432 loc_404432:
0000:00404432 mov esi, 1
0000:00404437 jmp short loc_404464
0000:00404439
0000:00404439 loc_404439:
0000:00404439 mov eax, ds:hCursor
0000:0040443E push eax ; hCursor
0000:0040443F call SetCursor
0000:00404444 jmp short loc_404464
0000:00404446
0000:00404446 loc_404446:
0000:00404446 push 0FFFFFFEBh ; nIndex
0000:00404448 mov eax, [ebp+hWnd]
0000:0040444B push eax ; hWnd
0000:0040444C call GetWindowLongA
0000:00404451 mov edx, [ebp+lParam]
0000:00404454 push edx ; lParam
0000:00404455 mov edx, [ebp+wParam]
0000:00404458 push edx ; wParam
0000:00404459 push ebx ; Msg
0000:0040445A mov edx, [ebp+hWnd]
0000:0040445D push edx ; hWnd
0000:0040445E push eax ; lpPrevWndFunc
0000:0040445F call CallWindowProcA
0000:00404464
0000:00404464 loc_404464:
0000:00404464 mov eax, esi
0000:00404466 pop esi
0000:00404467 pop ebx
0000:00404468 pop ebp
0000:00404469 retn 10h
0000:00404469 sub_4043FC endp
PS:其实这个函数在laoqian的文章里有,是他写的。不过这里还是逆一下。那
么,下面就给出WM_INITDIALOG和LinkProc:
WM_INITDIALOG:
Begin
GetClientRect(hDlg,sRectM);
sRectM.Bottom:=sRectM.Top+$14;
SetDlgItemText(hDlg,2011,szLink);
SetDlgItemText(hDlg,2008,szTime);
SetDlgItemText(hDlg,2005,szName);
SetDlgItemText(hDlg,2006,szBy);
SetDlgItemText(hDlg,2007,szCracker);
SetDlgItemText(hDlg,2012,szCopyright);
SetWindowText(hDlg,szMainCaption);
LFont:=CreateFont(-$C,0,0,0,$2BC,0,1,0,1,0,0,0,0,'宋体');
LinkHWND:=GetDlgItem(hDlg,2011);
SendMessage(LinkHWND,WM_SETFONT,LFont,0);//设置字体
SetLongRet:=SetWindowLong(LinkHWND,GWL_WNDPROC,LongWord(@LinkProc));
SetWindowLong(LinkHWND,GWL_USERDATA,SetLongRet);
DialogInit(hDlg);
End;
Function LinkProc(hDlg:HWND;Msg,wParam,lParam:DWORD):LRESULT;stdcall;
Begin
Result:=1;
Case Msg of
WM_SETCURSOR:
Begin
SetCursor(h_Cur);
End;
WM_NCHITTEST:
Begin
Result:=1;
End;
WM_LBUTTONUP:
Begin
ShellExecute(0,nil,szLink,nil,nil,0);//偷了点懒
End;
Else
Begin
CallWindowProc(Pointer(GetWindowLong(hDlg,GWL_USERDATA)),hDlg,Msg,wParam,lParam);
End;
End;
End;
还好有IDA,要不对照xRef肯定累死。
OK,还剩下最后的About对话框。请耐心等待,最迟不超过2周!
补充:
1、如果AboutProc为空,那么整个MainDLG都显示不正常的。
2、laoqian说没有逆出实时显示注册码部分。这是因为我分析的版本是老的,不
是那个2in1。所以里面没有实时显示的部分。新版一时找不到。不过恰好我以前写过
一个SDK程序,里面用到了Notification。所以,我还是自己写吧:
要实时显示注册码,就必须监测Edit内容的改变。这是被称为Notification的。
写过相关程序的人都知道,当菜单的某项被选中,一个子控件向父窗口发送一个
Notification,或者快捷键被按时,事件处理程序就会接到WM_COMMAND消息。这时,
wParam的低16位指明了菜单/子控件/快捷键的ID,而高16位则在wParam的低16位指明
了子控件的时候,存放Notification。就是说,判断ID时应该使用wParam的低位。但
是一般我们见到的KeyGen模板都是直接用wParam的。那么高位呢?原因是:一般情况
下,我们只用到了Button和Label。但是在Button的Notification里有以下一条定义:
{ Button Notification Codes }
const
{$EXTERNALSYM BN_CLICKED}
BN_CLICKED = 0;
这样,如果只是简单地按个按钮,Notification为BN_CLICKED,wParam就肯定等
于ID了。
下面就是修改的代码:
Case wParam AND $FFFF of
$7DA://就是RegName的ID,感觉越来越懒了……
Begin
Case wParam SHR 16 of
EN_CHANGE:
Begin
GetDlgItemText(hDlg,$7DA,@RegName,255);
GetRegCode;
SetDlgItemText(hDlg,$7D9,@RegCode);
End;
End;
End;
End;
=========================================================================非