C ++で文書化されていないクラスを使用します
-
26-09-2019 - |
質問
Windows実行可能ファイルをリバースエンジニアリングする過程にあります。実行可能ファイルに注入するコード(異なるスレッド、独自のスタック)に使用したいクラスを見つけました。メソッドアドレスとメンバー変数の構造を与えられた、そのようなクラスを宣言するにはどうすればよいですか?
たとえば、Fooというクラスを見つけたとしましょう。コンストラクター @ 0x4012D30とdothemario @ 40125d4の関数。また、プライベートデータの3つのdwordsを保持していることも知っています。両方の方法は_thiscallsであるため、コードでSOのようなクラスを宣言します。
class GuessedFoo {
private:
int bar;
char *cafebabe;
float deadbeef;
public:
GuessedFoo(int a, int b);
void doTheMario();
};
さて、これは完全にダンディクラスですが、コンパイラ /リンカーをクラスメソッドを以前の2つのアドレスにバインドする方法はありますか?もちろん、ASMラッパーを作成して、使用する必要があるすべての方法でstdcallをこのコールに変換し、クラスの代わりに構造体を使用することができますが、より良い方法が必要です。
現時点ではGCC/G ++を使用していますが、VC ++に切り替えることができます(GCCのインラインASMはとにかく頭痛がするため)。
解決
クラスにvtableがない場合、原則として、すべての関数呼び出しが適切な実際の実装を呼び出す独自のコードでそのようなクラスを作成できます。メンバーの機能を次のように絞ることでこれを行うことができます 裸の機能 実際の実装へのアセンブリジャンプ命令を含む。
クラスにvtableがある場合、事態ははるかに複雑になる可能性があります。 vtableを関数ポインターの構造として明示的に作成し、関数スタブを呼び出す必要がある可能性があります。これは、より複雑なシム関数を意味します。ジャンプを備えた単純な裸の機能では十分ではないかもしれず、実際の機能を使用する方が良いかもしれません。ただし、メンバーがwin32で機能することを覚えておいてください。 別の呼び出し条約;これは、通常のメンバー関数呼び出しが機能しないことを意味します。君は 五月 メンバーへのポインターを構築することで逃げることができますが、彼らが持っていることに留意してください むしろ奇妙な構造 彼らには、Vtableポインターと同じ表現を持つものと一致させる必要があります。幸運を!
他のヒント
ここではリバースエンジニアリングです。したがって、既存のコードとの対話に関しては、(ほぼ、おそらく)低くなることを余儀なくされています。
純粋なアセンブリコードを使用してこの関数を呼び出します。
EXEのベースアドレスが修正されている場合、さらに簡単になります。
例コード:
void main()
{
int bar = 5;
int * cafebabe = &bar;
__asm
{
push [bar];
push [cafebabe];
mov eax, 123456; // address of the function
call eax;
}
}
この関数が元のコードによってどのように呼び出されているかを確認して、引数をプッシュする必要がある順序を確認するだけです。いくつかの議論をレジスタを通過する必要があるかもしれないことを忘れないでください!
私はあなたを正しく理解しているかどうかは完全にはわかりませんが、とにかく:「手すり」の方法への最も簡単なルートは、機能ポインターを使用することだと思います。
C ++は、C ++クラスにあらゆる種類の動的結合を実装することはほとんど不可能であるため、いかなる種類のバイナリインターフェイスも定義されていません。
できる最善の方法は、2つの構造を宣言することです。1つは各メソッドのC関数Typedefを含み、もう1つはクラスデータレイアウトをミラーリングします。
もちろん - クラスメソッドで__ThiscallがECSレジスタを介して「This」を通過するため、同じ効果を持つ明示的なC関数宣言を実際に作成できるので、カスタムを介してすべての呼び出しを実行する必要があるかもしれませんアセンブリで書いた「CallThiscallMethodwithParameters」。