2012-05-08 230 views
0

我一直在编程最近的弯路和所有的它。我绕道了很多不同的功能; thiscall,stdcall,cdecl,虚函数等。但有一件事我没有管理(这可能甚至不可能),那就是钩住基类虚函数。例如;有一个Car类声明一个虚函数(空)Drive。然后有3个其他车类继承汽车并实施Drive虚拟功能和绕行

如果我勾住车内的(基类)Drive功能(使用一个简单的“JMP”钩)将它由Car后裔被触发,当他们引发Drive,如果他们这样做调用基函数?

为了更彻底地解释:

class Car 
{ 
    virtual void Drive(void) { } // Empty virtual function 
} 

class Lamborghini : public Car 
{ 
    void Drive(void) { // does lots of stuff, but does NOT call base function } 
} 

所以我不知道基方法获取的是否叫或者是否能以某种方式被钩住?请问功能exectution跳直接Lamborghini::Drive或是否以某种方式通过Car类,所以它的检测,只要一个电话后裔Drive

编辑:如果基类函数是空的,它甚至可以挂钩它,因为它需要5个字节的空间?

+0

http://en.wikipedia.org/wiki/Virtual_method_table也是这可能帮助,因为它你描述:http://code.google.com/p/ gmodmodules/source/browse/trunk/gm_slog/gm_slog/vfnhook.h?spec = svn74&r = 74 –

回答

5

没有,基本方法没有得到自动地调用。动态调度机制将检测哪个覆盖它需要调用,这将是被调用的函数。这通常通过虚拟表(vtable)来实现,该虚拟表存储指向类的每个虚拟函数的最终覆盖程序的指针。当使用动态分派时,编译器通过该表格注入间接调用并跳转到正确的函数。

注意,V表的呼叫转发到前实际持有指针的thunk蹦床可以潜在修改this(隐式的第一个参数)。使用这种方法的优点是,如果this不需要更新,编译器可以直接跳转到最终的覆盖。无论如何,你可以利用这个功能的优势和修改虚函数表指向你自己的代码(即您可以更新每个虚函数表--one每类型 - 指针指到自己功能

+0

不错:)完整答案! – besworland

+0

只是为了避免任何误解;这是可能的,我所需要做的就是修改虚拟表格?如果是这样的话,我也想问(由于缺乏知识),vtable是否只包含4个字节的指针?或者还有什么我现在应该(即它只是找到虚拟表和偏移量,然后取代指针指向我的'钩')? –

+0

@ElliottDarfink是的,你只需要找到vtable并替换指针。也可能是4个字节,但可能不取决于您的计算机的体系结构。 –

0

如果我正确地得到了您的问题,将根据虚拟功能表调用兰博基尼类中的Drive方法。如果你想调用一个基类的Drive方法,你必须写一些类似Car::Drive;的东西。由于VTBL,基类需要一些空间。希望我没有回答你的问题。

0

如果我理解正确的话,即使Lamborghini:Drive不直接调用基本函数,也要每次调用Lamborghini::Drive时都要调用Car::Drive

为此,最简单的方法是使用“内”功能,这将是虚拟的(和保护),而初始方法将非虚拟和将路由呼叫。 下面是一个例子:

class Car 
{ 
    void Drive(void) 
    { 
     // ... 
     Car::innerDrive(); // Base function call 
     // ... 
     this->innerDrive(); // 'Derived' function call 
     // ... 
    } 
protected: 
    virtual void innerDrive(void) { } // Empty virtual function 
} 

class Lamborghini : public Car 
{ 
protected: 
    void innerDrive(void) { // does lots of stuff, but does NOT call base function } 
} 
+0

问题是,我正在使用预编译的代码,这就是为什么我使用弯路:) –