Share via


Application Verifier – Häufig gestellte Fragen (FAQs)

Allgemeine Fragen

Im Folgenden erhalten Sie eine Liste mit Fragen zur allgemeinen Verwendung von Application Verifier.

Was ist Application Verifier?

Application Verifier ist ein Laufzeitüberprüfungstool, das verwendet wird, um Fehler in Microsoft Windows-Anwendungen zu finden. Da es sich um ein Laufzeittool handelt, muss der Anwendungscode ausgeführt werden, um überprüft zu werden. Eine gute Testabdeckung ist daher unerlässlich.

Das typische Verwendungsszenario von Application Verifier besteht darin, sie für die anwendungen von Interesse zu aktivieren (informationen hierzu finden Sie unten in den Fragen) und dann alle Tests auszuführen, die Sie für Ihre Anwendung geschrieben haben. Sie erhalten eine Benachrichtigung für jeden Fehler, der in Form eines Debuggerunterbrechungs oder eines Prüfprotokolleintrags gefunden wurde.

Gewusst wie Application Verifier deinstallieren?

Um die Anwendungsüberprüfung zu deinstallieren, greifen Sie auf die Systemsteuerung zu, indem Sie auf Start klicken, auf Programme hinzufügen oder entfernen, dann Programm entfernen, auf Application Verifier und dann auf Entfernen klicken.

Gewusst wie Application Verifier starten?

Nach der Installation von Application Verifier können Sie ihn entweder starten, indem Sie in Ihrer Programmliste darauf zugreifen oder Appverif.exe in einer Befehlszeile eingeben. Wechseln Sie dazu zu einer Eingabeaufforderung oder zum Feld Ausführen des Startmenüs. Geben Sie appverif.exe ein, und drücken Sie dann die EINGABETASTE. Dadurch wird application verifier gestartet.

Die Appverifer.exe Binärdatei wird im Systemverzeichnis installiert und wird verwendet, um die Tooleinstellungen vorzunehmen.

Wo werden die Protokolle gespeichert?

Die Protokolle werden in %USERPROFILE%\AppVerifierLogs gespeichert.

Was kann ich tun, wenn ich Probleme bei der Verwendung des Application Verifiers habe?

Stellen Sie sicher, dass Sie das neueste Release ausführen. Erwägen Sie, dieselbe App auf einem anderen PC oder sogar einer anderen Windows-Version auszuprobieren.

Überprüft Application Verifier verwalteten Code?

AppVerifier kümmert sich um die Schnittstellen zwischen dem Betriebssystem und der Anwendung. Es sei denn, Ihr verwalteter Code führt Interop für native APIs aus, die mit Heaps, Handles, Kritischem Abschnitt usw. zu tun haben. Ihre Testfälle ermöglichen keine Interaktion mit den überprüften Schnittstellen.

Es wird empfohlen, die Assistenten für verwaltetes Debuggen zu nutzen, um Ihren verwalteten Code zu überprüfen. Weitere Informationen finden Sie unter Debuggen von verwaltetem Code mithilfe des Windows-Debuggers.

Debuggerfragen

Im Folgenden finden Sie eine Liste mit Fragen zum Debugger.

Warum wurde mir eine Fehlermeldung angezeigt, dass ich einen Debugger benötige?

Die Überprüfungsebene "Grundlagen" innerhalb der Anwendungsüberprüfung erfordert, dass Sie Ihre Anwendung unter einem Debugger ausführen. Wenn Der Anwendung vor der Auswahl des Tests kein Debugger zugeordnet ist, erhalten Sie ein Dialogfeld, das Sie daran erinnert, dass Sie Ihre Anwendung unter einem Debugger ausführen müssen, um die protokollierten Informationen abzurufen.

Gewusst wie meine Anwendung unter einem Debugger ausführen?

Weitere Informationen finden Sie in den Themen Debuggerinstallation und -einrichtung – Erste Schritte mit Windows-Debugging.

Gewusst wie Erweiterung des Teststapels ohne andere Instrumentierung?

Im Allgemeinen sollte die Stapelerweiterung wirklich isoliert von anderen Überprüfungsebenen, einschließlich Heap, getestet werden. Der Grund ist folgender: Jede Überprüfungsebene "thunt" eine API oder einen exportierten Punkt mit einer Routine.

Beispielsweise ist ein Aufruf von CreateFileA ein Aufruf zum Appvocre! NS_SecurityChecks::CreateFileA, das könnte appvcore! NS_FillePaths::CreateFileA, das kernel32 aufrufen könnte! CreateFileA, die möglicherweise überprüfungserrufen! AVrfpNtCreateFile, das ntdll! NtCreateFile. Sie können sehen, dass die Instrumentierung 3 weitere "gestapelte" Funktionsaufrufe hinzugefügt hat, von denen jeder mehr Stapel nutzen kann und wird.

Im folgenden Fall ist die LH-verifier.dll jedes DllMain "Thunking", und der "instrumentierte" Heapcodepfad fügt eine weitere Stapelnutzung hinzu. Da der vom Debugger eingefügte Thread nicht die IMAGE_NT_HEADERS Standardwerte verwendet, reicht der anfängliche Commitstapel nicht aus, um den APC-Zustand eines Threads abzuschließen (ein Thread im APC-Zustand hat den Initialisierungscode ausgeführt).

Wenn Sie Stack-Ckecs verwenden möchten, ist es wahrscheinlich die einzige andere Überprüfungsebene, die Sie bei FirstChanceAccessViolation verwenden sollten.

Wenn Ich die !avrf-Erweiterung verwende, erhalte ich "Application Verifier is not enabled for this process..."

Der vollständige Fehler, der empfangen wurde: Application verifier is not enabled for this process. Use appverif.exe tool to enable it.

Wahrscheinlich haben Sie nur die Shim-Überprüfungsebenen und/oder den Heap im reinen Modus aktiviert. Dies sind einige der möglichen Ursachen.

Testszenariofragen

Im Folgenden ist eine Liste mit Fragen zu verschiedenen Testszenarien aufgeführt.

Wie kann ich application verifier für meinen Dienst aktivieren, aber nicht für andere?

Erstellen Sie eine Kopie von svchost.exe im System32-Verzeichnis, und rufen Sie die Kopie "Mysvchost.exe" auf.

Öffnen Sie mit regedit HKLM\System\CurrentControlSet\Services\MyService.

Bearbeiten Sie den Wert "ImagePath", der etwa "%SystemRoot%\system32\svchost.exe -k myservice" lautet, und ändern Sie svchost.exe in "Mysvchost.exe".

Fügen Sie der AppVerifier-Liste "Mysvchost.exe" hinzu, und überprüfen Sie die gewünschten Tests.

Starten Sie den Computer neu.

Gewusst wie Application Verifier für eine 64-Bit-Anwendung ausführen, die von einer 32-Bit-Anwendung gestartet wird, die unter WOW64 ausgeführt wird?

Einfache Version: Die goldene Regel zum Aktivieren der Überprüfungseinstellungen für eine bestimmte Anwendung besteht darin, die Bitanzahl des Tools und des Zielprozesses abzugleichen. Das heißt: Verwenden Sie die 32-Bit-appverif.exe für eine 32-Bit-Anwendung (beide ausgeführt unter WoW64) und verwenden Sie die 64-Bit-AppVerif.exe für das native native 64-Bit-Ziel.

Lange Version: Anwendungsüberprüfungseinstellungen sind die richtige Vereinigung von "Core"-Einstellungen und "shim"-Einstellungen.

Kerneinstellungen: Kerneinstellungen werden unter Optionen für die Ausführung von Bilddateien gespeichert.

Der Wert "Debugger" wird aus der Startanwendung gelesen. Wenn Sie also 32-Bit-devenv.exe das Starten von 64-Bit-my.exe und unter Debugger ausführen möchten, müssen Sie den 32-Bit-Registrierungsschlüssel unter WoW6432Node verwenden. Die anderen Werte für einen 32-Bit-Prozess werden von beiden Orten gelesen, sowohl vom nativen IFEO als auch vom WoW6432Node.

Die Begründung ist die folgende: Ein 32-Bit-Prozess, der unter WoW ausgeführt wird, ist ein 64-Bit-Prozess, der die Wow64-Emulationsschleife ausführt. Daher ist jeder 32-Bit-Prozess zunächst ein 64-Bit-Prozess und dann ein 32-Bit-Prozess. Das 64-Bit-IFEO aktiviert die Überprüfung für den Wow64cpu.dll Code, während das 32-Bit-IFEO die Überprüfung für den 32-Bit-Code aktiviert.

Aus Sicht des Endbenutzers wird verifier.dll zweimal geladen (einmal in der 64-Bit-Welt, einmal in der 32-Bit-Welt). Da sich die meisten Personen nicht um die Überprüfung wow64cpu.dll kümmern, ist das am häufigsten akzeptierte Verhalten für 32-Bit-Prozesse, nur den 32-Bit-Teil zu überprüfen. Aus diesem Grund gilt die goldene Regel "immer mit dem Bit übereinstimmen".

Gewusst wie Debuggen meines Diensts, der in einer nicht interaktiven Fensterstation ausgeführt wird

Führen Sie zum Debuggen eines Diensts, der in einer nicht interaktiven Fensterstation ausgeführt wird, die folgenden Schritte aus (gilt nur, wenn Sie ntsd/windbg verwenden):

Fügen Sie der Registrierung unter HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options einen Schlüssel hinzu. Der Name dieses Schlüssels sollte der Name des Prozesses (service.exe) sein.

Erstellen Sie einen REG_SZ Wert namens Debugger, und legen Sie diesen Wert auf den Pfad fest, in dem sich Ihr Debugger befindet. Er muss den vollständigen Pfad und nicht nur den Namen des Debuggers enthalten. Der Befehl sollte die Option –server und einen bestimmten Port oder Portbereich enthalten, an dem der Debugger lauschen soll. Ein Beispiel ist c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g –G.

Stellen Sie eine Verbindung mit dem Debuggerserver her, indem Sie den Debugger mit der Option –remote ausführen. Beispiel: windbg.exe –remote tcp:=localhost,port=55xx, wobei "xx" eine Zahl von 00 bis 99 ist, wenn Sie einen Bereich auf dem Server verwendet haben.

Führt AppVerifier die Erkennung von Lecks durch? Unter Windows 7 und höher gibt es eine Option zur Überprüfung von Lecks, die erkennt, wenn ein Prozess Arbeitsspeicher verloren hat. Unter früheren Betriebssystemen testt AppVerifier die Anwendung nicht auf Die Erkennung von Lecks, sondern sucht nach anderen Speicherproblemen.

Welche Tests werden für Sicherheitsbedenken empfohlen?

  • Heaps
  • Ziehpunkte
  • Locks
  • Stapel (nur für Dienste und wichtige Prozesse, die den Computer heruntersetzen können)

Beachten Sie, dass ObsoleteAPICalls nur eine Warnung für jeden Aufruf an eine API ausspuckt, die in MSDN als veraltet oder veraltet aufgeführt ist. Sie sollten von Fall zu Fall entscheiden, ob es für Ihre Anwendung wichtig ist, zu den neuen APIs zu wechseln. Einige der APIs sind gefährlich, und einige wurden lediglich von einer neueren API mit mehr Optionen ersetzt. Weitere Informationen finden Sie im Abschnitt "Gefährliche APIs" unter Schreiben von sicherem Code, 2. Ergänzung.

Für Anwendungen, die sehr zuverlässig sein müssen, z. B. Dienste und Serverprogramme, sollten Sie auch die Stacks-Überprüfung aktivieren. Dadurch wird überprüft, ob die Größe des Stapelcommittens angemessen ist, indem das Stapelwachstum deaktiviert wird. Wenn die Anwendung sofort mit einem Stapelüberlauf beendet wird, bedeutet dies, dass die Anwendung mit einer größeren Stapelcommitgröße neu kompiliert werden muss. Wenn Sie ein Tester sind und während der Verwendung der Stacks-Überprüfung ein Problem mit einer Anwendung auftreten, sollten Sie einen Fehler erstellen, ihn Ihrem Entwickler zuweisen, und testen Sie weiter.

Testen spezifischer Fragen

Im Folgenden ist eine Liste mit Fragen rund um das Testen aufgeführt. Klicken Sie auf die Frage, um die Antwort anzuzeigen:

Sind kritische Abschnittslecks wichtig?

Wenn Sie einen kritischen Abschnitt durchsickern, gehen Sie wie folgt vor: ein Ereignishandle, eine kleine Menge an Kernelpool und eine kleine Heapzuordnung. Diese werden bereinigt, wenn der Prozess beendet wird.

Wenn Ihr Prozess lange am Leben bleiben soll, können Diese Lecks Sie beißen. Da die Korrekturen in 99 % der Fälle sehr einfach sind (Entwickler haben einfach vergessen, RtlDeleteCriticalSection aufzurufen), sollten Sie sie behandeln.

Können wir mit Stapelüberläufen programmgesteuert umgehen?

Das Einrichten eines Ausnahmehandlers in der anfänglichen Threadfunktion ist nicht garantiert, dass die potenziellen Stapelüberläufe abfangen, die ausgelöst werden können. Dies liegt daran, dass der Code, der Ausnahmen ausgibt, auch ein wenig Stapel benötigt, um auf dem aktuellen Aktivierungsdatensatz ausgeführt zu werden. Da die Stapelerweiterung gerade nicht erfolgreich war, ist es sehr wahrscheinlich, dass wir das Ende des committeten Stapels überspringen und eine zweite Ausnahme auslösen, während wir versuchen, die erste zu senden. Eine Ausnahme mit doppeltem Fehler beendet den Prozess bedingungslos.

Der LoaderLock-Test gibt einen Fehler beim Aufrufen von DestroyWindow an. Warum kann ich DestroyWindow in DllMain nicht aufrufen? Sie steuern nicht, welcher Thread getrennt werden soll. Wenn es sich nicht um denselben Thread handelt, der das Fenster erstellt hat, können Sie das Fenster nicht zerstören. Sie haben also das Fenster verloren, und wenn das Fenster das nächste Mal eine Nachricht empfängt, stürzen Sie ab, da das Wndproc entladen wurde.

Sie müssen das Fenster zerstören, bevor Sie die Prozesstrennung erhalten. Die Gefahr besteht nicht darin, dass user32 entladen wird. Die Gefahr besteht darin, dass Sie entladen werden. Die nächste Nachricht, die das Fenster empfängt, stürzt den Prozess ab, da User32 die Nachricht an Ihren Wndproc übermittelt, die nicht mehr vorhanden ist.

Microsoft Windows-Betriebssystem hat Threadaffinität. Das Trennen von Prozessen ist nicht der Fall. Die Ladesperre ist nicht wirklich das große Problem. das Problem ist Dllmain. Das Trennen von Prozessen ist das letzte Mal, wenn Ihre DLL Code ausführen kann. Sie müssen alles loswerden, bevor Sie zurückkehren. Da Windows jedoch threadaffin ist, können Sie das Fenster nicht sauber, wenn Sie sich im falschen Thread befinden.

Die Ladesperre tritt in das Bild ein, wenn jemand einen globalen Hook installiert hat (z. B. wird spy++ ausgeführt). In diesem Fall geben Sie ein potenzielles Deadlockszenario ein. Auch hier besteht die Lösung darin, das Fenster zu zerstören, bevor Sie den Prozess trennen.

Ist es teuer, anfängliche Stapelcommits zu erhöhen, um Überläufe zu vermeiden?

Wenn Sie einen Commitstapel erstellen, reservieren Sie nur Speicherplatz für die Seitendatei. Es gibt keine Leistungseinbußen. Es wird kein physischer Arbeitsspeicher verwendet. Die einzigen zusätzlichen Kosten entstehen, wenn Sie tatsächlich den zugesagten Stapelspeicher berühren. Dies geschieht jedoch trotzdem, auch wenn Sie den Stapel nicht im Voraus committen.

Sehen wir uns an, wie hoch die Kosten wären, um alle Dienste, die in svchost.exe ausgeführt werden, schusssicher zu machen. Auf einem Testcomputer erhalte ich 9 svchost.exe Prozesse mit insgesamt 139 Threads. Wenn wir den Standardstapel für jeden Thread auf 32K festlegen, benötigen wir ungefähr 32K x 200 ~ 6,4 MB Seitendateispeicher, um alle Stapel im Voraus zu commiten.

Dies ist ein ziemlich kleiner Preis für Zuverlässigkeit zu zahlen.

Wie sieht es mit der reservierten Stapelgröße aus?

Es gibt interessante Elemente, z. B. die Ausnahmeverteilung für IA64/AMD64, die "unerwartete" zusätzliche Stapel erfordert. Es kann einige Verarbeitungen für RPC-Workerthreads geben, deren Stapelanforderungen in der Vergangenheit vernünftige Versuche sind, sie zu messen.

Zunächst sollten Sie sich ein Bild von allen Threadpools verschaffen, die in diesem Prozess leben. Der NT-Thread-Pool mit den warnungsfähigen Wartethreads ist manchmal besonders, da z. B. bei Verwendung einer Datenbankkomponente aus SQL warnungsfähige Ruhevorgänge für einen Thread verwendet werden, der ein Ziel von User-APC ist. Dies kann zu Problemen bei geschachtelten Aufrufen führen.

Sobald Sie alle Threadpools kennen, erhalten Sie eine Vorstellung davon, wie Sie deren Stapelanforderungen steuern können. Beispielsweise liest RPC einen Registrierungsschlüssel für den Stapelcommit. Die WDM-Pumpenthreads erhalten dies aus dem Image. Bei anderen Threadpools kann die Laufleistung variieren.

Wenn Sie alle Threads frei sind, können Sie maßnahmen ergreifen. Wenn Sie keinen großen reservierten Speicherplatz haben, können Sie die Fragmentierung des Speicherplatzes nur dann beheben, wenn Threads sehr häufig kommen und gehen. Wenn Sie über einen stabilen Threadpool verfügen, der sich in Ihrer Kontrolle befindet, haben Sie möglicherweise auch einen Vorteil darin, den reservierten Speicherplatz zu reduzieren. Es wird wirklich helfen, Adressraum für die Heaps und den Adressraum für Benutzer zu sparen.

Gibt es Empfehlungen zur Auswahl der richtigen Größe für LINKER_STACKCOMMITSIZE=?

Der Wert sollte durch die Seitengröße teilbar sein (je nach CPU 4k/8k). Im Folgenden finden Sie einige Richtlinien, um die gewünschte Größe zu bestimmen:

  1. Konvertieren Sie alle rekursiven Funktionen mit potenzieller ungebundener Tiefe (oder zumindest vom Benutzer induzierbarer hoher Tiefe) in iterativ.

  2. Reduzieren Sie die Alloca-Nutzung. Verwenden Sie heap oder safealloca.

  3. Führen Sie Prefast mit der Überprüfung der reduzierten Stapelgröße (z. B. 8k) aus. Korrigieren Sie diese Funktionen, die als zu viel Stapel gekennzeichnet sind.

  4. Legen Sie den Stapelcommit auf 16.000 fest.

  5. Führen Sie unter einer Debugger-Reihe von Tests mit der Überprüfung "Stacks" von Application Verifier aus.

  6. Wenn Der Stapelüberlauf angezeigt wird, ermitteln Sie die schlimmsten Täter und beheben Sie sie. (Siehe Schritt 5.)

  7. Wenn Sie die Stapelnutzung nicht mehr reduzieren können, stoßen Sie um 8.000. Wenn Sie 64.000 Uhr sind > , stimmt etwas nicht, verringern Sie wieder auf 64k, und sehen Sie sich Schritt 6 an. Fahren Sie andernfalls mit Schritt 5 fort.

Was sind die Arbeitsspeicheranforderungen für den Heaptest?

Für vollständige Heaptests benötigen Sie 256 MB RAM und mindestens eine Auslagerungsdatei mit 1 GB. Für normale Heaptests benötigen Sie mindestens 128 MB RAM. Es gibt keine spezifischen Prozessor- oder Datenträgeranforderungen.

Warum erhalte ich einen ALL_ACCESS Stopp?

Jede Anwendung, die _ALL_ACCESS verwendet, rendert das Objekt, auf das sie zugreift, nicht prüfbar, da das Überwachungsprotokoll nicht widerspiegelt, was Sie tatsächlich mit dem Objekt getan haben – nur das, was Sie mit dem -Objekt angefordert haben.

Diese Bedingung schafft eine Tarnung für einen hinterhältigeren Angriff. Ein Administrator, der eine Überprüfung auf eine laufende Angriffsaktivität durchführt, sieht nichts Falsches an der Person, die ALL_ACCESS auf Schlüssel X anfordert, da dies immer von einer bestimmten Anwendung ausgeführt wird. Der Administrator wird denken, dass "die Person wahrscheinlich nur Word ausführt". Der Administrator kann nicht feststellen, dass ein Hacker in mein Konto eingedrungen ist und jetzt das System untersucht, um zu ermitteln, welchen Zugriff ich habe, den er für seine ruchhaften Zwecke ausnutzen kann. Den Möglichkeiten sind keine Grenzen gesetzt.

Das ACL-Problem mit ALL_ACCESS besteht darin, dass Sie sie immer erhalten müssen. Wenn wir ihnen eines Tages den DELETE-Zugriff auf einen bestimmten Schlüssel verweigern möchten, wären wir nicht in der Lage. Obwohl Sie den Schlüssel nicht tatsächlich gelöscht haben, würden wir Ihre Anwendung unterbrechen, da Sie den Löschzugriff anfordern würden.

Warum erhalte ich keine Protokolle aus den Heap- und Sperrtests?

Bei diesen Tests handelt es sich um Überprüfungsebenen, die im Betriebssystem (und nicht im Paket) erstellt wurden und Fehler in einem Debugger melden. Wenn Sie eine Anwendung ausführen, bei der diese Tests aktiviert sind und keine Abstürze auftreten, werden keine Probleme gemeldet.

Wenn Es zu Abstürze kommt, müssen Sie die Ausführung unter einem Debugger durchführen oder die Anwendung an einen Entwickler übergeben, um genauer zu testen.

Warum funktioniert die Fehlerinjektion nicht?

Die Fehlereinschleusungswahrscheinlichkeit wurde in AppVerifier-Builds, die nach Februar 2007 veröffentlicht wurden, basierend auf Kundenfeedback auf Teile pro Million geändert. Also, eine Wahrscheinlichkeit von 0n20000 ist 2%, 0n50000 ist 50% und so weiter.

Die Debuggererweiterung !avrf –flt kann verwendet werden, um die Wahrscheinlichkeit im Debugger zu ändern. Damit dies funktioniert, sollte jedoch die Überprüfung der Low Resource Simulation für den Prozess aktiviert sein.

Die Debuggererweiterung !avrf ist Teil exts.dll, die im Lieferumfang des Debuggerpakets enthalten ist. Die Änderungen in !avrf, die die Wahrscheinlichkeitsänderung unterstützen, befinden sich im neuesten Debuggerpaket. Wenn Probleme mit der Fehlerinjektion auftreten, aktualisieren Sie bitte Ihre Debugger und das AppVerifier-Paket.

Warum meldet Leak Verifier bestimmte Ressourcenlecks nicht?

Leak Verifier meldet keine Ressourcenlecks, während eine DLL oder ein EXE-Modul geladen wird. Wenn ein Modul entladen wird, gibt Leak Verifier einen Stopp aus, wenn eine der Ressourcen, die vom Modul zugewiesen wurden, nicht freigegeben wurde.

Verwenden Sie die Debuggererweiterung !avrf -leak, um Ressourcen zu überprüfen, die von einer geladenen DLL oder EXE zugeordnet werden.

Weitere Informationen

Application Verifier – Übersicht

Application Verifier – Features

Application Verifier – Testen von Anwendungen

Application Verifier– Tests in Application Verifier

Anwendungsüberprüfung – Beenden von Codes und Definitionen

Application Verifier: Debuggen der Anwendungsüberprüfung wird beendet