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

基本

少なくとも、[基本] 設定が選択された状態でアプリケーション検証ツールを実行する必要があります。 これらはそれぞれ、クラッシュやその他の否定的なシナリオを引き起こす領域をテストし、カスタマー エクスペリエンスに直接的かつ重要な影響を与えます。

  • 例外 - 構造化例外処理を使用して、アプリケーションがアクセス違反を隠さないようにします。
  • ハンドル - アプリケーションが無効なハンドルを使用しようとしていないことを確認するためのテスト
  • ヒープ - ヒープ内のメモリ破損の問題をチェックします
  • リーク - dllがアンロードされるまでに解放されていないdllによって作成されたリソースを追跡することで、リークを検出します
  • ロック - クリティカル セクションの正しい使用法を確認します。
  • メモリ - 仮想空間操作用のAPIが正しく使用されていることを確認します (VirtualAlloc、MapViewOfFileなど)。
  • SRWLock - スリム リーダー/ライター (SRW) ロックの正しい使用法を検証します。
  • Threadpool - スレッドプールAPIの正しい使用を保証し、ダーティなスレッドプール スレッドやその他のスレッドプール関連の問題など、コールバック後のワーカー スレッド状態の整合性チェックを実施します。
  • TLS - スレッド ローカル ストレージAPIが正しく使用されるようにします

これらのテストによって生成される停止コードの例外については、「アプリケーション検証ツール - 停止コードと定義」を参照してください。 これらのエラーのデバッグについては、「アプリケーション検証ツール - アプリケーション検証ツールの停止のデバッグ」を参照してください 。

互換性

互換性検証レイヤー テストは、Microsoft Windows オペレーティング システムに問題がある可能性があるアプリケーションを特定するのに役立ちます。 これらのチェックの多くは、ロゴ/認定要件のテストにも使用できます。

これらのテストによって生成される停止コードの例外については、「アプリケーション検証ツール - 停止コードと定義」を参照してください。

HighVersionLie — Windows で最も一般的なアプリケーション互換性の問題の一部に関する問題を特定します。 オペレーティング システムのバージョンを正しく検出しないか、ハードコーディングされたバージョン情報を使用すると、後のオペレーティング システムでアプリケーションが失敗する可能性があります。

Cuzz

コンカレンシー ファジー (Cuzz) 検証レイヤーは、コンカレンシーのバグとデータ競合状態を検出します。 Cuzz は、アプリケーションのコード内の重要なポイントにランダムな遅延を挿入することで、スレッド のスケジューリングを調整します。 次のシナリオは、Cuzz 検証レイヤーによって検出される可能性があるコンカレンシーのバグの種類を示しています。

アプリケーションには親スレッドと子スレッドがあります。 親スレッドは子スレッドを開始し、構造体にメモリを割り当てます。

// Parent Thread
StartChildThread(...);
g_pointer = ... malloc(...);

子スレッドはポインターを逆参照します。

//Child Thread
LONG value = g_pointer->someMember;

上記のコードには、コンカレンシーのバグがあります。 親スレッドがメモリを割り当てる前に子スレッドがポインターを逆参照しようとすると、ポインターは無効になります。 ほとんどの場合、親スレッドは子スレッドが開始される前にメモリを割り当てるので、バグが現れる可能性はほとんどありません。 ただし、まれに、子スレッドが開始され、親スレッドがメモリを割り当てる前にポインターを逆参照しようとする場合があります。

Cuzz 検証レイヤーを使用すると、前の例に示すようなコンカレンシーのバグが見つかる可能性が高くなります。 Cuzz では、遅延の挿入以外に追加のチェックは実行されません。 そのため、Cuzz に直接関連付けられた検証停止はありません。 ただし、Cuzz を有効にすると、コンカレンシーバグが現れる場合は、他の検証レイヤーが役立ちます。 たとえば、競合状態でヒープ オーバーフローが発生した場合、競合状態が実行時に現れる場合を除き、ヒープ検証レイヤーはエラーを検出しません。 競合状態が発生する確率を高めることで、エラーを特定するヒープ 層の有効性が向上します。

Cuzz の最大の利点を得るには、できるだけ多くのテストで Cuzz を有効にし、同じテストを何度も繰り返します。 手動テスト、機能テスト、ストレス テストなど、すべてのテストで Cuzz を有効にすることができます。 また、できるだけ多くのアプリケーション検証ツール検証レイヤーを有効にします。

同じランダム シードで Cuzz を指定することで、バグを再現する確率を高めることができます (「プロパティ」を参照)。

Cuzz は、Win32 同期 API 呼び出しでのみ遅延を挿入します。

Cuzz プロパティ

Cuzz 検証レイヤーでは、次のプロパティを使用できます。 プロパティを設定するには、アプリケーション検証ツールのユーザー インターフェイスで Cuzz レイヤーを選択し、プロパティ ウィンドウを開きます。

プロパティ 説明
FuzzingLevel Cuzz のファジー レベルを制御します。 タイム クリティカルなアプリケーションの場合は 1、通常のアプリケーションの場合は 4 に設定します。
RandomSeed 起動時に Cuzz によって使用されるランダム シード。 これを 0 に設定すると、Cuzz によって時間ベースのランダム シードが生成されます。

低リソースのシミュレーション

リソースが少ないシミュレーションでは、メモリ不足などのリソースが少ない環境をシミュレートしようとします。 このシミュレーションでは、メモリ不足状態で発生するバグを特定します。 これはフォールト インジェクションとも呼ばれます。 リソースが少ない環境をシミュレートできます。これによって、次のエラー確率呼び出しを示す数値 (0 ~ 100) を定義できます。

  • 待機 (WaitForXXXX API など)。
  • Heap_Alloc (ヒープ割り当て API)。
  • Virtual_Alloc (仮想メモリ割り当て API)。
  • レジストリ (レジストリ API)
  • ファイル (CreateFile などのファイル API)。
  • イベント (CreateEvent などのイベント API)。
  • MapView (CreateMapView などの MapView API)。
  • Ole_Alloc (SysAllocString などの Ole API)。

リソースが少ないシミュレーション (フォールト インジェクションとも呼ばれます) は、メモリ不足など、リソースが少ない環境をシミュレートしようとします。 これにより、メモリ不足状態のバグが特定されます。

低リソース シミュレーションのプロパティ

プロパティを編集するには、[テスト] 領域の [低リソース シミュレーション] チェック ボックスをチェックし、右クリックしてプロパティを選択します。

プロパティ 説明
包含 エラーの制限は、指定された dll でのみ発生します。 行ごとにパスのない 1 つの dll 名。 '*' を指定すると、すべてのモジュールでエラーが発生します。
含めない 指定したモジュールの障害を除外します。 行ごとにパスのない 1 つの dll 名。
タイムアウト プロセスの初期化時にエラーがない場合は、タイム スロット (ミリ秒) を指定します。
待機 WaitForXXXX API のエラー確率を示す数値 [0 – 1000000] です。
Heap_Alloc ヒープ割り当て API のエラー確率を示す数値 [0 – 1000000] です。
Virtual_Alloc 仮想メモリ割り当て API の障害確率を示す数値 [0 - 1000000] です。
レジストリ レジストリ API のエラー確率を示す数値 [0 ~ 1000000]。
ファイル CreateFile などの File API のエラー確率を示す数値 [0 - 1000000] です。
イベント CreateEvent などの イベント API のエラー確率を示す数値 [0 - 1000000] です。
MapView CreateMapView などの MapView API のエラー確率を示す数値 [0 - 1000000] です。
Ole_Alloc SysAllocStringt などの Ole API のエラー確率を示す数値 [0 - 1000000] です。
スタック 各 Windows アプリケーション スレッドは、スタック予約とスタック コミット サイズで始まります。 通常の使用では、スタックの領域が増える必要がある場合は常にスタックコミットが増加します。 詳細については、 スレッドの作成スレッド スタック サイズ に関するページを参照してください。 システムでメモリの不足状態が発生している場合、スタック コミットの増加が失敗する可能性があります。 スタックの拡張に失敗し、アプリケーション全体がクラッシュする可能性が最も高いスレッド。 このようなクラッシュは、重要なシステム プロセス (サービスなど) では受け入れられません。 Stacks チェックでは、検証中のアプリケーションのスタック拡張が無効になるため、システム全体のメモリ不足状態をシミュレートすることなくスタックの増加エラーがシミュレートされます。 例外は、アプリケーションがスタックを拡張しようとしたときにスローされます。 これにより、検証ツールの停止は生成されません。

LuaPriv

制限付きユーザー アカウント特権予測 (LuaPriv) テストは、予測と診断の両方であり、管理特権を持つアプリケーションの実行に関連する問題と、そのアプリケーションが (通常のユーザーとして) 低い特権で実行された場合に同様に機能するかどうかを示します。

UACチェックとも呼ばれ、制限付きユーザー アカウント特権予測子 (LuaPriv) には、次の2つの主要な目的があります。

  • 予測: 管理特権を持つアプリケーションを実行しているときに、そのアプリケーションが (一般的には通常のユーザーとして) 低い特権で実行された場合も同様に動作するかどうかを予測します。 たとえば、アプリケーションが管理者のみにアクセスを許可しているファイルに書き込む場合、そのアプリケーションが管理者以外として実行されている場合、同じファイルに書き込むことはできなくなります。

  • 診断: 管理者以外の特権で実行しているときに、現在の実行で既に存在する可能性がある潜在的な問題を特定します。 前の例の続きで、アプリケーションが、管理者グループ メンバーのアクセスのみを許可するファイルに書き込もうとすると、アプリケーションに ACCESS_DENIED エラーが表示されます。 アプリケーションが正しく動作しない場合、この操作が原因である可能性があります。

LuaPriv は、次の種類の問題を特定します。

潜在的な問題 説明
制限付き名前空間 名前空間を使用せずに名前付き同期オブジェクト (イベント、セマフォ、ミューテックスなど) を作成すると、オペレーティング システムで制限付き名前空間にオブジェクトを配置することが選択される場合があるため、オペレーティング システムによっては特権なしでの実行が複雑になる可能性があります。 このようなオブジェクトを制限付き名前空間 (グローバル名前空間など) に作成するには、管理者にのみ付与される SeCreateGlobalPrivilege が必要です。
LuaPriv でこれらの問題が検出された場合、その両方にフラグを設定します。
ハード管理者の確認 アプリケーションによっては、ユーザーのセキュリティ トークンを調べて、そのユーザーにどれだけの特権があるかを確認します。 このような場合、アプリケーションは、ユーザーの能力に応じて動作を変更する可能性があります。
LuaPriv は、この情報を返す API 呼び出しにフラグを設定します。
特権の要求 アプリケーションは、必要な操作を実行する前に、セキュリティ関連の特権 (SeTcbPrivilege や SeSecurityPrivilege など) を有効にしようとする場合があります。
LuaPriv フラグは、セキュリティ関連の特権を有効にしようとします。
特権がありません ユーザーが持っていない特権をアプリケーションが有効にしようとすると、アプリケーションが特権を期待していることが通知され、動作に違いが生じる可能性があります。
LuaPriv フラグが特権の要求に失敗しました。
INI ファイルの操作 マップされた INI ファイル (WritePrivateProfileSection および同様の API) への書き込みを試行すると、管理者以外のユーザーの場合は失敗する可能性があります。
LuaPriv は、このような操作にフラグを設定します。
アクセスが拒否されました アプリケーションがオブジェクト (ファイル、レジストリ キーなど) へのアクセスを試みたが、アクセス権が不十分なため失敗した場合、そのアプリケーションは、それ以上の特権で実行されることが期待されている可能性があります。
LuaPriv は、ACCESS_DENIED と同様のエラーで失敗したオブジェクトを開く試行にフラグを設定します。
ACE を拒否する オブジェクトの DACL に Deny ACE がある場合は、特定のエンティティへのアクセスが明示的に拒否されます。
これは一般的なものではなく、予測が困難になるため、LuaPriv は検出されたときに DENY ACE にフラグを設定します。
アクセス制限 アプリケーションが、通常のユーザーに付与されていない権限のオブジェクトを開こうとした場合 (たとえば、管理者のみが書き込み可能なファイルに書き込もうとしている場合)、通常のユーザーとして実行しても、そのアプリケーションは同じように動作しない可能性が高くなります。
LuaPriv は、このような操作にフラグを設定します。
MAXIMUM_ALLOWED アプリケーションが MAXIMUM_ALLOWED のオブジェクトを開くと、オブジェクトに対する実際のアクセス チェックが他の場所で行われます。 これを行うほとんどのコードは正しく機能せず、特権なしで実行するとほとんどの場合に異なる動作をします。
LuaPriv は、MAXIMUM_ALLOWED のすべてのインシデントにフラグを設定します。

その他

見落とされがちな問題は、その他のテストでキャプチャされます。

  • 危険な API — アプリケーションが次の安全でないアクションを使用しているかどうかを追跡します。
    • TerminateThread の危険な呼び出し。
    • メモリ不足状態でスタック オーバーフローが発生する可能性があります。
    • 複数のスレッドがまだ実行されている間に呼び出されるプロセスを終了します。
    • LoadLibrary は DllMain 中に呼び出されます。
    • FreeLibrary は DllMain 中に呼び出されます。
  • ダーティ スタックは、スタックの未使用の部分をメモリ パターンで (定期的に) 埋めます。 これは、そのスレッドのコンテキストで将来の関数呼び出しで初期化されていない変数を検出するのに役立ちます。
  • TimeRollOver は、GetTickCount API と TimeGetTime API を通常よりも速くロールオーバーするように強制します。 これにより、アプリケーションは時間ロールオーバーの処理をより簡単にテストできます。

その他のプロパティ

危険な API チェックには、次の 1 つのプロパティを変更できます。

DllMainCheck - DllMain がアクティブな場合に LoadLibrary/FreeLibrary 呼び出しを確認します。

ネットワーク

ネットワーク テストは、WinSock API の不適切な使用を探します。 たとえば、WSAStartup() が成功する前、または分散が成功した WSACleanup() 呼び出しの後にネットワーク API が呼び出された場合です。 WinSock の詳細については、 winsock.h ヘッダーWindows ソケット 2 を参照してください。

プロパティ

Net 検証レイヤーでは、次のプロパティを使用できます。 プロパティを設定するには、アプリケーション検証ツールのユーザー インターフェイスで ネットワーキング プロバイダーを選択し、プロパティ ウィンドウを開きます。

プロパティ 説明
FragmentsEnabled TCP IPv4 および IPv6 ソケットで受信したデータ ストリームのフラグメント化を有効にします。
FragmentSize Winsock 受信 API 呼び出しに対してバッファーに返される最大バイト数を指定します。

FragmentsEnabled プロパティを使用すると、ネットワーク検証ツール プロバイダーの機能を使用して、ネットワークから TCP ストリームを解析するアプリケーションのテストと検証を容易にします。 有効にすると、Winsock にデータを受信するすべての呼び出しは、返す前にバッファー全体が特に満たされている必要がない限り、FragmentSize バイトまでしか受信できません (MSG_WAITALL フラグによって制御されます)。 TCP プロトコルも Winsock もバッファーに返される可能性のあるバイト数に関する保証を提供しないため、このチェックを有効にすると、Winsock の呼び出しごとに受信したバイト数とは無関係に、ネットワークからデータのストリームを解析するコードが正しく行われるかどうかの確認が容易になります。 ストリーム パーサーの問題は注目度の高いバグの原因であり、これらのプロパティは、テストが特に困難であるため、正確性の検証を容易にするために提供されています。 注: これは返されるデータを変更しません。特定の速度で速度が低下するだけです。アプリケーションは、これを有効または無効にしてまったく同じ方法で動作する必要があります。

次のコマンド ラインでは、myApp.exeで作成されたすべての TCP IPv4 および IPv6 ソケットと、myApp.exeによって読み込まれるすべてのバイナリに対するすべての受信 TCP ストリームの断片化を有効にします。

appverif -enable Networking -for myApp.exe -with Networking.FragmentsEnabled=True Networking.FragmentSize=10

!avrf デバッガー拡張機能

!avrf -net -socket count - 開いているソケット ハンドルと閉じたソケット ハンドルの数を表示します

!avrf -net -socket dump [-v] [HANDLE] - ソケット ハンドルを詳細に表示します。

!avrf -net -wsastacks - WSAStartup/WSACleanup の現在の WSA init カウントとスタック トレースの時系列リストを表示します。

!avrf -net -wsastacks count - 現在の WSA init カウントを表示します。

!avrf -net -socket count - このコマンドを実行すると、追跡対象のソケット ハンドルの総数が表示されます(開いているものも閉じているものも同じ)。 これらは循環キューで追跡されるため、追跡される合計に上限があることに注意してください。 ソケット ハンドルを割り当てる Winsock API のいずれかが呼び出されると、開いているリストにソケットが追加されます。 たとえば、socket()、WSASocket()、accept() などです。 ソケットは、そのソケット ハンドルで closesocket() 関数が呼び出されると、開いているリストから閉じたリストに移動されます。

!avrf -net -socket dump [-v] [HANDLE] - このコマンドはソケット ハンドルを列挙します。 "-socket dump" は、追跡されているすべての開いているソケット ハンドルと閉じられたソケット ハンドルを SOCKET 値で一覧表示します。 オプションの -v フラグは、各 SOCKET 値を印刷した直後に、オープン呼び出し履歴またはクローズ呼び出し履歴を出力します。 省略可能な HANDLE フィールドには、指定された SOCKET ハンドルとそのオープンまたはクローズ呼び出し履歴のみが一覧表示されます。

さまざまな -socket 使用法オプションの例を次に示します。

0:008> !avrf -net -socket count
Number of open socket handles   = 16
Number of closed socket handles = 12
 
0:008> !avrf -net -socket dump
CLOSED SOCKET HANDLE - 0x47c
CLOSED SOCKET HANDLE - 0x2cc
CLOSED SOCKET HANDLE - 0x8c4
CLOSED SOCKET HANDLE - 0x6bc
CLOSED SOCKET HANDLE - 0x44c
CLOSED SOCKET HANDLE - 0x578
CLOSED SOCKET HANDLE - 0x6f4
CLOSED SOCKET HANDLE - 0x5b4
CLOSED SOCKET HANDLE - 0x4d8
CLOSED SOCKET HANDLE - 0x3cc
CLOSED SOCKET HANDLE - 0x4fc
CLOSED SOCKET HANDLE - 0x4e0
OPEN SOCKET HANDLE - 0xfd4
OPEN SOCKET HANDLE - 0x7d8
OPEN SOCKET HANDLE - 0xf8c
OPEN SOCKET HANDLE - 0xf88
OPEN SOCKET HANDLE - 0xae0
OPEN SOCKET HANDLE - 0xe58
OPEN SOCKET HANDLE - 0xdfc
OPEN SOCKET HANDLE - 0xcf8
OPEN SOCKET HANDLE - 0xa18
OPEN SOCKET HANDLE - 0x7a0
OPEN SOCKET HANDLE - 0x7b0
OPEN SOCKET HANDLE - 0x534
OPEN SOCKET HANDLE - 0xcdc
OPEN SOCKET HANDLE - 0x1f0
OPEN SOCKET HANDLE - 0x444
OPEN SOCKET HANDLE - 0x8bc
 
0:008> !avrf -net -socket dump -v 0x47c
 
The socket handle is closed
 
vfNet!VfHookclosesocket
WININET!ICSocket::_UnSafeCloseSocket
WININET!ICSocket::Dereference
WININET!CFsm_GetConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::OpenConnection_Fsm
WININET!CFsm_OpenConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::OpenConnection
WININET!HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm
WININET!CFsm_MakeConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::SendRequest_Fsm
WININET!CFsm_SendRequest::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start
WININET!CFsm_HttpSendRequest::RunSM
WININET!CFsm::Run
WININET!CFsm::RunWorkItem
SHLWAPI!ExecuteWorkItemThreadProc
vfbasics!AVrfpRtlWorkerCallback
ntdll!RtlpTpWorkCallback
ntdll!TppWorkerThread
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart

!avrf -net -wsastacks [count]

Winsock では、アプリケーション開発者が Winsock 呼び出しを行う前に、WSAStartup() を少なくとも 1 回呼び出す必要があります。 これは Winsock プロセス全体で追跡されます。 初期参照カウントは、Winsock カタログとプロバイダーを初期化して読み込むための Winsock ライブラリ (ws2_32.dll) に指示します。 WSAStartup のその後の呼び出しでは、その参照カウントがインクリメントされます。 Winsock では、アプリケーション開発者が Winsock への呼び出しが完了したら、WSACleanup() を呼び出す必要もあります。 WSACleanup への呼び出しは、WSAStartup() の前の呼び出しと正しくペアリングされている必要があります。 WSACleanup() の呼び出しにより、プロセス全体の参照カウントがデクリメントされます。 参照カウントが 0 になると、Winsock はリソースを解放し、Winsock カタログとプロバイダーをアンロードします。

このコマンドは、現在の "WSAStartup" 初期化ルーチンの全体的な参照カウント値を指定し、プロセス内で行われた WSAStartup および WSACleanup の呼び出しに対する呼び出し履歴を一覧表示します。 これはメイン固定循環キュー内に保持されるため、完了するとは限りません。N 個の最新の呼び出しのみであることに注意してください。

さまざまな -wsastacks 使用法オプションの例を次に示します。

0:008> !avrf -net -wsastacks count
 
Current WSARefCount: 1 (WSAStartup call count minus WSACleanup call count for the target process)
 
 
0:008> !avrf -net -wsastacks
 
Current WSARefCount: 1 (WSAStartup call count minus WSACleanup call count for the target process)
 
 
THREAD ID: 0xe4c called WSAStartup
vfNet!WSAInitStacks<NetAllocatorViaPrivateHeap>::AddWSAStackTrace
vfNet!VfHookWSAStartup
WININET!LoadWinsock
WININET!GlobalDataInitialize
WININET!InternetSetOptionA
WININET!InternetSetOptionW
IEFRAME!LCIEUpdateSessionStartTime
IEFRAME!LCIETab_ThreadProc
iertutil!_IsoThreadProc
vfbasics!AVrfpStandardThreadFunction
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart

NTLM

このアプリケーション検証ツール プラグインは、NTLM プロトコルの使用を検出するために、認証 API AcquireCredentialsHandle と InitializeSecurityContext への個々のプロセスの呼び出しを監視します。 NTLM は古い認証プロトコルであり、アプリケーションとオペレーティング システムのセキュリティを侵害する可能性があり、使用しないでください。

NTLM 認証リスク

古い NTLM 認証プロトコルの最も重要な欠点は、サーバー認証の欠如です。これにより、攻撃者がユーザーを偽装したサーバーに接続する可能性があります。 サーバー認証が不足している場合、NTLM を使用するアプリケーションは、"リフレクション" 攻撃と呼ばれる種類の攻撃に対しても脆弱になる可能性があります。 この後者を使用すると、攻撃者はユーザーの認証会話を正当なサーバーにハイジャックし、それを使用してユーザーのコンピューターに対して攻撃者を認証できます。 NTLM の脆弱性とその悪用方法は、セキュリティ コミュニティでの研究活動の増加のターゲットです。

Kerberos は長年使用されてきましたが、多くのアプリケーションは NTLM のみを使用するように記述されています。 これにより、アプリケーションのセキュリティが不必要に低下します。 ただし、Kerberos では、すべてのシナリオで NTLM を置き換えることはできません。主に、クライアントが do に参加していないシステムに対して認証を行う必要がある場合メイン (おそらくこれらの中で最も一般的なホーム ネットワーク)。 Negotiate セキュリティ パッケージは、可能な限り Kerberos を使用し、他のオプションがない場合にのみ NTLM に戻す、下位互換性のある侵害を可能にします。 NTLM の代わりに Negotiate を使用するようにコードを切り替えると、アプリケーションの互換性がほとんどまたはまったく導入されない一方で、お客様のセキュリティが大幅に向上します。 ネゴシエート自体は銀色の箇条書きではありません。攻撃者が NTLM に強制的にダウングレードできますが、悪用が大幅に困難な場合があります。 ただし、直ちに改善された 1 つは、ネゴシエートを正しく使用するように記述されたアプリケーションが NTLM リフレクション攻撃に自動的に影響を受けないということです。

NTLM の使用に対する最後の注意: Windows では、オペレーティング システム レベルで NTLM の使用を無効にすることができます。 アプリケーションが NTLM に対してハード依存関係を持っている場合、NTLM が無効になっている場合、認証に失敗するだけです。

アプリケーションで NTLM が "ハードコーディング" される原因となる要因は何ですか?

NTLM にハード依存関係を引き起こす要因は 2 つあります。 1 つ目は、アプリケーションで使用する認証パッケージとして NTLM を明示的に選択することです。 一部のプロトコルと API では、API AcquireCredentialsHandle () の呼び出しなど、NTLM の選択は明白です。 他のプロトコルの場合、それほど明白ではない可能性があります。 たとえば、RPC の既定の認証パッケージ (RPC_C_AUTHN_DEFAULT) は、実際にはネットワーク経由で RPC を使用する場合に NTLM のエイリアスであり、NTLM を選択するための明示的なフラグにも NTLM の省略形が含まれません (RPC_C_AUTH_WINNT)。 この種のコンストラクトを使用すると、必ずしもそれを行ったことを知らなくても、NTLM を簡単に選択できます。

NTLM の代わりに、開発者はネゴシエート パッケージなどの他の認証方法を使用する必要があります (これは SPNEGO または SNEGO パッケージとも呼ばれます)。 ネゴシエートで Kerberos を使用できるようにするには、クライアントコンポーネントとサーバーコンポーネントの両方でパッケージの選択が一致する必要があります。そのため、アプリケーションのクライアントとサーバーの両方の部分でネゴシエートを使用する必要があります。 いずれかの側で NTLM が使用されている場合 (レガシ バージョンの場合と同様)、ネゴシエートは引き続き機能しますが、常に NTLM に戻ります。 Negotiate を使用するようにアプリケーションに指示する方法は、プロトコルによって異なります。 最も一般的なプロトコル (RPC、LDAP、DCOM、HTTP) の一部については、トピック 5000 の後半で詳しく説明します。アプリケーションには NTLM パッケージが明示的に選択されています。

NTLM が使用される 2 つ目の要因は、クライアントが認証プロセスに有効なサーバー ターゲット名を指定しない場合です。 相互認証 (Kerberos など) をサポートまたは必要とするプロトコルでは、ターゲット名は相互認証を実現するために使用されます。 認証 API (InitializeSecurityContext など) は、省略可能なパラメーターを受け取り、通常は "TargetName"、"PrincipalName"、"ServerPrincipalName" と呼ばれます。 これは、ターゲット サービスの資格情報を取得するための適切な doメイン アカウントを選択するために doメイン コントローラーによって使用される識別子です。 NTLM にはサーバー認証の概念がないため、NTLM を正常に認証するためにこのパラメーターは必要ありません。 一方、Kerberos では、クライアントが認証しているサービスに対して有効なサービス チケットをクライアントが取得する必要があります。 ターゲット名または無効なターゲット名が指定されていない場合、Kerberos 認証は常に失敗します。 パッケージとして Negotiate が選択されている場合、ターゲット名 (または無効なターゲット名) を指定すると、Kerberos が完全にスキップされ、NTLM が使用されます。 ほとんどの認証 API には、ターゲット名が省略可能なパラメーターとして指定されています。NULL の場合はエラーが発生しません。 開発者がこれをオーバーライドし、明示的なターゲット名を指定しない限り、NTLM (さらに、反映可能な NTLM) が結果になります。

NTLM プラグインのしくみ

検証ツール プラグは、次のエラーを検出します。

  • NTLM パッケージは、AcquireCredentialsHandle (またはそれ以上のレベルのラッパー API) の呼び出しで直接指定されます。

  • InitializeSecurityContext の呼び出しのターゲット名は NULL です。 この場合、ネゴシエートは NTLM に直接フォールバックします。

  • InitializeSecurityContext の呼び出しのターゲット名が、正しい形式の SPN、UPN、または NetBIOS スタイルの doメイン 名ではありません。 この場合、doメイン コントローラーは "プリンシパルが見つかりません" というエラーを返します。これにより、ネゴシエートが NTLM にフォールバックします。

このプラグインは、NTLM へのダウングレードを検出したときにも警告をログに記録します。たとえば、DOメイン コントローラーで SPN が見つからない場合などです。 これらは警告としてのみログに記録されます。これは、多くの場合、正当なケースであるためです。たとえば、参加していないシステムに対する認証メイン場合などです。

プラグイン停止オプションの構成

既定では、エラーとして分類されたすべてのイベントは、デバッグの中断を引き起こすように設定されます。 すべての警告イベントは、イベントの詳細のみをログに記録するように設定されます。

エラー イベントによって停止/中断が発生する:

  • 5000 – アプリケーションで NTLM パッケージが明示的に選択されている

  • 5001 – ネゴシエート パッケージ リストに NTLM のみが含まれる

  • 5002 – ネゴシエート パッケージ リスト間違った NTLM 除外

  • 5003 – サーバーのターゲット名または形式が正しくないターゲット名がありません

ログに記録された警告イベント:

  • 5010 – NTLM へのダウングレードが検出されました

NTLM 停止

5000 – アプリケーションで NTLM パッケージが明示的に選択されている

重要度:エラー

アプリケーションまたはサブシステムは、AcquireCredentialsHandle の呼び出しでネゴシエートの代わりに NTLM を明示的に選択します。 クライアントとサーバーが Kerberos を使用して認証できる可能性がある場合でも、NTLM を明示的に選択することでこれを防ぐことができます。

このエラーを修復する方法

このエラーの修正は、NTLM の代わりにネゴシエート パッケージを選択することです。 これを行う方法は、クライアントまたはサーバーで使用されている特定のネットワーク サブシステムによって異なります。 いくつかの例を次に示します。 使用している特定のライブラリまたは API セットに関するドキュメントを参照してください。

アプリケーションで使用される API(パラメーター) 不正な値 正しい値 メモ
AcquireCredentialsHandle (pszPackage) “NTLM” NEGOSSP_NAMEまたは "ネゴシエート"
RPC クライアント: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) RPC Server: RPCServerRegisterAuthInfo(AuthnSvc) RPC_C_AUTHN_WINNTまたはRPC_C_AUTH_DEFAULT RPC_C_AUTH_GSS_NEGOTIATE RPC サーバーが NTLM/WINNT パッケージを登録する際のエラーではありません。 これは多くの場合、NTLM のみをサポートする古いクライアントをサポートするために必要です。 NTLM パッケージのみが登録されている場合、Kerberos を使用できる場合でも、すべてのクライアントで NTLM が強制的に使用されるため、エラーになります。
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (COAUTHINFO 構造体の dwAuthnSvc メンバーとして渡され、それ自体が API に渡される CO Standard Edition RVERINFO 構造体のメンバーです) RPC_C_AUTHN_WINNT RPC_C_AUTHN_DEFAULTまたはRPC_C_AUTHN_GSS_NEGOTIATE ネゴシエートは、常にネットワーク経由で通信が行われる場合にのみ使用する必要があります。 同じコンピューター上のクライアントとサーバーの間で DCOM 呼び出しが発生した場合は、DEFAULT を使用し、使用する適切なパッケージを DCOM に選択できるようにする必要があります。
LDAP: ldap_bind_s (メソッド) LDAP_AUTH_NTLM LDAP_AUTH_NEGOTIATE
HTTP WinHTTPSetCredentials (AuthScheme) WINHTTP_AUTH_SCHEME_NTLM WINHTTP_AUTH_SCHEME_NEGOTIATE

5001 – ネゴシエート パッケージ リストに NTLM のみが含まれる

重要度:エラー

AcquireCredentialsHandle を使用する場合、Negotiate で使用または無視されるパッケージの一覧を指定できます。 指定されたリストによっては、最も適切で安全な認証パッケージを選択するために Negotiate に組み込まれているロジックがオーバーライドされる場合があります。 パッケージの一覧に NTLM のみが含まれているか、Kerberos が除外されている場合、結果はネゴシエートを完全にバイパスし、NTLM SSP パッケージを直接明示的に選択するのと同じです。

サブパッケージ リストを指定できるのは、AcquireCredentialsHandle を直接呼び出す場合のみです。これは、最も上位レイヤーの API (RPC など) では、呼び出し元がネゴシエート パッケージ リストを制御できないためです。

Microsoft では、アプリケーションがこのような方法で Negotiate パッケージ リストを操作しようとすることはお勧めしません。

このエラーを修復する方法

サブパッケージの一覧を指定せずに Negotiate パッケージを使用するか、Kerberos が含まれていることを確認します。

アプリケーションで使用される API(パラメーター) 不正な値 正しい値
AcquireCredentialsHandle (pAuthData パラメーターとして渡Standard Edition C_WINNT_AUTH_IDENTITY_EX構造体の PackageList メンバー) “!Kerberos” または “NTLM” NULL または "Kerberos、NTLM" または "Kerberos、!NTLM" または "!NTLM"

5002 – ネゴシエート パッケージ リスト間違った NTLM 除外

重要度 - 警告

AcquireCredentialsHandle を呼び出すとき、アプリケーションはネゴシエートでサポートされているパッケージの一覧から NTLM を除外しようとしました。 ただし、NTLM を除外するために間違った構文が使用されているため、一覧にメインされます。

このエラーを修正する方法 ネゴシエートから NTLM パッケージを除外するには、次の構文を使用します。

アプリケーションで使用される API(パラメーター) 不正な値 正しい値
AcquireCredentialsHandle (pAuthData パラメーターとして渡Standard Edition C_WINNT_AUTH_IDENTITY_EX構造体の PackageList メンバー) “-NTLM” “!NTLM”

5003 – サーバーのターゲット名または形式が正しくないターゲット名がありません

重要度:エラー

Negotiate パッケージを使用する場合、null または無効なターゲット名 (プリンシパル名とも呼ばれます) を指定すると、Kerberos が失敗し、NTLM がその代わりに使用されます。 認証呼び出しを行うときは、常に有効なターゲット名を指定する必要があります。 ターゲット名は、doメイン コントローラーが、アプリケーションが認証しようとしているサーバーのアカウントの詳細を取得できるようにする一意の識別子です。 doメイン コントローラーにこの情報が与えられると、クライアントとサーバーの両方で認識 (復号化可能) される適切な Kerberos チケットを作成できます。

このエラーを修復する方法

ターゲット名は 3 つの異なる形式で指定できます。各形式は、適切なサーバー アカウント オブジェクトを見つけるために doメイン コントローラーで使用できます。 これらの形式は、サービス プリンシパル名 (SPN)、ユーザー プリンシパル名 (UPN)、NetBIOS の 2 部構成の doメイン\account 名です。 SPN は最も一般的な形式であり、他の Kerberos 実装と最も相互運用可能です。 SPN の詳細については、このドキュメントでは説明しませんが、最も単純で最も一般的な SPN フォームには、サービス クラスとホスト名という 2 つの部分があります。 サービス クラスは、サーバー アプリケーションの種類 (http や ldap などの特定のアプリケーションの種類や、ホストとしてのジェネリックなど) を識別します。2 番目の部分は、サーバーの完全修飾 doメイン 名またはフラット (NetBIOS) 名です。 Windows クライアントとサーバーは、FQDN とフラット名の "ホスト" の SPN を自動的に登録します。 Doメイン コントローラーは、アプリケーション固有のサービス クラスの約 40 個を "http"、"ldap"、"rpc"、"tapi" などの "ホスト" SPN にマップします。

o サーバー オペレーティング システム (localsystem、ネットワーク サービス、localservice など) クライアント アプリケーションのコンテキストで実行されているアプリケーションのターゲット名を指定すると、自動的に登録された "ホスト" SPN またはそのエイリアスのいずれかを使用できます。 doメイン ユーザー アカウントのコンテキストで実行されているアプリケーションに対して認証を行うには、そのアカウントの SPN を登録する必要があります。

ユーザー アカウントの場合は、ユーザー アカウント名とアカウントが存在useraccountname@domain.domする doメイン から作成された暗黙的な UPN フォームを使用することもできます。 ユーザー アカウント用に追加の UPN を作成できますが (各 do に対して作成できる UPN サフィックスを使用メイン)、これらは Kerberos ターゲット名として機能しません。実際のログオン アカウント名と実際の実行に対応する UPN のみが使用できますメインアカウントが存在する場所です。

最後に、ローカル システム、ネットワーク サービス、または localservice として実行されているサービスの場合は、NT4 スタイルの doメイン\username (または doメイン\computername) を引き続き使用できます。 これは、doメイン ユーザー アカウントまたはコンピューター アカウントのコンテキストで実行されているターゲットに対して機能します。

アプリケーションで使用される API(パラメーター) ターゲット名を設定するパラメータ メモ
InitializeSecurityContext pszTargetName
RPC クライアント: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) ServerPrincipalName これは、サーバー/サービスが実行されているアカウントのターゲット名である必要があります。 RPCServerRegisterAuthInfo で設定された値と同じである必要はありません。
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (COAUTHINFO 構造体の dwAuthnSvc メンバーとして渡され、それ自体が API に渡される CO Standard Edition RVERINFO 構造体のメンバーです) pServerPrincName COLE_DEFAULT_PRINCIPALを使用して、COM がバインド情報から名前を自動的に選択できるようにする
LDAP: なし LDAP クライアントによって自動的に生成されます。
HTTP なし WinHTTP と WinInet は、URL サーバー名からターゲット名を指定します

5010 – NTLM へのダウングレードが検出されました

重要度 - 警告

アプリケーション固有のネゴシエートと正しい形式のターゲット名が使用されていても、ネゴシエートが NTLM にダウングレードされる原因として何かが発生しました。 状況によっては、エラーまたは予期される動作を示している可能性があります。 たとえば、コンピューターが doメイン の一部ではない場合、または doメイン コントローラーにアクセスできない場所で使用されている場合、ネゴシエートは NTLM を使用してアプリケーションを認証できるように自動的にダウングレードすることが期待されます。 ただし、ドメイン コントローラーが使用可能で、通常は Kerberos が使用されると予想される場合に、この停止が発生した場合は、ほぼ確実に何か問題があることを示しています。

このエラーを修復する方法

この状況で Kerberos を NTLM ではなく使用する必要があると判断したと仮定すると、ダウングレードが行われた理由は多数あります。

• ターゲット名が正しい形式であったとしても、ドメイン (またはフォレスト) に存在しませんでした。

o クライアント アプリケーションで正しいターゲット名を作成していることをチェックする必要があります。 サービス クラスは正しいですか? ホスト名は正しいですか?

o コンピューターまたは別の doメイン アカウントのコンテキストで実行されているサーバー プロセスです。 前者の場合、SPN は自動的に登録されます。後者の場合は、SPN を登録するか、暗黙的な UPN やフラット名などの代替形式を使用する必要があります。

o doメイン コントローラーまたは DNS サーバーとの通信を妨げるネットワーク接続の問題がある可能性がありますか?

o ターゲット SPN は複数のアカウントに登録されていますか? これにより、ドメイン コントローラーはそれに対する認証の試行を拒否します。

印刷

印刷検証ツールは、アプリケーションが印刷サブシステムを呼び出すときに発生する可能性のある問題の検出とトラブルシューティングに役立ちます。 印刷検証ツールは、印刷サブシステムの 2 つのレイヤーである PrintAPI レイヤーと PrintDriver レイヤーを対象としています。

印刷 API レイヤー

印刷検証ツールでは、プログラムと Winspool.drv と prntvpt.dll の間のインターフェイスのテストが行われ、それらの DLL のインターフェイスをテストします。 winspool.drv および prntvpt.dll でエクスポートされる API の MSDN ヘルプ セクションで、このインターフェイスで関数を呼び出すための規則を確認できます。

印刷ドライバー レイヤー

印刷検証ツールは、UNIDRV.DLL、UNIDRUI.DLL、PSCRIPT5.DLL、PS5UI.DLL、MXDWDRV.DLL などのコアプリント ドライバーと、プリント ドライバー プラグインとの間のインターフェイスもテストします。このインターフェイスに関する情報は MSDN と WDK にあります。

通常、デバッグ バージョンのみでアプリケーション検証ツールが実行されるため、パフォーマンスは通常問題になりません。 このアプリケーション検証ツール チェックまたは他のアプリケーション検証ツール チェックの使用によってパフォーマンスの問題が発生した場合は、必要なすべてのチェックを実行するまで、一度に 1 つずつチェックを実行します。

WebServices

Windows Webservices API (WWSAPI) 検証レイヤー

WWSAPI プラグインを使用すると、開発者は次のインスタンスをキャッチできます。

  • 無効な組み込み WWSAPI オブジェクトを参照する WWSAPI が呼び出されています。

  • 既に使用中のシングル スレッド オブジェクトを参照する WWSAPI が呼び出されています。

  • 非同期呼び出しが保留中で解放された組み込みオブジェクト。

  • 短いスレッドからのブロッキング API の呼び出し。

さらに、このプラグインは次のとおりです。

  • インスタンス化から削除までのオブジェクトの使用を追跡します。

  • 非同期的に完了できる呼び出しを強制的に同期的に完了させます。 これは、特定の動作に応じてアプリケーションがWS_ASYNC_CONTEXTを受け取る呼び出しを防ぐためです。

  • API が不適切なオブジェクトに渡されたとき、またはオブジェクトが !avrf –ws –obj デバッガー拡張機能を使用して使用されている場合に、人間が判読できる説明を提供します (以下を参照)。

  • チャネル、サービス プロキシ、およびサービス ホストの場合、追跡される各呼び出しには、オブジェクトの現在の状態が表示されます。

既定では、次のチェックが有効になっています。

プロパティ名DescriptionValidateObject組み込みオブジェクトが有効であることを検証しますTrackObjectオブジェクトの有効期間を通じてオブジェクトの使用を追跡します

プロパティ UI を使用してこのプロバイダーで有効にできるその他のチェックは次のとおりです。

プロパティ NameDescriptionCheckTimeoutValidates 非同期関数はタイムアウト内に完了します。TimeoutValForceSyncForce として指定されます。これは、WS_ASYNC_CONTEXT コンテキストが API に提供されるときに実行される同期パスです。

デバッガー拡張機能 (!avrf –ws –obj) が提供されています。この拡張機能には、開いている、または閉じられた組み込みの WWSAPI オブジェクトが表示されます。 この拡張子がオブジェクトによってサフィックス付けされている場合は、このオブジェクトの使用状況に関する詳細な情報が表示されます。

!avrf -ws –obj

このコマンドは、追跡中の組み込みの WWSAPI オブジェクトを表示します。作成済みオブジェクトとクローズオブジェクトの両方が表示されます。 閉じたオブジェクトは循環キューに格納されるため、追跡対象のオブジェクトの合計数に上限があることに注意してください。

次の API が正常に完了すると、オブジェクトが追加されます。WsCreateChannel()、WsCreateChannelForListener()、WsCreateServiceHost()、WsCreateServiceProxy()、WsCreateServiceProxyFromTemplate()、WsCreateError()、WsCreateHeap()、Ws WsCreateListener()、WsCreateMetadata()、WsCreateMessage()、WsCreateMessageForChannel()、WsCreateReader()、WsCreateWriter()、WsCreateXmlBuffer()、WsReadXmlBuffer()、WsReadXmlBufferFromBytes()

オブジェクトは、対応する WsFree*() 関数が呼び出されて完了すると、作成されたリストから解放されたリストに移動されます。

!avrf –ws –obj [OBJECT]

このコマンドは、組み込みの WWSAPI オブジェクトの使用法を表示します。 使用状況情報には、オブジェクトが作成、使用、解放されたときのスタックが含まれます。 オブジェクトがチャネル、サービス ホスト、またはサービス プロキシの場合、オブジェクトを使用する API が呼び出される前に、オブジェクトの状態が表示されます。

!avrf –ws –obj の使用オプションの例を次に示します。

0:001> !avrf -ws -obj
Objects dependent on internal objects allocated:


Objects currently allocated:

 0x00000000048566C0 (Type=Heap, Thread=0x000001bc, Pending Operations=0)
 0x0000000001BE6780 (Type=Error, Thread=0x000001bc, Pending Operations=0)
 0x0000000001C13580 (Type=Service Proxy, Thread=0x000001bc, Pending Operations=0)

Freed objects:

 0x0000000001C17170 (Type=Service Proxy, Thread=0x000001bc)
 0x0000000004856730 (Type=Heap, Thread=0x000001bc)
 0x0000000001BE6820 (Type=Error, Thread=0x000001bc)

0:001> !avrf -ws -obj 0x0000000001C13580

Object @ 0x0000000001C13580
        Type = Service Proxy
        Thread = 0x000001bc
        Internal Reference = 0x00000000026C5E80

Created stack:
  vfnws!VfHookWsCreateServiceProxy+0x00aa
  BLUESTONE!WST_WebServices::WsCreateServiceProxy+0x00d8
  BLUESTONE!ServiceProxy::Connect+0x0116
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Last 4 operations

Operation #1 created in thread 0x00000000000001BC

Service proxy state before operation = Created

Callstack:
  vfnws!VfHookWsGetServiceProxyProperty+0x0053
  BLUESTONE!WST_WebServices::WsGetServiceProxyProperty+0x009b
  BLUESTONE!ServiceProxy::GetState+0x004b
  BLUESTONE!ServiceProxy::VerifyState+0x001c
  BLUESTONE!ServiceProxy::Connect+0x01c7
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #2 created in thread 0x00000000000001BC

Service proxy state before operation = Created

Callstack:
  vfnws!VfHookWsOpenServiceProxy+0x0079
  BLUESTONE!WST_WebServices::WsOpenServiceProxy+0x0092
  BLUESTONE!ServiceProxy::Connect+0x03d3
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #3 created in thread 0x00000000000001BC

Service proxy state before operation = Open

Callstack:
  vfnws!VfHookWsGetServiceProxyProperty+0x0053
  BLUESTONE!WST_WebServices::WsGetServiceProxyProperty+0x009b
  BLUESTONE!ServiceProxy::GetState+0x004b
  BLUESTONE!ServiceProxy::VerifyState+0x001c
  BLUESTONE!ServiceProxy::Connect+0x0484
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #4 created in thread 0x00000000000001BC

Service proxy state before operation = Open

Callstack:
  vfnws!VfHookWsCall+0x00a6
  BLUESTONE!DefaultBinding_ICalculator_Add+0x008b
  BLUESTONE!ServiceModelTestGroup_Simple_Function+0x010a
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x069a
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Asynchronous Callback = BLUESTONE!ServiceModelTestGroup_Simple_Callback
Asynchronous CallbackState = 0x0000000005EBDC30

Completed asynchronously with HRESULT=0x00000000 in thread 0x00000000000001BC

Asynchronous callback stack:
  vfnws!VfHookWsCall+0x00e3
  BLUESTONE!DefaultBinding_ICalculator_Add+0x008b
  BLUESTONE!ServiceModelTestGroup_Simple_Function+0x010a
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x069a
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d


Closed stack:

0:001>

サービス

サービスは、Windows サービスを適切に使用するためにチェックテストします。 たとえば、サービスが正常に開始および停止されている場合などです。 これらのテストによって生成される停止コードの例外については、「アプリケーション検証ツール - 停止コード - サービス」を参照してください。

Perf

Perf テスト チェック、不適切な待機時間を使用する Windows 関数の呼び出しなど、システムのパフォーマンスとエネルギー消費量に影響を与える API を効率的に使用します。 これらのテストによって生成される停止コードの例外については、「アプリケーション検証ツール - 停止コード - Perf」を参照してください。

Hangs

Hangs は、DllMain スレッドがブロックされた別のスレッドを待機している場合などに、システムが応答しなくなる API の使用をテストします。 これらのテストによって生成される停止コードの例外については、「アプリケーション検証ツール - 停止コード - Hangs」を参照してください。

ARM64EC のサポート

次のプロバイダーはARM64ECをサポートしていないため、ARM64ECで実行されているプログラムがクラッシュします。

参照

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

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

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

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

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

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