如何使用函数指针从其内存地址调用成员函数

How to use function pointers to call member functions from its memory address?

本文关键字:函数 地址 调用 内存 成员 何使用 指针      更新时间:2023-10-16

我正在开发一个旧应用程序的补丁,该应用程序的所有者不再拥有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);

这将创建一个回调函数,该函数将对您的对象起作用。