アプリケーション検証ツール - よく寄せられる質問(FAQ)

一般的な質問

アプリケーション検証ツールの一般的な使用方法に関する質問の一覧を次に示します。

アプリケーション検証ツールとは

アプリケーション検証ツールは、Microsoft Windows アプリケーションのバグを見つけるために使用されるランタイム検証ツールです。 これはランタイム ツールであるため、検証するにはアプリケーション コードを実行する必要があります。 そのため、適切なテスト カバレッジが不可欠です。

アプリケーション検証ツールの一般的な使用シナリオは、目的のアプリケーションに対して有効にし (その方法については、以下の質問を参照)、アプリケーション用に記述したすべてのテストを実行することです。 デバッガーの中断または検証者のログ エントリの形式で見つかったバグに関する通知が表示されます。

アプリケーション検証ツール操作方法アンインストールしますか?

アプリケーション検証ツールをアンインストールするには、[スタート] をクリックしてコントロール パネルにアクセスし、[プログラムの追加と削除]、[プログラムの削除]、[アプリケーション検証ツール] の順にクリックし、[削除] をクリックします。

アプリケーション検証ツール操作方法起動しますか?

アプリケーション検証ツールをインストールした後は、プログラムの一覧からアプリケーション検証ツールにアクセスするか、コマンド ラインで「Appverif.exe」と入力して起動できます。 これを行うには、コマンド プロンプトまたは [スタートアップ] メニューの [実行] ボックスに移動します。 「appverif.exe」と入力し、Enter キーを押します。 これにより、アプリケーション検証ツールが起動します。

Appverifer.exe バイナリはシステム ディレクトリにインストールされ、ツールの設定に使用されます。

ログの保存場所

ログは %U Standard Edition RPROFILE%\AppVerifierLogs に格納されます

アプリケーション検証ツールの使用中に問題が発生した場合はどうすればよいですか?

最新リリースを実行していることを確認します。 別の PC または Windows のバージョンでも同じアプリを試すことを検討してください。

アプリケーション検証ツールはマネージド コードを検証しますか?

AppVerifier は、オペレーティング システムとアプリケーションの間のインターフェイスを考慮します。 その結果、マネージド コードが、ヒープ、ハンドル、クリティカル セクションなどに関係するネイティブ API に対して相互運用を実行している場合を除き、テスト ケースでは検証されたインターフェイスとの対話は行われません。

マネージド コードを検証するために、マネージド デバッグ アシスタントを利用することをお勧めします。 詳細 については、 Windows デバッガーを使用したマネージド コードのデバッグに関する記事を参照してください。

デバッガーに関する質問

デバッガーに関して受け取った質問の一覧を次に示します。

デバッガーが必要であることを示すエラーが表示されたのはなぜですか?

アプリケーション検証ツール内の基本検証レイヤーでは、デバッガーでアプリケーションを実行する必要があります。 テストを選択する前にアプリケーションにデバッガーが関連付けられていない場合は、ログに記録された情報を取得するためにデバッガーでアプリケーションを実行する必要があることを示すダイアログが表示されます。

アプリケーション操作方法デバッガーで実行しますか?

デバッガーのインストールとセットアップに関するトピック - Windows デバッグの概要

操作方法他のインストルメンテーションなしでスタック拡張をテストしますか?

一般に、スタック拡張は、ヒープを含む他の検証レイヤーから分離して実際にテストする必要があります。 その理由は、各検証レイヤーが API またはエクスポートされたポイントを何らかのルーチンで "サンク" します。

たとえば、CreateFileA の呼び出しは appvocre!NS_SecurityChecks::CreateFileA、appvcore!NS_FillePaths::Kernel32 を呼び出す可能性がある CreateFileA!CreateFileA。検証ツールを呼び出す可能性があります。AVrfpNtCreateFile。ntdll!NtCreateFile。 インストルメンテーションによってさらに 3 つの "スタック" 関数呼び出しが追加され、それぞれがより多くのスタックを消費する可能性があることがわかります。

次の例では、LH-verifier.dllはすべての DllMain を "サンキング" しており、"インストルメント化された" ヒープ コード パスによりスタック使用量が追加されます。 デバッガーから挿入されたスレッドは既定のIMAGE_NT_HEADERSを使用しないため、最初にコミットされたスタックでは、スレッドの APC 状態 (APC 状態のスレッドが初期化コードを実行) を完了するのに十分ではありません。

Stack-Ckecs を使用する場合は、FirstChanceAccessViolation の場合に使用する必要がある他の検証レイヤーはおそらく唯一です。

!avrf 拡張機能を使用すると、"アプリケーション検証ツールはこのプロセスで有効になっていません..." が表示されます。

完全なエラーが発生しました。 Application verifier is not enabled for this process. Use appverif.exe tool to enable it.

shim 検証レイヤーだけが有効になっているか、ヒープが "純粋" モードで有効になっている可能性があります。 考えられる原因のいくつかを次に示します。

テスト シナリオに関する質問

さまざまなテスト シナリオに関して受け取った質問の一覧を次に示します。

サービスでアプリケーション検証ツールを有効にすることはできますが、他のサービスでは有効にできません。

System32 ディレクトリにsvchost.exeのコピーを作成し、コピーを "Mysvchost.exe" と呼びます。

regedit を使用して、HKLM\System\CurrentControlSet\Services\MyService を開きます。

"%SystemRoot%\system32\svchost.exe -k myservice" のような値 "ImagePath" を編集し、svchost.exeを "Mysvchost.exe" に変更します。

AppVerifier リストに "Mysvchost.exe" を追加し、必要なテストをチェックします。

再起動します。

WOW64 で実行されている 32 ビット アプリケーションから起動された 64 ビット アプリケーションでアプリケーション検証ツールを実行操作方法。

簡易バージョン: 特定のアプリケーションで検証ツールの設定を有効にするためのゴールデン ルールは、ツールとターゲット プロセスのビット数と一致することです。 つまり、32 ビット アプリケーション (両方とも WoW64 で実行) に 32 ビット appverif.exeを使用し、ネイティブ 64 ビット ネイティブ ターゲットには 64 ビット AppVerif.exeを使用します。

長いバージョン: アプリケーション検証ツールの設定は、"コア" 設定と "shim" 設定の適切な和集合です。

コア設定 - コア設定は、イメージ ファイル実行オプションの下に格納されます。

"デバッガー" 値は、起動アプリケーションから読み取られます。 そのため、32 ビット devenv.exeで 64 ビット my.exeを起動し、デバッガーで実行する場合は、WoW6432Node で 32 ビット レジストリ キーを使用する必要があります。 32 ビット プロセスの他の値は、ネイティブ IFEO と WoW6432Node の両方の場所から読み取られます。

その理由は次のとおりです。WoW で実行されている 32 ビット プロセスは、Wow64 エミュレーション ループを実行する 64 ビット プロセスです。 そのため、各 32 ビット プロセスは最初に 64 ビット プロセス、次に 32 ビット プロセスです。 64 ビット IFEO はWow64cpu.dll コードで検証ツールを有効にし、32 ビット IFEO では 32 ビット コードで検証ツールを有効にします。

エンド ユーザーの観点からは、verifier.dllは 2 回読み込まれます (64 ビット世界に 1 回、32 ビット世界に 1 回)。 ほとんどの人はwow64cpu.dllの検証を気にしないため、32 ビット プロセスで最も受け入れられる動作は、32 ビット部分のみを検証することです。 そのため、"常にビットネスと一致する" というゴールデン ルールが適用されます。

非対話型ウィンドウ ステーションで実行されるサービスをデバッグ操作方法

非対話型ウィンドウ ステーションで実行されるサービスをデバッグするには、次の操作を行います (ntsd/windbg を使用している場合にのみ適用されます)。

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image ファイル実行オプションでレジストリにキーを追加します。 このキーの名前は、プロセスの名前 (service.exe) にする必要があります。

Debugger というREG_SZ値を作成し、この値をデバッガーが存在するパスに設定します。 デバッガーの名前だけでなく、完全なパスを含む必要があります。 このコマンドには、–server オプションと、デバッガーがリッスンする必要がある特定のポートまたはポート範囲が含まれている必要があります。 たとえば、c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g –G です。

–remote オプションを指定してデバッガーを実行して、デバッガー サーバーに接続します。 たとえば、windbg.exe –remote tcp:=localhost,port=55xx です。サーバーで範囲を使用した場合、'xx' は 00 から 99 の数です。

AppVerifier はリーク検出を行いますか? Windows 7 以降では、プロセスがメモリをリークしたときに検出するリーク チェック オプションがあります。 以前のオペレーティング システムでは、AppVerifier はリーク検出のためにアプリケーションをテストしませんが、他のメモリの問題を探します。

セキュリティ上の問題に推奨されるテストはどれですか?

  • ヒープ
  • ハンドル
  • Locks
  • スタック (マシンを停止できるサービスと重要なプロセスの場合のみ)

ObsoleteAPICalls は、MSDN で廃止または非推奨として一覧表示されている API に対して表示されるすべての呼び出しに対して警告を吐き出すだけであることに注意してください。 アプリケーションが新しい API に切り替える必要がある場合は、ケースごとに決定する必要があります。 API の中には危険なものもあれば、より多くのオプションを備えた新しい API に置き換えられたものもあります。 「セキュリティで保護されたコードの記述」の「危険な API」セクションを参照してください。2 つ目の追加情報を参照してください。

サービスやサーバー プログラムなど、信頼性の高いアプリケーションの場合は、Stacks チェックも有効にする必要があります。 このチェック、スタックの増加を無効にすることで、スタック コミット サイズが適切かどうかを確認できます。 アプリケーションがスタック オーバーフローですぐに終了した場合は、より大きなスタック コミット サイズでアプリケーションを再コンパイルする必要があることを意味します。 テスターであり、Stacks チェックの使用中にアプリケーションで問題が発生した場合は、バグを報告し、開発者に割り当てて、テストを続けてください。

特定の質問をテストする

テストに関する質問の一覧を次に示します。 質問をクリックすると、次の応答が表示されます。

重要なセクション リークは重要ですか?

重要なセクションをリークするたびに、イベント ハンドル、少量のカーネル プール、小さなヒープ割り当てをリークします。 プロセスが終了すると、これらはクリーンされます。

プロセスが長期間存続する場合は、これらのリークが問題になる可能性があります。 修正は99%のケースで非常に簡単なので(開発者は RtlDeleteCriticalSection を呼び出すのを忘れただけです)、それらに対処する必要があります。

スタック オーバーフローをプログラムで処理できますか?

初期スレッド関数で例外ハンドラーを確立しても、発生する可能性のあるスタック オーバーフローをキャッチすることは保証されません。 これは、例外をディスパッチするコードでは、現在のアクティブ化レコードの上で実行するスタックも少し必要であるためです。 スタック拡張機能を失敗させたので、コミットされたスタックの最後をステップオーバーし、最初のスタックをディスパッチしようとしている間に 2 番目の例外を発生させる可能性が非常に高くなります。 二重障害例外は、プロセスを無条件に終了します。

LoaderLock テストで DestroyWindow の呼び出しに関するエラーが発生しています。 DllMain で DestroyWindow を呼び出すことはできません。 デタッチするスレッドは制御しません。 ウィンドウを作成したスレッドと同じでない場合は、ウィンドウを破棄できません。 そのため、ウィンドウがリークし、次にウィンドウがメッセージを受信すると、Wndproc がアンロードされたためにクラッシュします。

プロセスデタッチを取得する前に、ウィンドウを破棄する必要があります。 危険なのは、user32 がアンロードされることではありません。 危険は、あなたがアンロードされていることです。 したがって、user32 はそれ以上存在しない Wndproc にメッセージを配信するため、ウィンドウが受信する次のメッセージによってプロセスがクラッシュします。

Microsoft Windows オペレーティング システムにはスレッド アフィニティがあります。 プロセスデタッチは行いません。 ローダーロックは実際には大きな問題ではありません。問題は Dllmain です。 プロセスデタッチは、DLL が最後にコードを実行するタイミングです。 戻る前にすべてを取り除く必要があります。 ただし、Windows にはスレッド アフィニティがあるため、間違ったスレッドを使用している場合はウィンドウをクリーンできません。

誰かがグローバルフックがインストールされている場合(spy++が実行されているなど)、ローダーロックが画像に入ります。 この場合は、デッドロックの可能性があるシナリオを入力します。 ここでも、解決策は、プロセスデタッチを取得する前にウィンドウを破棄することです。

オーバーフローを回避するために初期スタック コミットを増やすとコストが高くなりますか?

スタックをコミットするときは、ページ ファイル領域を予約するだけです。 パフォーマンスへの影響はありません。 実際には物理メモリは使用されません。 追加コストは、コミットしたスタック領域に実際に触れた場合にのみ発生します。 ただし、スタックを事前にコミットしない場合でも、これはとにかく発生します。

svchost.exe で実行されているすべてのサービスを完全に保護するのにかかるコストを確認しましょう。 テストマシンでは、合計 139 スレッドを持つ 9 つの svchost.exe プロセスを取得します。 各スレッドの既定のスタックを 32K に設定した場合、すべてのスタックを事前にコミットするには、約 32K x 200 ~ 6.4 Mb のページ ファイル領域が必要です。

これは信頼性のために支払う非常に小さな価格です。

予約済みスタック サイズはどうですか?

IA64/AMD64 での例外ディスパッチなど、"予期しない" 追加スタックを必要とする興味深い項目があります。 スタック要件が過去の妥当な測定試行である RPC ワーカー スレッドで、いくつかの処理が行われている可能性があります。

まず第一に、プロセスに含まれるすべてのスレッド プールのアイデアを得る必要があります。 たとえば、SQL からデータベース コンポーネントを使用する場合、ユーザー APC のターゲットであるスレッド上でアラート可能なスリープを使用するため、警告可能な待機スレッドを含む NT-Thread-Pool は特別な場合があります。 これにより、入れ子になった呼び出しで問題が発生する可能性があります。

すべてのスレッド プールを把握したら、スタック要件を制御する方法を把握します。 たとえば、RPC はスタック コミットのレジストリ キーを読み取ります。 WDM ポンプ スレッドは、イメージから取得します。 その他のスレッド プールの場合、走行距離は異なる場合があります。

すべてのスレッドが明確になったら、何らかのアクションを実行できます。 大量の予約領域がない場合は、スレッドが頻繁に発生する場合にのみ、アドレス空間の断片化に役立ちます。 コントロール内に安定したスレッド プールがある場合は、予約領域を減らすという利点もあります。 これは、ユーザーのヒープとアドレス空間のアドレス空間を節約するのに本当に役立ちます。

LINKER_STACKCOMMITSIZE= に適したサイズを選択する方法に関する推奨事項はありますか?

値はページ サイズで割り切れる必要があります (CPU に応じて 4k/8k)。 必要なサイズを決定するためのガイドラインを次に示します。

  1. 潜在的な非連結深度 (または少なくともユーザーの誘導性の高い深さ) を持つ再帰関数を反復的に変換します。

  2. alloca の使用量を減らします。 ヒープまたは safealloca を使用します。

  3. スタック サイズを小さくチェック (8k など) で Prefast を実行します。 スタックが多すぎるというフラグが設定された関数を修正します。

  4. スタック コミットを 16k に設定します。

  5. アプリケーション検証ツールの "スタック" チェックを使用して、デバッガーの一連のテストで実行します。

  6. スタック オーバーフローが表示されたら、最悪の違反者を特定し、修正します。 (手順 5 を参照)。

  7. スタックの使用量を減らすことができない場合は、それ以上 8k 増やしてください。 > 64k の場合は、どこかに問題があります。64k に戻して、ステップ 6 を参照してください。 それ以外の場合は、手順 5 に進みます。

ヒープ テストのメモリ要件は何ですか?

完全なヒープ テストには、256 MB (メガバイト)の RAM と少なくとも 1 GB のページ ファイルが必要です。 通常のヒープ テストでは、少なくとも 128 MB (メガバイト)の RAM が必要です。 特定のプロセッサまたはディスクの要件はありません。

ALL_ACCESS停止を受け取る理由

_ALL_ACCESSを使用するすべてのアプリケーションは、アクセス対象のオブジェクトをレンダリングします。監査ログには、オブジェクトに対して実際に行ったことが反映されず、オブジェクトに対して実行するように求められた操作のみが反映されないためです。

この条件は、より悪質な攻撃のためのカモフラージュを作成します。 進行中の攻撃アクティビティをスキャンする管理者は、キー X に対してALL_ACCESSを要求しているユーザーに問題はありません。これは、特定のアプリケーションが常に行うためです。 管理者は、"ユーザーはおそらく Word を実行しているだけ" と考えるでしょう。 管理者は、ハッカーが私のアカウントに侵入したことを知ることができず、現在、私が持っているアクセスを決定するためにシステムを調べて、彼は彼の悪質な目的のために悪用することができます。 可能性は無限です。

ALL_ACCESSの ACL の問題は、常に付与する必要があるということです。 特定のキーへの DELETE アクセスをいつか拒否したい場合は、アクセスできません。 実際にキーを削除していない場合でも、削除アクセスを要求するため、アプリケーションが中断されます。

ヒープ テストとロック テストからログを取得しないのはなぜですか?

これらのテストは、動作中のシステム (パッケージ内ではなく) に構築された検証レイヤーであり、デバッガーでエラーを報告します。 これらのテストを有効にしてアプリケーションを実行し、クラッシュがない場合、問題は報告されません。

クラッシュが発生した場合は、デバッガーで実行するか、アプリケーションを開発者に渡して、より厳密にテストする必要があります。

フォールト インジェクションが機能しないのはなぜですか?

2007 年 2 月以降にリリースされた AppVerifier ビルドでは、お客様からのフィードバックに基づいて、フォールト インジェクション確率が 100 万個あたりの部品数に変更されました。 そのため、確率 0n20000 は 2%、0n500000 は 50% などです。

!avrf –flt デバッガー拡張機能を使用して、デバッガーの実行中の確率を変更できます。 ただし、これを機能させるには、プロセスの低リソース シミュレーション チェックをオンにする必要があります。

!avrf デバッガー拡張機能は、デバッガー パッケージに付属するexts.dllの一部です。 確率の変化をサポートする !avrf の変更は、最新のデバッガー パッケージに含まれています。 障害の挿入で問題が発生している場合は、デバッガーと AppVerifier パッケージを更新してください。

リーク検証ツールが特定のリソース リークを報告しないのはなぜですか?

DLL または EXE モジュールが読み込まれている間、リーク検証ツールはリソース リークを報告しません。 モジュールがアンロードされると、モジュールによって割り当てられたリソースのいずれかが解放されていない場合、Leak Verifier は停止を発行します。

読み込まれた DLL または EXE によって割り当てられたリソースを検査するには、!avrf -leak デバッガー拡張機能を使用します。

参照

アプリケーション検証ツール - 概要

アプリケーション検証ツール - 機能

アプリケーション検証ツール - アプリケーションのテスト

アプリケーション検証ツール - アプリケーション検証ツール内のテスト

アプリケーション検証ツール - 停止コードと定義

アプリケーション検証ツール - アプリケーション検証ツール停止のデバッグ