Application Verifier - Domande frequenti

Domande generali

Di seguito è riportato un elenco di domande ricevute sull'utilizzo generale di Application Verifier.

Che cos'è Application Verifier?

Application Verifier è uno strumento di verifica di runtime usato per trovare bug nelle applicazioni Di Microsoft Windows. Poiché si tratta di uno strumento di runtime, è necessario esercitare il codice dell'applicazione per poter essere verificato. Una buona copertura dei test è quindi essenziale.

Lo scenario di utilizzo tipico di Application Verifier consiste nell'abilitarlo per le applicazioni di interesse (vedere le domande seguenti per informazioni su come eseguire questa operazione) e quindi eseguire tutti i test scritti per l'applicazione. Si riceverà una notifica per qualsiasi bug trovato sotto forma di interruzione del debugger o di una voce del log di verifica.

Ricerca per categorie disinstallare Application Verifier?

Per disinstallare Application Verifier, accedere al pannello di controllo facendo clic su Start, selezionare Installazione applicazioni, quindi Rimuovi un programma, fare clic su Verifica applicazione e quindi su Rimuovi.

Ricerca per categorie avviare Application Verifier?

Dopo aver installato Application Verifier, è possibile avviarlo accedendo all'elenco dei programmi OPPURE digitando Appverif.exe in una riga di comando. A tale scopo, passare a un prompt dei comandi o alla casella Esegui del menu Avvio. Digitare appverif.exe e quindi premere INVIO. Verrà avviato Application Verifier.

Il file binario Appverifer.exe viene installato nella directory di sistema e viene usato per impostare le impostazioni dello strumento.

Dove vengono archiviati i log?

I log vengono archiviati in %USERPROFILE%\AppVerifierLogs

Cosa devo fare se si verificano problemi durante l'uso di Application Verifier?

Assicurarsi di eseguire la versione più recente. Provare la stessa app in un PC diverso o anche in una versione di Windows.

Application Verifier verifica il codice gestito?

AppVerifier si occupa delle interfacce tra il sistema operativo e l'applicazione. Di conseguenza, a meno che il codice gestito non esegua l'interoperabilità con le API native che hanno a che fare con heap, handle, sezione critica e così via. I test case non forniscono alcuna interazione con le interfacce verificate.

È consigliabile usare gli Assistenti debug gestiti per verificare il codice gestito. Per altre informazioni, vedere Debug di codice gestito tramite il debugger di Windows.

ARM64EC è supportato?

Application Verifier non supporta ARM64EC.

Domande sul debugger

Di seguito è riportato l'elenco delle domande ricevute relative al debugger.

Perché è stato visualizzato un errore che indica che è necessario un debugger?

Il livello di verifica Di base all'interno di Application Verifier richiede l'esecuzione dell'applicazione in un debugger. Se non si dispone di un debugger associato all'applicazione prima di selezionare il test, si riceverà una finestra di dialogo che ricorda che sarà necessario eseguire l'applicazione in un debugger per ottenere le informazioni registrate.

Ricerca per categorie eseguire l'applicazione in un debugger?

Vedere gli argomenti relativi all'installazione e all'installazione del debugger - Introduzione al debug di Windows

Ricerca per categorie'espansione dello stack di test senza altre strumentazioni?

In generale, l'espansione dello stack deve essere effettivamente testata in isolamento da altri livelli di verifica, incluso l'heap. Il motivo è il seguente: ogni livello di verifica "kubernetes" un'API o un punto esportato con alcune routine.

Ad esempio, una chiamata a CreateFileA sarà una chiamata ad appvocre! NS_SecurityChecks::CreateFileA, che potrebbe chiamare appvcore! NS_FillePaths::CreateFileA che potrebbe chiamare kernel32! CreateFileA, che potrebbe chiamare verifier! AVrfpNtCreateFile, che chiamerà ntdll! NtCreateFile. È possibile notare che la strumentazione ha aggiunto altre 3 chiamate di funzione in pila, ognuna di esse può e utilizzerà più stack.

Nel caso seguente, il LH-verifier.dll è "clusterking" ogni DllMain e il percorso del codice heap "instrumentato" aggiungerà un maggiore utilizzo dello stack. Poiché il thread inserito dal debugger non usa le impostazioni predefinite IMAGE_NT_HEADERS, lo stack di cui è stato eseguito inizialmente il commit non sarà sufficiente per completare lo stato APC di un thread (un thread nello stato APC ha eseguito il codice di inizializzazione).

Se si vuole usare Stack-Ckecs, probabilmente l'unico livello di verifica da usare se FirstChanceAccessViolation.

Quando si usa l'estensione !avrf si ottiene 'Application verifier is not enabled for this process...'

Errore completo ricevuto: Application verifier is not enabled for this process. Use appverif.exe tool to enable it.

Probabilmente sono abilitati solo i livelli di verifica shim e/o l'heap in modalità "pura". Queste sono alcune delle possibili cause.

Domande sullo scenario di test

Di seguito è riportato un elenco di domande ricevute per diversi scenari di test.

Come è possibile abilitare Application Verifier nel servizio, ma non altri?

Creare una copia di svchost.exe nella directory System32 e chiamare la copia "Mysvchost.exe".

Usando regedit aprire HKLM\System\CurrentControlSet\Services\MyService.

Modificare il valore "ImagePath", che sarà simile a "%SystemRoot%\system32\svchost.exe -k myservice" e modificare svchost.exe in "Mysvchost.exe".

Aggiungere "Mysvchost.exe" all'elenco AppVerifier e controllare i test desiderati.

Riavvia.

Ricerca per categorie eseguire Application Verifier in un'applicazione a 64 bit avviata da un'applicazione a 32 bit in esecuzione in WOW64?

Versione semplice: la regola di riferimento per l'abilitazione delle impostazioni del verificatore in una determinata applicazione consiste nel corrispondere al livello di bit dello strumento e al processo di destinazione. Ovvero, usare il appverif.exe a 32 bit per un'applicazione a 32 bit (sia in esecuzione in WoW64) sia usare il AppVerif.exe a 64 bit per la destinazione nativa a 64 bit.

Versione estesa: le impostazioni di Application Verifier sono l'unione corretta delle impostazioni "core" e delle impostazioni "shim".

Impostazioni principali: le impostazioni di base vengono archiviate in Opzioni di esecuzione file di immagine.

Il valore "Debugger" viene letto dall'applicazione di avvio. Quindi, se si vuole avere devenv.exe avviare my.exe a 64 bit e eseguirlo nel debugger, è necessario usare la chiave del Registro di sistema a 32 bit in WoW6432Node. Gli altri valori, per un processo a 32 bit, vengono letti da entrambe le posizioni, sia l'IFEO nativo che il WoW6432Node.

Il motivo è il seguente: un processo a 32 bit in esecuzione in WoW è un processo a 64 bit che esegue il ciclo di emulazione Wow64. Ogni processo a 32 bit è quindi prima un processo a 64 bit e quindi un processo a 32 bit. L'IFEO a 64 bit abiliterà il verificatore nel codice Wow64cpu.dll, mentre l'IFEO a 32 bit abiliterà il verificatore nel codice a 32 bit.

Dal punto di vista dell'utente finale, verifier.dll viene caricato due volte (una volta nel mondo a 64 bit, una volta nel mondo a 32 bit). Poiché la maggior parte delle persone non si preoccupa di verificare wow64cpu.dll, il comportamento più accettato per i processi a 32 bit consiste nel verificare solo la parte a 32 bit. Questo è il motivo per cui si applica la regola d'oro di "sempre corrispondere al bit-ness".

Ricerca per categorie eseguire il debug del servizio in una stazione finestra non interattiva

Per eseguire il debug di un servizio eseguito in una stazione finestra non interattiva, eseguire le operazioni seguenti (si applica solo se si usa ntsd/windbg):

Aggiungere una chiave al Registro di sistema in HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options. Il nome di questa chiave deve essere il nome del processo (service.exe).

Creare un valore REG_SZ denominato Debugger e impostare questo valore sul percorso in cui risiede il debugger. Deve contenere il percorso completo, non solo il nome del debugger. Il comando deve includere l'opzione –server e un intervallo di porte o porta specifico su cui deve essere in ascolto il debugger. Un esempio è c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g –G.

Connettersi al server del debugger eseguendo il debugger con un'opzione -remote. Un esempio è: windbg.exe –remote tcp:=localhost,port=55xx dove 'xx' è un numero compreso tra 00 e 99 se è stato usato un intervallo nel server.

AppVerifier esegue il rilevamento delle perdite? In Windows 7 e versioni successive è disponibile un'opzione di controllo Perdite che rileverà quando un processo perde memoria. Nei sistemi operativi precedenti AppVerifier non testa l'applicazione per il rilevamento delle perdite, ma cerca altri problemi di memoria.

Quali test sono consigliati per i problemi di sicurezza?

  • Cumuli
  • Handle
  • Locks
  • Stack (solo per i servizi e i processi importanti che possono arrestare il computer)

Tenere presente che ObsoleteAPICalls inserirà semplicemente un avviso per ogni chiamata visualizzata a un'API elencata come obsoleta o deprecata in MSDN. È consigliabile decidere caso per caso se è importante che l'applicazione passi alle nuove API. Alcune API sono pericolose e alcune sono semplicemente state sostituite da un'API più recente con altre opzioni. Per altre informazioni, vedere la sezione "API pericolose" di Scrittura di codice sicuro.

Per le applicazioni che devono essere altamente affidabili, ad esempio servizi e programmi server, è necessario abilitare anche il controllo Stack. In questo modo si verifica se le dimensioni del commit dello stack sono adeguate, disabilitando l'aumento dello stack. Se l'applicazione viene chiusa immediatamente con un overflow dello stack, significa che l'applicazione deve essere ricompilata con dimensioni di commit dello stack maggiori. Se si è un tester e si verifica un problema con un'applicazione durante l'uso del controllo Stacks, inviare un bug, assegnarlo allo sviluppatore e continuare a eseguire il test.

Domande specifiche sul test

Di seguito è riportato un elenco di domande relative ai test. Fare clic sulla domanda per visualizzare la risposta:

Le perdite di sezione critiche sono importanti?

Ogni volta che si perde una sezione critica, si perde quanto segue: un handle eventi, una piccola quantità di pool di kernel e un'allocazione di heap piccola. Questi verranno puliti se il processo viene chiuso.

Se il processo dovrebbe rimanere vivo a lungo, allora queste perdite possono morderti. Poiché le correzioni sono molto facili nel 99% dei casi (lo sviluppatore ha appena dimenticato di chiamare RtlDeleteCriticalSection) è necessario risolverli.

È possibile gestire a livello di codice gli overflow dello stack?

Non è garantito che la definizione di un gestore eccezioni nella funzione thread iniziale intercetta i potenziali overflow dello stack che potrebbero essere generati. Questo perché il codice che invia le eccezioni richiede anche un po' di stack da eseguire sopra il record di attivazione corrente. Poiché l'estensione dello stack non è riuscita, è molto probabile che si eseguirà un passaggio alla fine dello stack di cui è stato eseguito il commit e venga generata una seconda eccezione durante il tentativo di invio della prima. Un'eccezione a doppio errore terminerà il processo in modo incondizionato.

Il test LoaderLock restituisce un errore relativo alla chiamata a DestroyWindow. Perché non è possibile chiamare DestroyWindow in DllMain? Non è possibile controllare quale thread scollegare. Se non è lo stesso thread che ha creato la finestra, non è possibile eliminare definitivamente la finestra. Quindi si perde la finestra e la successiva volta che la finestra riceve un messaggio, si arresta in modo anomalo perché Wndproc è stato scaricato.

È necessario eliminare definitivamente la finestra prima di ottenere lo scollegamento del processo. Il pericolo non è che user32 verrà scaricato. Il pericolo è che si sta scaricando. Il messaggio successivo ricevuto dalla finestra arresta in modo anomalo il processo perché user32 recapita il messaggio al Wndproc che non esiste più.

Il sistema operativo Microsoft Windows ha affinità di thread. Lo scollegamento del processo non è. Il blocco del caricatore non è davvero il grande problema; il problema è Dllmain. Lo scollegamento del processo è l'ultima volta che la DLL ottiene il codice. Devi liberarti di tutto prima di tornare. Tuttavia, poiché Windows ha affinità di thread, non è possibile pulire la finestra se si è nel thread errato.

Il blocco del caricatore entra nell'immagine se qualcuno ha un hook globale installato (ad esempio, spy++ è in esecuzione). In questo caso, si immette un potenziale scenario di deadlock. Anche in questo caso, la soluzione consiste nell'eliminare definitivamente la finestra prima di ottenere lo scollegamento del processo.

È costoso aumentare i commit iniziali dello stack per evitare gli overflow?

Quando si esegue il commit dello stack, si riserva solo lo spazio dei file di pagina. Non c'è alcun impatto sulle prestazioni. In realtà non viene usata alcuna memoria fisica. L'unico costo aggiuntivo si verifica se si tocca effettivamente lo spazio dello stack di cui si è eseguito il commit. Ma questo accadrà comunque anche se non si esegue il commit iniziale dello stack.

Vediamo quale sarebbe il costo per rendere tutti i servizi in esecuzione in svchost.exe a prova di proiettile. In un computer di test si ottengono 9 processi svchost.exe con un totale di 139 thread. Se si imposta lo stack predefinito per ogni thread a 32K, saranno necessari circa 32.000 x 200 ~ 6,4 Mb di spazio di file di pagina per eseguire il commit di tutti gli stack iniziali.

Questo è un prezzo piuttosto piccolo da pagare per l'affidabilità.

Che ne dici delle dimensioni dello stack riservato?

Ci sono elementi interessanti, ad esempio l'invio di eccezioni in IA64/AMD64 che richiede uno stack aggiuntivo "imprevisto". Potrebbero verificarsi alcune operazioni di elaborazione sui thread di lavoro RPC i cui requisiti dello stack hanno superato tentativi ragionevoli di misurarli.

Prima di tutto, si dovrebbe avere un'idea di tutti i pool di thread che vivono nel processo. Il pool NT-Thread, con i thread di attesa avvisabili è talvolta speciale, perché, ad esempio, se si usa un componente di database da SQL, userà sospensioni avvisabili su un thread destinato a user-APC. Ciò può causare problemi con le chiamate nidificate.

Dopo aver appreso tutti i pool di thread, ottenere un'idea di come controllare i requisiti dello stack. Ad esempio, RPC legge una chiave del Registro di sistema per il commit dello stack. I thread della pompa WDM ottengono questo valore dall'immagine. Per altri pool di thread, il chilometraggio può variare.

Quando tutti i thread sono chiari, è possibile eseguire alcune azioni. Non avere uno spazio riservato enorme consente la frammentazione dello spazio di indirizzi solo se i thread arrivano e vanno molto spesso. Se si dispone di un pool di thread stabile che si trova nel controllo, si potrebbe avere anche un vantaggio nella riduzione dello spazio riservato. Consentirà davvero di risparmiare spazio indirizzi per gli heap e lo spazio indirizzi per gli utenti.

Sono disponibili raccomandazioni su come scegliere le dimensioni corrette per LINKER_STACKCOMMITSIZE=?

Il valore deve essere divisibile per le dimensioni della pagina (4k/8k a seconda della CPU). Ecco alcune linee guida per determinare le dimensioni necessarie:

  1. Convertire tutte le funzioni ricorsive con una potenziale profondità non associata (o almeno una profondità elevata inducibile dall'utente) in iterativa.

  2. Ridurre l'utilizzo dell'alloca. Usare heap o safealloca.

  3. Eseguire Prefast con un controllo ridotto delle dimensioni dello stack (ad esempio 8.000). Correggere queste funzioni contrassegnate come usando un numero eccessivo di stack.

  4. Impostare il commit dello stack su 16.000.

  5. Eseguire in un gruppo di test del debugger con il controllo "Stack" di Application Verifier.

  6. Quando viene visualizzato l'overflow dello stack, determinare i peggiori trasgressori e correggerli. Vedere il passaggio 5.

  7. Quando non è possibile ridurre l'utilizzo dello stack per 8k. Se si è > 64k c'è qualcosa di sbagliato, diminuire a 64k e vedere il passaggio 6. In caso contrario, andare al passaggio 5.

Quali sono i requisiti di memoria per il test dell'heap?

Per i test heap completi, sono necessari 256 MB di RAM e almeno un file di pagina da 1 GB. Per i test heap normali, sono necessari almeno 128 MB di RAM. Non sono previsti requisiti specifici per il processore o il disco.

Perché ricevo un ALL_ACCESS stop?

Qualsiasi applicazione che usa _ALL_ACCESS esegue il rendering dell'oggetto a cui accede non controllabile perché il log di controllo non rifletterà ciò che è stato effettivamente fatto con l'oggetto, ma solo ciò che è stato richiesto di fare con l'oggetto .

Questa condizione crea una mimetica per un attacco più devioso. Un amministratore che esegue l'analisi di un'attività di attacco in corso non vedrà nulla di sbagliato con la persona che richiede ALL_ACCESS sulla chiave X, perché una particolare applicazione esegue sempre questa operazione. L'amministratore penserà che "la persona sta probabilmente semplicemente eseguendo Word". L'amministratore non può dire che un hacker ha penetrato il mio account e ora sta provando il sistema per determinare quale accesso ho, che può sfruttare per le sue estremità nefarie. Le possibilità sono infinite.

Il problema dell'ACL con ALL_ACCESS è che è necessario concederlo sempre. Se si vuole negare a un giorno l'accesso DELETE a una determinata chiave, non sarebbe possibile. Anche se la chiave non è stata effettivamente eliminata, l'applicazione verrà eliminata perché è necessario eliminare l'accesso.

Perché non si ottengono log dall'heap e dai test di blocco?

Questi test sono livelli di verifica compilati nel sistema operativo (e non nel pacchetto) e segnalano errori in un debugger. Se si esegue un'applicazione con tali test abilitati e non si verificano arresti anomali, non segnalano problemi.

Se si verificano arresti anomali, sarà necessario eseguire in un debugger o passare l'applicazione a uno sviluppatore per testarla più attentamente.

Perché l'iniezione di errore non funziona?

La probabilità di inserimento degli errori è stata modificata in parti per milione nelle build di AppVerifier rilasciate dopo febbraio 2007 in base al feedback dei clienti. Quindi, una probabilità di 0n20000 è 2%, 0n500000 è 50% e così via.

L'estensione del debugger !avrf –flt può essere usata per modificare la probabilità in tempo reale nel debugger. Tuttavia, per il funzionamento del processo deve essere attivato il controllo Simulazione risorse bassa.

L'estensione del debugger !avrf fa parte exts.dll fornita con il pacchetto del debugger. Le modifiche in !avrf che supportano la modifica della probabilità si trovano nel pacchetto del debugger più recente. Se si verificano problemi con l'inserimento di errori, aggiornare i debugger e il pacchetto AppVerifier.

Perché il verifier di perdita non segnala determinate perdite di risorse?

La verifica delle perdite non segnala perdite di risorse durante il caricamento di un modulo DLL o EXE. Quando un modulo viene scaricato, La verifica della perdita genera un arresto se una delle risorse allocate dal modulo non è stata rilasciata.

Per controllare le risorse allocate da una DLL o exe caricate, usare l'estensione del debugger !avrf -leak.

Vedi anche

Application Verifier - Panoramica

Application Verifier - Funzionalità

Application Verifier - Testing Applications

Verifica applicazione - Test all'interno di Application Verifier

Application Verifier - Codici e definizioni di arresto

Application Verifier - Debug dell'applicazione verifier arresta