奇怪的钩子行为32/64位

时间:2012-09-03 18:28:40

标签: dll hook c++builder 32bit-64bit setwindowshookex

我正在使用带有ms字(OpusApp)的本地钩子(WH_KEYBOARD)。好吧,据我所知,带有32bit DLL的32位应用只能使用32bit target applications。奇怪的是,该程序只适用于64位应用!就是这样,只有64bits APPS!例如,it works with IE 64 but not with IE 32! 应用程序和dll是使用radstudio XE2编译的32位,我将该版本确认为PE标头。 在32位操作系统中,app和dll不起作用。

我在网上找不到任何解决方案,并没有找到解决这个奇怪问题的起点。

DLL代码:

// Exported functions

extern "C" __declspec(dllexport)bool __stdcall InstallMouseHook(unsigned long, void *);

extern "C" __declspec(dllexport)bool __stdcall RemoveMouseHook();

// Callback Procedure Declaration

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

// Global variables

HHOOK HookHandle;
HINSTANCE DllInstance;
typedef void (__stdcall *CALLIT)(int,WPARAM,LPARAM);
CALLIT callIt = NULL;

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
  DllInstance=hinst;
  return 1;
}

bool __stdcall InstallMouseHook(unsigned long pid, void *function)
{

     callIt = ( CALLIT ) function;

     if (function == NULL) {

        ShowMessage("function is null!");

     } else if (callIt == NULL) {

        ShowMessage("callIt is null!");

     }  

     HookHandle=SetWindowsHookEx(WH_KEYBOARD ,reinterpret_cast<HOOKPROC> (HookProc),DllInstance,pid);

    if (HookHandle==NULL)return false;

    else return true;

}

bool __stdcall  RemoveMouseHook()
{
  if(UnhookWindowsHookEx(HookHandle)==0)
  {
    return false;
  }
  else return true;
}

LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code<0) {
        return CallNextHookEx(HookHandle,code,wParam,lParam);
    }

    if (callIt != NULL) {
        callIt(code,wParam,lParam);
    } else {
        ShowMessage("HookProc - no function to execute OR 32/64 bits problem!");
    }

  //Call the next hook in the chain
  return CallNextHookEx(HookHandle,code,wParam,lParam);
}

EXE呼叫代码:

void __fastcall TfrmMouseHook::btnHookAppDllClick(TObject *Sender)
{
    HWND hWindow;
    unsigned long pid;

    String s = "MouseHookDLL.dll";
    DllHandle=LoadLibrary(s.w_str());
    MOUSEHOOKFCT_2 InstHook=reinterpret_cast<MOUSEHOOKFCT_2> (GetProcAddress(DllHandle,"InstallMouseHook"));

    hWindow = FindWindow(ComboBox1->Text.w_str(),NULL);

    if (!hWindow) {
        msg("hWindow fail");
        return;
    }

    pid = GetWindowThreadProcessId(hWindow ,0);
    if (!pid) {
       msg("pid fail");
       return;
    }

    if(!InstHook(pid, (void *) callIt )) {
        msg("Unable to install  hook!");
    } else {
        msg(" #### hook INSTALLED! ####");
    }


}

CALLIT callIt(code,wParam,lParam) {
    frmMouseHook->msg("hook callit: code="+IntToStr(code) +" wparam="+IntToStr(wParam)+" lparam="+IntToStr(lParam) );
}



   Call IT is a function pointer to a hooker app function.

    Any ideas will be very wellcome!

2 个答案:

答案 0 :(得分:1)

32位应用程序在物理上不可能安装32位挂钩DLL并在64位进程中执行它。 32位DLL根本无法注入64位进程。期。 MSDN在多个地方说明了这一点,包括SetWindowsHookEx() documentation

  

SetWindowsHookEx可用于将DLL注入另一个进程。一个   32位DLL无法注入64位进程和64位DLL   无法注入32位进程。如果申请需要   在其他进程中使用钩子,它需要一个32位   应用程序调用SetWindowsHookEx将32位DLL注入32位   进程和一个64位应用程序调用SetWindowsHookEx来注入一个   将64位DLL转换为64位进程。 32位和64位DLL必须具有   不同的名字。

     

因为钩子在应用程序的上下文中运行,所以它们必须匹配   应用程序的“位数”。如果32位应用程序安装了   64位Windows上的全局钩子,32位钩子被注入每个钩子   32位进程(通常的安全边界适用)。在64位   进程中,线程仍被标记为“挂钩”。但是,因为一个   32位应用程序必须运行钩子代码,系统执行   挂钩应用程序的上下文;特别是,在线程上   叫做SetWindowsHookEx。这意味着挂钩应用程序必须   继续抽取消息或它可能阻止正常运作   64位进程。

     

如果64位应用程序在64位Windows上安装全局挂钩,则   64位钩子被注入每个64位进程,而所有32位进程   进程使用对挂钩应用程序的回调。

你说你的应用程序和DLL在32位操作系统版本上不起作用的事实表明你的挂钩代码有缺陷。但是你没有显示足够的代码来诊断这种或那种方式。

答案 1 :(得分:0)

会发生什么?除了 MSDN 或者其他人说的,XE6 有一些 bug,在较新版本的 IDE 中编译 DLL 使这种行为消失,实际上,新的 DLL 崩溃并没有钩住任何东西。

正如 Remy 指出的,通过测试,我向 DLL 传递了一个函数指针,这是一件错误的事情,但是,当加上 Embarcadero 所做的错误事情时,就可以正常工作了。

到现在为止,我知道人们会生气,我将两种方法(错误的和正确的挂钩)放在同一个 DLL 和我的应用程序中,然后……变得疯狂……可以挂钩到 32 位和 64 位只有一个 DLL 的应用。

不相信?安装 XE6 并尝试!

并且适用于 Windows 10 以及 Windows 7。