初めて、レジストリキーのブレークポイントがWindows XPに登場しました
BREAK_ON_OPEN
フラグ(デバッグフラグ)でレジストリキーを開くとき、またはそのようなキーの一部としてサブキーを作成するときに、カーネルはint 3命令を実行する機能を実現しました。

図 1:CmpDoOpen関数のスニペット
この機能は、サービスパックがリリースされる前からカーネルに登場しており、デバッグ(「チェック済み」)バージョンのカーネルをインストールする必要はありませんでした。 同時に、
BREAK_ON_OPEN
フラグを設定するためのAPI関数がなかったため、HEXエディターでレジストリハイブを使用してファイルを編集することによってのみ、このフラグをキーに設定できました。
Windows Vista以降、使用可能なデバッグフラグのリストが拡張され、NtSetInformationKey API関数を介してこれらのフラグを設定できるようになりましたが、機能自体はカーネルのデバッグバージョン(Windows Driver Kitから取得可能)にのみ残っていました。
タブ。 1:デバッグフラグの可能な値
旗 | 価値 | ご注意 |
---|---|---|
BREAK_ON_OPEN | 0x01 | キーオープニング |
BREAK_ON_DELETE | 0x02 | キーの削除 |
BREAK_ON_SECURITY_CHANGE | 0x04 | セキュリティ記述子の変更 |
BREAK_ON_CREATE_SUBKEY | 0x08 | サブキーを作成する |
BREAK_ON_DELETE_SUBKEY | 0x10 | サブキーを削除 |
BREAK_ON_SET_VALUE | 0x20 | 設定値 |
BREAK_ON_DELETE_VALUE | 0x40 | 値を削除 |
BREAK_ON_KEY_VIRTUALIZE | 0x80 | キー仮想化 |
デバッグフラグを設定するには、NtSetInformationKey関数を呼び出して、デバッグフラグを設定する最初の引数としてレジストリキーのハンドルを渡す必要があります。 2番目の引数はKeySetDebugInformationで、最後の2つの引数は、デバッグフラグ(または2つ以上のフラグの組み合わせ)の値を含むダブルワード(DWORD)を含むバッファーを記述する必要があります。
説明したブレークポイントをアクティブにするには、CmpRegDebugBreakEnabledカーネル変数の値を1に設定する必要があります。
例
例として、マウントされたボリュームに関する情報が保存されているレジストリキー「
HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices
」に値を書き込む瞬間をキャッチして、そこにデータを書き込むWindowsコンポーネントを決定してみましょう。 これを行うには、
BREAK_ON_SET_VALUE
デバッグフラグで指定されたキーをマークし、CmpRegDebugBreakEnabled変数の値を1に変更して
BREAK_ON_SET_VALUE
、テストディスクをフォーマットしてからマウントします。
その結果、ブレークポイントがトリガーされ、次のコールスタックが表示されます。
# Child-SP RetAddr Call Site 00 ffffd000`79b851a0 fffff803`7ccf88fa nt!CmSetValueKey+0x158 01 ffffd000`79b852b0 fffff803`7c69eac3 nt!NtSetValueKey+0x73e 02 ffffd000`79b85470 fffff803`7c697e40 nt!KiSystemServiceCopyEnd+0x13 03 ffffd000`79b85678 fffff803`7d08f11e nt!KiServiceLinkage 04 ffffd000`79b85680 fffff801`46d6fcaa nt!RtlWriteRegistryValue+0x9e 05 ffffd000`79b856f0 fffff801`46d6b58c mountmgr+0xecaa 06 ffffd000`79b85820 fffff803`7cd9cd78 mountmgr+0xa58c 07 ffffd000`79b85850 fffff803`7cd9bdd5 nt!PnpNotifyDriverCallback+0x1b8 08 ffffd000`79b85900 fffff803`7cdd6755 nt!PnpNotifyDeviceClassChange+0x2f9 09 ffffd000`79b859d0 fffff803`7c66dcb7 nt!PnpDeviceEventWorker+0x4c1 0a ffffd000`79b85b50 fffff803`7c5e7071 nt!ExpWorkerThread+0x177 0b ffffd000`79b85be0 fffff803`7c699836 nt!PspSystemThreadStartup+0x23d 0c ffffd000`79b85c60 00000000`00000000 nt!KiStartSystemThread+0x16
コールスタックは、レコードがmountmgrコンポーネントを開始することを明確に示しており、そのコードで必要なnt!RtlWriteRegistryValueコールを見つけることができます。
fffff801`46d6fca4 ff15fe44ffff call qword ptr [mountmgr+0x31a8 (fffff801`46d641a8)] // nt!RtlWriteRegistryValue fffff801`46d6fcaa 488d55b7 lea rdx,[rbp-49h]
結論
説明した機能は、カーネルとドライバーのデバッグに直接関連する問題を解決するため、および指定されたレジストリキーを使用する調査中のシステムイメージ内のプログラムを検索するなど、サードパーティのタスクを解決するために使用できます。