Condividi tramite


Verifica applicazione - Test all'interno di Application Verifier

supporto ARM64EC

Application Verifier non supporta ARM64EC.

Nozioni di base

Come minimo, è necessario eseguire Application Verifier con l'impostazione Informazioni di base selezionata. Ognuno di questi test verificherà un'area che causerà arresti anomali o altri scenari negativi, che hanno un impatto diretto e significativo dell'esperienza del cliente.

  • Eccezioni : assicura che le applicazioni non nascondono violazioni di accesso tramite la gestione strutturata delle eccezioni
  • Handle : verifica che l'applicazione non tenti di usare handle non validi
  • Heap : verifica la presenza di problemi di danneggiamento della memoria nell'heap
  • Perdita : rileva le perdite rilevando le risorse effettuate da una DLL che non vengono liberate dal momento in cui la dll è stata scaricata
  • Blocchi: verifica l'utilizzo corretto per le sezioni critiche
  • Memoria : assicura che le API per le manipolazioni dello spazio virtuale vengano usate correttamente (ad esempio, VirtualAlloc, MapViewOfFile)
  • SRWLock : verifica l'utilizzo corretto per i blocchi SRW (Reader/Writer) sottili.
  • Threadpool : garantisce l'uso corretto delle API del pool di thread e applica controlli di coerenza sugli stati del thread di lavoro dopo un callback, ad esempio threadpool dirty e altri problemi correlati al threadpool.
  • TLS : garantisce che le API di archiviazione locale del thread vengano usate correttamente

Per informazioni sulle eccezioni di codice di arresto generate da questi test, vedere Application Verifier - Stop Codes and Definitions. Per informazioni sul debug di questi errori, vedere Application Verifier - Debugging Application Verifier Stops

Compatibilità

I test del livello di verifica della compatibilità consentono di identificare un'applicazione che potrebbe avere problemi con il sistema operativo Microsoft Windows. Molti di questi controlli possono essere usati anche per verificare i requisiti di logo/certificazione.

Per informazioni sulle eccezioni di codice di arresto generate da questi test, vedere Application Verifier - Stop Codes and Definitions.

HighVersionLie : identifica i problemi relativi ad alcuni dei problemi di compatibilità delle applicazioni più comuni in Windows. Il rilevamento non corretto della versione del sistema operativo o l'uso di informazioni sulla versione hardcoded può causare un errore dell'applicazione nei sistemi operativi successivi.

Cuzz

Il livello di verifica Concurrency Fuzzing (Cuzz) rileva bug di concorrenza e race condition dei dati. Cuzz regola la pianificazione dei thread inserendo ritardi casuali nei punti chiave nel codice di un'applicazione. Lo scenario seguente illustra il tipo di bug di concorrenza che potrebbe essere rilevato dal livello di verifica Cuzz.

Un'applicazione ha un thread padre e un thread figlio. Il thread padre avvia il thread figlio e quindi alloca la memoria per una struttura.

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

Il thread figlio dereferenzia il puntatore.

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

Il codice precedente presenta un bug di concorrenza. Se il thread figlio tenta di dereferenziare il puntatore prima che il thread padre allochi la memoria, il puntatore non sarà valido. Il bug è molto improbabile che si manifesti, perché nella maggior parte dei casi, il thread padre allocherà la memoria prima dell'avvio del thread figlio. In rari casi, tuttavia, il thread figlio potrebbe iniziare e tentare di dereferenziare il puntatore prima che il thread padre abbia allocato la memoria.

Il livello di verifica Cuzz aumenta la probabilità di trovare bug di concorrenza come quello illustrato nell'esempio precedente. Cuzz non esegue controlli aggiuntivi oltre ai ritardi di inserimento. Di conseguenza, non ci sono arresti di verifica direttamente associati a Cuzz. Tuttavia, se l'abilitazione di Cuzz genera un bug di concorrenza che si manifesta, altri livelli di verifica trarranno vantaggio. Ad esempio, se una race condition genera un overflow dell'heap, il livello di verifica heap non troverà l'errore a meno che la race condition non si manifesti in fase di esecuzione. Aumentando la probabilità che si verifichi la race condition, Cuzz migliora l'efficacia del livello heap nell'identificazione dell'errore.

Per ottenere il massimo vantaggio di Cuzz, abilitare Cuzz per il maggior numero possibile di test e ripetere lo stesso test più volte. Cuzz può essere abilitato in tutti i test, inclusi test manuali, test funzionali e test di stress. Abilitare anche il maggior numero possibile di livelli di verifica di Application Verifier.

È possibile aumentare la probabilità di riprodurre un bug fornendo cuzz con lo stesso valore di inizializzazione casuale (vedere Proprietà).

Cuzz inserisce ritardi solo nelle chiamate API di sincronizzazione Win32.

Proprietà Cuzz

Per il livello di verifica Cuzz sono disponibili le proprietà seguenti. Per impostare le proprietà, selezionare il livello Cuzz nell'interfaccia utente di Application Verifier e aprire la finestra delle proprietà.

Proprietà Descrizione
FuzzingLevel Controlla il livello di fuzzing per Cuzz. Impostare questo valore su 1 per le applicazioni critiche e 4 per le applicazioni normali.
RandomSeed Valore di inizializzazione casuale utilizzato da Cuzz all'inizio. Se si imposta questa proprietà su 0, Cuzz genera un valore di inizializzazione casuale basato sul tempo.

Simulazione di risorse basse

La simulazione di risorse insufficiente tenta di simulare un ambiente con risorse basse, ad esempio memoria insufficiente. Questa simulazione identificherà i bug che si verificano in condizioni di memoria insufficiente. Questa operazione è nota anche come inserimento di errori. È possibile simulare un ambiente con risorse basse, in cui è possibile definire un numero (0-100) che indica le chiamate di probabilità di errore di:

  • Wait (ad esempio, l'API WaitForXXXX).
  • Heap_Alloc (API di allocazione heap).
  • Virtual_Alloc (API di allocazione della memoria virtuale).
  • Registro di sistema (API del Registro di sistema).
  • File (API file, ad esempio CreateFile).
  • Evento (API evento, ad esempio CreateEvent).
  • MapView ( API MapView, ad esempio CreateMapView).
  • Ole_Alloc (API Ole, ad esempio SysAllocString).

La simulazione di risorse bassa (nota anche come inserimento di errori) tenta di simulare un ambiente con risorse basse, ad esempio memoria insufficiente. Ciò identificherà il bug all'interno di condizioni di memoria insufficiente.

Proprietà di simulazione risorse basse

Per modificare le proprietà, selezionare la casella di controllo Simulazione risorse bassa nell'area Test, fare clic con il pulsante destro del mouse e selezionare proprietà:

Proprietà Descrizione
Includi Il limite degli errori si verifica solo nelle DLL specificate. Un nome dll senza percorso per riga. Se si specifica '*', si verificheranno errori per tutti i moduli.
Escludi Escludere gli errori per i moduli specificati. Un nome dll senza percorso per riga.
Timeout Assegnare uno slot di tempo (in millisecondo) quando non si verificano errori durante l'inizializzazione del processo.
Wait. Numero [0 - 1000000] che indica la probabilità di errore per l'API WaitForXXXX.
Heap_Alloc Numero [0 - 1000000] che indica la probabilità di errore per l'API di allocazione heap.
Virtual_Alloc Numero [0 - 1000000] che indica la probabilità di errore per l'API di allocazione della memoria virtuale.
Registro Numero [0 - 1000000] che indica la probabilità di errore per l'API del Registro di sistema.
file Numero [0 - 1000000] che indica la probabilità di errore per l'API File, ad esempio CreateFile.
Event Numero [0 - 1000000] che indica la probabilità di errore per l'API evento, ad esempio CreateEvent
MapView Numero [0 - 1000000] che indica la probabilità di errore per l'API MapView, ad esempio CreateMapView.
Ole_Alloc Numero [0 - 1000000] che indica la probabilità di errore per l'API Ole, ad esempio SysAllocString.
Stack Ogni thread dell'applicazione Windows inizia con una riserva dello stack e una dimensione del commit dello stack. Con un utilizzo normale, il commit dello stack aumenta ogni volta che è necessario più spazio nello stack. Per altre informazioni, vedere Creazione di thread e dimensioni dello stack di thread. Se il sistema riscontra condizioni di memoria insufficiente, l'aumento del commit dello stack potrebbe non riuscire. Il thread che non riesce a aumentare lo stack e l'intera applicazione si arresterà molto probabilmente in modo anomalo. Questo tipo di arresto anomalo non è accettabile per i processi di sistema importanti (ad esempio per i servizi). Il controllo Stacks disabiliterà qualsiasi aumento dello stack per l'applicazione verificata in modo da simulare gli errori di crescita dello stack senza la necessità di simulare l'intera condizione di memoria insufficiente del sistema. Le eccezioni verranno generate quando l'applicazione tenta di espandere lo stack. Non vengono generati arresti di verifica.

LuaPriv

I test luaPriv (Limited User Account Privilege Predictor) sono sia predittivi che diagnostici e funzionano per risolvere i problemi relativi all'esecuzione di un'applicazione con privilegi amministrativi e se l'applicazione funzioni anche se viene eseguita con privilegi inferiori (in genere, come utente normale).

Noto anche come controlli di controllo dell'account utente, il predictor dei privilegi dell'account utente limitato (LuaPriv) ha due obiettivi principali:

  • Predittivo: durante l'esecuzione di un'applicazione con privilegi amministrativi, prevedere se l'applicazione funzionerebbe anche se l'esecuzione con privilegi inferiori (in genere, come utente normale). Ad esempio, se l'applicazione scrive in file che consentono solo l'accesso agli amministratori, tale applicazione non sarà in grado di scrivere nello stesso file se eseguita come non amministratore.

  • Diagnostica: durante l'esecuzione con privilegi non di amministratore, identificare potenziali problemi che potrebbero esistere già con l'esecuzione corrente. Continuando l'esempio precedente, se l'applicazione tenta di scrivere in un file che concede solo l'accesso ai membri del gruppo Administrator, l'applicazione riceverà un errore ACCESS_DENIED. Se l'applicazione non funziona correttamente, questa operazione può essere il colpevole.

LuaPriv identifica i tipi di problemi seguenti:

Potenziale problema Descrizione
Spazi dei nomi con restrizioni La creazione di un oggetto di sincronizzazione denominato (Event, Semaphore, Mutex e così via) senza uno spazio dei nomi può complicare l'esecuzione senza privilegi per alcuni sistemi operativi perché il sistema operativo può scegliere di inserire l'oggetto in uno spazio dei nomi con restrizioni. La creazione di un oggetto di questo tipo in uno spazio dei nomi con restrizioni ,ad esempio lo spazio dei nomi Globale, richiede SeCreateGlobalPrivilege, che viene concesso solo agli amministratori.
LuaPriv contrassegna entrambi questi problemi se li rileva.
Controlli hard administrator Alcune applicazioni interrogano il token di sicurezza dell'utente per scoprire quanti privilegi ha. In questi casi, l'applicazione può modificarne il comportamento a seconda della potenza che ritiene che l'utente abbia.
Le chiamate API luaPriv flags che restituiscono queste informazioni.
Richiesta di privilegi Un'applicazione può tentare di abilitare un privilegio rilevante per la sicurezza, ad esempio SeTcbPrivilege o SeSecurityPrivilege, prima di eseguire un'operazione che lo richiede.
I flag LuaPriv tentano di abilitare privilegi rilevanti per la sicurezza.
Privilegi mancanti Se un'applicazione tenta di abilitare un privilegio che l'utente non ha, probabilmente segnala che l'applicazione prevede il privilegio, che può causare differenze di comportamento.
Flag LuaPriv non riuscite richieste di privilegi.
Operazioni INI-File I tentativi di scrittura nei file INI mappati (WritePrivateProfileSection e API simili) possono non riuscire come utente non amministratore.
LuaPriv contrassegna tali operazioni.
Accesso negato Se l'applicazione tenta di accedere a un oggetto (File, chiave del Registro di sistema e così via), ma il tentativo ha esito negativo a causa di un accesso insufficiente, l'applicazione probabilmente prevede l'esecuzione con più privilegi rispetto a quanto previsto.
LuaPriv contrassegna i tentativi di apertura dell'oggetto che hanno esito negativo con errori ACCESS_DENIED e simili.
Nega ACL Se un oggetto dispone di ACL nega nell'elenco di controllo di accesso, nega in modo esplicito l'accesso a entità specifiche.
Questa situazione non è comune e rende difficile la stima, quindi LuaPriv contrassegna Nega gli ACL quando li trova.
Accesso con limitazioni Se un'applicazione tenta di aprire un oggetto per i diritti che non vengono concessi agli utenti normali (ad esempio, provando a scrivere in un file che è scrivibile solo dagli amministratori), l'applicazione probabilmente non funzionerà come un utente normale.
LuaPriv contrassegna tali operazioni.
MAXIMUM_ALLOWED Se un'applicazione apre un oggetto per MAXIMUM_ALLOWED, il controllo di accesso effettivo sull'oggetto verrà eseguito altrove. La maggior parte del codice che esegue questa operazione non funziona correttamente e funziona quasi certamente in modo diverso quando viene eseguita senza privilegi.
LuaPriv contrassegna quindi tutti gli eventi imprevisti di MAXIMUM_ALLOWED.

Varie

I problemi comunemente trascurati vengono acquisiti nei test vari.

  • API pericolose: tiene traccia per verificare se l'applicazione usa le azioni unsafe seguenti:
    • Chiamata pericolosa a TerminateThread.
    • Potenziale overflow dello stack in condizioni di memoria insufficiente.
    • Processo di uscita chiamato mentre sono ancora in esecuzione più thread.
    • LoadLibrary viene chiamato durante DllMain.
    • FreeLibrary viene chiamato durante DllMain.
  • Gli stack dirty riempiono (periodicamente) la parte inutilizzata dello stack con un modello di memoria. Ciò consente di rilevare variabili non inizializzate nelle chiamate di funzione future nel contesto del thread.
  • TimeRollOver forza il rollover delle API GetTickCount e TimeGetTime più velocemente del normale. Ciò consente alle applicazioni di testare più facilmente la gestione del rollover del tempo.

Proprietà varie

Il controllo delle API pericolose ha una proprietà che può essere modificata:

DllMainCheck : controlla loadLibrary/FreeLibrary chiamando quando DllMain è attivo.

Rete

I test di rete cercano un uso improprio delle API WinSock. Ad esempio, se un'API di rete chiamata prima di una chiamata WSAStartup() o dopo una chiamata WSACleanup() riuscita al bilanciamento è stata effettuata. Per altre informazioni su WinSock, vedi intestazione winsock.h e Windows Sockets 2.

Proprietà

Per il livello di verifica Net sono disponibili le proprietà seguenti. Per impostare le proprietà, selezionare il provider di rete nell'interfaccia utente Application Verifier e aprire la finestra delle proprietà.

Proprietà Descrizione
FragmentsEnabled Abilita il frammento dei flussi di dati ricevuti dai socket TCP IPv4 e IPv6.
FragmentSize Specifica il numero massimo di byte restituiti in un buffer a qualsiasi chiamata API di ricezione Winsock.

La proprietà FragmentsEnabled consente la funzionalità nel provider di verifica della rete per facilitare il test e la verifica di un'applicazione che analizza i flussi TCP all'esterno di una rete. Una volta abilitata, tutte le chiamate a Winsock per ricevere i dati riceveranno solo fino a FragmentSize byte, a meno che l'applicazione non richieda in modo specifico l'intero buffer riempito prima di restituire (controllato dal flag MSG_WAITALL). Poiché né il protocollo TCP né Winsock forniscono garanzie sul numero di byte eventualmente restituiti in un buffer, l'abilitazione di questo controllo faciliterà la verifica che il codice che analizza il flusso di dati dalla rete lo fa correttamente, indipendentemente dal numero di byte ricevuti per ogni chiamata a Winsock. I problemi nei parser di flusso sono stati una fonte di bug ad alto profilo e queste proprietà vengono fornite per facilitare la verifica della correttezza, in quanto questo è particolarmente difficile da testare. Nota: ciò non modifica i dati restituiti, ma rallenta solo a una frequenza specifica: l'applicazione deve comportarsi esattamente come questa opzione abilitata o disabilitata.

La riga di comando seguente consente la frammentazione di tutti i flussi TCP in ingresso in tutti i socket IPv4 e IPv6 TCP creati in myApp.exe e tutti i file binari caricati da myApp.exe.

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

Estensione del debugger !avrf

!avrf -net -socket count - visualizza il numero di handle socket aperti e chiusi

!avrf -net -socket dump [-v] [HANDLE] - visualizza i quadratini socket, in modo dettagliato o meno.

!avrf -net -wsastacks : visualizza il conteggio init WSA corrente e l'elenco cronologico delle tracce dello stack per WSAStartup/WSACleanup.

!avrf -net -wsastacks count : visualizza il conteggio init WSA corrente.

!avrf -net -socket count - Questo comando darà il numero complessivo di handle socket monitorati, aperti e chiusi. Si noti che questi vengono rilevati in una coda circolare, quindi c'è un tetto al totale da tenere traccia. I socket vengono aggiunti all'elenco aperto quando viene chiamata una delle API Winsock che alloca un handle socket. Ad esempio, socket(), WSASocket(), accept(). I socket vengono spostati dall'elenco aperto all'elenco chiuso quando viene chiamata la funzione closesocket() su tale handle socket.

!avrf -net -socket dump [-v] [HANDLE] - Questo comando enumererà gli handle del socket. "-socket dump" elenca tutti gli handle socket aperti e chiusi rilevati in base ai relativi valori SOCKET. Il flag facoltativo -v stampa anche lo stack di chiamate aperto o chiuso immediatamente dopo la stampa di ogni valore SOCKET. Il campo HANDLE facoltativo elenca solo l'handle SOCKET specificato e il relativo stack di chiamate aperto o chiuso.

Ecco un esempio delle varie opzioni di utilizzo del 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 richiede agli sviluppatori di applicazioni di chiamare WSAStartup() almeno una volta prima di effettuare chiamate Winsock. Questo viene rilevato dal processo Winsock a livello di processo. Il conteggio dei riferimenti iniziale indica a una libreria Winsock (ws2_32.dll) di inizializzare e caricare il catalogo e i provider Winsock. Altre chiamate a WSAStartup incrementa il conteggio dei riferimenti. Winsock richiede inoltre agli sviluppatori di applicazioni di chiamare WSACleanup() al termine della chiamata a Winsock. Le chiamate a WSACleanup devono essere associate correttamente a una chiamata precedente a WSAStartup(). La chiamata a WSACleanup() decrementa il conteggio dei riferimenti a livello di processo. Quando il conteggio dei riferimenti scende a zero, Winsock rilascia le risorse e scarica il catalogo e i provider Winsock.

Questo comando darà il valore totale del conteggio dei riferimenti della routine di inizializzazione "WSAStartup" corrente ed elenca gli stack di chiamate a WSAStartup e WSACleanup effettuati all'interno del processo. Si noti che questa operazione viene mantenuta all'interno di una coda circolare fissa, quindi non è garantito che sia completa, ma solo le N chiamate più recenti.

Ecco un esempio delle varie opzioni di utilizzo di -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

Questo plug-in Application Verifier monitora le chiamate di un singolo processo alle API di autenticazione AcquireCredentialsHandle e InitializeSecurityContext per rilevare gli usi del protocollo NTLM. NTLM è un protocollo di autenticazione obsoleto con difetti che potrebbero compromettere la sicurezza delle applicazioni e del sistema operativo e non devono essere usati.

Rischio di autenticazione NTLM

Il protocollo di autenticazione NTLM obsoleto più importante è la mancanza di autenticazione server, che potrebbe consentire a un utente malintenzionato di ingannare gli utenti a connettersi a un server spoofed. Come contesto di autenticazione server mancante, le applicazioni che usano NTLM possono anche essere vulnerabili a un tipo di attacco noto come attacco "reflection". Questo secondo consente a un utente malintenzionato di dirottare la conversazione di autenticazione di un utente in un server legittimo e usarlo per autenticare l'utente malintenzionato nel computer dell'utente. Le vulnerabilità e i modi di sfruttarli di NTLM sono l'obiettivo di aumentare l'attività di ricerca nella community della sicurezza.

Sebbene Kerberos sia disponibile per molti anni, molte applicazioni vengono comunque scritte solo per l'uso di NTLM. Ciò riduce inutilmente la sicurezza delle applicazioni. Kerberos non può tuttavia sostituire NTLM in tutti gli scenari, principalmente quelli in cui un client deve eseguire l'autenticazione ai sistemi che non sono aggiunti a un dominio (una rete domestica probabilmente è la più comune di queste). Il pacchetto di sicurezza Negotiate consente una compromissione compatibile con le versioni precedenti che usa Kerberos quando possibile e ripristina solo NTLM quando non è disponibile un'altra opzione. Il passaggio del codice per l'uso di Negotiate invece di NTLM aumenterà significativamente la sicurezza per i clienti, introducendo al tempo stesso poche o nessuna compatibilità delle applicazioni. Negoziare da solo non è un proiettile silver: ci sono casi in cui un utente malintenzionato può forzare il downgrade a NTLM, ma questi sono significativamente più difficili da sfruttare. Tuttavia, un miglioramento immediato è che le applicazioni scritte per l'uso di Negotiate correttamente sono automaticamente immuni agli attacchi di reflection NTLM.

Per una parola finale di cautela contro l'uso di NTLM: in Windows è possibile disabilitare l'uso di NTLM a livello di sistema operativo. Se le applicazioni hanno una dipendenza rigida da NTLM, non riusciranno semplicemente a eseguire l'autenticazione quando NTLM è disabilitato.

Quali fattori fanno sì che NTLM sia "hardcoded" in un'applicazione?

Esistono due fattori che causeranno una dipendenza rigida da NTLM. Il primo consiste nel selezionare in modo esplicito NTLM come pacchetto di autenticazione da usare dall'applicazione. Per alcuni protocolli e API la scelta di NTLM è ovvia, ad esempio nella chiamata all'API AcquireCredentialsHandle (). Per altri protocolli, potrebbe non essere così ovvio. Ad esempio, il pacchetto di autenticazione predefinito di RPC (RPC_C_AUTHN_DEFAULT) è in realtà un alias per NTLM quando RPC viene usato in rete e anche il flag esplicito per selezionare NTLM non ha l'abbreviazione NTLM in qualsiasi punto (RPC_C_AUTH_WINNT). Questo tipo di costrutto semplifica la selezione di NTLM senza necessariamente sapere che è stato fatto.

Al posto di NTLM, gli sviluppatori devono usare, altri metodi di autenticazione, ad esempio il pacchetto Negotiate (detto anche pacchetto SPNEGO o SNEGO). La selezione dei pacchetti deve corrispondere sia ai componenti client che ai componenti server per consentire a Negotiate di tentare di usare Kerberos, quindi sia le parti client che server dell'applicazione devono usare Negotiate. Se uno dei due lati usa NTLM (come potrebbe essere il caso delle versioni legacy) Negotiate continuerà a funzionare, ma verrà sempre ripristinato NTLM. Come indicare all'applicazione di usare Negotiate varia in base al protocollo. Alcuni dei protocolli più comuni (RPC, LDAP, DCOM, HTTP) sono descritti in dettaglio più avanti nell'argomento 5000 - Pacchetto NTLM selezionato in modo esplicito.

Il secondo fattore che determina l'uso di NTLM è quando il client non fornisce un nome di destinazione server valido al processo di autenticazione. Nei protocolli che supportano o richiedono l'autenticazione reciproca (ad esempio Kerberos) il nome di destinazione è quello usato per ottenere l'autenticazione reciproca. Le API di autenticazione (ad esempio InitializeSecurityContext) accettano un parametro facoltativo, in genere denominato "TargetName", "PrincipalName" o "ServerPrincipalName". Si tratta dell'identificatore usato dai controller di dominio per selezionare l'account di dominio corretto per ottenere le credenziali per il servizio di destinazione. Poiché NTLM non ha alcun concetto di autenticazione server, questo parametro non è necessario affinché NTLM esegua correttamente l'autenticazione. Kerberos, d'altra parte, richiede che un client ottenga un ticket di servizio valido per il servizio a cui il client esegue l'autenticazione. L'autenticazione Kerberos avrà sempre esito negativo se non viene specificato alcun nome di destinazione o un nome di destinazione non valido. Quando Negotiate viene selezionato come pacchetto, non specificando alcun nome di destinazione (o un nome di destinazione non valido), Kerberos verrà ignorato completamente e verrà usato NTLM. La maggior parte delle API di autenticazione ha il nome di destinazione come parametro facoltativo accetta se NULL senza errori. A meno che lo sviluppatore non esegua l'override di questo oggetto e fornisca un nome di destinazione esplicito, NTLM (e, inoltre, NTLM riflettebile) è il risultato.

Funzionamento del plug-in NTLM

Il plug verifier rileva gli errori seguenti:

  • Il pacchetto NTLM viene specificato direttamente nella chiamata a AcquireCredentialsHandle (o api wrapper di livello superiore).

  • Il nome di destinazione nella chiamata a InitializeSecurityContext è NULL. In questo caso, Negotiate esegue direttamente il fallback a NTLM.

  • Il nome di destinazione nella chiamata a InitializeSecurityContext non è un nome di dominio di tipo SPN, UPN o NetBIOS correttamente formato. In questo caso, il controller di dominio restituisce un errore "principal not found", che causa il fallback di Negotiate a NTLM.

Il plug-in registra anche avvisi quando rileva il downgrade a NTLM; ad esempio, quando un nome SPN non viene trovato dal controller di dominio. Questi vengono registrati solo come avvisi perché sono spesso casi legittimi, ad esempio quando si esegue l'autenticazione in un sistema che non è aggiunto a un dominio.

Configurazione delle opzioni di arresto plug-in

Per impostazione predefinita, tutti gli eventi classificati come Error sono impostati per causare un'interruzione di debug. Tutti gli eventi di avviso sono impostati per registrare solo i dettagli dell'evento.

Gli eventi di errore causano un arresto o un'interruzione:

  • 5000 : l'applicazione ha selezionato in modo esplicito il pacchetto NTLM

  • 5001 - Negotiate Package List Include solo NTLM

  • 5002 - Esclusione NTLM errata dell'elenco di pacchetti negotiate

  • 5003 - Nessun nome di destinazione o nome di destinazione in formato non valido per Server

Eventi di avviso registrati:

  • 5010 - È stato rilevato il downgrade a NTLM

Arresti NTLM

5000 : l'applicazione ha selezionato in modo esplicito il pacchetto NTLM

Gravità : errore

L'applicazione o il sottosistema seleziona in modo esplicito NTLM anziché Negotiate nella chiamata a AcquireCredentialsHandle. Anche se può essere possibile che il client e il server eseguano l'autenticazione tramite Kerberos, questa operazione viene impedita dalla selezione esplicita di NTLM.

Come correggere l'errore

La correzione per questo errore consiste nel selezionare il pacchetto Negotiate al posto di NTLM. La modalità di funzionamento dipenderà dal particolare sottosistema di rete usato dal client o dal server. Di seguito sono riportati alcuni esempi. È consigliabile consultare la documentazione relativa alla libreria o al set di API specifico in uso.

API(parameter) Usate dall'applicazione Valore non corretto Valore corretto Note
AcquireCredentialsHandle (pszPackage) "NTLM" NEGOSSP_NAME o "Negotiate"
Client RPC: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) RPC Server: RPCServerRegisterAuthInfo(AuthnSvc) RPC_C_AUTHN_WINNT o RPC_C_AUTH_DEFAULT RPC_C_AUTH_GSS_NEGOTIATE Non si tratta di un errore per un server RPC per registrare il pacchetto NTLM/WINNT. Questo è spesso necessario per supportare i client meno recenti che supportano solo NTLM. Si tratta di un errore se viene registrato solo il pacchetto NTLM perché forza tutti i client a usare NTLM anche se sono in grado di usare Kerberos.
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (passato come membro dwAuthnSvc della struttura COAUTHINFO, che è un membro dello struct COSERVERINFO passato all'API) RPC_C_AUTHN_WINNT RPC_C_AUTHN_DEFAULT o RPC_C_AUTHN_GSS_NEGOTIATE La negoziazione deve essere usata solo se la comunicazione si verifica sempre attraverso una rete. Se la chiamata DCOM si verifica mai tra client e server nello stesso computer, è necessario usare DEFAULT e consentire a DCOM di scegliere il pacchetto corretto da usare.
LDAP: ldap_bind_s (metodo) LDAP_AUTH_NTLM LDAP_AUTH_NEGOTIATE
HTTP WinHTTPSetCredentials (AuthScheme) WINHTTP_AUTH_SCHEME_NTLM WINHTTP_AUTH_SCHEME_NEGOTIATE

5001 - Negotiate Package List Include solo NTLM

Gravità : errore

Quando si usa AcquireCredentialsHandle, è possibile specificare un elenco di pacchetti da usare o ignorare da Negotiate. A seconda dell'elenco specificato, è possibile eseguire l'override della logica incorporata in Negotiate per scegliere il pacchetto di autenticazione più appropriato e sicuro. Se l'elenco dei pacchetti include solo NTLM o esclude Kerberos, il risultato è identico a ignorare completamente Negotiate e selezionare in modo esplicito il pacchetto SSP NTLM direttamente.

Specificare un elenco di pacchetti secondari è possibile solo quando si chiama AcquireCredentialsHandle direttamente perché la maggior parte delle API di livello superiore (ad esempio RPC) non consente al chiamante di controllare l'elenco di pacchetti Negotiate.

Microsoft non consiglia alle applicazioni di provare a modificare l'elenco di pacchetti Negotiate in questo modo.

Come correggere l'errore

Usare il pacchetto Negotiate senza specificare un elenco di sottopacchetto o assicurarsi che Kerberos sia incluso.

API(parameter) Usate dall'applicazione Valore non corretto Valore corretto
AcquireCredentialsHandle (membro PackageList di SEC_WINNT_AUTH_IDENTITY_EX struct passato come parametro pAuthData) “! Kerberos" o "NTLM" NULL o "Kerberos, NTLM" o "Kerberos, ! NTLM" o "! NTLM"

5002 - Esclusione NTLM errata dell'elenco di pacchetti negotiate

Gravità - Avviso

Quando si chiama AcquireCredentialsHandle, l'applicazione ha tentato di escludere NTLM dall'elenco di pacchetti supportati da Negotiate. Tuttavia, la sintassi errata è stata usata per escludere NTLM, quindi rimane nell'elenco.

Come correggere questo errore Utilizzare la sintassi seguente per escludere il pacchetto NTLM da Negotiate:

API(parameter) Usate dall'applicazione Valore non corretto Valore corretto
AcquireCredentialsHandle (membro PackageList di SEC_WINNT_AUTH_IDENTITY_EX struct passato come parametro pAuthData) "-NTLM" “! NTLM"

5003 - Nessun nome di destinazione o nome di destinazione in formato non valido per Server

Gravità : errore

Quando si usa il pacchetto Negotiate, specificando un nome di destinazione null o non valido (talvolta definito nome dell'entità), Kerberos avrà esito negativo e NTLM verrà usato al suo posto. È sempre necessario specificare un nome di destinazione valido quando si effettua una chiamata di autenticazione. Il nome di destinazione è un identificatore univoco che consente a un controller di dominio di ottenere i dettagli dell'account del server a cui l'applicazione sta tentando di eseguire l'autenticazione. Una volta che il controller di dominio ha queste informazioni, può creare ticket Kerberos appropriati che verranno riconosciuti (decrittografabili) sia dal client che dal server.

Come correggere l'errore

I nomi di destinazione possono essere specificati in tre formati diversi, ognuno dei quali può essere usato dai controller di dominio per individuare l'oggetto account server corretto. Questi formati sono Nome entità servizio (SPN), Nome entità utente (UPN) e Nome account NetBIOS in due parti. Il nome SPN è il formato più comune e il più interoperabile con altre implementazioni Kerberos. Una descrizione completa dei nomi SPN esula dall'ambito di questo documento, ma il modulo SPN più semplice e comune ha due parti: una classe del servizio e un nome host. La classe del servizio identifica il tipo di applicazione server ,ad esempio un tipo di applicazione specifico, ad esempio http o ldap o generico come host. La seconda parte è il nome di dominio completo o flat (NetBIOS) del server. I client e i server Windows registrano automaticamente i nomi SPN per "host" per il nome FQDN e i nomi flat. I controller di dominio eseguono anche il mapping di circa 40 classi di servizi specifiche dell'applicazione sul nome SPN "host" per elementi come "http", "ldap", "rpc", "tapi" e così via.

o specificare un nome di destinazione per un'applicazione in esecuzione nel contesto del sistema operativo server (ad esempio, sistema locale, servizio di rete o servizio locale) le applicazioni client possono usare il nome SPN "host" registrato automaticamente o uno dei relativi alias. Per eseguire l'autenticazione a un'applicazione in esecuzione nel contesto di un account utente di dominio, è necessario registrare un nome SPN per tale account.

Per gli account utente è anche possibile usare il modulo UPN implicito compilato dal nome dell'account utente e dal dominio in cui risiede l'account: useraccountname@domain.dom. Sebbene sia possibile creare UPN aggiuntivi per l'account utente (usando i suffissi UPN che possono essere creati per ogni dominio), questi non funzioneranno come nomi di destinazione Kerberos, ma solo l'UPN corrispondente al nome dell'account di accesso effettivo e al dominio effettivo in cui è possibile usare l'account.

Infine, è comunque possibile usare il dominio in stile NT4\username (o domain\computername nel caso di servizi in esecuzione come sistema locale, networkservice o localservice). Questa operazione funziona per le destinazioni in esecuzione nel contesto dell'account utente di dominio o degli account computer.

API(parameter) Usate dall'applicazione Parametro per impostare il nome di destinazione Note
InitializeSecurityContext pszTargetName
Client RPC: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) ServerPrincipalName Deve trattarsi del nome di destinazione per l'account in cui è in esecuzione il server o il servizio. Non deve essere uguale al valore impostato in RPCServerRegisterAuthInfo
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (passato come membro dwAuthnSvc della struttura COAUTHINFO, che è un membro dello struct COSERVERINFO passato all'API) pServerPrincName Può usare COLE_DEFAULT_PRINCIPAL per consentire a COM di selezionare automaticamente il nome dalle informazioni di associazione
LDAP: nessuno Generato automaticamente dal client LDAP.
HTTP none WinHTTP e WinInet forniscono il nome di destinazione dal nome del server URL

5010 - È stato rilevato il downgrade a NTLM

Gravità - Avviso

Anche se l'applicazione specifica Negotiate e ha usato un nome di destinazione formattato correttamente, si è verificato un problema che causa il downgrade di Negotiate a NTLM. A seconda delle circostanze, questo potrebbe indicare un errore o un comportamento previsto. Ad esempio, quando un computer non fa parte di un dominio o viene usato in un percorso in cui un controller di dominio non è accessibile, è previsto che Negotiate eseguirà automaticamente il downgrade per consentire all'applicazione di eseguire l'autenticazione tramite NTLM. Tuttavia, se questo arresto si verifica quando un controller di dominio è disponibile e normalmente ci si aspetta che Kerberos venga usato quasi certamente indica che qualcosa non è corretto.

Come correggere questo errore

Supponendo di aver determinato che Kerberos dovrebbe essere stato usato e non NTLM in questa circostanza, esistono diverse possibilità per cui è stato effettuato il downgrade:

• Il nome di destinazione, anche se potrebbe essere stato nel formato corretto, non esisteva nel dominio (o foresta).

o Verificare di compilare il nome di destinazione corretto nell'applicazione client. La classe del servizio è corretta? Il nome host è corretto?

o Processo server in esecuzione nel contesto del computer o di un altro account di dominio. Nel primo caso i nomi SPN vengono registrati automaticamente, nel secondo caso potrebbe essere necessario registrare il nome SPN o usare un modulo alternativo, ad esempio un UPN implicito o un nome flat.

o Potrebbero verificarsi problemi di connettività di rete che impediscono la comunicazione con un controller di dominio o un server DNS?

o Il nome SPN di destinazione è registrato in più account? In questo modo il controller di dominio rifiuterà i tentativi di autenticazione.

Stampa

Print Verifier consente di individuare e risolvere i problemi che possono verificarsi quando un'applicazione chiama il sottosistema di stampa. Print Verifier è destinato ai due livelli del sottosistema di stampa, il livello PrintAPI e il livello PrintDriver.

Livello API di stampa

Print Verifier verifica l'interfaccia tra un programma e Winspool.drv e prntvpt.dll e testa le interfacce di tali DLL. È possibile esaminare le regole per chiamare le funzioni in questa interfaccia nella sezione della Guida MSDN per le API esportate da winspool.drv e prntvpt.dll.

Livello driver di stampa

Print Verifier testa anche l'interfaccia tra un driver di stampa principale, ad esempio UNIDRV.DLL, UNIDRUI.DLL, PSCRIPT5.DLL, PS5UI.DLL o MXDWDRV.DLL e i plug-in del driver di stampa. Per informazioni su questa interfaccia, vedere MSDN e WDK.

In genere, solo le versioni di debug eseguono Application Verifier, quindi le prestazioni non sono in genere un problema. Se si verificano problemi di prestazioni dall'uso di questo o da qualsiasi altro controllo di Verifica applicazione, eseguire un controllo alla volta fino a quando non sono stati eseguiti tutti i controlli necessari.

WebServices

Livello di verifica dell'API WebServices windows (WWSAPI)

Il plug-in WWSAPI consente agli sviluppatori di rilevare le istanze di:

  • Oggetto WWSAPI chiamato che fa riferimento a un oggetto WWSAPI intrinseco non valido.

  • WwsAPI chiamato che fa riferimento a un singolo oggetto a thread già in uso.

  • Oggetto intrinseco liberato con una chiamata asincrona in sospeso.

  • Chiamata di API di blocco da thread brevi.

Inoltre, questo plug-in:

  • Tiene traccia dell'uso di oggetti dalla creazione di istanze all'eliminazione.

  • Forzare le chiamate che possono essere completate in modo asincrono per essere completate in modo sincrono. Ciò consente di impedire alle applicazioni a seconda di un particolare comportamento da una chiamata che esegue un WS_ASYNC_CONTEXT.

  • Fornisce una descrizione leggibile quando un'API viene passata a un oggetto non valido oppure un oggetto è in uso usando l'estensione del debugger !avrf –ws –obj (illustrato di seguito)

  • Per il canale, il proxy del servizio e l'host del servizio, ogni chiamata rilevata mostrerà lo stato corrente dell'oggetto.

Per impostazione predefinita, sono abilitati i controlli seguenti:

Property NameDescriptionValidateObjectValidates che l'oggetto intrinseco è validoTrackObjectTrackTracks l'uso di un oggetto durante la sua durata

Altri controlli che possono essere abilitati in questo provider tramite l'interfaccia utente delle proprietà sono:

Nome proprietàDescriptionCheckTimeoutValidates che le funzioni asincrone vengono completate entro il timeout, specificato come TimeoutValForceSyncForce, il percorso di sincronizzazione da intraprendere quando viene fornito un contesto WS_ASYNC_CONTEXT a un'API.

Viene fornita un'estensione del debugger (!avrf –ws –obj) che visualizza gli oggetti WWSAPI aperti e chiusi. Se questa estensione è suffisso da un oggetto , visualizzerà informazioni dettagliate sull'utilizzo di questo oggetto.

!avrf -ws –obj

Questo comando visualizza gli oggetti WWSAPI intrinseci che vengono rilevati, creati e chiusi. Si noti che gli oggetti chiusi vengono archiviati in una coda circolare, quindi è presente un limite massimo per il numero totale di oggetti rilevati.

Gli oggetti vengono aggiunti al completamento delle API seguenti: WsCreateChannel(), WsCreateChannelForListener(), WsCreateServiceHost(), WsCreateServiceProxy(), WsCreateServiceProxyFromTemplate(), WsCreateError(), WsCreateHeap(), WsCreateHeap(), WsCreateListener(), WsCreateMetadata(), WsCreateMessage(), WsCreateMessageForChannel(), WsCreateReader(), WsCreateWriter(), WsCreateXmlBuffer(), WsReadXmlBuffer(), WsReadXmlBufferFromBytes()

Gli oggetti vengono spostati dall'oggetto creato all'elenco libero quando viene chiamata e completata la funzione WsFree*() corrispondente.

!avrf –ws –obj [OBJECT]

Questo comando visualizza l'utilizzo di un oggetto WWSAPI intrinseco. Le informazioni sull'utilizzo includono lo stack quando l'oggetto è stato creato, usato e liberato. Se l'oggetto è un canale, un host del servizio o un proxy di servizio, verrà visualizzato lo stato dell'oggetto prima della chiamata all'API tramite l'oggetto .

Di seguito è riportato un esempio delle opzioni di utilizzo !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>

Servizi

I servizi testano l'uso corretto dei servizi Windows. Ad esempio, i servizi vengono avviati e arrestati correttamente. Per informazioni sulle eccezioni di codice di arresto generate da questi test, vedere Application Verifier - Stop Codes - Services .

Perf

I test perf controllano l'uso efficiente delle API che influisce sulle prestazioni del sistema e sul consumo energetico, ad esempio la chiamata di una funzione Windows che usa un periodo di attesa non corretto. Per informazioni sulle eccezioni di codice di arresto generate da questi test, vedere Application Verifier - Stop Codes - Perf.

Pende

I test di blocco per l'uso delle API che causano la mancata risposta del sistema, ad esempio quando il thread DllMain è in attesa di un altro thread bloccato. Per informazioni sulle eccezioni di codice di arresto generate da questi test, vedere Application Verifier - Stop Codes - Hangs ( Verifica dell'applicazione - Codici di arresto - Blocchi).

Vedi anche

Application Verifier - Panoramica

Application Verifier - Funzionalità

Application Verifier - Testing Applications

Application Verifier - Codici e definizioni di arresto

Application Verifier - Debug dell'applicazione verifier arresta

Application Verifier - Domande frequenti