Share via


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

Grundlagen

Zumindest sollten Sie Application Verifier mit der Einstellung „Grundlagen“ ausführen. Jeder dieser Tests testt auf einen Bereich, der Abstürze oder andere negative Szenarien verursacht, die eine direkte und signifensive Auswirkung auf die Kundenerfahrung haben.

  • Ausnahmen – Stellt sicher, dass Anwendungen Zugriffsverletzungen nicht mithilfe der strukturierten Ausnahmebehandlung ausblenden
  • Handles – Tests, um sicherzustellen, dass die Anwendung nicht versucht, ungültige Handles zu verwenden
  • Heaps – Sucht nach Problemen mit Speicherbeschädigungen im Heap
  • Leak - Erkennt Lecks, indem die Ressourcen einer DLL nachverfolgt werden, die nicht zum Zeitpunkt der Entladung der DLL freigegeben wurden.
  • Sperren – Überprüft die richtige Verwendung für kritische Abschnitte
  • Arbeitsspeicher – Stellt sicher, dass APIs für Manipulationen im virtuellen Raum richtig verwendet werden (z. B. VirtualAlloc, MapViewOfFile)
  • SRWLock – überprüft die richtige Verwendung für slim Reader/Writer (SRW)-Sperren.
  • Threadpool – Stellt die korrekte Verwendung von Threadpool-APIs sicher und erzwingt Konsistenzüberprüfungen bei Workerthreadzuständen nach einem Rückruf wie modifiziert Threadpoolthreads und anderen Threadpool-bezogenen Problemen.
  • TLS – Stellt sicher, dass threadlokale Speicher-APIs ordnungsgemäß verwendet werden

Informationen zu den von diesen Tests generierten Stop-Code-Ausnahmen finden Sie unter Application Verifier – Stop Codes and Definitions. Informationen zum Debuggen dieser Fehler finden Sie unter Application Verifier – Debugging Application Verifier Stops

Kompatibilität

Kompatibilitätsüberprüfungsschichttests helfen bei der Identifizierung einer Anwendung, die möglicherweise Probleme mit dem Microsoft Windows-Betriebssystem hat. Viele dieser Prüfungen können auch verwendet werden, um die Logo-/Zertifizierungsanforderungen zu testen.

Informationen zu den von diesen Tests generierten Stop-Code-Ausnahmen finden Sie unter Application Verifier – Stop Codes and Definitions.

HighVersionLie – Identifiziert Probleme bei einigen der häufigsten Anwendungskompatibilitätsprobleme in Windows. Das Fehlerhafte Erkennen der Version des Betriebssystems oder die Verwendung hartcodierter Versionsinformationen kann dazu führen, dass die Anwendung auf späteren Betriebssystemen fehlschlägt.

Cuzz

Die Überprüfungsebene für Parallelitäts-Fuzzen (Cuzz) erkennt Parallelitätsfehler und Datenrennensbedingungen. Cuzz passt die Threadplanung an, indem zufällige Verzögerungen an wichtigen Punkten im Code einer Anwendung eingefügt werden. Das folgende Szenario veranschaulicht den Typ des Parallelitätsfehlers, der von der Cuzz-Überprüfungsebene erkannt werden kann.

Eine Anwendung verfügt über einen übergeordneten Thread und einen untergeordneten Thread. Der übergeordnete Thread startet den untergeordneten Thread und weist dann Speicher für eine Struktur zu.

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

Der untergeordnete Thread leitet den Zeiger ab.

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

Der vorangehende Code weist einen Parallelitätsfehler auf. Wenn der untergeordnete Thread versucht, den Zeiger abzuleiten, bevor der übergeordnete Thread den Speicher zuweist, ist der Zeiger ungültig. Der Fehler ist sehr unwahrscheinlich, dass er sich selbst manifestiert, da der übergeordnete Thread in den meisten Fällen den Speicher zuweist, bevor der untergeordnete Thread gestartet wird. In seltenen Fällen konnte der untergeordnete Thread jedoch beginnen und versuchen, den Zeiger abzuleiten, bevor der übergeordnete Thread den Speicher zugewiesen hat.

Die Cuzz-Überprüfungsschicht erhöht die Wahrscheinlichkeit, dass Parallelitätsfehler wie im vorherigen Beispiel veranschaulicht werden. Cuzz führt keine zusätzlichen Prüfungen abgesehen von einzufügenden Verzögerungen durch. Daher gibt es keine Überprüfungsstopps, die direkt mit Cuzz verbunden sind. Wenn die Aktivierung von Cuzz jedoch zu einem Parallelitätsfehler führt, der sich selbst manifestiert, profitieren andere Überprüfungsebenen. Wenn beispielsweise eine Rennbedingung zu einem Heap-Überlauf führt, findet die Heaps-Überprüfungsschicht den Fehler nur dann, wenn sich die Racebedingung zur Laufzeit manifestiert. Durch die Erhöhung der Wahrscheinlichkeit, dass die Racebedingung auftritt, verbessert Cuzz die Wirksamkeit der Heaps-Ebene bei der Identifizierung des Fehlers.

Um den maximalen Vorteil von Cuzz zu erzielen, aktivieren Sie Cuzz bei so vielen Tests wie möglich, und wiederholen Sie den gleichen Test mehrmals. Cuzz kann für alle Tests aktiviert werden, einschließlich manueller Tests, Funktionstests und Stresstests. Aktivieren Sie außerdem so viele Überprüfungsebenen der Anwendungsüberprüfung wie möglich.

Sie können die Wahrscheinlichkeit erhöhen, einen Fehler zu reproduzieren, indem Sie Cuzz mit demselben zufälligen Seed (siehe Eigenschaften) bereitstellen.

Cuzz fügt Verzögerungen nur bei Win32-Synchronisierungs-API-Aufrufen ein.

Cuzz-Eigenschaften

Die folgenden Eigenschaften sind für die Cuzz-Überprüfungsebene verfügbar. Um die Eigenschaften festzulegen, wählen Sie die Cuzz-Ebene in der Benutzeroberfläche der Anwendungsüberprüfung aus, und öffnen Sie das Eigenschaftenfenster.

Eigenschaft Beschreibung
FuzzingLevel Steuert die Fuzzenstufe für Cuzz. Legen Sie dies für zeitkritische Anwendungen und 4 für reguläre Anwendungen auf 1 fest.
RandomSeed Der zufällige Samen, der von Cuzz am Anfang verwendet wird. Wenn Sie dies auf 0 festlegen, generiert Cuzz einen zeitbasierten zufallsbasierten Ausgangswert.

Simulation geringer Ressourcen

Die Simulation geringer Ressourcen versucht, eine Umgebung unter niedrigen Ressourcen zu simulieren, z. B. nicht genügend Arbeitsspeicher. Diese Simulation identifiziert Fehler, die unter geringen Arbeitsspeicherbedingungen auftreten. Dies wird auch als Fault Injection bezeichnet. Sie können eine Umgebung unter niedrigen Ressourcen simulieren, wobei Sie eine Zahl (0–100) definieren können, die die Fehlerwahrscheinlichkeitsaufrufe angibt:

  • Warten (z. B. die WaitForXXXX-API).
  • Heap_Alloc (Heap Allocation API).
  • Virtual_Alloc (Virtual Memory allocation API).
  • Registrierung (Registrierungs-API).
  • Datei (Datei-API wie CreateFile).
  • Ereignis (Ereignis-API wie CreateEvent).
  • MapView ( MapView-API wie CreateMapView).
  • Ole_Alloc (Ole-API wie SysAllocString).

Bei der Simulation geringer Ressourcen (auch als Fehlereinfügung bezeichnet) wird versucht, eine Umgebung unter niedrigen Ressourcen zu simulieren, z. B. außerhalb des Arbeitsspeichers. Dadurch werden Fehler in geringen Arbeitsspeicherbedingungen identifiziert.

Eigenschaften der Low Resource Simulation

Um die Eigenschaften zu bearbeiten, aktivieren Sie das Kontrollkästchen "Low Resource Simulation" im Bereich "Tests", klicken Sie mit der rechten Maustaste, und wählen Sie Eigenschaften aus:

Eigenschaft Beschreibung
Einschließen Grenzwertfehler werden nur in den angegebenen DLL-Dateien ausgeführt. Ein DLL-Name ohne Pfad pro Zeile. Wenn '*' angegeben ist, treten Fehler für alle Module auf.
Exclude Schließen Sie Fehler für die angegebenen Module aus. Ein DLL-Name ohne Pfad pro Zeile.
Timeout Geben Sie ein Zeitfenster (in Millisekunden) an, wenn bei der Prozessinitialisierung kein Fehler aufgetreten ist.
Warten Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die WaitForXXXX-API angibt.
Heap_Alloc Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die Heap-Zuordnungs-API angibt.
Virtual_Alloc Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die VIRTUAL Memory-Zuordnungs-API angibt.
Registrierung Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die Registrierungs-API angibt.
Datei Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die Datei-API wie CreateFile angibt.
Ereignis Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die Ereignis-API angibt, z. B. CreateEvent
MapView Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die MapView-API wie CreateMapView angibt.
Ole_Alloc Eine Zahl [0 – 1000000], die die Fehlerwahrscheinlichkeit für die Ole-API angibt, z. B. SysAllocString.
Stacks Jeder Windows-Anwendungsthread beginnt mit einer Stapelreserve und einer Stapel-Commit-Größe. Unter normaler Verwendung wächst der Stapel-Commit, wenn mehr Speicherplatz auf dem Stapel erforderlich ist. Weitere Informationen finden Sie unter Erstellen von Threads und Threadstapelgröße . Wenn das System niedrige Arbeitsspeicherbedingungen aufweist, kann das Stapel-Commit-Wachstum fehlschlagen. Der Thread, der seinen Stapel nicht vergrößert, und die gesamte Anwendung stürzt höchstwahrscheinlich ab. Diese Art von Absturz ist für wichtige Systemprozesse (z. B. für Dienste) nicht akzeptabel. Die Stapelüberprüfung deaktiviert jedes Stapelwachstum für die überprüfte Anwendung, sodass die Stapelwachstumsfehler simuliert werden, ohne dass die gesamten Systembedingungen mit geringem Arbeitsspeicher simuliert werden müssen. Ausnahmen werden ausgelöst, wenn die Anwendung versucht, den Stapel zu erweitern. Dadurch werden keine Prüferstopps generiert.

LuaPriv

Limited User Account Privilege Predictor (LuaPriv)-Tests sind sowohl Predictive als auch Diagnose und Arbeit, um Probleme im Zusammenhang mit der Ausführung einer Anwendung mit Administratorrechten anzuzeigen, und ob diese Anwendung auch dann funktionieren würde, wenn sie mit weniger Berechtigungen (im Allgemeinen als normaler Benutzer) ausgeführt wird.

Auch als UAC-Prüfungen bezeichnet, hat der Vorhersage für eingeschränkte Benutzerkontenberechtigungen (LuaPriv) zwei hauptzielige Ziele:

  • Prädiktiv: Beim Ausführen einer Anwendung mit Administratorrechten können Sie vorhersagen, ob diese Anwendung auch dann funktioniert, wenn sie mit weniger Berechtigungen ausgeführt wird (im Allgemeinen als normaler Benutzer). Wenn die Anwendung beispielsweise in Dateien schreibt, auf die nur Administratoren zugreifen können, kann diese Anwendung nicht in dieselbe Datei schreiben, wenn sie nicht als Administrator ausgeführt wird.

  • Diagnose: Identifizieren Sie potenzielle Probleme, die möglicherweise bereits bei der aktuellen Ausführung vorhanden sind, während sie mit Nicht-Administratorrechten ausgeführt werden. Wenn die Anwendung versucht, in eine Datei zu schreiben, auf die nur Mitglieder der Gruppe „Administrator“ Zugriff haben, erhält sie einen ACCESS_DENIED-Fehler. Wenn die Anwendung nicht ordnungsgemäß funktioniert, kann dieser Vorgang der Grund dafür sein.

LuaPriv identifiziert die folgenden Arten von Problemen:

Potenzielle Probleme Beschreibung
Eingeschränkte Namespaces Das Erstellen eines benannten Synchronisierungsobjekts (Event, Semaphore, Mutex usw.) ohne einen Namespace kann die Ausführung ohne Berechtigungen auf einigen Betriebssystemen erschweren, da das Betriebssystem das Objekt möglicherweise in einem eingeschränkten Namespace platzieren möchte. Zum Erstellen eines solchen Objekts in einem eingeschränkten Namespace (z. B. dem globalen Namespace) ist SeCreateGlobalPrivilege erforderlich, das nur Administratoren gewährt wird.
LuaPriv kennzeichnet beide Probleme, wenn sie erkannt werden.
Strenge Administratorüberprüfungen Einige Anwendungen fragen das Sicherheitstoken des Benutzers ab, um herauszufinden, wie viele Berechtigungen er/sie hat. In diesen Fällen kann die Anwendung ihr Verhalten ändern, je nachdem, welche Befugnisse sie beim Benutzer vermutet.
LuaPriv kennzeichnet API-Aufrufe, die diese Informationen zurückgeben.
Anfordern von Berechtigungen Eine Anwendung kann versuchen, eine sicherheitsrelevante Berechtigung (z. B. SeTcbPrivilege oder SeSecurityPrivilege) zu aktivieren, bevor sie einen Vorgang ausführt, der dies erfordert.
LuaPriv kennzeichnet Versuche, sicherheitsrelevante Berechtigungen zu aktivieren.
Fehlende Berechtigungen Wenn eine Anwendung versucht, eine Berechtigung zu aktivieren, die der Benutzer nicht hat, signalisiert sie wahrscheinlich, dass die Anwendung die Berechtigung erwartet, was zu Verhaltensunterschieden führen kann.
LuaPriv kennzeichnet fehlgeschlagene Berechtigungsanfragen.
INI-Dateivorgänge Versuche, in zugeordnete INI-Dateien (WritePrivateProfileSection und ähnliche APIs) zu schreiben, können als Nicht-Administratorbenutzer fehlschlagen.
LuaPriv kennzeichnet solche Vorgänge.
Zugang verweigert Wenn die Anwendung versucht, auf ein Objekt zuzugreifen (Datei, Registrierungsschlüssel usw.), aber der Versuch aufgrund eines unzureichenden Zugriffs fehlschlägt, erwartet die Anwendung wahrscheinlich, dass sie mit mehr Berechtigungen ausgeführt wird, als sie hat.
LuaPriv kennzeichnet Objekt-Öffnungsversuche, die mit ACCESS_DENIED und ähnlichen Fehlern fehlschlagen.
AcEs verweigern Wenn ein Objekt ACEs in seiner DACL verweigert, verweigert es explizit den Zugriff auf bestimmte Entitäten.
Dies ist ungewöhnlich und macht die Vorhersage schwierig, daher kennzeichnet LuaPriv ACEs, wenn sie gefunden werden.
Zugriff eingeschränkt Wenn eine Anwendung versucht, ein Objekt mit Rechten zu öffnen, die normalen Benutzern nicht gewährt werden (z. B. wenn versucht wird, in eine Datei zu schreiben, die nur von Administratoren geschrieben werden kann), dann funktioniert die Anwendung wahrscheinlich nicht so, wenn sie unter einem normalen Benutzer ausgeführt wird.
LuaPriv kennzeichnet solche Vorgänge.
MAXIMUM_ALLOWED Wenn eine Anwendung ein Objekt für MAXIMUM_ALLOWED öffnet, erfolgt die tatsächliche Zugriffsüberprüfung für das Objekt an anderer Stelle. Der meiste Code, der dies tut, funktioniert nicht korrekt und wird mit ziemlicher Sicherheit anders funktionieren, wenn er ohne Berechtigung ausgeführt wird.
LuaPriv kennzeichnet somit alle Vorfälle von MAXIMUM_ALLOWED.

Verschiedenes

Häufig übersehene Probleme werden in den verschiedenen Tests erfasst.

  • Gefährliche APIs – Verfolgt nach, ob die Anwendung die folgenden unsicheren Aktionen verwendet:
    • Gefährlicher Aufruf von TerminateThread.
    • Potenzieller Stapelüberlauf in geringen Arbeitsspeicherbedingungen.
    • Der Beendigungsprozess wird aufgerufen, während noch mehrere Threads ausgeführt werden.
    • LoadLibrary wird während dllMain aufgerufen.
    • FreeLibrary wird während dllMain aufgerufen.
  • Dirty Stacks füllt den nicht verwendeten Teil des Stapels in regelmäßigen Abständen mit einem Speichermuster. Dies kann dazu beitragen, nicht initialisierte Variablen in zukünftigen Funktionsaufrufen im Kontext dieses Threads zu erkennen.
  • TimeRollOver erzwingt die GetTickCount- und TimeGetTime-APIs, einen Rollover schneller als normalerweise. Auf diese Weise können Anwendungen ihre Handhabung des Zeitrollovers einfacher testen.

Verschiedene Eigenschaften

Die Überprüfung gefährlicher APIs verfügt über eine Eigenschaft, die geändert werden kann:

DllMainCheck - Überprüfen Sie LoadLibrary/FreeLibrary-Aufrufe, wenn DllMain aktiv ist.

Netzwerk

Die Netzwerktests suchen nach nicht ordnungsgemäßer Verwendung von WinSock-APIs. Wenn z. B. eine Netzwerk-API vor einem erfolgreichen WSAStartup() oder nach einem erfolgreichen WSACleanup()-Aufruf aufgerufen wurde. Weitere Informationen zu WinSock finden Sie unter winsock.h-Header und Windows Sockets 2.

Eigenschaften

Die folgenden Eigenschaften sind für die Net-Überprüfungsschicht verfügbar. Um die Eigenschaften festzulegen, wählen Sie den Netzwerkanbieter auf der Benutzeroberfläche der Anwendungsüberprüfung aus, und öffnen Sie das Eigenschaftenfenster.

Eigenschaft Beschreibung
FragmentsEnabled Ermöglicht die Fragmentierung von Datenströmen, die von TCP IPv4- und IPv6-Sockets empfangen werden.
Fragmentgröße Gibt die maximale Anzahl von Bytes an, die in einem Puffer an einen Winsock-Api-Aufruf zurückgegeben werden.

Die FragmentsEnabled-Eigenschaft ermöglicht die Funktionalität im Netzwerküberprüfungsanbieter, um das Testen und Überprüfen einer Anwendung zu vereinfachen, die TCP-Datenströme von einem Netzwerk analysiert. Nach der Aktivierung erhalten alle Aufrufe von Winsock zum Empfangen von Daten nur bis zu FragmentSize-Bytes, es sei denn, die Anwendung erfordert den gesamten Puffer, der vor der Rückgabe (gesteuert durch das MSG_WAITALL-Flag) gefüllt ist. Da weder das TCP-Protokoll noch Winsock Garantien für die Anzahl der Bytes bereitstellen, die möglicherweise in einen Puffer zurückgegeben werden, erleichtert die Aktivierung dieser Überprüfung die Überprüfung, ob der Code den Datenstrom aus dem Netzwerk richtig analysiert, unabhängig von der Anzahl der Bytes, die pro Aufruf von Winsock empfangen werden. Probleme in Streamparsern waren eine Quelle von profilreichen Fehlern, und diese Eigenschaften werden bereitgestellt, um die Überprüfung der Korrektheit zu erleichtern, da dies besonders schwierig zu testen ist. Hinweis: Dadurch werden die zurückgegebenen Daten nicht geändert – sie verlangsamt sie nur mit einer bestimmten Rate: Die Anwendung sollte sich genau so verhalten, wie diese aktiviert oder deaktiviert ist.

Die folgende Befehlszeile ermöglicht die Fragmentierung aller eingehenden TCP-Streams auf alle TCP-IPv4- und IPv6-Sockets, die in myApp.exe erstellt wurden, und alle binärdateien, die von myApp.exe geladen wurden.

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

!avrf Debugger Extension

!avrf -net -socket count - Zeigt die Anzahl der geöffneten und geschlossenen Sockethandle an.

!avrf -net -socket dump [-v] [HANDLE] - Zeigt Socketziehpunkt(n), ausführlich oder nicht an.

!avrf -net -wsastacks - Zeigt die aktuelle WSA-Init-Anzahl und die chronologische Liste der Stapelablaufverfolgungen für WSAStartup/WSACleanup an.

!avrf -net -wsastacks count - zeigt die aktuelle WSA-Initanzahl an.

!avrf -net -socket count - Dieser Befehl gibt die Gesamtanzahl der Socketziehpunkte an, die nachverfolgt werden, sowohl geöffnet als auch geschlossen. Beachten Sie, dass diese in einer kreisförmigen Warteschlange nachverfolgt werden, sodass es eine Obergrenze für die Gesamtspur gibt. Sockets werden der geöffneten Liste hinzugefügt, wenn eine der Winsock-APIs, die ein Sockethandle zuweist, aufgerufen wird. Beispiel: socket(), WSASocket(), accept(). Sockets werden aus der geöffneten Liste in die geschlossene Liste verschoben, wenn die Closesocket()-Funktion auf diesem Sockethandle aufgerufen wird.

!avrf -net -socket dump [-v] [HANDLE] - Mit diesem Befehl werden die Sockethandles aufgelistet. "-socket dump" listet alle nachverfolgten geöffneten und geschlossenen Socketziehpunkte anhand ihrer SOCKET-Werte auf. Das optionale Flag "-v" druckt zusätzlich den geöffneten oder schließenden Aufrufstapel unmittelbar nach dem Drucken jedes SOCKET-Werts. Das optionale HANDLE-Feld listet nur das angegebene SOCKET-Handle und den geöffneten oder schließenen Aufrufstapel auf.

Hier sehen Sie ein Beispiel für die verschiedenen Optionen für die Verwendung von -sockets:

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 erfordert, dass Anwendungsentwickler mindestens einmal WSAStartup() aufrufen, bevor Sie Winsock-Aufrufe ausführen. Dies wird von Winsock prozessweit nachverfolgt. Die anfängliche Referenzanzahl weist eine Winsock-Bibliothek (ws2_32.dll) an, den Winsock-Katalog und -Anbieter zu initialisieren und zu laden. Weitere Aufrufe von WSAStartup erhöhen die Anzahl der Verweise. Winsock erfordert außerdem, dass Anwendungsentwickler WSACleanup() aufrufen, wenn sie das Aufrufen von Winsock abgeschlossen haben. Die Aufrufe von WSACleanup müssen ordnungsgemäß mit einem vorherigen Aufruf von WSAStartup() gekoppelt werden. Der Aufruf von WSACleanup() erhöht die prozessweite Verweisanzahl. Wenn die Referenzanzahl auf Null fällt, gibt Winsock seine Ressourcen frei und entlädt den Winsock-Katalog und die Anbieter.

Dieser Befehl gibt den Gesamtwert der Referenzanzahl der aktuellen "WSAStartup"-Initialisierungsroutine an und listet die Aufrufstapel für Aufrufe an WSAStartup und WSACleanup im Prozess auf. Beachten Sie, dass dies in einer festen Zirkelwarteschlange Standard enthalten ist, sodass sie nicht garantiert abgeschlossen werden kann - nur die letzten N-Anrufe.

Hier sehen Sie ein Beispiel für die verschiedenen -wsastacks-Verwendungsoptionen:

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

Dieses Application Verifier-Plug-In überwacht die Aufrufe eines einzelnen Prozesses an die Authentifizierungs-APIs AcquireCredentialsHandle und InitializeSecurityContext, um die Verwendung des NTLM-Protokolls zu erkennen. Das NTLM ist ein veraltetes Authentifizierungsprotokoll mit Fehlern, die potenziell die Sicherheit von Anwendungen und des Betriebssystems gefährden und nicht verwendet werden sollten.

NTLM-Authentifizierungsrisiko

Der wichtigste Hinweis auf veraltetes NTLM-Authentifizierungsprotokoll ist das Fehlen der Serverauthentifizierung, was es einem Angreifer ermöglichen könnte, Benutzer dazu zu bringen, eine Verbindung mit einem gefälschten Server herzustellen. Als Folge fehlender Serverauthentifizierung können Anwendungen, die NTLM verwenden, auch anfällig für einen Angriffstyp sein, der als "Spiegelungsangriff" bezeichnet wird. Letzteres ermöglicht es einem Angreifer, die Authentifizierungsunterhaltung eines Benutzers auf einen legitimen Server zu entführern und ihn zum Authentifizieren des Angreifers auf dem Computer des Benutzers zu verwenden. Die Sicherheitslücken und Möglichkeiten der Exploits von NTLM sind das Ziel, die Forschungsaktivitäten in der Sicherheitscommunity zu erhöhen.

Obwohl Kerberos seit vielen Jahren verfügbar ist, werden viele Anwendungen immer noch für die Verwendung von NTLM geschrieben. Dadurch wird die Sicherheit von Anwendungen unnötig reduziert. Kerberos kann NTLM jedoch in allen Szenarien nicht ersetzen – hauptsächlich diejenigen, bei denen ein Client sich bei Systemen authentifizieren muss, die nicht mit einer Do verbunden sind Standard (ein Heimnetzwerk ist vielleicht am häufigsten von diesen). Das Negotiate-Sicherheitspaket ermöglicht eine abwärtskompatible Kompromittierung, die Kerberos wann immer möglich verwendet, und nur rückgängig machen zu NTLM, wenn keine andere Option vorhanden ist. Der Wechsel von Code zur Verwendung von Negotiate anstelle von NTLM erhöht die Sicherheit für unsere Kunden erheblich, während nur wenige oder keine Anwendungskompatibilitäten eingeführt werden. Verhandlungen allein sind keine silbernen Aufzählungszeichen – es gibt Fälle, in denen ein Angreifer ein Downgrade auf NTLM erzwingen kann, aber diese sind wesentlich schwieriger auszunutzen. Eine sofortige Verbesserung besteht jedoch darin, dass Anwendungen, die für die ordnungsgemäße Verwendung von Negotiate geschrieben wurden, automatisch immun gegen NTLM-Spiegelungsangriffe sind.

Mit einem abschließenden Wort der Vorsicht gegen die Verwendung von NTLM: In Windows ist es möglich, die Verwendung von NTLM auf Betriebssystemebene zu deaktivieren. Wenn Anwendungen eine harte Abhängigkeit von NTLM haben, können sie sich einfach nicht authentifizieren, wenn NTLM deaktiviert ist.

Welche Faktoren bewirken, dass NTLM in einer Anwendung "hartcodiert" wird?

Es gibt zwei Faktoren, die eine harte Abhängigkeit von NTLM verursachen. Als erstes wird NTLM explizit als Authentifizierungspaket ausgewählt, das von der Anwendung verwendet werden soll. Bei einigen Protokollen und APIs ist die Wahl von NTLM offensichtlich, z. B. im Aufruf der API AcquireCredentialsHandle (). Bei anderen Protokollen ist es möglicherweise nicht so offensichtlich. Beispielsweise ist das Standardauthentifizierungspaket (RPC_C_AUTHN_DEFAULT) von RPC tatsächlich ein Alias für NTLM, wenn RPC über das Netzwerk verwendet wird, und sogar das explizite Flag zum Auswählen von NTLM verfügt nicht über die NTLM-Abkürzung an einer beliebigen Stelle (RPC_C_AUTH_WINNT). Diese Art von Konstrukt erleichtert die Auswahl von NTLM, ohne dass Sie dies wissen müssen.

Anstelle von NTLM sollten Entwickler andere Authentifizierungsmethoden verwenden, z. B. das Negotiate-Paket (dies wird manchmal auch als SPNEGO- oder SNEGO-Paket bezeichnet). Die Paketauswahl muss für Client- und Serverkomponenten übereinstimmen, damit Negotiate versuchen kann, Kerberos zu verwenden. Daher müssen Client- und Serverteile der Anwendung Negotiate verwenden müssen. Wenn beide Seiten NTLM verwenden (wie es bei älteren Versionen der Fall sein kann), funktioniert Negotiate weiterhin, wird aber immer rückgängig machen zu NTLM. Wie Sie Ihrer Anwendung die Verwendung von Negotiate mitteilen, variiert je nach Protokoll. Einige der am häufigsten verwendeten Protokolle (RPC, LDAP, DCOM, HTTP) werden weiter unten in Thema 5000 ausführlich behandelt – Application Has Explicitly Selected NTLM Package.

Der zweite Faktor, der dazu führt, dass NTLM verwendet wird, ist, wenn der Client keinen gültigen Serverzielnamen für den Authentifizierungsprozess angibt. In Protokollen, die die gegenseitige Authentifizierung (z. B. Kerberos) unterstützen oder erfordern, wird der Zielname verwendet, um die gegenseitige Authentifizierung zu erreichen. Authentifizierungs-APIs (z. B. InitializeSecurityContext) verwenden einen optionalen Parameter, der normalerweise als "TargetName", "PrincipalName" oder "ServerPrincipalName" bezeichnet wird. Dies ist der Bezeichner, der von do Standard-Controllern verwendet wird, um die richtige Do auszuwählen Standard Konto zum Abrufen von Anmeldeinformationen für den Zieldienst. Da NTLM kein Konzept der Serverauthentifizierung hat, ist dieser Parameter nicht erforderlich, damit NTLM erfolgreich authentifiziert werden kann. Kerberos erfordert andererseits, dass ein Client ein Dienstticket abruft, das für den Dienst gültig ist, für den der Client authentifiziert wird. Die Kerberos-Authentifizierung schlägt immer fehl, wenn kein Zielname oder ein ungültiger Zielname angegeben ist. Wenn "Aushandeln" als Paket ausgewählt ist, wird beim Angeben des Zielnamens (oder eines ungültigen Zielnamens) Kerberos vollständig übersprungen und NTLM verwendet. Die meisten Authentifizierungs-APIs weisen den Zielnamen als optionalen Parameter auf, wenn NULL ohne Fehler akzeptiert wird. Sofern der Entwickler dies nicht außer Kraft setzt und einen expliziten Zielnamen bereitstellt, ist NTLM (und darüber hinaus reflektierbare NTLM) das Ergebnis.

Funktionsweise des NTLM-Plug-Ins

Der Verifier-Plug erkennt die folgenden Fehler:

  • Das NTLM-Paket wird direkt im Aufruf von AcquireCredentialsHandle (oder der API auf höherer Ebene) angegeben.

  • Der Zielname im Aufruf von InitializeSecurityContext ist NULL. In diesem Fall fällt Negotiate direkt auf NTLM zurück.

  • Der Zielname im Aufruf von InitializeSecurityContext ist kein ordnungsgemäß gebildeter SPN-, UPN- oder NetBIOS-Stil Standard Name. In diesem Fall gibt der Do Standard-Controller einen Fehler "Prinzipal nicht gefunden" zurück, der bewirkt, dass Negotiate auf NTLM zurückfällt.

Das Plug-In protokolliert auch Warnungen, wenn downgrades auf NTLM erkannt werden; Beispiel: Wenn ein SPN nicht vom Do Standard Controller gefunden wird. Diese werden nur als Warnungen protokolliert, da sie häufig legitime Fälle sind – z. B. bei der Authentifizierung bei einem System, das nicht zu tun ist Standard eingebunden ist.

Konfigurieren von Plug-In-Stoppoptionen

Standardmäßig werden alle Ereignisse, die als Fehler kategorisiert sind, festgelegt, um einen Debugunterbrechung zu verursachen. Alle Warnungsereignisse werden so festgelegt, dass nur die Ereignisdetails protokolliert werden.

Fehlerereignisse verursachen einen Stopp/Unterbrechung:

  • 5000 – Anwendung hat explizit NTLM-Paket ausgewählt

  • 5001 – Aushandeln der Paketliste enthält nur NTLM

  • 5002 – Aushandlung eines falschen NTLM-Ausschlusses für Paketliste

  • 5003 – Kein Zielname oder falsch formatierter Zielname für Server

Protokollierte Warnungsereignisse:

  • 5010 – Downgrade auf NTLM erkannt

NTLM-Stopps

5000 – Anwendung hat explizit NTLM-Paket ausgewählt

Schweregrad – Fehler

Die Anwendung oder das Subsystem wählt NTLM explizit aus, anstatt im Aufruf von AcquireCredentialsHandle auszuhandeln. Obwohl es für den Client und den Server möglich sein kann, sich mithilfe von Kerberos zu authentifizieren, wird dies durch die explizite Auswahl von NTLM verhindert.

Beheben dieses Fehlers

Die Lösung für diesen Fehler besteht darin, das Aushandeln-Paket anstelle von NTLM auszuwählen. Wie dies geschieht, hängt vom jeweiligen Netzwerksubsystem ab, das vom Client oder Server verwendet wird. Unten sind einige Beispiele angegeben. Sie sollten sich in der Dokumentation zu der jeweiligen Bibliothek oder api-Gruppe befinden, die Sie verwenden.

Von Anwendung verwendete APIs(Parameter) Falscher Wert Richtiger Wert Hinweise
AcquireCredentialsHandle (pszPackage) "NTLM" NEGOSSP_NAME oder "Aushandeln"
RPC-Client: RPCBindingSetAuthInfoEx (AuthnSv) RPC-Server: RPCServerRegisterAuthInfo(AuthnSvc) RPC_C_AUTHN_WINNT oder RPC_C_AUTH_DEFAULT RPC_C_AUTH_GSS_NEGOTIATE Es ist kein Fehler für einen RPC-Server, das NTLM/WINNT-Paket zu registrieren. Dies ist häufig erforderlich, um ältere Clients zu unterstützen, die nur NTLM unterstützen. Es ist ein Fehler, wenn nur das NTLM-Paket registriert ist, da dadurch alle Clients gezwungen werden, NTLM zu verwenden, auch wenn sie Kerberos verwenden können.
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (übergeben als dwAuthnSvc-Mitglied der COAUTHINFO-Struktur, die selbst ein Mitglied der an die API übergebenen COSERVERINFO-Struktur ist) RPC_C_AUTHN_WINNT RPC_C_AUTHN_DEFAULT oder RPC_C_AUTHN_GSS_NEGOTIATE Die Aushandlung sollte nur verwendet werden, wenn die Kommunikation immer über ein Netzwerk erfolgt. Wenn der DCOM-Aufruf jemals zwischen Client und Server auf demselben Computer erfolgt, müssen Sie DEFAULT verwenden und DCOM erlauben, das richtige Paket zu verwenden.
LDAP: ldap_bind_s (Methode) LDAP_AUTH_NTLM LDAP_AUTH_NEGOTIATE
HTTP WinHTTPSetCredentials (AuthScheme) WINHTTP_AUTH_SCHEME_NTLM WINHTTP_AUTH_SCHEME_NEGOTIATE

5001 – Aushandeln der Paketliste enthält nur NTLM

Schweregrad – Fehler

Bei Verwendung von AcquireCredentialsHandle ist es möglich, eine Liste von Paketen bereitzustellen, die von Negotiate verwendet oder ignoriert werden sollen. Je nach der angegebenen Liste setzt dies möglicherweise die in Negotiate integrierte Logik außer Kraft, um das am besten geeignete und sichere Authentifizierungspaket auszuwählen. Wenn die Paketliste nur NTLM enthält oder Kerberos ausschließt, ist das Ergebnis identisch mit der Vollständigen Aushandlung und expliziten Auswahl des NTLM SSP-Pakets.

Die Angabe einer Unterpaketliste ist nur beim direkten Aufrufen von AcquireCredentialsHandle möglich, da die meisten APIs mit höherer Ebene (z. B. RPC) dem Aufrufer nicht erlauben, die Negotiate-Paketliste zu steuern.

Microsoft empfiehlt nicht, dass Anwendungen versuchen, die Aushandlungspaketliste auf diese Weise zu bearbeiten.

Beheben dieses Fehlers

Verwenden Sie das Negotiate-Paket, ohne eine Liste von Unterpaketen anzugeben oder sicherzustellen, dass Kerberos enthalten ist.

Von Anwendung verwendete APIs(Parameter) Falscher Wert Richtiger Wert
AcquireCredentialsHandle (PackageList-Element von SEC_WINNT_AUTH_IDENTITY_EX struktur übergeben als pAuthData-Parameter) "! Kerberos oder "NTLM" NULL oder "Kerberos, NTLM" oder "Kerberos, ! NTLM" oder "! NTLM"

5002 – Aushandlung eines falschen NTLM-Ausschlusses für Paketliste

Schweregrad – Warnung

Beim Aufrufen von AcquireCredentialsHandle hat die Anwendung versucht, NTLM aus der Liste der pakete auszuschließen, die von Negotiate unterstützt werden. Die falsche Syntax wurde jedoch verwendet, um NTLM auszuschließen, daher werden sie in der Liste erneut Standard.

Behebung dieses Fehlers Verwenden Sie die folgende Syntax, um das NTLM-Paket aus Negotiate auszuschließen:

Von Anwendung verwendete APIs(Parameter) Falscher Wert Richtiger Wert
AcquireCredentialsHandle (PackageList-Element von SEC_WINNT_AUTH_IDENTITY_EX struktur übergeben als pAuthData-Parameter) "-NTLM" "! NTLM"

5003 – Kein Zielname oder falsch formatierter Zielname für Server

Schweregrad – Fehler

Wenn Sie das Negotiate-Paket verwenden, führt die Angabe eines NULL- oder ungültigen Zielnamens (manchmal auch als Prinzipalname bezeichnet) dazu, dass Kerberos fehlschlägt und NTLM an seiner Stelle verwendet wird. Sie sollten beim Tätigen eines Authentifizierungsaufrufs immer einen gültigen Zielnamen angeben. Der Zielname ist ein eindeutiger Bezeichner, mit dem ein Do Standard Controller die Kontodetails des Servers abrufen kann, bei dem Ihre Anwendung sich authentifizieren möchte. Sobald der Controller über diese Informationen verfügt Standard kann er geeignete Kerberos-Tickets erstellen, die sowohl vom Client als auch vom Server verstanden (entschlüsselbar) werden.

Beheben dieses Fehlers

Zielnamen können in drei verschiedenen Formaten angegeben werden, die jeweils von den Controllern verwendet werden können Standard um das richtige Serverkontoobjekt zu finden. Diese Formate sind Service Principal Name (SPN), User Principal Name (UPN) und NetBIOS two-part do Standard\account name. Der SPN ist die am häufigsten verwendete Form und die interoperabelsten mit anderen Kerberos-Implementierungen. Eine vollständige Erläuterung von SPNs liegt außerhalb des Umfangs dieses Dokuments, aber das einfachste und am häufigsten verwendete SPN-Formular besteht aus zwei Teilen: einer Dienstklasse und einem Hostnamen. Die Dienstklasse identifiziert den Typ der Serveranwendung (z. B. spezifischer Anwendungstyp wie http oder ldap oder als generisch als Host). Der zweite Teil ist entweder der vollqualifizierte Do Standard Name oder der Flache (NetBIOS)-Name des Servers. Windows-Clients und -Server registrieren SPNs automatisch für "Host" für den FQDN und flache Namen. Do Standard-Controller ordnen auch rund 40 anwendungsspezifische Dienstklassen dem SPN "host" zu, z. B. "http", "ldap", "rpc", "tapi" usw.

o geben Sie einen Zielnamen für eine Anwendung an, die im Kontext des Serverbetriebssystems ausgeführt wird (z. B. lokales System, Netzwerkdienst oder localservice) Clientanwendungen können den automatisch registrierten "host"-SPN oder einen seiner Aliase verwenden. Um sich bei einer Anwendung zu authentifizieren, die im Kontext einer Do-Anwendung ausgeführt wird Standard müssen Sie einen SPN für dieses Konto registrieren.

Für Benutzerkonten können Sie auch das implizite UPN-Formular verwenden, das aus dem Benutzernamen und dem Vorgang erstellt wurde Standard in dem sich das Konto befindet: useraccountname@domain.dom. Sie können zwar zusätzliche UPNs für ein Benutzerkonto erstellen (unter Verwendung der UPN-Suffixe, die für jede Do erstellt werden können Standard), funktionieren diese jedoch nicht als Kerberos-Zielnamen – nur der UPN, der dem tatsächlichen Anmeldekontonamen und tatsächlichen Do entspricht Standard wo das Konto verwendet werden kann.

Schließlich können Sie weiterhin die NT4-Formatvorlage do Standard\username (oder do Standard\computername im Fall von Diensten verwenden, die als lokales System, Netzwerkdienst oder localservice ausgeführt werden). Dies funktioniert für Ziele, die im Kontext von do Standard Benutzerkonto- oder Computerkonten ausgeführt werden.

Von Anwendung verwendete APIs(Parameter) Parameter zum Festlegen des Zielnamens Hinweise
InitializeSecurityContext pszTargetName
RPC-Client: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) ServerPrincipalName Dies sollte der Zielname für das Konto sein, unter dem der Server/Dienst ausgeführt wird. Er muss nicht mit dem Wert übereinstimmen, der in RPCServerRegisterAuthInfo festgelegt ist.
DCOM: SetBlanket CoSetProxyBlanket (dwAuthnSvc) CoCreateInstanceEx (übergeben als dwAuthnSvc-Mitglied der COAUTHINFO-Struktur, die selbst ein Mitglied der an die API übergebenen COSERVERINFO-Struktur ist) pServerPrincName Kann COLE_DEFAULT_PRINCIPAL verwenden, damit COM automatisch den Namen aus Bindungsinformationen auswählen kann.
LDAP: keine Automatisch vom LDAP-Client generiert.
HTTP none WinHTTP und WinInet geben den Zielnamen aus dem URL-Servernamen an.

5010 – Downgrade auf NTLM erkannt

Schweregrad – Warnung

Obwohl die anwendungsspezifische Negotiate-Anwendung einen korrekt formatierten Zielnamen verwendet hat, ist ein Fehler aufgetreten, der dazu führt, dass Negotiate auf NTLM herabgestuft wird. Je nachdem, unter welchen Umständen dies der Fall war, kann auf einen Fehler oder ein erwartetes Verhalten hinweisen. Wenn z. B. ein Computer nicht Teil einer Do Standard ist oder an einem Ort verwendet wird, an dem ein Do Standard-Controller nicht zugänglich ist, wird erwartet, dass Negotiate im Hintergrund downgradet, damit die Anwendung sich mithilfe von NTLM authentifizieren kann. Wenn dieser Stopp jedoch auftritt, wenn ein Do Standard-Controller verfügbar ist und Sie normalerweise erwarten, dass Kerberos verwendet wird, zeigt es fast sicher an, dass etwas falsch ist.

Beheben dieses Fehlers

Angenommen, Sie haben festgestellt, dass Kerberos in diesem Fall verwendet und nicht NTLM verwendet werden sollte, gibt es eine Reihe von Möglichkeiten, warum das Downgrade stattgefunden hat:

• Der Zielname, auch wenn er möglicherweise im richtigen Format vorhanden war, ist in der Do nicht vorhanden Standard (oder Gesamtstruktur).

o Sie sollten überprüfen, ob Sie den richtigen Zielnamen in der Clientanwendung erstellen. Ist die Dienstklasse richtig? Ist der Hostname richtig?

o Wird der Serverprozess im Kontext des Computers oder eines anderen Do Standard Kontos ausgeführt. In dem früheren Fall werden SPNs automatisch registriert, in letzterem Fall müssen Sie möglicherweise den SPN registrieren oder ein alternatives Formular wie einen impliziten UPN oder einen flachen Namen verwenden.

o Kann es Probleme mit der Netzwerkkonnektivität geben, die die Kommunikation mit einem Do Standard Controller oder DNS-Server verhindern?

o Ist der Ziel-SPN für mehrere Konten registriert? Dies führt dazu Standard Controller, Authentifizierungsversuche abzulehnen.

Es wird gedruckt

Die Drucküberprüfung hilft beim Auffinden und Beheben von Problemen, die auftreten können, wenn eine Anwendung das Drucksubsystem aufruft. Print Verifier zielt auf die beiden Schichten des Druck-Subsystems, die PrintAPI-Schicht und die PrintDriver-Schicht.

Druck-API-Schicht

Print Verifier testet die Schnittstelle zwischen einem Programm und Winspool.drv und prntvpt.dll und testet die Schnittstellen dieser DLLs. Sie können die Regeln für den Aufruf von Funktionen in dieser Schnittstelle im MSDN-Hilfeabschnitt für APIs, die von winspool.drv und prntvpt.dll exportiert werden, überprüfen.

Drucktreiberschicht

Print Verifier testet auch die Schnittstelle zwischen einem zentralen Druckertreiber wie UNIDRV.DLL, UNIDRUI.DLL, PSCRIPT5.DLL, PS5UI.DLL oder MXDWDRV.DLL und den Druckertreiber-Plug-ins. Informationen zu dieser Schnittstelle finden Sie in MSDN und WDK.

Normalerweise führen nur Debug-Versionen den Application Verifier aus, so dass die Leistung im Allgemeinen kein Problem darstellt. Wenn bei der Verwendung dieser oder einer anderen Application Verifier-Prüfung Leistungsprobleme auftreten, führen Sie eine Überprüfung nach der anderen durch, bis Sie alle erforderlichen Überprüfungen durchgeführt haben.

WebServices

Überprüfungsebene der Windows Webservices-API (WWSAPI)

Mit dem WWSAPI-Plug-In können Entwickler Instanzen von:

  • Eine WWSAPI, die aufgerufen wird, die auf ein ungültiges systeminternes WWSAPI-Objekt verweist.

  • Eine WWSAPI, die aufgerufen wird, die bereits auf ein einzelnes Threadobjekt verweist.

  • Ein systeminternes Objekt, das mit einem asynchronen Aufruf aussteht.

  • Aufrufen von Blockierungs-APIs aus kurzen Threads.

Darüber hinaus ist dieses Plug-In:

  • Verfolgt die Verwendung von Objekten vom Instanziieren bis zum Löschen nach.

  • Erzwingen sie, dass Aufrufe asynchron abgeschlossen werden können, um synchron abgeschlossen zu werden. Dadurch wird verhindert, dass Anwendungen abhängig von einem bestimmten Verhalten von einem Aufruf WS_ASYNC_CONTEXT werden.

  • Stellt eine lesbare Beschreibung bereit, wenn eine API ein ungültiges Objekt übergeben wird oder ein Objekt mit der Erweiterung !avrf -ws –obj debugger verwendet wird (siehe unten)

  • Für Kanal-, Dienstproxy- und Diensthosts zeigt jeder nachverfolgte Aufruf den aktuellen Status des Objekts an.

Standardmäßig sind die folgenden Kontrollkästchen aktiviert:

Property NameDescriptionValidateObjectValidates, dass das systeminterne Objekt validTrackObjectTracks ist, die Verwendung eines Objekts über seine Lebensdauer

Andere Prüfer, die in diesem Anbieter über die Eigenschaften-UI aktiviert werden können, sind:

Property NameDescriptionCheckTimeoutValidates, dass asynchrone Funktionen innerhalb des Timeouts abgeschlossen werden, angegeben als TimeoutValForceSyncForce, der Synchronisierungspfad, der ausgeführt werden soll, wenn ein WS_ASYNC_CONTEXT Kontext an eine API bereitgestellt wird.

Eine Debuggererweiterung wird bereitgestellt (!avrf –ws –obj), die geöffnete und geschlossene systeminterne WWSAPI-Objekte anzeigt. Wenn diese Erweiterung durch ein Objekt suffixiert ist, werden ausführliche Informationen zur Verwendung dieses Objekts angezeigt.

!avrf -ws –obj

Dieser Befehl zeigt die systeminternen WWSAPI-Objekte an, die nachverfolgt werden, sowohl erstellt als auch geschlossen. Beachten Sie, dass die geschlossenen Objekte in einer Kreiswarteschlange gespeichert werden, sodass eine Obergrenze für die Gesamtanzahl der nachverfolgten Objekte vorhanden ist.

Objekte werden hinzugefügt, wenn die folgenden APIs erfolgreich abgeschlossen wurden: WsCreateChannel(), WsCreateChannelForListener(), WsCreateServiceHost(), WsCreateServiceProxy(), WsCreateServiceProxyFromTemplate(), WsCreateError(), WsCreateHeap(), WsCreateListener(), WsCreateMetadata(), WsCreateMessage(), WsCreateMessageForChannel(), WsCreateReader(), WsCreateWriter(), WsCreateXmlBuffer(), WsReadXmlBuffer(), WsReadXmlBufferFromBytes()

Objekte werden aus der erstellten Liste in die freigegebene Liste verschoben, wenn die entsprechende WsFree*()-Funktion aufgerufen und abgeschlossen wird.

!avrf –ws –obj [OBJECT]

Dieser Befehl zeigt die Verwendung eines systeminternen WWSAPI-Objekts an. Die Verwendungsinformationen enthalten den Stapel, wenn das Objekt erstellt, verwendet und freigegeben wurde. Wenn es sich bei dem Objekt um einen Kanal-, Diensthost- oder Dienstproxy handelt, wird der Status des Objekts vor der API mit dem Objekt aufgerufen.

Hier ist ein Beispiel für die Verwendungsoptionen !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>

Dienste

Die Dienste testen, überprüfen Sie, ob Windows-Dienste ordnungsgemäß verwendet werden. Beispielsweise, dass Dienste gestartet und ordnungsgemäß beendet werden. Informationen zu den von diesen Tests generierten Stop-Code-Ausnahmen finden Sie unter Application Verifier - Stop Codes - Services.

Perf

Die Perf-Tests überprüfen die effiziente Verwendung von APIs, die sich auf die Systemleistung und den Energieverbrauch auswirken, z. B. das Aufrufen einer Windows-Funktion, die einen falschen Wartezeitszeitraum verwendet. Informationen zu den von diesen Tests generierten Stop-Code-Ausnahmen finden Sie unter Application Verifier - Stop Codes - Perf.

Hängt

Die Hangs-Tests für die Verwendung von APIs, die dazu führen, dass das System nicht mehr reagiert, z. B. wenn der DllMain-Thread auf einen anderen blockierten Thread wartet. Informationen zu den von diesen Tests generierten Stop-Code-Ausnahmen finden Sie unter Application Verifier - Stop Codes - Hangs.

ARM64EC-Support

Die folgenden Anbieter unterstützen ARM64EC nicht und stürzt daher ein Programm ab, das in ARM64EC ausgeführt wird:

Weitere Informationen

Application Verifier - Übersicht

Application Verifier - Features

Application Verifier – Testen von Anwendungen

Application Verifier - Stop Codes and Definitions

Application Verifier – Debuggen von Application Verifier-Stopps

Application Verifier – Häufig gestellte Fragen