简体   繁体   English

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

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

I'm developing a patch to an old application which the owners doesn't have the src code anymore. 我正在为旧应用程序开发补丁,该应用程序的所有者不再拥有src代码。

I'm injecting a dll into the target application's .exe before its main(). 我在其main()之前将dll注入到目标应用程序的.exe中。 This dll install the patches I did. 这个dll安装了我做的补丁。

The application have a C++ custom type (class or struct) of what seems to be a drawing font manager which have functions that I need to call through some of these patches. 该应用程序具有C ++自定义类型(类或结构),似乎是图形字体管理器,具有一些我需要通过其中一些补丁调用的功能。

The way I usually call these "native" member functions is creating a wrapper function that calls the native member function through asm inline. 我通常称这些“本机”成员函数的方式是创建一个包装函数,该函数通过asm内联调用本机成员函数。 I do this way because I can't find out how to accomplish this through C++ function pointers. 我这样做是因为我无法找到如何通过C ++函数指针来完成此操作。

I'm trying again to accomplish this in a better way than creating a lot of bloated function wrappers. 与创建许多肿的函数包装器相比,我再次尝试以更好的方式完成此任务。 This time I'm trying to use a class/struct as a virtual wrapper of that native type, but it seems I'm missing something related to function pointer syntax that I can't figure out. 这次,我尝试使用类/结构作为该本机类型的虚拟包装器,但是似乎缺少与我无法弄清的函数指针语法相关的内容。

This is a sample of what I'm trying to do: 这是我正在尝试做的一个示例:

/* 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)();
}

In case it is clear what I want, is there a better way to accomplish it besides that function wrappers? 如果很清楚我想要什么,除了该函数包装器之外,还有更好的方法吗?

Thanks in advance. 提前致谢。

One of your problems is at least that your code doesn't match your question. 您的问题之一至少是您的代码与您的问题不匹配。 You talk about function pointers, yet you write void(NC_FontDevice::*_UseTexturesTransparency)() . 您谈论的是函数指针,但您编写的是void(NC_FontDevice::*_UseTexturesTransparency)() That is not a function pointer. 不是函数指针。 That is a pointer to member function (PMF). 这是指向成员函数(PMF)的指针。 Entirely different beasts, and you can't assume these are simple pointers. 完全不同的野兽,您不能假设它们是简单的指针。 They're generally not even the same size. 它们通常甚至都不相同。

I suspect that you've found a function at 0x635FD0 . 我怀疑您在0x635FD0处找到了一个函数。 That function probably looks like void _UseTexturesTransparency(NC_FontDevice*) . 该函数可能看起来像void _UseTexturesTransparency(NC_FontDevice*) Sure, it might have been (part of) a member function when it was compiled, but that doesn't really matter. 当然,在编译时它可能是成员函数的一部分,但这并不重要。 This is hacking, we're being pragmatic here. 这是黑客行为,我们在这里很实用。 Why deal with the complexities of a PMF if we can treat this as an ordinary function pointer? 如果我们可以将它视为普通的函数指针,为什么还要处理PMF的复杂性呢?

[edit] Per the comments, MSVC++ will have used ECX for the this argument in member functions; [edit]根据注释,MSVC ++将在成员函数中使用ECX作为this参数。 as it happens it also supports the __fastcall calling convention for regular functions which puts the first 32 bit argument in ECX . 碰巧的是,它还支持常规函数的__fastcall调用约定,该约定将前32位参数放入ECX It's not a perfect replacement; 这不是一个完美的替代品。 __fastcall also uses EDX for its second argument. __fastcall还使用EDX作为第二个参数。 You might need a dummy argument there, if the existing code expects further arguments on the stack. 如果现有代码在堆栈上需要其他参数,则可能需要在其中使用虚拟参数。

You can check for stack arguments because under the __thiscall calling convention for member functions, the callee cleans the stack. 您可以检查堆栈参数,因为在成员函数的__thiscall调用约定下,被调用方将清理堆栈。 Luckily this matches the __fastcall convention. 幸运的是,这与__fastcall约定匹配。

Have you thought of using std::bind and std::function instead ? 您是否考虑过使用std :: bind和std :: function代替? C++11 and boost have it. C ++ 11和boost有它。

    std::function x = std::bind(&ClassName::function,this);

This will create a callback function which will work on your object. 这将创建一个对您的对象起作用的回调函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM