Freigeben über


Application Verifier - Häufig gestellte Fragen (FAQs)

Allgemeine Fragen

Es folgt eine Liste der 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, es für die anwendungen von Interesse zu aktivieren (siehe die nachstehenden Fragen, wie dies zu tun ist) und dann alle Tests ausführen, die Sie für Ihre Anwendung geschrieben haben. Sie erhalten eine Benachrichtigung für alle Fehler, die in Form eines Debuggerwechsels oder eines Prüfprotokolleintrags gefunden wurden.

Gewusst wie Application Verifier deinstallieren?

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

Gewusst wie Anwendungsprüfer starten?

Nach der Installation von Application Verifier können Sie sie entweder starten, indem Sie auf sie in Ihrer Liste der Programme zugreifen oder Appverif.exe in eine 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 die Anwendungsüberprüfung gestartet.

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

Wo werden die Protokolle gespeichert?

Die Protokolle werden in %USERPROFILE%\AppVerifierLogs gespeichert.

Was sollte ich tun, wenn ich Probleme bei der Verwendung der Anwendungsprüfer habe?

Stellen Sie sicher, dass Sie die neueste Version ausführen. Erwägen Sie, dieselbe App auf einem anderen PC oder sogar einer anderen Version von Windows zu versuchen.

Überprüft Application Verifier verwalteten Code?

AppVerifier kümmert sich um die Schnittstellen zwischen dem Betriebssystem und der Anwendung. Dies führt dazu, dass Ihr verwalteter Code keine Interoperabilität mit systemeigenen APIs durchführt, die mit Heaps, Handles, Critical Section usw. zu tun haben. Ihre Testfälle geben Ihnen keine Interaktion mit den überprüften Schnittstellen.

Es wird empfohlen, die Verwalteten Debugging-Assistenten für die Überprüfung Ihres verwalteten Codes zu nutzen. Weitere Informationen finden Sie unter Debuggen von verwaltetem Code mithilfe des Windows-Debuggers.

Wird ARM64EC unterstützt?

Application Verifier unterstützt ARM64EC nicht.

Debuggerfragen

Im Folgenden finden Sie die Liste der Fragen, die sie zum Debugger erhalten haben.

Warum erhalte ich eine Fehlermeldung, die mir mitteilt, 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 Sie der Anwendung vor der Auswahl des Tests keinen Debugger zugeordnet haben, erhalten Sie ein Dialogfeld, in dem Sie daran erinnert werden, 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 zum Installieren und Einrichten des Debuggers – Erste Schritte mit dem Windows-Debugging

Gewusst wie Teststapelerweiterung ohne andere Instrumentierung?

Im Allgemeinen sollte die Stapelerweiterung wirklich isoliert von anderen Überprüfungsebenen, einschließlich Heap, getestet werden. Der Grund hierfür ist: Jede Überprüfung schichtt "thunks" eine API oder einen exportierten Punkt mit einer routine.

Beispielsweise wird ein Aufruf von CreateFileA ein Aufruf von "appvocre" sein. NS_SecurityChecks::CreateFileA, das appvcore aufrufen kann! NS_FillePaths::CreateFileA, die kernel32 aufrufen kann! CreateFileA, das kann verifier aufrufen! AVrfpNtCreateFile, das ntdll! NtCreateFile. Sie können sehen, dass die Instrumentierung drei weitere "gestapelte" Funktionsaufrufe hinzugefügt hat, jeder davon kann und mehr Stapel verbrauchen.

Im folgenden Fall ist die LH-verifier.dll "thunking" jedes DllMain, und der "instrumentierte" Heap-Codepfad fügt weitere Stapelnutzung hinzu. Da der injizierte Thread aus dem Debugger nicht die IMAGE_NT_HEADERS Standardwerte verwendet, reicht der anfänglich zugesicherte Stapel nicht aus, um den APC-Zustand eines Threads abzuschließen (ein Thread im APC-Zustand, der den Initialisierungscode ausgeführt hat).

Wenn Sie Stack-Ckecs verwenden möchten, sollten Sie wahrscheinlich die einzige andere Überprüfungsschicht verwenden, die Sie verwenden sollten, wenn FirstChanceAccessViolation.

Bei verwendung der Erweiterung !avrf erhalte ich "Application Verifier is not enabled for this process..."

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

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

Testszenario-Fragen

Es folgt eine Liste der Fragen, die sie in verschiedenen Testszenarien erhalten haben.

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.

Neustart.

Gewusst wie Application Verifier auf einer 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 von Prüfeinstellungen für eine bestimmte Anwendung besteht darin, der Bit-Ness des Tools und des Zielprozesses zu entsprechen. Das heißt: Verwenden Sie die 32-Bit-appverif.exe für eine 32-Bit-Anwendung (beide unter WoW64 ausgeführt) und verwenden Sie die 64-Bit-AppVerif.exe für das systemeigene 64-Bit-Native-Ziel.

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

Kerneinstellungen – Kerneinstellungen werden unter "Bilddateiausführungsoptionen" gespeichert.

Der Wert "Debugger" wird aus der Startanwendung gelesen. Wenn Sie also eine 32-Bit-devenv.exe starten möchten, die 64-Bit-my.exe startet und diese unter Debugger ausgeführt wird, müssen Sie den 32-Bit-Registrierungsschlüssel unter WoW6432Node verwenden. Die anderen Werte für einen 32-Bit-Prozess werden von beiden Stellen gelesen, sowohl vom nativen IFEO als auch vom WoW6432Node.

Die Begründung lautet wie folgt: Ein 32-Bit-Prozess, der unter WoW ausgeführt wird, ist ein 64-Bit-Prozess, bei dem die Wow64-Emulationsschleife ausgeführt wird. Jeder 32-Bit-Prozess ist also zuerst ein 64-Bit-Prozess und dann ein 32-Bit-Prozess. Das 64-Bit-IFEO aktiviert den Prüfer im Wow64cpu.dll Code, während der 32-Bit-IFEO die Überprüfung im 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 darum kümmern, wow64cpu.dll zu überprüfen, besteht das am meisten akzeptierte Verhalten für 32-Bit-Prozesse darin, nur die 32-Bit-Komponente zu überprüfen. Aus diesem Grund gilt die goldene Regel "immer mit der Bit-Ness übereinstimmen".

Gewusst wie debuggen meinen Dienst, der in einer nicht interaktiven Fensterstation ausgeführt wird

Gehen Sie wie folgt vor, um einen Dienst zu debuggen, der in einer nicht interaktiven Fensterstation ausgeführt wird (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 der Debugger befindet. Er muss den vollständigen Pfad enthalten, nicht nur den Namen des Debuggers. Der Befehl sollte die Option "–server" und einen bestimmten Port oder Portbereich enthalten, auf den 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 einer Remoteoption ausführen. Ein Beispiel ist: 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 Leckerkennung durch? Unter Windows 7 und höher gibt es eine Überprüfungsoption für Lecks, die erkennt, wann ein Prozess speicherleckt. Unter früheren Betriebssystemen teste AppVerifier die Anwendung nicht auf die Leckerkennung, sondern sucht nach anderen Speicherproblemen.

Welche Tests werden für Sicherheitsbedenken empfohlen?

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

Denken Sie daran, dass ObsoleteAPICalls nur eine Warnung für jeden Aufruf aussah, der für eine API angezeigt wird, die in MSDN als veraltet oder veraltet aufgeführt ist. Sie sollten fallweise 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 weiteren Optionen abgelöst. Sehen Sie sich den Abschnitt "Gefährliche APIs" zum Schreiben von sicherem Code, 2. Ergänzung für weitere Informationen an.

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 Stapel-Commits 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 Stapel-Commit-Größe neu kompiliert werden muss. Wenn Sie Tester sind und beim Verwenden der Stacks-Prüfung ein Problem mit einer Anwendung auftreten, geben Sie einen Fehler ein, weisen Sie sie Ihrem Entwickler zu, und führen Sie die Tests durch.

Testen spezifischer Fragen

Es folgt eine Liste der Fragen zum Testen. Klicken Sie auf die Frage, um die Antwort anzuzeigen:

Sind kritische Abschnittslecks wichtig?

Wenn Sie einen kritischen Abschnitt durchlecken, wird Folgendes geleert: ein Ereignishandle, eine kleine Menge Kernelpool und eine kleine Heap-Zuordnung. Diese werden bereinigt, wenn der Prozess beendet wird.

Wenn Ihr Prozess lange lebendig bleiben soll, können diese Lecks Sie bissen. Da die Korrekturen in 99 % der Fälle sehr einfach sind (Entwickler haben gerade vergessen, RtlDeleteCriticalSection aufzurufen), sollten Sie sie adressieren.

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

Das Einrichten eines Ausnahmehandlers in der anfänglichen Threadfunktion ist nicht garantiert, die potenziellen Stapelüberläufe abzufangen, die ausgelöst werden können. Dies liegt daran, dass der Code, der Ausnahmen verteilt, auch ein wenig Stapel benötigt, um über dem aktuellen Aktivierungseintrag ausgeführt zu werden. Da wir gerade die Stapelerweiterung fehlgeschlagen sind, ist es sehr wahrscheinlich, dass wir das Ende des zugesicherten Stapels überschreiten und eine zweite Ausnahme auslösen, während sie versuchen, die erste zu verteilen. Eine Ausnahme des doppelten Fehlers beendet den Prozess bedingungslos.

Der LoaderLock-Test gibt einen Fehler beim Aufrufen von DestroyWindow. Warum kann ich "DestroyWindow" in DllMain nicht aufrufen? Sie steuern nicht, welcher Thread abtrennt werden soll. Wenn es nicht derselbe Thread ist, der das Fenster erstellt hat, können Sie das Fenster nicht zerstören. Sie können also das Fenster auslaufen und wenn das Fenster das nächste Mal eine Nachricht empfängt, abstürzen, da der Wndproc entladen wurde.

Sie müssen das Fenster zerstören, bevor Sie die Prozessablösung erhalten. Die Gefahr besteht nicht darin, dass Der Benutzer32 entladen wird. Die Gefahr besteht darin, dass Sie entladen werden. Daher stürzt die nächste Nachricht, die das Fenster empfängt, den Prozess ab, da Der Benutzer32 die Nachricht an Ihren Wndproc weitergibt, der nicht mehr vorhanden ist.

Das Microsoft Windows-Betriebssystem verfügt über Threadaffinität. Die Prozesstrennzeichen werden nicht abgetrennt. Die Ladesperre ist nicht wirklich das große Problem; das Problem ist Dllmain. Die Prozesstrennfunktion ist das letzte Mal, wenn die DLL Code ausführt. Sie müssen alles loswerden, bevor Sie zurückkehren. Da Windows jedoch threadaffin ist, können Sie das Fenster nicht bereinigen, wenn Sie sich im falschen Thread befinden.

Die Ladesperre tritt in das Bild ein, wenn jemand einen globalen Hook installiert hat (z. B. Spy++ läuft). In diesem Fall geben Sie ein potenzielles Deadlock-Szenario ein. Auch hier besteht die Lösung darin, das Fenster zu zerstören, bevor Sie prozessdetachieren.

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

Wenn Sie einen Commit-Stapel ausführen, reservieren Sie einfach den Seitendateispeicher. Es gibt keine Auswirkungen auf die Leistung. Tatsächlich wird kein physischer Speicher verwendet. Die einzigen zusätzlichen Kosten treten auf, wenn Sie tatsächlich den von Ihnen zugesicherten Stapelbereich berühren. Dies geschieht aber trotzdem, auch wenn Sie den Stapel nicht vorab übernehmen.

Lassen Sie uns sehen, was die Kosten wären, um alle Dienste in svchost.exe Bulletproof laufen zu lassen. 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 32 KB x 200 ~ 6,4 Mb Seitendateibereich, um alle Stapel vorab zu übernehmen.

Dies ist ein ziemlich kleiner Preis, um für Zuverlässigkeit zu bezahlen.

Was ist mit reservierter Stapelgröße?

Es gibt interessante Elemente, z. B. die Ausnahmeversand auf IA64/AMD64, die einen "unerwarteten" zusätzlichen Stapel erfordern. Möglicherweise gibt es einige Verarbeitungen in RPC-Workerthreads, deren Stapelanforderungen über angemessene Versuche zur Messung der Daten verfügen.

Zunächst sollten Sie eine Vorstellung von allen Threadpools erhalten, die im Prozess leben. Der NT-Thread-Pool mit den warnbaren Wartethreads ist manchmal besonders, da z. B. wenn Sie eine Datenbankkomponente aus SQL verwenden, über einen Thread, der ein Ziel von User-APC ist, warnungsfähige Ruhezustande verwendet. Dies kann zu Problemen mit geschachtelten Aufrufen führen.

Sobald Sie alle Threadpools kennen, erhalten Sie eine Vorstellung davon, wie Sie ihre Stapelanforderungen steuern können. Beispielsweise liest RPC einen Registrierungsschlüssel für den Stapel-Commit vor. Die WDM-Pumpenthreads erhalten dies aus dem Bild. Bei anderen Threadpools kann die Kilometerzahl variieren.

Wenn Sie alle Threads klar sind, können Sie eine Aktion ausführen. Wenn Kein riesiger reservierter Platz vorhanden ist, hilft die Fragmentierung des Adressraums nur, wenn Threads kommen und sehr häufig gehen. Wenn Sie über einen stabilen Threadpool verfügen, der sich in Ihrem Steuerelement befindet, haben Sie möglicherweise auch einen Vorteil beim Verringern des reservierten Speicherplatzes. Es hilft wirklich, Adressraum für die Heaps und den Adressraum für Benutzer zu sparen.

Gibt es Empfehlungen zum Auswählen der richtigen Größe für LINKER_STACKCOMMITSIZE=?

Der Wert sollte durch die Seitengröße divisierbar sein (4k/8k je nach CPU). Im Folgenden finden Sie einige Richtlinien zum Bestimmen der benötigten Größe:

  1. Konvertieren Sie rekursive Funktionen mit potenzieller ungebundener Tiefe (oder zumindest benutzerinduzierter hoher Tiefe) in iterativ.

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

  3. Führen Sie prefast mit reduzierter Stapelgrößesprüfung aus (z. B. 8k). Korrigieren Sie diese Funktionen, die als zu viel Stapel gekennzeichnet sind.

  4. Legen Sie den Stapel-Commit auf 16k fest.

  5. Führen Sie unter einem Debugger-Bündel von Tests mit der Prüfung "Stacks" von Application Verifier aus.

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

  7. Wenn Sie die Stapelnutzung nicht um 8k reduzieren können. Wenn Sie > 64k sind, gibt es etwas Falsches, verringern Sie wieder auf 64k und sehen Sie Schritt 6. Wechseln Sie andernfalls zu Schritt 5.

Was sind die Speicheranforderungen für den Heaptest?

Für vollständige Heap-Tests benötigen Sie 256 MB RAM und mindestens eine 1 GB-Seitendatei. Für normale Heap-Tests 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 es zugreift, kann nicht überprüft werden, da das Überwachungsprotokoll nicht widerspiegelt, was Sie tatsächlich mit dem Objekt getan haben – nur das, was Sie mit dem Objekt zu tun haben.

Diese Bedingung schafft eine Tarnung für einen verschänderen Angriff. Ein Administrator, der nach einer laufenden Angriffsaktivität sucht, sieht nichts falsch mit der Person, die ALL_ACCESS auf Schlüssel X anfordert, da eine bestimmte Anwendung dies immer tut. Der Administrator wird denken, dass "die Person wahrscheinlich nur Word ausführt". Der Administrator kann nicht sagen, dass ein Hacker mein Konto eingedrungen hat und jetzt das System probiert, um zu bestimmen, welchen Zugriff ich habe, was er für seine nefarigen Enden ausnutzen kann. Den Möglichkeiten sind keine Grenzen gesetzt.

Das ACL-Problem mit ALL_ACCESS besteht darin, dass Sie es immer erhalten müssen. Wenn wir Ihnen irgendwann den DELETE-Zugriff auf einen bestimmten Schlüssel verweigern möchten, dann 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?

Diese Tests sind Überprüfungsebenen, die im operativen System (und nicht im Paket) integriert sind, und Fehler in einem Debugger melden. Wenn Sie eine Anwendung mit aktivierten Tests ausführen und keine Abstürze haben, werden keine Probleme gemeldet.

Wenn Abstürze auftritt, müssen Sie die Anwendung unter einem Debugger ausführen oder die Anwendung an einen Entwickler übergeben, um den Test genauer zu testen.

Warum funktioniert fehlerinjektion nicht?

Die Fehlereinfügungswahrscheinlichkeit wurde auf Teile pro Million in AppVerifier-Builds geändert, die nach Februar 2007 basierend auf Kundenfeedback veröffentlicht wurden. Also, eine Wahrscheinlichkeit von 0n20000 ist 2%, 0n500000 ist 50 % usw.

!avrf –flt debugger extension can be used to change the probability on the fly in the debugger. Die Prüfung der Low Resource Simulation für den Prozess sollte jedoch aktiviert sein, damit dies funktioniert.

!avrf debugger extension is part exts.dll that ships with the debugger package. Die Änderungen in !avrf, die die Wahrscheinlichkeitsänderung unterstützen, befinden sich im neuesten Debuggerpaket. Wenn Probleme mit der Fehlereinfügung auftreten, aktualisieren Sie die Debugger und das AppVerifier-Paket.

Warum meldet Leak Verifier bestimmte Ressourcenlecks nicht?

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

Verwenden Sie die Erweiterung "!avrf -leak debugger", um ressourcen zu prüfen, die einer geladenen DLL oder EXE zugeordnet wurden.

Weitere Informationen

Anwendungsüberprüfung – Überblick

Anwendungsüberprüfung – Funktionen

Anwendungsüberprüfung – Testen von Anwendungen

Anwendungsüberprüfung – Tests innerhalb der Anwendungsüberprüfung

Anwendungsüberprüfung – Stoppcodes und Definitionen

Anwendungsüberprüfung – Debuggen von Stopps der Anwendungsüberprüfung