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

自己写的破烂居然被加精了……这里做个说明,由于这个KeyGen的RE有点难度,目前
手上完成了的也就一点点,够写3篇。以后的要等我慢慢分析了。不过我保证,一定
会全部RE出来的,而且在PEDIY发全。

PS:本来是要发到CSDN的Blog上的,不过那个Blog有点烂,发不上去。于是就扔到
PEDIY来了。以为不会有人注意,结果居然被最想躲开的人看见了……实际上某人的
猜想是对的。他写了某篇文章给我看到了,于是我就拿了某个程序开刀,幸运的是
那个程序没有用某些软件处理过,要不就没有这篇破烂了。莫怪莫怪。

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

  下面处理LicenseProc,就是sub_404DD4。为了便于查看,这里先把主框架rip出
来。

0000:00404DD4 sub_404DD4      proc near
0000:00404DD4
0000:00404DD4 Paint           = PAINTSTRUCT ptr -48h
0000:00404DD4 pt              = POINT ptr -8
0000:00404DD4 hWnd            = dword ptr  8
0000:00404DD4 Msg             = dword ptr  0Ch
0000:00404DD4 wParam          = dword ptr  10h
0000:00404DD4 lParam          = word ptr  14h
//4个参数,2个局部变量
0000:00404DD4
0000:00404DD4                 push    ebp
0000:00404DD5                 mov     ebpesp
//标准的Delphi调用框架
0000:00404DD7                 add     esp, 0FFFFFFB8h
//这里相当于sub esp,48h。注意上面的Paint=PAINTSTRUCT ptr -48h
//相当有趣。
0000:00404DDA                 push    ebx
0000:00404DDB                 xor     ebxebx
0000:00404DDD                 mov     eax, [ebp+Msg]
0000:00404DE0                 cmp     eax, 111h       ; WM_COMMAND
0000:00404DE5                 jg      short loc_404E0B
0000:00404DE7                 jz      loc_404EF8
//我没有反过VC,但这里显然和通常的思维不大一样。
//WM_COMMAND被当作分界线以减少判断。
0000:00404DED                 sub     eax, 0Fh        ; WM_PAINT
//sub!居然不是cmp!
0000:00404DF0                 jz      loc_404EBD
0000:00404DF6                 sub     eax, 1Ch        ; WM_DRAWITEM
0000:00404DF9                 jz      loc_404F3F
0000:00404DFF                 sub     eax, 0E5h       ; WM_INITDIALOG
0000:00404E04                 jz      short loc_404E2B
0000:00404E06                 jmp     loc_404F8D
//这里就退出了
0000:00404E0B loc_404E0B:
0000:00404E0B                 sub     eax, 136h       ; WM_CTLCOLORDLG
0000:00404E10                 jz      loc_404F4B
0000:00404E16                 sub     eax, 2          ; WM_CTLCOLORSTATIC
0000:00404E19                 jz      loc_404F6C
0000:00404E1F                 sub     eax, 0C9h       ; WM_LBUTTONDOWN
0000:00404E24                 jz      short loc_404E79
0000:00404E26                 jmp     loc_404F8D
//退出
...
0000:00404F8D loc_404F8D:
0000:00404F8D
0000:00404F8D                 xor     ebxebx
//下面要把ebx作为返回值的。
0000:00404F8F loc_404F8F:
0000:00404F8F
0000:00404F8F                 mov     eaxebx
0000:00404F91                 pop     ebx
0000:00404F92                 mov     espebp
0000:00404F94                 pop     ebp
0000:00404F95                 retn    10h

  结合SDK程序的写法,得到主消息循环。

Function LicenseProc(hDlg:HWND;Msg,wParam,lParam:DWORD):LRESULT;stdcall;
Var
  sPaint:PAINTSTRUCT;
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;
  End;
End;

  不寻常的事发生了。它用了两个不常见的消息:WM_CTLCOLORDLG和
WM_CTLCOLORSTATIC。

  先看WM_COMMAND:

0000:00404EF8 loc_404EF8:
0000:00404EF8                 mov     eax, [ebp+wParam]
0000:00404EFB                 sub     eax, 3E9h
//照例是sub的把戏,反正参数是传值的
//结合dump出的RC可以看到这是一个按钮的ID
0000:00404F00                 jz      short loc_404F0C
0000:00404F02                 dec     eax
0000:00404F03                 jz      short loc_404F23
0000:00404F05                 sub     eax, 2
0000:00404F08                 jz      short loc_404F30
0000:00404F0A                 jmp     short loc_404F3B
0000:00404F0C loc_404F0C:
0000:00404F0C                 mov     ds:dword_4060B0, 0FFFFFFFFh
//注意这里,这就是那个返回的Flag!因为程序开头先把它清0了
//所以这里只需要赋个值就可以了。注意,Delphi里True是非0的!
0000:00404F16                 push    0               ; nResult
0000:00404F18                 mov     eax, [ebp+hWnd]
0000:00404F1B                 push    eax             ; hDlg
0000:00404F1C                 call    EndDialog
0000:00404F21                 jmp     short loc_404F3B
0000:00404F23 loc_404F23:
0000:00404F23                 push    0               ; nResult
0000:00404F25                 mov     eax, [ebp+hWnd]
0000:00404F28                 push    eax             ; hDlg
0000:00404F29                 call    EndDialog
0000:00404F2E                 jmp     short loc_404F3B
0000:00404F30 loc_404F30:
0000:00404F30                 push    0               ; nResult
0000:00404F32                 mov     eax, [ebp+hWnd]
0000:00404F35                 push    eax             ; hDlg
0000:00404F36                 call    EndDialog
0000:00404F3B
0000:00404F3B loc_404F3B:
0000:00404F3B
0000:00404F3B                 xor     ebxebx
0000:00404F3D                 jmp     short loc_404F8F

  好的,现在WM_COMMAND的处理有了。

        Case wParam of
          LICENSE_YES:
            Begin
              Flag:=True;
              EndDialog(hDlg,0);
            End;
          LICENSE_NO:
            Begin
              EndDialog(hDlg,0);
            End;
          LICENSE_CLOSE:
            Begin
              EndDialog(hDlg,0);
            End;
        End;
        
  很清楚,不是吗?下面是WM_CTLCOLORDLG和WM_CTLCOLORSTATIC。

0000:00404F4B loc_404F4B:
0000:00404F50                 mov     eax, [ebp+wParam]
0000:00404F53                 push    eax             ; HDC
0000:00404F54                 call    SetTextColor
0000:00404F59                 push    1               ; int
0000:00404F5B                 mov     eax, [ebp+wParam]
0000:00404F5E                 push    eax             ; HDC
0000:00404F5F                 call    SetBkMode
0000:00404F64                 mov     ebxds:hbr
//这里有点费解,从CreateSolidBrush的说明可以知道,如果函数
//失败,返回的是null,就是false。这里估计是利用了这点。
//一旦CreateSolidBrush失败,这里就可以退出了。有点意思。
0000:00404F6A                 jmp     short loc_404F8F
0000:00404F6C loc_404F6C:
0000:00404F6C                 push    0A0A0A0h        ; COLORREF
0000:00404F71                 mov     eax, [ebp+wParam]
0000:00404F74                 push    eax             ; HDC
0000:00404F75                 call    SetTextColor
0000:00404F7A                 push    1               ; int
0000:00404F7C                 mov     eax, [ebp+wParam]
0000:00404F7F                 push    eax             ; HDC
0000:00404F80                 call    SetBkMode
0000:00404F85                 mov     ebxds:hbr
0000:00404F8B                 jmp     short loc_404F8F

  给出相应的SRC:

    WM_CTLCOLORDLG:
      Begin
        SetTextColor(wParam,$A0A0A0);
        SetBkMode(wParam,TRANSPARENT);
        Result:=h_Brush;
        //如果要清楚一点可以改为Result:=h_Brush<>nil;
        //当然函数返回类型要改。
      End;
    WM_CTLCOLORSTATIC:
      Begin
        SetTextColor(wParam,$A0A0A0);
        SetBkMode(wParam,TRANSPARENT);
        Result:=h_Brush;
      End;