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

时间:2019-02-11 22:33:53

标签: c++ function-pointers inline-assembly

我正在为旧应用程序开发补丁,该旧应用程序的所有者不再具有src代码。

我正在将dll注入目标应用程序的.exe的main()之前。该dll将安装我所做的补丁。

该应用程序具有C ++自定义类型(类或结构),似乎是图形字体管理器,具有一些我需要通过其中一些补丁调用的功能。

我通常称这些“本机”成员函数的方式是创建一个包装函数,该函数通过asm内联调用本机成员函数。我之所以这样做,是因为我无法找到如何通过C ++函数指针来完成此操作。

与创建大量of肿的函数包装器相比,我再次尝试以更好的方式完成此任务。这次,我试图使用类/结构作为该本机类型的虚拟包装,但是似乎我缺少与我无法弄清的函数指针语法相关的内容。

这是我正在尝试做的一个示例:

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

如果很清楚我想要什么,除了该函数包装器之外,还有更好的方法吗?

谢谢。

2 个答案:

答案 0 :(得分:3)

您的问题之一至少是您的代码与您的问题不符。您谈论的是函数指针,但是您编写了void(NC_FontDevice::*_UseTexturesTransparency)()。那不是不是函数指针。这是指向成员函数(PMF)的指针。完全不同的野兽,您不能假设它们是简单的指针。它们通常甚至都不相同。

我怀疑您在0x635FD0处找到了一个函数。该函数可能看起来像void _UseTexturesTransparency(NC_FontDevice*)。当然,在编译时它可能是成员函数的一部分,但这并不重要。这是黑客行为,我们在这里很实用。如果我们可以将它视为普通的函数指针,为什么还要处理PMF的复杂性呢?

[编辑] 根据注释,MSVC ++将在成员函数中的ECX参数中使用this。实际上,它还支持常规函数的__fastcall调用约定,该约定将第一个32位参数放在ECX中。这不是一个完美的替代品。 __fastcall还使用EDX作为第二个参数。如果现有代码在堆栈上需要其他参数,则可能需要在其中使用一个哑元参数。

您可以检查堆栈参数,因为在成员函数的__thiscall调用约定下,被调用方将清理堆栈。幸运的是,这符合__fastcall约定。

答案 1 :(得分:0)

您是否考虑过使用std :: bind和std :: function代替? C ++ 11和boost拥有它。

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

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