访问钩子程序中的钩子

时间:2012-02-11 22:16:08

标签: c++ c winapi hook

如何从他的程序中访问钩子的句柄?

示例:

HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)hookProc, GetModuleHandle(NULL), 0);

LRESULT CALLBACK hookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    //I want my HHOOK here :O
}

2 个答案:

答案 0 :(得分:3)

您需要将HHOOK变量存储在全局内存中。不要将它声明为调用SetWindowsHookEx()的任何函数的局部变量。

编辑:以下是32位CPU的基于类的示例:

class THookKeyboardLL
{
private:
    HHOOK hHook;

    void *pProxy;
    static LRESULT CALLBACK ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam);

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

public:
    THookKeyboardLL();
    ~THookKeyboardLL();
};

#include <pshpack1.h>
struct sProxy
{
    unsigned char PopEax;
    unsigned char Push;
    void *ThisPtr;
    unsigned char PushEax;
    unsigned char Jmp;
    int JmpOffset;
};
#include <poppack.h>

long CalcJmpOffset(void *Src, void *Dest)
{
    return reinterpret_cast<long>(Dest) - (reinterpret_cast<long>(Src) + 5);
}

LRESULT CALLBACK THookKeyboardLL::ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam)
{
    return This->HookProc(nCode, wParam, lParam);
}

THookKeyboardLL::THookKeyboardLL()
    : hHook(NULL), pProxy(NULL)
{
    sProxy *Proxy = (sProxy*) VirtualAlloc(NULL, sizeof(sProxy), MEM_COMMIT, PAGE_READWRITE);

    Proxy->PopEax = 0x58;
    Proxy->Push = 0x68;
    Proxy->ThisPtr = this;
    Proxy->PushEax = 0x50;
    Proxy->Jmp = 0xE9;
    Proxy->JmpOffset = CalcJmpOffset(&(Proxy->Jmp), &ProxyStub);

    // Note: it is possible, but not in a portable manner, to
    // get the memory address of THookKeyboardLL::HookProc()
    // directly in some compilers.  If you can get that address,
    // then you can pass it to CalcJmpOffset() above and eliminate
    // THookKeyboardLL::ProxyStub() completely. The important
    // piece is that the Proxy code above injects this class
    // instance's "this" pointer into the call stack before
    // calling THookKeyboardLL::HookProc()...

    DWORD dwOldProtect;
    VirtualProtect(Proxy, sizeof(sProxy), PAGE_EXECUTE, &dwOldProtect);
    FlushInstructionCache(GetCurrentProcess(), Proxy, sizeof(sProxy));

    pProxy = Proxy;
    hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)pProxy, GetModuleHandle(NULL), 0);
}

THookKeyboardLL::~THookKeyboardLL()
{
    if (hHook != NULL)
        UnhookWindowsHookEx(hHook);

    if (pProxy)
        VirtualFree(pProxy, 0, MEM_RELEASE);
}

LRESULT CALLBACK THookKeyboardLL::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // ...

    return CallNextHookEx(hHook, nCode, wParam, lParam);
    // when this method exits, it will automatically jump
    // back to the code that originally called the Proxy.
    // The Proxy massaged the call stack to ensure that...
}

答案 1 :(得分:1)

如果查看CallNextHookEx的{​​{3}},您会看到HHOOK参数在Windows NT上是可选的,如果您需要支持Windows 9x,则需要将HHOOK存储在全局变量中。

你的示例代码显示你正在创建一个全局钩子,全局钩子是昂贵的,所以如果你想注册多个回调函数你应该抽象这个,以便你的应用程序只设置一个钩子和你在那里调用的回调函数调用你的真实功能(在链表等)。