首页
社区
课程
招聘
Delphi逆向工程笔记[6]
发表于: 2004-11-17 10:38 8606

Delphi逆向工程笔记[6]

2004-11-17 10:38
8606

先废话一会。本来这篇东西昨天晚上写好的,但是打算发时发现论坛上不去了。一直到刚才才打开。不知道是不是被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     ebp, esp
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     ebx, ebx
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     ebx, ebx
0000:00404CF7 loc_404CF7:
0000:00404CF7                 mov     eax, ebx
0000:00404CF9                 pop     edi
0000:00404CFA                 pop     esi
0000:00404CFB                 pop     ebx
0000:00404CFC                 mov     esp, ebp
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     eax, ds: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     edi, eax
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     eax, esi        ; 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     ebp, esp
0000:004043FF                 push    ebx
0000:00404400                 push    esi
0000:00404401                 mov     ebx, [ebp+arg_4]
0000:00404404                 mov     esi, 1
//现在esi是返回值,下面可以看到
0000:00404409                 mov     eax, ebx
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     eax, ds: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     eax, esi
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;
==========================================================================


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
2
实时计算注册码,你怎么没逆出来呢?
2004-11-17 10:55
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
3
最初由 laoqian 发布
实时计算注册码,你怎么没逆出来呢?


我用的版本是最初的,不是那个2合1,里面没有实时计算的部分。

至于那个实时的东东,过两天我看看。
2004-11-17 11:08
0
雪    币: 413
活跃值: (752)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
好,收藏
2004-11-17 11:18
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
5
OK,恰好我以前写过一个SDK程序,里面用到了Notification。一时找不到那个2in1。那么,我就自己写了:

把WM_COMMAND里的case改成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;

就可以了。

有点懒,ID直接放数字了。

PS:上面的文章已经更新。
2004-11-17 11:33
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
6
我是直接这样写的:
case Loword(wParam) of
“子控件向父窗口发送的消息是WM_COMMAND,并在传递的参数wPara的底位中包括控件的ID号,消息号在wParam的高位,lParam中则包括了子控件的窗口的句柄”

以上是Edit属性框

但是若Text属性框,可是无论在case Loword(wParam) of还是case wParam of里面,都没有要我们的ID!我不明白了。

请解释一下?
2004-11-17 13:13
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
7
我实验了一下,也没有结果。

我的理解是:Text只是用来显示信息的,不象edit,combo什么可以随着用户操作而改变外观(找不到更恰当的描述,但我的意思是在调用窗口的callback以前),所以也就没有必要返回id了。

另外,SDK文档里说得非常清楚,只有当菜单的某项被选中,一个子控件向父窗口发送一个Notification,或者快捷键被按时,事件处理程序才会接到WM_COMMAND消息。所以,在WM_COMMAND处理时看不到Text的id也是可以理解的。

两种理解方法,随便选哪种。
2004-11-17 13:52
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
8
那么,Text属性也有ID,那么这个ID是什么呢?总有调用的地方,是否可以diy一下呢?
2004-11-17 15:56
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
9
最初由 laoqian 发布
那么,Text属性也有ID,那么这个ID是什么呢?总有调用的地方,是否可以diy一下呢?


老实说,我对SDK编程不是很熟悉。但是可以肯定一点,这个ID是窗口内控件的唯一标识。到目前为止,我只看见过SetDlgItemText、GetDlgItemText之类的地方需要Text的ID。当然,还有Get/SetWindowLong。

我个人认为,Text的ID除了标识以外,就是在需要向Text发消息时才用到。

共同探讨。
2004-11-17 16:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
其实我觉得如果是SDK编程,几乎对控件所有的操作,都是从这个ID开始滴,连HAMDLE都是通过GetDialogItem()得到的,这些SetDlgItemText之类的对话框专用的api,个人觉得也就是对SetWindowsText等的封装,省去了自己得到窗口句柄,在消息处理中,无疑也是利用的id来区分控件的,至于vb,delphi我就不知道了,vb窗体基本是解释执行的好像,至于怎么处理的控件,想知道的可以去问msvbvm呵呵。
2004-11-17 18:46
0
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
11
最初由 yafeng 发布
其实我觉得如果是SDK编程,几乎对控件所有的操作,都是从这个ID开始滴


你显然忘了CreateWindow,否则不会这么说。
2004-11-17 19:30
0
雪    币: 98745
活跃值: (201039)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
12
支持!!!
2004-11-17 23:23
0
游客
登录 | 注册 方可回帖
返回
//