【问题标题】:Getting function by name in c++在 C++ 中按名称获取函数
【发布时间】:2015-02-19 16:19:46
【问题描述】:

代码:

#include <tchar.h>
#include <windows.h>


typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);



int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    lolMessageBoxA UchwytMessageBoxA;

    UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));

    UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
    return 0;
}

当我在制作钩子之前正常调用 MessageBoxA 时,钩子部分工作得很好。但是当我删除那部分并只留下“挂钩”部分时它失败了......

已解决:

#include <tchar.h>
#include <windows.h>


typedef INT (WINAPI * lolMessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);



int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    lolMessageBoxA UchwytMessageBoxA;
    LoadLibraryA("User32.dll");
    UchwytMessageBoxA = lolMessageBoxA(GetProcAddress(GetModuleHandle("User32.dll"),"MessageBoxA"));

    UchwytMessageBoxA(NULL,"TEST WINDOWS","TEXT 2", MB_OKCANCEL | MB_ICONWARNING);
    return 0;
}

【问题讨论】:

  • 你调试了吗?你检查过GetProcAddress 没有返回NULL吗?并详细说明“它失败了”。
  • 正如其他人所说,您绝不需要加载 user32.dll。如果您想使用 WinApi,请包含 windows.h 并使用 -mwindows 标志链接到库
  • @Evan Carslake 事实并非如此。我只想加载一个特定的库...

标签: c++ winapi hook


【解决方案1】:

如此处所述,进程没有理由加载user32.dll。所以对GetModuleHandle 的调用将返回NULL。然后对GetProcAddress 的调用也将失败并返回NULL。好吧,你可以看看接下来会发生什么。

当您直接调用MessageBoxA 时,链接器会生成一个导入表,强制加载程序加载user32.dll。但是当您删除对MessageBoxA 的调用时,它就没有必要这样做了。

您应该将调用GetModuleHandle 替换为调用LoadLibrary,从而强制加载库。

最后,您提出这个问题的真正原因是您的代码忽略了错误检查。不要那样做。检查 Win32 函数调用返回的值。如果你这样做了,你就可以自己解决这个问题了。

【讨论】:

  • 我也在想同样的事情,但是 user32.dll 通常会在每个进程中加载​​。它就像 kernel32.dll。只有 NT 进程可能没有加载它。除非它在您第一次对对话框/事件循环等进行任何操作时被加载。否则它不会在 WinMain() 之后立即加载。
  • @sashoalm 我认为没有理由将 user32 加载到此过程中。将调用 user32 中的哪个函数? Kernel32 不同。它保证被加载。另外,什么是NT进程?按需加载可能会发生延迟加载。但通常导入表会确定加载哪些 DLL。如果这个程序有一个消息循环,那么 user32 就会被加载。但是看看代码。该程序调用 GetModuleHandle 和 GetProcAddress。
  • 嗯,通常我总是在 Process Explorer 中为每个进程看到它,这就是我的意思。但也许这是因为几乎任何进程都必然会在某些时候显示一些与 UI 相关的东西,比如窗口。
  • @sashoalm 这正是我在回答中所描述的。编译后的程序没有与 user32 链接,因此加载器不会加载它。要么调用LoadLibrary 来加载它,要么从user32 调用一个函数,然后行为就会改变。除非您有充分的理由这样做,否则您不应假定保证加载 DLL。大多数进程加载 user32 并不是一个好的理由。
猜你喜欢
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
相关资源
最近更新 更多