Delphi逆向工程筆記[6]――關於String區域性變數

看雪資料發表於2004-11-15

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;
=========================================================================非

相關文章