0

記述が不十分なコードの変更不可能なライブラリに対応するために、コードを少しハックするという課題に再び直面しました。

何時間も調査した後(関数ポインターにどのような状態も渡すことができないことがわかった後)、EAXを0xCCCCCCCCにリセットする関数ヘッダー内のASMバイトをNOPアウトする必要があります。

組み込みのVC++デバッガーを使用して関数の「アドレス」を取得し、チートエンジンでバイトの配列エントリを手動で作成することで(これはこの種のことには驚くほど便利です)、バイトを正常にプルアップし、NOPを実行できました。手動で5バイトのシーケンス。

ただし、これをプログラムで行うことは少し異なります。

次のいずれかを実行すると、アドレスはデバッガーが報告しているアドレスよりも大幅に高くなり、間違ったバイトへのポインターが表示されます。

unsigned int ptr = reinterpret_cast<unsigned int>(testhack);
unsigned char* tstc = (unsigned char*)&testhack;
FARPROC prc = GetProcAddress(GetModuleHandle("mod.dll"), "testhack"); // Still
                    // returns the incorrect address (same as the previous two)

正しいアドレスを見つけるためにデバッガーは何をしていますか?プログラムで正しいアドレスを見つけるにはどうすればよいですか?

4

2 に答える 2

1

おそらく、関数アドレスは DLL 内にあります。その場合、あなたが見ているのは、たとえば&testhack、プログラムがロードされているメモリの正しい場所にアドレスを再配置しているローダーです。デバッガーはおそらく再配置について既に認識しており、バイトを変更できるように自動的に処理してくれます。

残念ながら、これを回避するメカニズムはわかりませんが、静的にリンクすると、実行時ではなくリンク時にアドレスが修正されます。

于 2012-08-16T18:49:58.450 に答える
0

理解した。

ルックアップテーブル(私が信じているもの)を完全に忘れてしまいました。私が受け取ったアドレスは、ルックアップテーブルエントリへのポインタでした。これは、実際の関数本体への単純な5バイトの無条件JMPでした。オフセットを取得し、ルックアップテーブルエントリの最後に追加するだけで、正しいアドレスを取得できました。

関数の正しい開始アドレスに到達するためのコードは次のとおりです。

// Get the lookup table address
const char* ptr = (const char*)&testhack;
// Get the offset (+ 1 byte retrieved as a long)
unsigned int offset = (unsigned int)(*((unsigned int*)(ptr + 1)));
// Add to the original look up pointer, +5 (the offset starts after the
//    end of the instruction)
const char* tst = (const char*)(ptr + offset + 5);

tst次に、正しいアドレスを保持します!

現在のところ、ASM命令を呼び出すと、関数ポインターを含む構造体へのポインターがEAXに配置されます。通常、コールバック関数はEAXをリセットします。しかし、私はこのハックを適用し、その部分をNOPしました。mov [ptr],eax関数内のコードの最初の行はローカルポインターを作成し、次にアドレスへのインラインアセンブリをポインターに入れます。そうすれば、ポインタを通常どおりに使用できます。

于 2012-08-16T18:55:03.310 に答える