Delphi逆向工程筆記[4]

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

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

  下面處理WM_LBUTTONDOWN。

0000:00404E79 loc_404E79:
0000:00404E79                 movzx   eax, [ebp+lParam]
//取lParam的低16位,注意它用的是movzx,和下面不同。
//開始靜態分析沒有看出來差別,還是debug了一下才明白。
0000:00404E7D                 mov     [ebp+pt.x], eax
0000:00404E80                 mov     eaxdword ptr [ebp+lParam]
0000:00404E83                 call    sub_403C6C
//這個call實際是取eax的高16位
0000:00404E88                 movzx   eaxax
//截掉廢的bit
0000:00404E8B                 mov     [ebp+pt.y], eax
0000:00404E8E                 push    [ebp+pt.y]
0000:00404E91                 push    [ebp+pt.x]      ; pt
0000:00404E94                 push    offset sRect    ; lprc
0000:00404E99                 call    PtInRect
//這個API有點意思,一般API傳結構都是傳地址,比如sRect,但是它
//傳Point就直接傳值了。以前還真沒有看到這樣的API。
0000:00404E9E                 test    eaxeax
0000:00404EA0                 jz      loc_404F8F
//返回True才繼續
0000:00404EA6                 push    0               ; lParam
0000:00404EA8                 push    2               ; wParam
0000:00404EAA                 push    0A1h ; '?      ; Msg
//碰到這種Msg,應該查出它的名稱。當然直接用值也可以,但是不利於理解
//上面還有2個引數,雖然查到意思,還是不很明白。
0000:00404EAF                 mov     eax, [ebp+hWnd]
0000:00404EB2                 push    eax             ; hWnd
0000:00404EB3                 call    PostMessageA
0000:00404EB8                 jmp     loc_404F8F

0000:00403C6C sub_403C6C      proc near
0000:00403C6C
0000:00403C6C                 shr     eax, 10h
0000:00403C6F                 retn
0000:00403C6F sub_403C6C      endp

  OK,下面就是WM_LBUTTONDOWN的程式碼了:

    WM_LBUTTONDOWN:
      Begin
        sPoint.x:=lParam AND $FFFF;
        sPoint.y:=lParam SHR 16;
        //這裡就不能用Hi和Lo了
        If PtInRect(sRect,sPoint) Then
          Begin
            PostMessage(hDlg,WM_NCLBUTTONDOWN,2,0);
          End;
      End;

  執行一下,效果出來了。雖然還是沒有看到標題欄,但是那個地方點上去已經可以
拖了。
  好,還有2個WM。大概看看,WM_DRAWITEM量比較少,而WM_PAINT寫了一堆。當然先
逆WM_DRAWITEM了。

0000:00404F3F loc_404F3F:
0000:00404F3F                 mov     eaxdword ptr [ebp+lParam]
0000:00404F42                 call    sub_4042AC
//拜託,又是一個公用call。引數就是lParam的值
0000:00404F47                 xor     ebxebx
0000:00404F49                 jmp     short loc_404F8F

0000:004042AC sub_4042AC      proc near
//怎麼知道它是公用的call?很簡單,IDA有ref資訊的。不過我貼的時候去掉了
0000:004042AC
0000:004042AC String          = byte ptr -0Ch
0000:004042AC
0000:004042AC                 push    ebx
0000:004042AD                 add     esp, 0FFFFFFF4h
//sub esp,0CH
0000:004042B0                 mov     ebxeax
//入口引數
0000:004042B2                 mov     eaxds:hbr
0000:004042B7                 push    eax             ; hbr
0000:004042B8                 lea     eax, [ebx+1Ch]
//有麻煩了,ebx到底是什麼?還好Delphi帶的SDK文件很不錯,可以查到
//WM_DRAWITEM的lParam是^DRAWITEMSTRUCT
//另外,注意這裡用了LEA取地址,所以eax=ebx+1ch,是一個地址
//對照Windows.pas裡的定義可以看到它用的定義是const lprc: TRect。
//所以把結構的成員直接寫了沒有問題的,Delphi會自己轉換。
//後面的呼叫也有這個問題,但是Delphi很不錯。用匯編就要自己注意了。
0000:004042BB                 push    eax             ; lprc
0000:004042BC                 mov     eax, [ebx+18h]
0000:004042BF                 push    eax             ; hDC
0000:004042C0                 call    FillRect
0000:004042C5                 push    0A0A0A0h        ; COLORREF
0000:004042CA                 mov     eax, [ebx+18h]
0000:004042CD                 push    eax             ; HDC
0000:004042CE                 call    SetTextColor
0000:004042D3                 push    1               ; int
0000:004042D5                 mov     eax, [ebx+18h]
0000:004042D8                 push    eax             ; HDC
0000:004042D9                 call    SetBkMode
0000:004042DE                 push    0Fh             ; grfFlags
//在SDK裡可以查到是一些值的組合,下面還有。
0000:004042E0                 push    1               ; edge
0000:004042E2                 lea     eax, [ebx+1Ch]
0000:004042E5                 push    eax             ; qrc
0000:004042E6                 mov     eax, [ebx+18h]
0000:004042E9                 push    eax             ; hdc
0000:004042EA                 call    DrawEdge
0000:004042EF                 push    0Ah             ; nMaxCount
0000:004042F1                 lea     eax, [esp+10h+String]
0000:004042F5                 push    eax             ; lpString
0000:004042F6                 mov     eax, [ebx+14h]
0000:004042F9                 push    eax             ; hWnd
0000:004042FA                 call    GetWindowTextA
0000:004042FF                 push    25h             ; uFormat
0000:00404301                 lea     eax, [ebx+1Ch]
0000:00404304                 push    eax             ; lpRect
0000:00404305                 push    0FFFFFFFFh      ; nCount
0000:00404307                 lea     eax, [esp+18h+String]
0000:0040430B                 push    eax             ; lpString
0000:0040430C                 mov     eax, [ebx+18h]
0000:0040430F                 push    eax             ; hDC
0000:00404310                 call    DrawTextA
0000:00404315                 test    byte ptr [ebx+10h], 1
0000:00404319                 jz      short loc_404350
0000:0040431B                 push    0DDFFh          ; COLORREF
0000:00404320                 mov     eax, [ebx+18h]
0000:00404323                 push    eax             ; HDC
0000:00404324                 call    SetTextColor
0000:00404329                 push    25h             ; uFormat
0000:0040432B                 lea     eax, [ebx+1Ch]
0000:0040432E                 push    eax             ; lpRect
0000:0040432F                 push    0FFFFFFFFh      ; nCount
0000:00404331                 lea     eax, [esp+18h+String]
0000:00404335                 push    eax             ; lpString
0000:00404336                 mov     eax, [ebx+18h]
0000:00404339                 push    eax             ; hDC
0000:0040433A                 call    DrawTextA
0000:0040433F                 push    0Fh             ; grfFlags
0000:00404341                 push    2               ; edge
0000:00404343                 lea     eax, [ebx+1Ch]
0000:00404346                 push    eax             ; qrc
0000:00404347                 mov     eax, [ebx+18h]
0000:0040434A                 push    eax             ; hdc
0000:0040434B                 call    DrawEdge
0000:00404350
0000:00404350 loc_404350:
0000:00404350                 add     esp, 0Ch
0000:00404353                 pop     ebx
0000:00404354                 retn
0000:00404354 sub_4042AC      endp


  好的,WM_DRAWITEM和sub_4042AC出來了。

    WM_DRAWITEM:
      Begin
        ItemDraw(PDrawItemStruct(lParam));
        Result:=0;
      End;

Procedure ItemDraw(lpDIS:PDrawItemStruct);
Var
  Str:String;
Begin
  FillRect(lpDIS^.hDC,lpDIS^.rcItem,h_Brush);
  SetTextColor(lpDIS^.hDC,$A0A0A0);
  SetBkMode(lpDIS^.hDC,TRANSPARENT);
  DrawEdge(lpDIS^.hDC,lpDIS^.rcItem,BDR_RAISEDOUTER,BF_RECT);
  GetWindowText(lpDIS^.hwndItem,PChar(Str),10);
  DrawText(lpDIS^.hDC,PChar(Str),-1,lpDIS^.rcItem,DT_SINGLELINE OR DT_VCENTER OR DT_CENTER);
  
  If lpDIS^.itemState MOD 2=1 Then
    Begin
      SetTextColor(lpDIS^.hDC,$DDFF);
      DrawText(lpDIS^.hDC,PChar(Str),-1,lpDIS^.rcItem,DT_SINGLELINE OR DT_VCENTER OR DT_CENTER);
      DrawEdge(lpDIS^.hDC,lpDIS^.rcItem,BDR_SUNKENOUTER,BF_RECT);
    End;
End;

  試試看,原來是畫三維邊框。
  另外,不知道大家注意到沒有,貼上來的PAS程式碼其實都是排好的。直接C&P就可以,
連縮排也不用做。
  還有,上面的程式碼有個問題,至少我認為是個問題。就是在GetWindowText那裡。
雖然已經限制了長度,但是Str沒有初始化,這個在以前沒有什麼,因為都是Short的。
但是現在還有個PChar,而且和Short都對應到String型別。以前老是有人抱怨說PChar
出AccessViolation,結果最後發現是沒有初始化,PChar都指到隨機地址了。後來用了
SetLength就OK了。不過這裡因為Str是在堆疊分配的,所以個人認為問題不大。不知老
錢怎麼看這個問題,最好是請他指教一下。

相關文章