Delphi逆向工程筆記[3]

看雪資料發表於2004-10-27

抱歉,剛才把沒有整理完全的發了。

=================================================================================

  下面處理WM_INITDIALOG。

0000:00404E2B loc_404E2B:
0000:00404E2B                 push    offset sRect    ; lpRect
//注意,這裡是我手動改名的結果。
//sRect是一個全域性變數,這從下面對它的引用也可以看出來。
0000:00404E30                 mov     eax, [ebp+hWnd]
0000:00404E33                 push    eax             ; hWnd
0000:00404E34                 call    GetClientRect
//這裡沒有什麼好說的。
0000:00404E39                 mov     eaxds:sRect.top
0000:00404E3E                 add     eax, 14h
0000:00404E41                 mov     ds:sRect.bottom, eax
//這裡好象是得到一個新的RECT,高度是14。估計是一個標題欄。
因為程式沒有用系統的標題欄,而是自己畫了一個。
0000:00404E46                 push    offset word_404F98 ; lpString
0000:00404E4B                 mov     eax, [ebp+hWnd]
0000:00404E4E                 push    eax             ; hWnd
0000:00404E4F                 call    SetWindowTextA
0000:00404E54                 push    offset aBbbbA   ; lpString
0000:00404E59                 push    3EDh            ; nIDDlgItem
0000:00404E5E                 mov     eax, [ebp+hWnd]
0000:00404E61                 push    eax             ; hDlg
0000:00404E62                 call    SetDlgItemTextA
//授權協議。但奇怪的是協議本身可以看到,那個標題看不到。
//懷疑是目前rip出的程式碼不完整,缺了WM_PAINT和WM_DRAWITEM。
0000:00404E67                 mov     eax, [ebp+hWnd] ; hWnd
0000:00404E6A                 call    sub_404358
//這是一個奇怪的call,從其程式碼可以看到,eax是入口引數。
//而且它是一個公用子程式。
0000:00404E6F                 mov     ebx, 1
//這裡就必須返回1說明訊息已經處理了。
0000:00404E74                 jmp     loc_404F8F

  OK,下面就是WM_INITDIALOG了:

    WM_INITDIALOG:
      Begin
        GetClientRect(hDlg,sRect);
        sRect.Bottom:=sRect.Top+$14;
        SetWindowText(hDlg,szLicenseCaption);
        SetDlgItemText(hDlg,1005,szLicenseText);
        DialogInit(hDlg);
        //暫且叫這個名字吧。
        Result:=1;
      End;

  好,來看看那個奇怪的call:

0000:00404358 ; int __fastcall sub_404358(HWND hWnd)
0000:00404358 sub_404358      proc near
0000:00404358
0000:00404358
0000:00404358 X               = word ptr -14h
0000:00404358 Y               = word ptr -12h
0000:00404358 Rect            = tagRECT ptr -10h
//這些區域性變數也被改名了,目的是便於閱讀分析。
0000:00404358
0000:00404358                 push    ebx
0000:00404359                 push    esi
0000:0040435A                 push    edi
0000:0040435B                 push    ebp
0000:0040435C                 add     esp, 0FFFFFFECh
//這裡相當於sub esp,14h。真不知道Borland那幫人是怎麼想的。
//實際上,如果後面沒有push,這句就是多餘的。這是編譯器最佳化的結果。
//PS:記得TP裡是用bp做Local指標的。
0000:0040435F                 mov     edieax
0000:00404361                 push    0               ; nCmdShow
0000:00404363                 push    edi             ; hWnd
0000:00404364                 call    ShowWindow
0000:00404369                 lea     eax, [esp+14h+Rect]
//esp+14h,明白了?
0000:0040436D                 push    eax             ; lpRect
0000:0040436E                 push    edi             ; hWnd
0000:0040436F                 call    GetWindowRect
0000:00404374                 mov     eax, [esp+14h+Rect.right]
//因為API是自己處理esp,所以這裡依然是+14h
0000:00404378                 mov     edxeax
0000:0040437A                 sub     edx, [esp+14h+Rect.left]
0000:0040437E                 sar     edx, 1
0000:00404380                 jns     short loc_404385
0000:00404382                 adc     edx, 0
//OK,這裡其實就是取Rect的X軸方向中點。
//sar移過以後,最高位是保持原來的,所以要判斷一下,如果<0就
//加回來。這個組合比較巧妙。
//Borland那幫人確實與眾不同!
0000:00404385
0000:00404385 loc_404385:
0000:00404385                 mov     [esp+14h+X], dx
0000:00404389                 mov     edx, [esp+14h+Rect.bottom]
0000:0040438D                 sub     edx, [esp+14h+Rect.top]
0000:00404391                 sar     edx, 1
0000:00404393                 jns     short loc_404398
0000:00404395                 adc     edx, 0
0000:00404398
0000:00404398 loc_404398:
0000:00404398                 mov     [esp+14h+Y], dx
0000:0040439D                 mov     ebpeax
//這裡eax等於Rect.right
0000:0040439F                 sar     ebp, 1
0000:004043A1                 jns     short loc_4043A6
0000:004043A3                 adc     ebp, 0
0000:004043A6
0000:004043A6 loc_4043A6:
0000:004043A6                 test    bpbp
//應該是進一步保證bp>0,結合下面可以看到,bp是迴圈變數
0000:004043A9                 jl      short loc_4043F2
0000:004043AB                 inc     ebp
0000:004043AC                 xor     ebxebx
//因為ebp在迴圈體內沒有用到,所以可以和ebx合併處理
0000:004043AE
0000:004043AE loc_4043AE:
//迴圈體就沒有什麼值得注意的地方了,頂多是注意暫存器的變化
0000:004043AE                 movsx   ecx, [esp+14h+Y]
0000:004043B3                 movsx   eaxbx
0000:004043B6                 add     ecxeax
0000:004043B8                 push    ecx             ; int
0000:004043B9                 movsx   edx, [esp+18h+X]
//因為上面push了一下。所以偏移要修改。當時分析時一時沒看出來
0000:004043BE                 mov     ecxedx
0000:004043C0                 add     ecxeax
0000:004043C2                 push    ecx             ; int
0000:004043C3                 movsx   ecx, [esp+1Ch+Y]
//這裡也是
0000:004043C8                 sub     ecxeax
0000:004043CA                 push    ecx             ; int
0000:004043CB                 sub     edxeax
0000:004043CD                 push    edx             ; int
0000:004043CE                 call    CreateRectRgn
0000:004043D3                 mov     esieax
0000:004043D5                 push    0FFFFFFFFh      ; bRedraw
0000:004043D7                 push    esi             ; hRgn
0000:004043D8                 push    edi             ; hWnd
0000:004043D9                 call    SetWindowRgn
0000:004043DE                 push    5               ; nCmdShow
0000:004043E0                 push    edi             ; hWnd
0000:004043E1                 call    ShowWindow
0000:004043E6                 push    esi             ; HGDIOBJ
0000:004043E7                 call    DeleteObject
0000:004043EC                 inc     ebx
0000:004043ED                 dec     bp
0000:004043F0                 jnz     short loc_4043AE
0000:004043F2
0000:004043F2 loc_4043F2:
0000:004043F2                 add     esp, 14h
0000:004043F5                 pop     ebp
0000:004043F6                 pop     edi
0000:004043F7                 pop     esi
0000:004043F8                 pop     ebx
0000:004043F9                 retn
0000:004043F9 sub_404358      endp

  這樣,我們就得到了那個奇怪的call。

Procedure DialogInit(hDlg:HWND);
Var
  RECT:TRect;
  X,Y:Word;
  i:Word;
  Rgn:HRGN;
Begin
  ShowWindow(hDlg,SW_HIDE);
  GetWindowRect(hDlg,RECT);
  X:=(RECT.Right-RECT.Left) DIV 2;
  Y:=(RECT.Bottom-RECT.Top) DIV 2;
  
  For i:=1 to RECT.Right DIV 2 do
    Begin
      Rgn:=CreateRectRgn(X-i,Y-i,X+i,Y+i);
      SetWindowRgn(hDlg,Rgn,True);
      ShowWindow(hDlg,SW_SHOW);
      DeleteObject(Rgn);
    End;
End;

  需要說明的是,這裡在迴圈變數的處理上和原程式不一樣,但是效果應該沒有什麼
差別(起碼我的眼睛沒有好到那樣的程度)。
  這樣,我們已經可以知道那個call是幹什麼的了――視窗的RoomIn特效!(實際
上我是執行了才知道的,呵呵)

==================================================================
這樣,我目前RE出來的部分就發完了。以後再發可能就沒有這麼完整的結構了,而且間隔也會加長。

抱歉,因為我不是專職做這個。

相關文章