0

私は最近、回り道とそれに付随するすべてを使ってプログラミングしています。私は多くの異なる機能を迂回しました。thiscall、stdcall、cdecl、仮想関数など。しかし、私が管理していないことが 1 つあります (これは不可能かもしれません)。それは、基本クラスの仮想関数をフックすることです。例えば; 仮想関数 (empty) を宣言する Car クラスがありますDrive。次に、 car を継承して を実装する他の 3 つの car クラスがありますDrive

Car の (基本クラス)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 }
}

それで、基本メソッドが呼び出されたのか、それとも何らかの方法でフックできるのか疑問に思っていますか? 関数の実行は直接ジャンプしますか、それとも何らかの方法でクラスLamborghini::Driveを通過するCarので、子孫が呼び出すたびに検出できますDriveか?

編集:そして、基本クラス関数が空の場合、5 バイトのスペースが必要なので、それをフックすることさえ可能ですか?

4

3 に答える 3

5

いいえ、基本メソッドは自動的に呼び出されません。動的ディスパッチ メカニズムは、どのオーバーライドを呼び出す必要があるかを検出し、それが呼び出される関数になります。これは通常、クラス内の各仮想関数の最終オーバーライドへのポインターを格納する仮想テーブル (vtable) によって実装されます。動的ディスパッチが使用されると、コンパイラはそのテーブルを介して間接呼び出しを挿入し、適切な関数にジャンプします。

vtable は実際には、呼び出しを転送する前に潜在的に変更される可能性があるサンクまたはトランポリンthisへのポインターを保持することに注意してください(暗黙の最初の引数)。このアプローチを使用する利点は、this更新する必要がない場合、コンパイラが最終的なオーバーライドに直接ジャンプできることです。いずれにせよ、この機能を利用して、vtables を変更して独自のコードを指すようにすることができます (つまり、各 vtable 内のポインターを更新して (タイプごとに 1 つ)、独自のサンクまたは関数を参照することができます) 。

于 2012-05-08T12:33:07.900 に答える
0

私が正しく理解していれば、基本関数を直接呼び出さなくても、呼び出さCar::Driveれるたびに呼び出されたいですか?Lamborghini::DriveLamborghini: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 }
}
于 2012-05-08T13:23:14.480 に答える
0

あなたの質問が正しければ、Lamborghini クラスのメソッド Drive が仮想関数のテーブルに基づいて呼び出されます。基本クラスの Drive メソッドを呼び出したい場合は、次のように記述する必要がありますCar::Drive;。また、VTBL のため、基本クラスにはある程度のスペースが必要です。あなたの質問に答えていないことを願っています。

于 2012-05-08T12:32:50.543 に答える