特別なプール (Special Pool)
皆さん、こんにちは。A寿です。
突然ですが、皆さんは、水陸両用バスに乗ったことはありますか?・・・このお話にご興味のある方は本文の最後の【閑話休題】までどうぞ。
さて、以前、さなえすさんの記事「ドライバー検証ツール」で、カーネルモードにおけるメモリ破壊 (プール破壊) の調査に、Driver Verifier と Gflags が効果的であるというご紹介をしました。今回は、その記事の補足として、特別なプール (Special Pool) についてお話ししようと思います。
特別なプールとは、上記の記事の「■Driver Verifier の設定」の「(4) チェックを行う項目にチェックボックスを ON にします」の画像(下図)にある通り、Driver Verifier の設定項目です。
この設定により、以下のような典型的なプール破壊を検出できます。
・解放後のプールにアクセス
・N バイト アロケートしたプールに N+1 バイト以上アクセス
以下の図のように、下方向に向かってアドレスの値が増えていくとしますと、特別なプールがない場合、自分のドライバのバッファ (N バイト) を超えた、アクセスをすることを「バッファオーバーラン」、自分のドライバのバッファより手前の領域にアクセスすることを「バッファアンダーラン」と言います。
バッファオーバーランやバッファアンダーランにより、自分のドライバのバッファに隣接する、自分以外のモジュールの領域に書き込んでしまいますと、自分以外のモジュールのデータが破壊されます。データが破壊されたタイミングでは必ずしも、BSOD になったりするわけではなく、かなり時間がたってからそのデータを使おうとして、挙動がおかしくなったり BSOD が起こったりして初めて気づき、それからダンプファイルを解析しても、誰が破壊したかは、わからないことが多いです。
そこで、特別なプールの出番です。これがあれば、上記のバッファオーバーランやバッファアンダーランを検出したタイミングで BSOD を発生させるので、破壊が発生したタイミングにより近い状態のダンプファイルを入手できます。
それでは、特別なプールの検証動作の詳細について、説明していきます。
特別なプールを有効にすると、通常のカーネルモードメモリプールではなく、検証用の特殊な領域 ( Special Pool 領域 ) からメモリを確保します。連続領域ではなく、意図的に分かれたページに配置し、前後に無効なページ(Invalid Page) を配置します。これにより、無効なページへの書き込みが発生したら、即 BSOD を発生させます。また、メモリを確保した場合、ページの余った領域には、特別なパターンの文字列を書き込みます。これにより、メモリ解放時に文字列が変更されていれば、BSOD を発生させます。
Gflags.exe の [System Registry] の [Kernel Special Pool Tag] (下図参照) を使うと、上記の検証動作を変更できます。
例えば、デフォルトでは Verify End が有効であるため、以下のような動作となります。
・バッファオーバーランの即時検出→Bugcheck Code 0xCD、0xD6
・メモリ解放時のSpecial Patterns の検証 (バッファアンダーランの検出) → 0xC1
・メモリ解放後のアクセス→ 0xCC
これを Verify Start を有効にするよう変更すると、以下のような動作となります。
・バッファアンダーランの即時検出→Bugcheck Code 0xCD
・メモリ解放時のSpecial Patterns の検証 (バッファオーバーランの検出) → 0xC1
・メモリ解放後のアクセス→ 0xCC
もしカーネルモードドライバー開発時にメモリ破壊が疑われる場合は、上記がご参考になれば幸いです。
ではまた。
[参考]
Driver Verifier
https://msdn.microsoft.com/en-us/library/windows/hardware/ff545448(v=vs.85).aspx
Special Pool
https://msdn.microsoft.com/en-us/library/windows/hardware/ff551832(v=vs.85).aspx
Bug Check 0xCD: PAGE_FAULT_BEYOND_END_OF_ALLOCATION
https://msdn.microsoft.com/en-us/library/windows/hardware/ff560219(v=vs.85).aspx
Bug Check 0xD6: DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION
https://msdn.microsoft.com/en-us/library/windows/hardware/ff560267(v=vs.85).aspx
Bug Check 0xC1: SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION
https://msdn.microsoft.com/en-us/library/windows/hardware/ff560183(v=vs.85).aspx
Bug Check 0xCC: PAGE_FAULT_IN_FREED_SPECIAL_POOL
https://msdn.microsoft.com/en-us/library/windows/hardware/ff560216(v=vs.85).aspx
――――――――――――――――
【閑話休題】突然ですが、皆さんは、水陸両用バスに乗ったことはありますか?
私は日本で乗ったかどうか思い出せませんが、海外では二回乗ったことがあります。
1回目は、北米で乗ったのですが、それほど観光すべきところがない割には、運転手やスタッフが、お客様を楽しませ、盛り上げようとしていて、初めて水陸両用バスに乗ったこと以上に楽しかったです。例えば、運転手は、話題や観光スポットに応じて次々とかぶる帽子を変えていきました。野球場などの観光スポットにくると、大きなホットドッグの形をした帽子をかぶって、左手で運転しながら右手のグローブを突き出して、「ボールを取ったぞー!」というアクションをしたり、ダンスミュージックをかけたかと思いきや、乗客に両手だけでできる振付をレッスンしだして、自分もハンドルから両手を放して手拍子したり、体の左右に両腕を振ったりと、非常に楽しいですが、同時に身の危険も感じる、スリリングな体験でした。(水陸両用バスで、湖に入ったのですが、そこで両手を放すならまだしも、市街地で十字路が多いところだったので焦りました。)
2回目は、東南アジア方面で乗ったのですが、普通に観光案内のアナウンスが流れるイヤホンをして、日本語の音声を聞きながら、通過する場所付近の観光情報を聞くだけのもので、こんなもんか~、という感じでした。おそらく、1回目が楽しすぎたので、感想がぱっとしなくなったのだと思います。
皆様も、継続していろいろ楽しむためには、初回にあまり衝撃的な体験をしないようご注意ください。