如何使用函数指针从其内存地址调用成员函数
How to use function pointers to call member functions from its memory address?
我正在开发一个旧应用程序的补丁,该应用程序的所有者不再拥有src代码。
在main()之前,我正在将dll注入目标应用程序的.exe中。这个dll安装了我做的修补程序。
该应用程序有一个C++自定义类型(类或结构),它似乎是一个绘图字体管理器,我需要通过其中一些补丁调用这些函数。
我通常调用这些"本机"成员函数的方式是创建一个包装函数,通过asm-inline调用本机成员函数。我这样做是因为我找不到如何通过C++函数指针来实现这一点。
我再次尝试用一种比创建大量臃肿的函数包装器更好的方式来实现这一点。这一次,我试图使用类/结构作为本机类型的虚拟包装器,但似乎缺少了一些与函数指针语法相关的东西,我无法理解。
这是我尝试做的一个示例:
/* NC for Native Class */
class NC_FontDevice
{
public:
typedef void(NC_FontDevice::*_UseTexturesTransparency)();
_UseTexturesTransparency *UseTexturesTransparency = reinterpret_cast<_UseTexturesTransparency*>(0x635FD0);
private:
NC_FontDevice(){}
};
NC_FontDevice* GetFontDevice()
{
NC_FontDevice* lpFontDevice = nullptr;
/*
This asm inline block is here to show more or less what I do in those wrappers I told.
I know this can be converted to a simple function pointer.
*/
__asm
{
mov eax, 0x0041FE10
call eax
mov lpFontDevice, eax
}
return lpFontDevice;
}
void foo()
{
auto lpFontDevice = GetFontDevice();
// Here I get and "identifier X is undefined"
(lpFontDevice->**UseTexturesTransparency)();
}
如果我想要的东西很清楚,除了函数包装器之外,还有更好的方法来实现它吗?
提前谢谢。
您的问题之一至少是您的代码与您的问题不匹配。您谈论的是函数指针,但您编写的是void(NC_FontDevice::*_UseTexturesTransparency)()
。这不是函数指针。这是一个指向成员函数(PMF)的指针。完全不同的野兽,你不能认为这些都是简单的指针。它们通常甚至不一样大。
我怀疑您在0x635FD0
中找到了一个函数。这个函数可能看起来像void _UseTexturesTransparency(NC_FontDevice*)
。当然,它在编译时可能是成员函数的一部分,但这并不重要。这是黑客行为,我们在这里很务实。如果我们可以把它当作一个普通的函数指针,为什么要处理PMF的复杂性呢?
[编辑]根据注释,MSVC++将使用ECX
作为成员函数中的this
参数;碰巧,它还支持用于正则函数的__fastcall
调用约定,该约定将第一个32位参数放入ECX
中。这不是一个完美的替代品;__fastcall
还使用EDX作为其第二个参数。如果现有代码需要堆栈上的其他参数,则可能需要一个伪参数。
您可以检查堆栈参数,因为根据成员函数的__thiscall
调用约定,被调用者会清理堆栈。幸运的是,这符合__fastcall
惯例。
您有没有想过使用std::bind和std::function?C++11和boost拥有它。
std::function x = std::bind(&ClassName::function,this);
这将创建一个回调函数,该函数将对您的对象起作用。
- 为什么成员函数地址离自由函数这么远?
- MFC 消息映射中的函数地址
- 设置成员 GlobalCEFApp->OnWebKit使用函数地址初始化 C++生成器
- 在Visual C 中找到调用函数地址(安全)
- 获取函数地址时出现奇怪行为
- 函数地址
- 如何在C++中打印成员函数地址
- 为什么函数指针、函数地址和函数相同
- 匹配布尔值与常量 void* 重载的函数地址
- 函数地址和函数地址的地址没有区别吗?
- 在 Linux 库中查找静态函数地址
- 调用传递给 gcc 内联汇编器 (avr-gcc) 的 const 函数地址
- 使用32位应用程序从64位kernel32.dll获取函数地址
- 为什么函数地址不是常量表达式
- 将函数地址转换为 64 位整数:未定义/行为不当
- Visual Studio在打印函数地址时出错
- 获取有关函数地址的信息
- 通过函数地址调用另一个类的函数
- 打印成员函数地址的最简单方法是什么?
- 圆括号成员函数地址错误