3

我正在对 Windows 可执行文件进行逆向工程。我从注入可执行文件(不同的线程,自己的堆栈)的一些代码中找到了一个我想使用的类。给定方法地址和成员变量结构,我将如何声明这样一个类?

例如,假设我找到了一个名为 foo 的类,它的构造函数 @ 0x4012D30 和一个函数 doTheMario @ 40125D4。我也知道它包含三个 DWORD 的私人数据。由于这两种方法都是 _thiscalls,我在我的代码中声明了一个这样的类:

class GuessedFoo {
    private:
        int bar;
        char *cafebabe;
        float deadbeef;
    public:
        GuessedFoo(int a, int b);
        void doTheMario();
};

现在,这是一个完美的花花公子类,但是现在有什么方法可以让编译器/链接器将类方法绑定到我前面提到的两个地址?当然,我可以编写一个 asm 包装器,为我需要使用的每个方法将 stdcall 转换为 thiscall,然后使用结构而不是类,但必须有更好的方法。

我目前使用 gcc/g++,但我可以切换到 VC++(因为 gcc 的内联 asm 无论如何都让我头疼)。

4

4 回答 4

4

如果该类没有 vtable,原则上,您可以在自己的代码中创建这样的类,其中所有函数调用都会调用适当的实际实现。您可以通过将成员函数作为包含汇编跳转指令的裸函数来执行此操作,以实现真正的实现。

如果这个类有一个 vtable,事情可能会变得更加复杂;您可能需要将 vtable 显式创建为函数指针的结构,并让您的函数存根调用它们。这意味着更复杂的垫片功能;一个简单的带有跳转的裸函数可能还不够,使用真正的函数可能会更好。但是请记住,win32 上的成员函数使用不同的调用约定;这意味着普通的成员函数调用将不起作用。您可能能够摆脱构建指向成员函数的指针,但请记住它们对它们有一个相当奇怪的结构,您需要将它与具有与 vtable 指针相同表示的东西匹配。祝你好运!

于 2010-08-06T05:35:30.653 回答
1

您在这里进行逆向工程,因此(几乎,可能)在与现有代码交互时被迫降低。

我会使用纯汇编代码调用这个函数。
如果 EXE 的基地址是固定的,那就更容易了。
示例代码:

void main()
{
    int bar = 5;
    int * cafebabe = &bar;
    __asm
    {
        push [bar];
        push [cafebabe];
        mov eax, 123456; // address of the function
        call eax;
    }
}

只需检查原始代码是如何调用此函数的,以查看您需要按什么顺序推送参数。不要忘记一些参数可能需要通过寄存器传递!

于 2010-08-06T05:39:42.970 回答
0

我不完全确定我是否正确理解了您,但无论如何:我认为“手动定位”方法的最简单途径是使用函数指针。

于 2010-08-06T05:05:08.263 回答
0

C++ 没有定义任何类型的二进制接口,因此几乎不可能为 C++ 类实现任何类型的动态绑定。

您可以做的最好的事情是声明两个结构 - 一个包含每个方法的 c 函数 typedef,另一个反映类数据布局。

当然 - 因为类方法上的 __thiscall 通过 ecs 寄存器传递 'this',我不相信您实际上可以做出具有相同效果的显式 c 函数声明,因此您可能需要通过自定义执行所有调用您在程序集中编写的“CallThisCallMethodWithParameters”。

于 2010-08-06T05:23:47.577 回答