欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

对[FCG]KeyGen2.0按钮特效的分析[1].txt

对[FCG]KeyGen2.0按钮特效的分析[1].txt

  首先,注意一个比较特别的现象。原始版本在某些Windows上会崩溃,而崩溃后的Runtime Error对话框的OK按钮居然也是特效。说明什么?一定是钩子。
  用IDA反汇编正常的KG2,注意到和KG1的不同点,可以发现多了一个WM_SHOWWINDOW。其处理程序如下:
CODE:00408482 loc_408482:
CODE:00408482                 push    0
CODE:00408484                 call    sub_406984
CODE:00408489                 jmp     loc_4088E0
  可以看到,这是个stdcall/pascal类型的过程。至于到底是哪种,无关紧要。这里的参数只有一个,所以不必担心顺序。
CODE:00406984 sub_406984      proc near
CODE:00406984
CODE:00406984 arg_0           = dword ptr  8
CODE:00406984
CODE:00406984                 push    ebp
CODE:00406985                 mov     ebp, esp
//这里是典型的pascal/stdcall调用的开头。但是因为只有1个参数,无法肯定是哪个类型。
//值得注意的是,这是个VC的obj。所以不能因为是VC编译的obj就一概使用cdecl。
CODE:00406987                 push    ebx
CODE:00406988                 mov     ebx, [ebp+arg_0]
CODE:0040698B                 xor     eax, eax
CODE:0040698D                 test    ebx, ebx
CODE:0040698F                 jnz     short loc_4069CC
CODE:00406991                 cmp     ds:hhk, 0
CODE:00406998                 jnz     short loc_4069D2
CODE:0040699A                 push    1               ; lParam
CODE:0040699C                 push    offset fn       ; lpfn
CODE:004069A1                 call    GetCurrentThreadId_0
CODE:004069A6                 push    eax             ; dwThreadId
CODE:004069A7                 call    EnumThreadWindows
CODE:004069AC                 call    GetCurrentThreadId_0
CODE:004069B1                 push    eax             ; dwThreadId
CODE:004069B2                 push    0               ; hmod
CODE:004069B4                 push    offset sub_406D4A ; lpfn
CODE:004069B9                 push    4               ; idHook
CODE:004069BB                 call    SetWindowsHookExA
CODE:004069C0                 mov     ds:hhk, eax
CODE:004069C5                 mov     eax, ds:hhk
CODE:004069CA                 jmp     short loc_4069D2
CODE:004069CC
CODE:004069CC loc_4069CC:
CODE:004069CC                 push    ebx
CODE:004069CD                 call    sub_406A1F
CODE:004069D2
CODE:004069D2 loc_4069D2:
CODE:004069D2                 pop     ebx
CODE:004069D3                 pop     ebp
CODE:004069D4                 retn    4
CODE:004069D4 sub_406984      endp
  这个初始化过程(实际是个函数)的流程还是非常清楚的。但是这个参数到底是什么?从上面来看,如果参数为0,那么就枚举当前线程的窗口。看来应该是某窗口的句柄。通过查看sub_406A1F,发现00406A53处有对GetWindowLong的调用,而且传过去的ebx作为首个参数。这样,可以判断它是个窗口句柄。这里给出该过程的Pascal形式

代码:

Var
  CurrentHook:HHOOK;
Function Init(Window:HWND):HHOOK;
Begin
  Result:=0;
  If Window=0 Then
    Begin
      If CurrentHook=0 Then
        Begin
          EnumThreadWindows(GetCurrentThreadId,,1);
          CurrentHook:=SetWindowsHookEx(WH_CALLWNDPROC,sub_406D4A,0,GetCurrentThreadId);
          Result:=CurrentHook;
        End;
    End
  Else
    Begin
      sub_406A1F(Window);
    End;
End;

   CurrentHook又是什么呢?从上面看,应该是起类似于标志的作用。初始值为0,Hook过以后就是
Hook函数的句柄。所以修改一下定义
代码:

Const
  CurrentHook:HHOOK=0;

????    首先看看sub_406D4A,这是一个CallWndProc函数。MSDN中有关定义如下:
代码:

LRESULT CALLBACK CallWndProc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam
);

????    再看看函数体:
seg000:00406D4A ; LRESULT __stdcall sub_406D4A(int,WPARAM,LPARAM)
seg000:00406D4A sub_406D4A      proc near               ; DATA XREF: sub_406984+30
seg000:00406D4A
seg000:00406D4A arg_0           = dword ptr  8
seg000:00406D4A wParam          = dword ptr  0Ch
seg000:00406D4A arg_8           = dword ptr  10h
seg000:00406D4A
seg000:00406D4A                 push    ebp
seg000:00406D4B                 mov     ebp, esp
seg000:00406D4D                 push    ebx
seg000:00406D4E                 push    esi
seg000:00406D4F                 mov     ebx, [ebp+arg_8]
//ebx:=LPARAM
//注意这里是一个地址,指向一个CWPSTRUCT结构
seg000:00406D52                 mov     esi, [ebp+arg_0]
//esi:=nCode
seg000:00406D55                 cmp     dword ptr [ebx+8], 1
//判断CWPSTRUCT.Message
//由于BN_PAINT=WM_CREATE=1,所以
//具体1是哪个message,需要根据进一步的分析来判断
seg000:00406D59                 jnz     short loc_406D67
seg000:00406D5B                 test    esi, esi
seg000:00406D5D                 jl      short loc_406D67
seg000:00406D5F                 push    dword ptr [ebx+0Ch]
//CWPSTRUCT.hwnd
seg000:00406D62                 call    sub_406A1F
seg000:00406D67
seg000:00406D67 loc_406D67:                             ; CODE XREF: sub_406D4A+F
seg000:00406D67                                         ; sub_406D4A+13
seg000:00406D67                 push    ebx             ; lParam
seg000:00406D68                 push    [ebp+wParam]    ; wParam
seg000:00406D6B                 push    esi             ; nCode
seg000:00406D6C                 push    ds:hhk          ; hhk
seg000:00406D72                 call    CallNextHookEx
seg000:00406D77                 pop     esi
seg000:00406D78                 pop     ebx
seg000:00406D79                 pop     ebp
seg000:00406D7A                 retn    0Ch
seg000:00406D7A sub_406D4A      endp
    其中的CWPSTRUCT结构:
代码:

typedef struct {
    LPARAM lParam;
    WPARAM wParam;
    UINT message;
    HWND hwnd;
} CWPSTRUCT, *PCWPSTRUCT;

????    这个函数也不复杂:
代码:

Procedure CallBackWndProc(nCode:Integer;wParam:Cardinal;var lParam:CWPSTRUCT);stdcall;
Begin
  If (lParam.message=1) AND (nCode<0) Then
    Begin
      sub_406A1F(lParam.hwnd);
    End;
  CallNextHookEx(CurrentHook,nCode,wParam,lParam);
End;

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功