
A DTrace on Windows Reimplementation
Steve's Tracer。Windows システムコールフックの DTrace 再実装です。ハックなしの PatchGuard 互換 SSDT フックと考えてください。SSSDT(win32k API)はサポートされません。DTrace システムコール API 自体がこの追加テーブルをサポートしていないためです。Zw* カーネル API に加えて、すべてのユーザーモード SSDT システムコールをトレースできます。
STrace 用の新しいプラグインを開発する場合は、この README を最後までお読みください。
Windows 上の DTrace は複数のプローブタイプをサポートしています。これには syscall、fbt、etw、profile などが含まれます。この再実装は syscall と etw プローブタイプのみを再実装します。他のすべてのプローブタイプはこのプロジェクトの対象範囲外であり、今後もサポートされることはありません。追加のプローブタイプを追加したい場合は、プロジェクトをフォークしてください。対象範囲を syscall と etw プローブのみに限定したのは、他のプローブタイプとそれらが関わるシステムの複雑さによるものです。
この再実装は、D スクリプト言語(注: より一般的な現代言語である DLang ではない)を完全に廃止しています。元の DTrace 実装のようなカーネル内 VM の複雑さは、このプロジェクトには不適切です。その代わりに、この実装は DTrace Windows カーネルインターフェイスに接続するために必要な関連 C コールバックを直接公開します。スクリプトの「ホットローディング」を可能にするために、元の dtrace の VM + スクリプト環境の代わりとして DLL ベースのプラグインシステムが使用されました。このプラグインシステムは、セキュリティチェックや外部依存関係を有効にしない「通常の」ユーザーモード DLL を受け入れ、それをカーネルアドレス空間に手動でマッピングします。プラグイン DLL には、カーネルシステムコールコールバックが発生したときに呼び出されるエクスポートがあります。カーネル API は DLL の通常のインポートテーブル(IAT)を介して解決され、プラグイン DLL は ntoskrnl.lib にリンクし、ドライバーはロード時にこれらの API を解決するため、プラグイン DLL 内で任意のシステム API を通常どおり呼び出すことができます。このプラグインシステムのパフォーマンスは優れています。スクリプトインタープリターや JIT ではなく、ネイティブコードがシステムコールの ENTRY と RETURN の間で直接実行されるためです。この設計により、Microsoft が提供する dtrace 実装よりもパフォーマンスが向上します。
フックの設定は非常に簡単です。API 名でフックを登録/解除するルーチンと、システムコール前後のコールバックが用意されています。コールバックには、読み取り専用値としてアクセスできる引数と戻り値があります。戻り値は return プローブで偽装でき、引数は entry プローブで変更できますが、元のシステムコールを通常は置き換えたり「キャンセル」したりすることはできません。この API はオブザーバーとして機能します。ただし、(https://github.com/everdox/InfinityHook および https://github.com/everdox/InfinityHook/raw/master/resources/perf.png) に記載されているものと同様の見落としが存在し、スタック上のシステムコールポインターを置き換えることができます。この見落としにより、システムコールを、制御するルーチンへのポインターで完全に置き換えることが可能です。イベントが発生してフックコールバックが起動すると、好きなことを実行できます。コールバックは同期式です。つまり、エントリーコールバックで while ループに座るなどして実行を遅延させると、システムコール呼び出しもその時間だけ遅延します。システムコールの実行は、エントリーコールバックからの戻り直後、リターンコールバックのエントリー直前に行われます。このシステムは完全に PatchGuard 互換ですが、DSE は無効にする必要があります。残念ながら Microsoft はこの種のカーネル拡張を NT カーネルの一部と見なしており、ルート署名者が Windows であることを検証するためです。これは、カスタムカーネル署名者を有効にするようなトリックでは機能しません。DSE はカーネルブート中に本当に無効にする必要があります。
ValidationFlags=IMGP_LATEST_MS_ROOT_REQUIRED | IMGP_WINDOWS_ROOT_REQUIRED | IMGP_MS_SIGNATURE_REQUIRED
Scenario=ImgSigningScenarioWindows
Rust ドライバーは、C++ ドライバーで使用される DLL ベースのプラグインシステムを廃止し、代わりに Web アセンブリインタープリターを使用して wasm スクリプトを Windows カーネルでホストしようと試みます。これは、VM を使用する元の dtrace 実装により似せるためですが、DLang よりも優れた言語を使用します。これにより、サンドボックス化やその他の利点が得られます。POC は完成して動作しますが、残念ながら WASMI で WASM をインタープリター実行する際のパフォーマンス問題のため、実用には適しません。この代替設計を機能させるには、NT カーネル互換の JIT ベースの wasm エンジンが必要です。これは面白い目新しさとして含まれており、少し手を加えれば他の目的に使用できるかもしれません。
このプロジェクトは、主に C++ コンポーネントと Rust コンポーネントに分かれています。C ドライバーは機能が完全であり、優先して使用する必要があります。大まかに、プロジェクトには次のコンポーネントがあります。
Visual Studio と DDK をセットアップします。
ドライバーと CLI をビルドし、ファイルをスクリプトと同じフォルダーに移動して、install フォルダー内の PowerShell スクリプトを管理者として実行します。
./install_as_admin.ps1
再起動して、STrace ブートエントリーを選択し、この画面で F8 キーを押します(Enter ではありません!)。

この画面が表示されるので、DSE 無効で起動を選択します。

起動が成功したら、CLI を使用してプラグイン DLL をロードおよびアンロードしてトレースを開始できます。2 つのサンプルプラグインが用意されています。問題が発生した場合は、以下の詳細をよく読んでください。最初のうちはもう一度再起動する必要があるかもしれません。また、process hacker などのツールを使用して、STrace サービスを手動で「起動時」に自動開始するように設定する必要があるかもしれません。
元の DTrace のインストールはこちら: https://techcommunity.microsoft.com/t5/windows-kernel-internals/dtrace-on-windows-20h1-updates/ba-p/1127929。元の DTrace ではセキュアブートと仮想化ベースのセキュリティの構成が必要ですが、STrace ではそのような機能を必要とするプローブタイプ(FBT)を実装していないため、その必要はありません。
このプロジェクトはインストーラーと同じ操作を行いますが、MSI ではなく単純な PowerShell スクリプトを使用します。プロセスは単純です。まず apiset DLL を system32 にコピーして、カーネル拡張がアクティブになるようにします。次にドライバーエントリーをインストールして、ユーザーモード通信用にシステム起動時にドライバーメインが実行されるようにします。ApiSet DLL はデジタル署名されているため、必要に応じて元の Microsoft apiset が使用されました。このファイルはバイナリ形式でのみ提供され、拡張インポートを実装ドライバー(ext-ms-win-ntos-trace-l1-1-0 -> dtrace.sys)にポイントする以外のロジックは含まれていません。このメカニズムの詳細については、https://www.geoffchappell.com/studies/windows/win32/apisetschema/index.htm (ApiSetSchemaExtensions)を参照してください。
STrace はカーネル初期化の非常に早い段階で読み込まれるため、ブート構成データベース(BCD)でテスト署名を有効にするだけでは不十分です。ドライバー署名の強制(DSE)は、STrace が正常に読み込まれるために無効にする必要があり、これは毎回の起動時に手動で行う必要があります。これを容易にするために、インストールスクリプトはユーザーが選択しやすい簡単なブートメニューエントリーを作成します。再起動後も DSE を永続的に無効にできる BCD フラグはありません。カーネルがこれを明示的に禁止しているためです。
起動時に DSE を無効にするのを忘れると、再起動時に自動修復メニューに直行することになります。害なく再試行できますが、起動が失敗し続ける場合は、STrace ドライバーをドライバーフォルダーから手動で削除する必要があります。起動の失敗により、STrace サービスの自動実行フラグが Windows によって無効にされる可能性があることに注意してください。起動の失敗が発生した場合は、これを自動実行に戻す必要があるかもしれません。
独自のプラグインを開発するには、既存のプラグインのいずれかをベースプロジェクトとして使用するのが最適です。Visual Studio プロジェクトは、依存関係のない独立したバイナリを生成するために、非常に特殊な設定が多数設定されています。デフォルト以外の設定は多すぎて列挙できないため、プロジェクトの 1 つをコピーして、コードを変更して独自のロジックを追加してください(https://stackoverflow.com/questions/884255/visual-studio-copy-project)。**有用なプラグインを作成した場合は、PR を送信してください**! プラグインが増えれば増えるほど、このシステムは皆にとってより有用になります。