我正在开发旧应用程序的补丁,该应用程序的所有者不再拥有 src 代码。
我在 main() 之前将一个 dll 注入(inject)到目标应用程序的 .exe 中。这个 dll 安装了我做的补丁。
该应用程序有一个 C++ 自定义类型(类或结构),似乎是一个绘图字体管理器,它具有我需要通过其中一些补丁调用的功能。
我通常调用这些“ native ”成员函数的方式是创建一个包装函数,通过 asm 内联调用 native 成员函数。我这样做是因为我找不到如何通过 C++ 函数指针来完成此操作。
我再次尝试以一种比创建大量臃肿的函数包装器更好的方式来完成此任务。这次我尝试使用类/结构作为该 native 类型的虚拟包装器,但似乎我遗漏了一些我无法理解的与函数指针语法相关的内容。
这是我正在尝试做的示例:
/* 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
约定。
关于c++ - 如何使用函数指针从其内存地址调用成员函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54640172/