
Windows 10 21h1 上で TLS 変数を使用してすべてのシステムコールが確実にキャッチされるようにするインストルメンテーションコールバックの概念実証です。
Instrumentation callbacks(インストルメンテーションコールバック)は、Windowsのあまり文書化されていない面白い機能です。 このリポジトリ内のすべてのコードはMITライセンスの下で公開されています。 このリポジトリはGoogleスタイルのC++スペーシングを使用しています。
問題、バグを見つけた場合、または特定の機能を追加すべきだと考える場合は、PRを歓迎します。
インストルメンテーションコールバックを使用すると、コールバックを設定したプロセスによってディスパッチされるすべてのシステムコール(および例外!)を処理できます。
もちろん、すべてのシステムコールがキャッチされます。そのため、コールバックの実行中は、再帰を無限に続けたくない限り、通常は内部でこれ以上システムコールを発行すべきではありません。
これにより、コールバック内で実行できることが大幅に制限されるか、少なくとも何らかの設計上の課題が生じます。しかし、次の段落では、この問題に対するかなりエレガントな解決策を紹介します。
完璧ではありません。悪意のある攻撃者が意図的に変数を設定してコールバックを無効にすることも可能ですが、分析目的にはほぼ完璧です。
この問題に対する1つの解決策は、コールバックの分析機能を有効/無効にするフラグをtrue/falseに設定することです。これにより、別のシステムコールがすでに処理されている場合、本質的にすべてのシステムコールを通過させることができます。
しかし、これではほとんどのシステムコールが漏れてしまいます。
代わりに、このリポジトリでは、TLS依存の変数を設定することで、コールバック内でシステムコールを発行できないという問題を解決します。これにより、すべてのスレッドからのすべてのシステムコールを処理しつつ、自分自身でそれらを呼び出すことが可能になります。唯一見逃すシステムコールは、コールバック内部から発行するものだけです。これは(ソフトウェアを分析している場合など、ほとんどの状況では)おそらく問題になりません。
インストルメンテーションコールバックには多くの用途が考えられます。その1つはアンチチート目的です。プロセスからのシステムコールを分析し、それらが不正なアドレス空間から来ているのか、悪意のある目的で使用されているのかを判断できます。その際、システムDLLにバイトパッチやフックを仕込む必要はありません。
また、これらを使用してプロセス内でコード実行を得ることもできます。メモリを割り当てて書き込み、プロセス情報を設定できれば、システムコールを実行中のスレッドをハイジャックし、自分自身のコールバックを呼び出させることができます。
もちろん、私はこのリポジトリや他のリポジトリのコードをチート/悪意のあるソフトウェアの開発に使用することを容認しません。
これを使って何をするかは、あなた自身の責任です。