
C++ DLLで、PEヘッダーを解析し、インポートされた関数アドレスを対象プロセス内のカスタムフックへリダイレクトすることで、Import Address Tableフッキングを実行します。
フッキングとは、プログラムの実行フローをリダイレクトすることを可能にするテクニックです。ほとんどの場合、関数フッキングを使用します。関数を独自のものに置き換えるか、リダイレクトするかのいずれかであり、これは非常に便利で、複数のユースケースがあります。フッキングには複数の方法がありますが、ここでは IAT Hooking を見ていきます。これは Import Address Table の略です。実行時に埋められる大きなテーブル内の関数のアドレスを、独自のものに置き換えることで構成されます。別のリポジトリでも述べたように、このコードの IAT パース部分を理解するために PE Format についてもっと読むことをお勧めします。
以下は IAT Hooking がどのように機能するかの基本的な図です。この例では、悪意のあるコードが実行された後に元の関数が呼び出されています。この例では、元の関数の代わりに単に別の関数を呼び出します。このテクニックの利点は、通常の detours による .text パッチフックのように関数の本体を変更する必要がないことです。通常のフックでは、例えば jmp を配置するために関数の先頭の命令を変更しなければなりません。
実際には聞こえるよりもずっと簡単です。物事を簡単にするために内部的に進めます。つまり、このリポジトリは DLL にコンパイルされ、私の LoadLibraryA または Manual Mapping インジェクターを使用してターゲットプロセスに注入できます。
まず、ターゲットプロセスの PE Headers をパースして、次のように Import Descriptor を特定します:
process_base + nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
次に、インポートされた各モジュールをループし、このモジュール内の各関数をループして(ネストされたループの理由)、実行時に埋められたその関数のアドレスを見つけます。この例では、Windows が GUI のイベントを処理するために使用する TranslateMessage をフックします。その関数のアドレスを見つけたら、以前に定義した独自の関数のアドレスに置き換えます。これは内部からの実行であるため、リモートプロセスのコンテキスト内に存在します。その場所に書き込む権限があることを確認するために VirtualProtect を使用することを忘れないでください。
VirtualProtect(&firstThunk->u1.Function, sizeof(uint64_t), PAGE_READWRITE, &old_protection);
firstThunk->u1.Function = (uint64_t)hookfunction;
ご覧のとおり、notepad が TranslateMessage を呼び出すとき(ほぼ常に)、フック関数が実行され、最終的にメッセージボックスが表示されます!
image