EasyHook 停止捕获一些消息

EasyHook stop catching some messages

一旦 EasyHook EasyHook64.dll 拦截了第一条 DefWindowProcW 消息,并从中启动了一个线程,它就不再捕获任何 DefWindowProcW:

|___ DefWindowProcW (caught)
     |--
     |--
     |--
     |-- DefWindowProcW (don't 'intercept' anymore)
     |-- ...

它会停止 'catching' 所有 DefWindowProcW 消息,直到线程结束。

有人告诉我:

This is by design, it is part of the thread deadlock barrier.

并且:

You could install two hooks for the same function, leaving the second disabled until you enter your first hook, you would enable it by setting its ACL inclusive to the current thread, then disable it again as you leave the first hook.

然后我试着这样称呼它:


HOOK_TRACE_INFO hHook  = { NULL }; 
HOOK_TRACE_INFO hHook2 = { NULL }; 
HOOK_TRACE_INFO hHook3 = { NULL };


LRESULT __stdcall DefWindowProcW_Hook(  HWND   hWnd,    UINT   Msg, WPARAM wParam,  LPARAM lParam)
{

    switch (Msg) {
        //......
    }

    ULONG ACLEntries[1]  = { 0 };
    LhSetInclusiveACL(ACLEntries, 1, &hHook);
    ULONG ACLEntries2[1] = { 0 };
    LhSetInclusiveACL(ACLEntries2, 1, &hHook2);
    ULONG ACLEntries3[1] = { 0 };
    LhSetInclusiveACL(ACLEntries2, 1, &hHook3); 

   return DefWindowProcW(hWnd, Msg, wParam, lParam);
}


// =======================================

void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* inRemoteInfo)
{

        LhInstallHook(
            GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
            DefWindowProcW_Hook,    NULL,   &hHook);

        ULONG ACLEntries[1] = { 0 };
        LhSetExclusiveACL(ACLEntries4, 1, &hHook);
        

        LhInstallHook(
            GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
            DefWindowProcW_Hook,    NULL,   &hHook2);

        LhInstallHook(
            GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
            DefWindowProcW_Hook,    NULL,   &hHook3);
}

但是现在,看起来所有的钩子都在做同样的事情:

结果:

想问一下使用过或已经使用过EasyHook的人,当有第二个或更多嵌套调用时如何正确读取相同的函数。

在 EasyHook 中没有完美的解决方案,但是如果您愿意为嵌套级别安装尽可能多的中间挂钩,您可以将它们链接在一起。

最外面的挂钩将是最初启用的唯一挂钩。

它将首先确保禁用所有最里面的挂钩,然后启用下一个挂钩。

为了防止为同一个 DefWindowProcW 调用调用挂钩,我们可以检索下一个挂钩的绕过地址并调用它,而不是像通常那样调用原始的 DefWindowProcW。

正如您已经发现的那样,一旦在钩子的钩子处理程序中,它不会再次触发同一个钩子,直到 return 语句完成并且我们返回调用堆栈。这是由于 EasyHook 中的线程死锁屏障。

示例:

HOOK_TRACE_INFO hHook  = { NULL };
HOOK_TRACE_INFO hHook2 = { NULL };
HOOK_TRACE_INFO hHook3 = { NULL };
typedef LRESULT __stdcall DefWindowProcFunc(HWND, UINT, WPARAM, LPARAM);

// Innermost hook handler
LRESULT __stdcall DefWindowProcW_Hook( HWND   hWnd, UINT   Msg, WPARAM wParam, LPARAM lParam)
{

switch (Msg) {
//......
}

   // Innermost hook just call original

   return DefWindowProcW(hWnd, Msg, wParam, lParam);
}


// Middle hook handler
LRESULT __stdcall DefWindowProcW_Hook2( HWND   hWnd, UINT   Msg, WPARAM wParam, LPARAM lParam)
{

switch (Msg) {
//......
}

   // Activate next hook handler for next nesting level
   ULONG ACLEntries[1]  = { 0 };
   LhSetInclusiveACL(ACLEntries, 1, &hHook);

   PVOID* bypass_address;
   LhGetHookBypassAddress(&hHook, &bypass_address);
   
   //return DefWindowProcW(hWnd, Msg, wParam, lParam);
   
   // Bypass the handler for THIS call to DefWindowProcW - the next nested call will be captured in  DefWindowProcW_Hook
   return ((DefWindowProcFunc*)bypass_address)(hWnd, Msg, wParam, lParam);
}

// Outermost hook handler
LRESULT __stdcall DefWindowProcW_Hook3( HWND   hWnd, UINT   Msg, WPARAM wParam, LPARAM lParam)
{
    // Outermost hook handler - this will be called first for new calls to DefWindowProcW

switch (Msg) {
//......
}

   // Disable innermost hook(s) - do this for each inner hook that isn't the next hook
   ULONG disableACLEntries[1]  = { 0 };
   LhSetExclusiveACL(disableACLEntries, 1, &hHook);

   // Activate next hook handler for first nesting level
   ULONG ACLEntries[1]  = { 0 };
   LhSetInclusiveACL(ACLEntries, 1, &hHook2);

   PVOID* bypass_address;
   LhGetHookBypassAddress(&hHook2, &bypass_address);
   
   //return DefWindowProcW(hWnd, Msg, wParam, lParam);

   // Bypass the handler for THIS call to DefWindowProcW - the next nested call will be captured in DefWindowProcW_Hook2
   return ((DefWindowProcFunc*)bypass_address)(hWnd, Msg, wParam, lParam);
}

// =======================================

void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* inRemoteInfo)
{
    // NOTE: the last installed hook handler will be the first called i.e. hHook3, then hHook2 then hHook.
    LhInstallHook(
        GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
        DefWindowProcW_Hook, NULL, &hHook);

    LhInstallHook(
        GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
        DefWindowProcW_Hook2, NULL, &hHook2);
       
    LhInstallHook(
        GetProcAddress(GetModuleHandle(TEXT("user32")), "DefWindowProcW"),
        DefWindowProcW_Hook3, NULL, &hHook3);
       
    // Activate outermost hook (ie last installed hook which will be the first called - hHook3)
    ULONG ACLEntries[1] = { 0 };
    LhSetExclusiveACL(ACLEntries, 1, &hHook3);
}