• 标 题:Delphi逆向工程笔记[6]——关于String局部变量
  • 作 者:firstrose
  • 时 间:004-11-15,00:34
  • 链 接:http://bbs.pediy.com

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     ebpesp
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     ebxebx
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     ebxebx
0000:00404CF7 loc_404CF7:
0000:00404CF7                 mov     eaxebx
0000:00404CF9                 pop     edi
0000:00404CFA                 pop     esi
0000:00404CFB                 pop     ebx
0000:00404CFC                 mov     espebp
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     eaxds: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     edieax
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     eaxesi        ; 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     ebpesp
0000:004043FF                 push    ebx
0000:00404400                 push    esi
0000:00404401                 mov     ebx, [ebp+arg_4]
0000:00404404                 mov     esi, 1
//现在esi是返回值,下面可以看到
0000:00404409                 mov     eaxebx
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     eaxds: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     eaxesi
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;
=========================================================================非