以下のインターセプトメソッドが一般的に使用されます。
- 関数の位置に無条件ジャンプを挿入します(x86-5バイトjmp addr、x64-12バイト、mov rax addr、jmp rax)
- 元の関数呼び出しの場所への呼び出しステートメントの挿入(hooked_function_entry:call my_function)
- アプリケーションインポートテーブルの変更、プロキシDLLの実装。
- ハードウェアブレークポイントを使用してコードを変更せずに傍受する。
- Zw / Nt関数のカーネルドライバーを介した傍受。
ユーザーモードからのインターセプトを検出するための次のメソッドをリストできます。
1.呼び出す前の関数の先頭と機械語命令のオペコードとの比較:
//0x90 - nop //0xE9 - jmp //0xE8 - call if (*mainFunc == 0xE9 || *mainFunc == 0x90 || *mainFunc == 0xE8 ...) printf("Hook detected");
このメソッドは静的であり、よりインテリジェントな遷移を簡単に省くことができます。
2.上記のインターセプトの方法はメモリの修正であり、crcチェックサムチェックによって検出できますが、メモリを読み取るためのapiもインターセプトでき、誤った結果が返されます。
3.重要なAPIを復元して、制御されたプロセスを生成します(それ自体のアクティブなデバッグを使用)。
4.システムライブラリのエクスポートテーブルを使用して、重要なAPIを列挙し、逆アセンブルされた関数の長さと元の関数の長さを比較します。
5.ライブラリからバイトをコピーして変更されたAPIを復元するためのスキームの例は次のとおりです。
-特定のモジュールのベースを取得する
-イテレーションのエクスポート
-必要な機能のRVAを取得します。
-変換RVA-> FileOffset。
-オリジナルの読み取りとメモリへの書き込み。
-場合によっては、再ロックを忘れないでください。
6.ライブラリインポートテーブルを表示し、別のシステムライブラリからインポートされた関数ごとに、コンプライアンスチェックを行い、一致しない場合はディスクから読み取り、メモリに書き込みます。
7. syscalls、int2e in(windowsの古いバージョン)を使用したNt / Zwのシステム機能のシミュレーション、すべてのシステムのsyscallテーブルはGoogleで簡単に見つかります。
Nt / Zw関数もインターセプトできるため、7番目の方法について説明します。この方法も完全にはほど遠いですが、私の意見では、上記のすべての方法が最善です。
Windows 7 SP1でのNtCreateFile関数の実装を見てみましょう

次のことが起こります。
-eaxはsyscall-aの番号です。
-ecxをリセットします(wow64インデックス?)。
-edxには、パラメーターへのポインターが含まれています。
-さらに呼び出し、スタックの調整とリターン。
win7およびwin8でのx64呼び出し

次のx86擬似コードを使用して、「ディスク上にファイルを作成できます。」
// NtCreateFile typedef NTSTATUS (NTAPI * NTCREATEFILE) (OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength); #define InitializeObjectAttributes( p, n, a, r, s ) { \ (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } typedef VOID (NTAPI * RTLINITUNICODESTRING)(IN OUT PUNICODE_STRING, IN PCWSTR); unsigned char dNtCreateFile[] = {0xb8,0x52,0x00,0x00,0x00,0x33,0xc9,0x8d,0x54,0x24,0x04,0x64, 0xff,0x15,0xc0,0x00,0x00,0x00,0x83,0xc4,0x04,0xc2,0x2c,0x00}; ... RtlInitUnicodeString InitializeObjectAttributes ... DWORD oldp; VirtualProtect(&dNtCreateFile, sizeof(dNtCreateFile), PAGE_EXECUTE_READ, &oldp); auto func = (NTCREATEFILE) ((void*)dNtCreateFile); Ntstatus = (func)(&fileHandle, DesiredAccess, ObjectAttritubes, ioStatusBlock, 0, FileAttributes, ShareAccess, CreateDisposition ,CreateOptions, Optional_Buffer, 0);
この擬似コードはWindows 7 sp1でのみ機能しますが、ポイント5からの方法を使用してdNtCreateFileを「動的に」生成でき、その後、winxp以降のすべてのシステムで軽微な変更を加えたコードが機能します。 コメント内の考えは歓迎します。カーネルモードは極端なケースです。