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

基本

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

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

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

互換性

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

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

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

Cuzz

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

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

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

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

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

上記のコードには、同時実行のバグがあります。 親スレッドがメモリを割り当てる前に、子スレッドがポインターを逆参照しようとすると、ポインターは無効になります。 このバグは、ほとんどの場合、子スレッドが開始される前に親スレッドによってメモリが割り当てられるので、このような状況はほとんどありません。 ただし、まれに、子スレッドが開始され、親スレッドがメモリを割り当てられる前にポインターを逆参照しようとする場合があります。

Cuzz 検証レイヤーを使用すると、前の例で示したような同時実行のバグを検出する可能性が高くなります。 Cuzz では、挿入の遅延を除き、追加のチェックは実行されません。 そのため、Cuzz に直接関連する検証は停止されません。 ただし、Cuzz を有効にした場合、同時実行のバグが manifesting になると、他の検証レイヤーにメリットが得られます。 たとえば、競合状態が原因でヒープオーバーフローが発生した場合、競合状態が実行時にマニフェストに含まれていなければ、ヒープ検証レイヤーではエラーが検出されません。 競合状態が発生する確率を上げることにより、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)。
  • Registry (レジストリ API)。
  • File (CreateFile などのファイル API)。
  • イベント (CreateEvent などのイベント API)。
  • MapView (CreateMapView などの MapView API)。
  • Ole_Alloc (SysAllocString などの Ole API)。

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

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

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

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

LuaPriv

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

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

  • 予測: 管理特権を持つアプリケーションを実行している間に、(通常のユーザーとして) 低い特権で実行した場合に、そのアプリケーションが同様に機能するかどうかを予測します。 たとえば、アプリケーションが管理者のアクセスのみを許可するファイルに書き込む場合、非管理者として実行した場合、そのアプリケーションは同じファイルに書き込む必要があります。

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

LuaPriv は、次の種類の問題を識別します。

潜在的な問題 説明
制限付き名前空間 名前空間を使用せずに名前付き同期オブジェクト (Event、Semaphore、Mutex など) を作成すると、オペレーティング システムが制限付き名前空間にオブジェクトを配置する場合があるため、一部のオペレーティング システムでは特権なしで実行が複雑になる可能性があります。 このようなオブジェクトを制限付き名前空間 (グローバル名前空間など) に作成するには、SeCreateGlobalPrivilege が必要です。これは管理者にのみ付与されます。
LuaPriv では、これら両方の問題が検出された場合にフラグが設定されます。
ハード管理者のチェック 一部のアプリケーションでは、ユーザーのセキュリティ トークンを問い合って、自分が持っている特権の量を確認します。 このような場合、アプリケーションの動作は、ユーザーが持っていると思う力に応じて変更される可能性があります。
LuaPriv は、この情報を返す API 呼び出しにフラグを設定します。
特権の要求 アプリケーションは、必要な操作を実行する前に、セキュリティ関連の特権 (SeTcbPrivilege や SeSecurityPrivilege など) を有効にしようとする場合があります。
LuaPriv フラグは、セキュリティ関連の特権を有効にしようと試みる。
不足している特権 アプリケーションがユーザーに付与されていない特権を有効にしようとすると、アプリケーションが特権を期待している可能性が通知され、動作の違いが発生する可能性があります。
LuaPriv は、失敗した特権要求にフラグを設定します。
INI-File操作 マップされた INI ファイル (WritePrivateProfileSection および同様の API) への書き込みは、管理者以外のユーザーとして失敗する可能性があります。
LuaPriv は、このような操作にフラグを設定します。
アクセス拒否 アプリケーションがオブジェクト (ファイル、レジストリ キーなど) にアクセスしようとしても、アクセスが不十分な場合に試行が失敗した場合、アプリケーションはおそらく、より多くの特権で実行されている必要があります。
LuaPriv では、オブジェクトと同様のエラーで失敗するオブジェクトACCESS_DENIEDにフラグを設定します。
Deny ACEs オブジェクトの DACL に Deny AES がある場合、オブジェクトは特定のエンティティへのアクセスを明示的に拒否します。
これは一般的ではなく、予測が難しくなるので、LuaPriv では、見つけたら ACL を拒否するフラグを設定します。
制限付きアクセス アプリケーションが、通常のユーザーに許可されていない権限 (たとえば、管理者だけが書き込み可能なファイルに書き込もうとした場合) にオブジェクトを開しようとすると、通常のユーザーとして実行しても、アプリケーションは同じように動作しない可能性があります。
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() が正常Networking API前に、または分散が成功した WSACleanup() 呼び出しが行われた後に、 が呼び出された場合などです。 WinSock の詳細については、「winsock.h ヘッダー」と「Windows Sockets 2」を参照してください

Properties

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

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

FragmentsEnabled プロパティを使用すると、ネットワーク検証ツール プロバイダーの機能を使用して、ネットワークから TCP ストリームを解析するアプリケーションのテストと検証を容易に行えます。 有効にすると、Winsock を呼び出してデータを受信すると、アプリケーションが (MSG_WAITALL フラグによって制御される) 戻る前にバッファー全体を格納する必要がない限り、FragmentSize バイトまでしか受信されません。 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 Debugger Extension

!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 の 1 つが呼び出された場合、開いているリストにソケットが追加されます。 たとえば、socket()、WSASocket()、accept() などです。 ソケットハンドルで closesocket () 関数が呼び出されると、ソケットは、開いているリストから閉じられたリストに移動されます。

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

次に、ソケットのさまざまな使用方法の例を示します。

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 を呼び出すには、アプリケーション開発者が少なくとも1回 WSAStartup () を呼び出す必要があります。 これは、Winsock プロセス全体で追跡されます。 最初の参照カウントは、winsock ライブラリ (ws2_32.dll) に対して、Winsock カタログとプロバイダーを初期化して読み込むように指示します。 さらに WSAStartup を呼び出すと、その参照カウントがインクリメントされます。 また、winsock に ' finished'calling ' が含まれている場合、アプリケーション開発者は WSACleanup () を呼び出す必要があります。 WSACleanup の呼び出しは、WSAStartup () の前の呼び出しと正しく組み合わせる必要があります。 WSACleanup () の呼び出しは、プロセス全体の参照カウントをデクリメントします。 参照カウントがゼロになると、Winsock によってそのリソースが解放され、Winsock カタログとプロバイダーがアンロードされます。

このコマンドは、現在の "WSAStartup" 初期化ルーチンの全体の参照カウント値を指定し、プロセス内で WSAStartup と WSACleanup を呼び出した呼び出し履歴を一覧表示します。 これは固定された循環キュー内で保持されるため、完全な呼び出しだけが完了するとは限りません。

次に、さまざまな 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 を置き換えることはできません。たとえば、クライアントがドメインに参加していないシステムに対して認証する必要がある場合 (ホームネットワークはおそらく最も一般的であると考えられます)。 Negotiate セキュリティパッケージでは、可能な場合は常に Kerberos を使用し、他のオプションがない場合にのみ NTLM に戻るように、下位互換性のある侵害を行うことができます。 NTLM ではなく Negotiate を使用するようにコードを切り替えると、アプリケーション互換性をほとんどまたはまったく導入せずに、顧客のセキュリティが大幅に向上します。 自己交渉はシルバーの箇条書きではありません。攻撃者が NTLM に強制的にダウングレードする可能性はありますが、これらの脆弱性を悪用するのは非常に困難です。 ただし、ただちに改善されたのは、Negotiate を使用するように記述されたアプリケーションは、NTLM リフレクション攻撃に自動的には反映されません。

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

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

NTLM にハードな依存関係が生じる要因は2つあります。 1つ目は、アプリケーションで使用される認証パッケージとして NTLM を明示的に選択することです。 プロトコルと Api によっては、API Acquirecredentialshandle が () の呼び出しなど、NTLM の選択が明らかになります。 他のプロトコルについては、あまり明らかでない場合があります。 たとえば、rpc がネットワーク経由で使用されていて、NTLM を選択する明示的なフラグでも、ntlm の省略形がどこにもない場合 (RPC_C_AUTH_WINNT)、RPC の既定の認証パッケージ (RPC_C_AUTHN_DEFAULT) は実際には NTLM のエイリアスです。 この種のコンストラクトを使用すると、NTLM を選択しても、必ずしも知っておく必要がなくなります。

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

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

NTLM プラグインのしくみ

検証機能プラグインは次のエラーを検出します。

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

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

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

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

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

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

エラーイベントによって停止または中断が発生します。

  • 5000–アプリケーションによって NTLM パッケージが明示的に選択されました

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

  • 5002–パッケージ一覧のネゴシエートが間違った NTLM の除外を示しています

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

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

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

NTLM 停止

5000–アプリケーションによって NTLM パッケージが明示的に選択されました

重要度–エラー

アプリケーションまたはサブシステムは、Acquirecredentialshandle がの呼び出しで、Negotiate ではなく NTLM を明示的に選択します。 クライアントとサーバーが Kerberos を使用して認証できる場合でも、NTLM を明示的に選択することはできません。

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

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

アプリケーションで使用される Api (パラメーター) 値が正しくありません 正しい値 メモ
Acquirecredentialshandle が (pszPackage) ML NEGOSSP_NAME または "Negotiate"
RPC クライアント: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) RPC サーバー: 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 に渡される COSERVERINFO 構造体のメンバーです) RPC_C_AUTHN_WINNT RPC_C_AUTHN_DEFAULT または RPC_C_AUTHN_GSS_NEGOTIATE Negotiate は、通信が常にネットワーク経由で発生する場合にのみ使用してください。 同じコンピューター上のクライアントとサーバーの間で DCOM 呼び出しが行われる場合は、既定値を使用して、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 を除外する場合、結果は Negotiate を完全にバイパスし、NTLM SSP パッケージを直接選択することと同じです。

サブパッケージリストを指定できるのは、Acquirecredentialshandle がを直接呼び出すときだけです。これは、ほとんどの上位層の Api (RPC など) では、呼び出し元が [パッケージのネゴシエート] の一覧を制御することを許可しないためです。

Microsoft では、アプリケーションがこの方法で [パッケージのネゴシエート] の一覧を操作しようとしていることを推奨していません。

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

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

アプリケーションで使用される Api (パラメーター) 値が正しくありません 正しい値
Acquirecredentialshandle が (pAuthData パラメーターとして渡される SEC_WINNT_AUTH_IDENTITY_EX 構造体の PackageList メンバー) "!Kerberos "または" NTLM " NULL または "Kerberos, NTLM" または "Kerberos,!NTLM "または"!ML

5002–パッケージ一覧のネゴシエートが間違った NTLM の除外を示しています

重要度-警告

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

このエラーを修正する方法次の構文を使用して、Negotiate から NTLM パッケージを除外します。

アプリケーションで使用される Api (パラメーター) 値が正しくありません 正しい値
Acquirecredentialshandle が (pAuthData パラメーターとして渡される SEC_WINNT_AUTH_IDENTITY_EX 構造体の PackageList メンバー) "-NTLM" "!ML

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

重要度–エラー

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

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

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

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

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

最後に、NT4 形式の domain\username (または、localsystem、networkservice、または localservice として実行されているサービスの場合は domain\computername) を使用することもできます。 これは、ドメインユーザーアカウントまたはコンピューターアカウントのコンテキストで実行されているターゲットに対して機能します。

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

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

重要度-警告

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

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

この状況では、NTLM ではなく Kerberos を使用する必要があると判断した場合、ダウングレードが発生する可能性がいくつかあります。

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

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

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

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

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

印刷

印刷検証ツールを使用すると、アプリケーションが印刷サブシステムを呼び出すときに発生する問題の検出とトラブルシューティングを行うことができます。 印刷検証ツールは、印刷サブシステム、PrintAPI レイヤー、および Printapi レイヤーの2つのレイヤーを対象とします。

印刷 API レイヤー

印刷検証ツールは、プログラムと Winspool と prntvpt.dll 間のインターフェイスをテストし、これらの Dll のインターフェイスをテストします。 Winspool および prntvpt.dll によってエクスポートされた Api については、MSDN ヘルプセクションで、このインターフェイスの関数を呼び出す規則を確認できます。

プリンタドライバレイヤー

また、印刷検証ツールは、UNIDRV.DLL、UNIDRUI.DLL、PSCRIPT5.DLL、PS5UI.DLL、MXDWDRV.DLL などの主要な印刷ドライバーと、印刷ドライバープラグインの間のインターフェイスもテストします。このインターフェイスに関する情報については、MSDN および WDK を参照してください。

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

WebServices

Windows の API (wwsapi) 検証レイヤー

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

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

  • 既に使用されている 1 つのスレッド オブジェクトを参照する、呼び出される WWSAPI。

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

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

さらに、このプラグインは次の機能を備備しています。

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

  • 非同期的に完了できる呼び出しを強制的に同期的に完了します。 これは、呼び出しによって特定の動作に依存するアプリケーションが呼び出しを受け取WS_ASYNC_CONTEXT。

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

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

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

プロパティ名DescriptionValidateObjectValidates 組み込みオブジェクトが validTrackObjectTracks の有効期間を通じてオブジェクトの使用を追跡します

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

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

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

!avrf -ws –obj

このコマンドは、追跡対象の組み込みの WWSAPI オブジェクトを表示します。これは、作成と終了の両方です。 閉じたオブジェクトは循環キューに格納されます。そのため、追跡対象のオブジェクトの総数に対する最大の値が設定されます。

オブジェクトは、WsCreateChannel()、WsCreateChannelForListener()、WsCreateServiceHost()、WsCreateServiceProxy()、WsCreateServiceProxyFromTemplate()、WsCreateError()、WsCreateHeap()、WsCreateHeap()、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」を参照してください

ハング

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

関連項目

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

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

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

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

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

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