• 标 题:Delphi逆向工程笔记[3]
  • 作 者:firstrose
  • 时 间:004-10-27,17:12
  • 链 接:http://bbs.pediy.com

抱歉,刚才把没有整理完全的发了。

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

  下面处理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出来的部分就发完了。以后再发可能就没有这么完整的结构了,而且间隔也会加长。

抱歉,因为我不是专职做这个。