我正在对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无论如何都让我感到头痛)。
答案 0 :(得分:4)
如果类没有vtable,原则上你可以在自己的代码中创建这样一个类,其中所有函数调用都会调用相应的实际实现。您可以通过将包含程序集跳转指令的naked functions成员函数拧到实际实现中来实现此目的。
如果班级有vtable,事情可能会变得复杂得多;您可能需要显式创建vtable作为函数指针的结构,并使函数存根调用它们。这意味着更复杂的垫片功能;一个简单的带跳跃的裸功能可能还不够,最好配合一个真正的功能。但请记住,win32上的成员函数使用different calling convention;这意味着普通的成员函数调用将不起作用。你可以能够建立指向成员函数的指针,但请记住,他们有rather strange structure,你需要将它与与vtable指针具有相同的表示形式。祝你好运!
答案 1 :(得分:1)
你在这里进行逆向工程,因此(几乎可能)在与现有代码交互时被迫降低。
我使用纯汇编代码调用此函数 如果EXE的基地址是固定的,那就更容易了 示例代码:
void main()
{
int bar = 5;
int * cafebabe = &bar;
__asm
{
push [bar];
push [cafebabe];
mov eax, 123456; // address of the function
call eax;
}
}
只需检查原始代码如何调用此函数,以查看推送参数的顺序。不要忘记可能需要通过寄存器传递一些参数!
答案 2 :(得分:0)
我不完全确定我是否理解正确,但无论如何:我认为“手动定位”方法的最简单方法是使用函数指针。
答案 3 :(得分:0)
C ++没有定义任何类型的二进制接口,几乎不可能为c ++类实现任何类型的动态绑定。
你能做的最好的事情是声明两个结构 - 一个包含每个方法的c函数typedef,另一个反映类数据布局。
当然 - 因为类方法上的__thiscall通过ecs寄存器传递'this',我不相信你实际上可以做一个具有相同效果的显式c函数声明,因此你可能需要执行所有的调用通过你在汇编中编写的自定义“CallThisCallMethodWithParameters”。