文書化されていないWindows機能:レジストリキーのブレークポイント

場合によっては、プログラム(ドライバーを含む)のリバース開発中に、特定のレジストリキーで何らかのアクションを実行する瞬間にその実行を中断することが必要になる場合があります;この状況では、レジストリキーのブレークポイントの文書化されていない機能を使用できます。



初めて、レジストリキーのブレークポイントが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]
      
      





結論



説明した機能は、カーネルとドライバーのデバッグに直接関連する問題を解決するため、および指定されたレジストリキーを使用する調査中のシステムイメージ内のプログラムを検索するなど、サードパーティのタスクを解決するために使用できます。



All Articles