c++ - 关于修改虚表绕道的问题

标签 c++ gcc vtable detours abi

我一直在使用与 Microsoft Detours 相同的方法来练习 detours(用 jmp 和地址替换前五个字节)。最近我一直在阅读有关通过修改虚拟表来绕行的内容。如果有人能够通过提及此方法与前面提到的方法相比的一些优点和缺点来阐明该主题,我将不胜感激!

我还想询问有关堆栈上修补的 vtable 和对象的信息。考虑以下情况:

// Class definition
struct Foo
{
 virtual void Call(void) { std::cout << "FooCall\n"; }
};

// If it's GCC, 'this' is passed as the first parameter
void MyCall(Foo * object)
{
 std::cout << "MyCall\n";
}

// In some function
Foo * foo = new Foo; // Allocated on the heap
Foo foo2; // Created on the stack

// Arguments: void ** vtable, uint offset, void * replacement
PatchVTable(*reinterpret_cast<void***>(foo), 0, MyCall);

// Call the methods
foo->Call(); // Outputs: 'MyCall'
foo2.Call(); // Outputs: 'FooCall'

在这种情况下,foo->Call()最终会调用MyCall(Foo * object),而foo2.Call()调用原始函数(即 Foo::Call(void) 方法)。这是因为如果可能的话,编译器将尝试在编译时决定任何虚拟调用(如果我错了,请纠正我)。这是否意味着只要您使用堆栈上的对象(而不是堆分配的),是否修补虚拟表并不重要?

最佳答案

堆栈与堆并不重要 - 重要的是编译器在编译时知道对象的类型。除非优化器非常聪明,否则以下内容可能会生成相同的结果:

Foo foo2; // Created on the stack
Foo * foo = &foo2; // Also on the stack, in fact the same object

由于 foo2 的类型已知,编译器可以直接调用该函数,而无需查找任何 vtable。它不能对 foo 执行相同的操作,因为指针也可以指向派生对象。

关于c++ - 关于修改虚表绕道的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11435570/

相关文章:

c++ - 模板化构造函数的专用模板不会被调用

c++ - Visual C++ - 设置模板实例化的深度

gcc - LD:链接描述文件中的对齐与子对齐

C 中冲突的类型和变量命名

c++ - 如果派生类还具有基类中不存在的虚函数,则创建的 vptr 数

c++ - 虚函数和多重继承情况下的对象布局

c++ - 避免对仅在源文件中定义的类发出弱虚表警告

c++ libcurl - 使用前一个 curl 的响应作为另一个 curl 的参数

C++ CodeBlocks 反汇编;代码太多了?

c++ - 树向量化 : gcc optimization flag