Wie ich mir den Urlaub mit WSC-Reverse-Engineering ruiniert habe
(blog.es3n1n.eu)- defendnot, entstanden während einer Reise nach Seoul, war ein Tool, das die Windows-Security-Center-(WSC-)Service-API direkt aufrief, um Windows Defender zu deaktivieren – und führte zu mehreren Tagen Reverse Engineering
- Das frühere Tool no-defender nutzte bestehenden Antivirus-Code, um bei WSC zu registrieren, dass ein anderer Virenschutz vorhanden sei; nach rund 1,5k GitHub-Sternen wurde es auf DMCA-Antrag des Antivirus-Herstellers gelöscht
- Zunächst ließen sich die COM-API-Aufrufe von WSC in etwa einer Stunde nachbilden, doch da WSC den aufrufenden Prozess verifiziert, wurde der Zugriff aus normalen Prozessen verweigert
- Die Analyse zeigte, dass WSC die WinDefend-SID, Administratorrechte, Signatur und im PE-
DllCharacteristics-Feld dasForceIntegrity-Flag prüfte; in der finalen Implementierung wurdeTaskmgr.exeverwendet - In einer Umgebung mit arm64-MacBook, Remote-PC in den USA, 210 ms Latenz über Parsec und einer Shadow.tech-VM wurde die Implementierung abgeschlossen, nachdem ein
ctx.bin-Pfadfehler und ein Problem mit Energiebedingungen beim Autorun behoben waren
Hintergrund: Wie es zu defendnot kam
- defendnot ist ein Tool, das die Windows-Security-Center-Service-API direkt nutzt, um Windows Defender zu deaktivieren
- Der Kern der Implementierung lag weniger im WSC-Aufruf selbst, sondern darin, die Schutz- und Prüfbedingungen sowie die unbequeme Arbeitsumgebung Schritt für Schritt zu umgehen
- Ausführlichere technische Dokumentation zu WSC soll später von jemand anderem veröffentlicht werden
no-defender und DMCA vor einem Jahr
- Das vor etwa einem Jahr veröffentlichte no-defender nutzte eine Windows-API für Antivirus-Produkte, um Windows Defender abzuschalten
- Diese API ist dafür gedacht, dem System mitzuteilen: „Es gibt einen anderen Virenschutz, daher muss Defender keinen Scan ausführen“
- Die Systemkomponente, die diesen Bereich verwaltet, ist das Windows Security Center (WSC)
- no-defender funktionierte, indem es Third-Party-Code eines bestehenden Antivirus-Produkts nutzte und erzwang, dass sich dieses Produkt bei WSC registriert
- Innerhalb weniger Wochen nach Veröffentlichung erhielt es rund 1,5k stars; nachdem der Hersteller des verwendeten Antivirus-Produkts einen DMCA-Takedown beantragt hatte, wurde der Repository-Inhalt gelöscht und die Sache beendet
Während der Seoul-Reise wieder mit der WSC-Analyse begonnen
- Während eines Aufenthalts in einem Airbnb in Seoul schrieb MrBruh, der sich no-defender angesehen hatte, dass er untersuche, ob eine „saubere“ Implementierung ohne Antivirus-Binary möglich sei
- Für CTFs oder x86-Reversing-Aufgaben nimmt der Autor normalerweise ein separates x86-Notebook mit, hatte auf dieser Reise aber nur ein M4Pro MacBook dabei
- Trotz der ungünstigen Bedingungen ohne x86-Reversing-Hardware begann die WSC-Analyse in der Zeit, bevor die Freunde aufwachten
Tag 1: WSC-COM-API nachgebildet und erste Zugriffssperre
- MrBruh stellte aktuelle WSC-Binaries bereit, und die zuvor genutzte WSC-Registrierungsimplementierung des Antivirus diente als Referenz
- WSC bietet eine COM-API, die Antivirus-Produkte verwenden; die Aufrufe des bestehenden Antivirus ließen sich in etwa einer Stunde nachbilden
- Zum Testen wurde arm64-Windows in Parallels gebootet, das Ergebnis war jedoch access denied
- Aus früherer Erfahrung war bekannt, dass WSC den Prozess prüft, der die API aufruft; zunächst lag der Verdacht auf einer Signaturprüfung
- Nachdem Code in den Prozess injiziert wurde, den der bestehende Antivirus für WSC-Aufgaben verwendete, funktionierten die COM-Aufrufe zur Registrierung eines neuen Antivirus und zur Statusaktualisierung korrekt
Versuch, die Antivirus-Binary zu entfernen
- Damit das neue Projekt nicht erneut Einwände des bestehenden Antivirus-Anbieters auslöst, sollte statt der Antivirus-Binary eine vom System bereitgestellte Binary verwendet werden
- Als erster Zielprozess wurde
cmd.exegewählt, doch die WSC-API-Aufrufe wurden verweigert - Ein Blick in
wscsvc.dllzeigte Code, der prüfte, ob der aufrufende Prozess PPL ist - Ein per schlichtem
CreateProcessAerzeugter Prozess war kein PPL-geschützter Prozess, und in dieser Nacht ging es nicht weiter
Tag 2: Eine unbequeme Remote-Debugging-Umgebung aufbauen
- Auf dem arm64-MacBook war x86-Windows schwer vernünftig zu handhaben, und der Autor wollte vermeiden, in einer arm64-Umgebung zu arbeiten oder auf x64dbg verzichten zu müssen
- Der Freund pindos erlaubte den Zugriff auf seinen PC, die Remote-Verbindung lief über Parsec
- Da die Verbindung von Korea zu einem PC in den USA ging, lag die durchschnittliche Latenz bei etwa 210 ms
- Der damalige Workflow war äußerst umständlich
- Modul unter Windows arm64 in Parallels mit MSVC bauen
- Build-Artefakte über einen Shared Folder mit dem Host teilen
- Artefakte per AnyDesk in eine VM auf pindos’ PC kopieren
- Den WSC-Service in einer Parsec-Umgebung mit 210 ms Latenz debuggen
- Die Umgebung war so unbequem, dass Entwicklungs- und Analysegeschwindigkeit stark litten
WSC-Service-Debugging und WinDefend-SID
- Der WSC-Service ist eine von
svchostausgeführte DLL; der wichtigste Faktor, der das Anhängen eines Debuggers verhinderte, war der PPL-Schutz - In der VM wurde der Testmodus aktiviert, und ein Treiber verwendet, der im Kernel-Mode mit wenigen Zeilen Code PPL beim Zielprozess entfernte
- Der Punkt, an dem
cmd.exebeim Versuch scheiterte, bei WSC einen Antivirus zu registrieren, warWscServiceUtils::CreateExternalBaseFromCaller - Diese Funktion imitiert den RPC-Client und prüft anschließend, ob das Token des aufrufenden Prozesses die
WinDefend-SID enthält - Da das Verhalten von Windows-Tokens zu diesem Zeitpunkt nicht gut verstanden war, entstand die Einschätzung, man könne die Prüfung bestehen, indem man
WinDefendimitiert - Unter Schlafmangel wurde zudem fälschlich interpretiert, dass auch die bestehende Antivirus-Binary diese
IsMember-Prüfung bestehe
Versuch und Scheitern der WinDefend-Impersonation
- Nach einigen Stunden Beschäftigung mit Windows-Tokens wurde eine Implementierung in Richtung eines Tokens mit enthaltener WinDefend-SID gebaut, um die WSC-Prüfung zu bestehen
- Code wurde mit an
cmdangehängterWinDefend-SID ausgeführt; obwohl der COM-AufrufSTATUS_SUCCESSzurückgab, wurde tatsächlich kein neuer Antivirus registriert - Dieser Ansatz erwies sich letztlich als nicht nützlich und musste am nächsten Tag erneut überprüft werden
Tag 3: Den echten Verifikationsalgorithmus rekonstruiert
- Bei erneuter Prüfung zeigte sich, dass die bestehende Antivirus-Binary die WinDefend-SID-Prüfung nicht bestand
- Wenn diese Prüfung bestanden wird, landet man beim WSC-Objekt von Windows Defender; allein mit WSC-Aufrufen lässt sich Defender aber nicht direkt deaktivieren, daher war das nutzlos
- Der Code zur WinDefend-Impersonation wurde entfernt und der andere Zweig der Bedingung analysiert
- In diesem Zweig wird für die aufrufende Binary Folgendes geprüft
- ob der Prozess elevated ist
- ob die Binary-Signatur gültig ist
- ob in den
DllCharacteristicsdes PE ein bestimmtes Flag gesetzt ist
- Das in
CSecurityVerificationManager::CreateExternalBaseFromPESettingsgeprüfteDllCharacteristics-Flag war ForceIntegrity - Code, der die Binary-Prüfung von WSC nachbildet, wurde im Ordner
wsc-binary-checkdes defendnot-Repositorys erstellt und gegen System32-Binaries getestet
Taskmgr.exe verwendet und ctx.bin-Bug
- Da der Freund seinen PC wieder selbst brauchte, wurde direkt per Parsec auf die VM zugegriffen; zusammen mit Software-Encoding wurde die Umgebung noch langsamer
- Statt
cmd.exewurdeTaskmgr.exeverwendet, doch es traten weiterhin RPC-Fehler auf - Wegen Latenz und Eingabeproblemen wurde das Debugging in derselben VM schwierig; auf Empfehlung wurden $30 für ein Abo bei shadow.tech bezahlt
- Die Shadow.tech-VM hatte eine ältere Windows-Version, in der der
wscsvc-Code noch nicht so stark wie in der neuesten Version in eine Funktion inline eingebettet war; auch das Decompiler-Ergebnis war besser lesbar - Die tatsächliche Fehlerursache war ein falscher AV-Name, der an WSC übergeben wurde
- Um Daten von
defendnot-loaderandefendnot.dllzu übergeben, wurdectx.binmit serialisierten Parametern verwendet - Für die Statusverfolgung war separates IPC implementiert, doch für die Konfigurationsübergabe blieb die alte
ctx.bin-Methode als Überbleibsel aus no-defender erhalten - Die Funktion zum Finden des
ctx.bin-Pfads orientierte sich nicht am Basisordner vonnodefend.dll, sondern am Basisordner des ModulsTaskmgr.exe - Dadurch wurde ein Null-Byte als AV-Name übergeben, und WSC lehnte diesen Buffer ab
- Um Daten von
- Nach Behebung des Pfadproblems war der Test erfolgreich
Code aufräumen und Autorun-Problem
- Um noch am selben Tag fertig zu werden, wurden bis 8 Uhr morgens Code aufgeräumt und zusätzliche Funktionen implementiert
- Zu den zusätzlichen Funktionen gehörte, sich selbst zu autorun hinzuzufügen
- Um 8 Uhr morgens funktionierte nur Autorun noch nicht richtig; nach dem Testen mehrerer Methoden ohne Erfolg ging der Autor schlafen
- Am nächsten Tag stellte sich heraus, dass zwei Energieoptionen beim Erstellen der Aufgabe im Task Scheduler die Ursache waren
- Da das Notebook nicht am Netzteil hing, wurde die Aufgabe nicht ausgeführt; nach Deaktivierung dieser Flags funktionierte Autorun
- Danach wurde der Code noch einige Stunden weiter aufgeräumt und die Arbeit abgeschlossen
Fazit
- Die Arbeit selbst machte Spaß, aber die über mehrere Tage wiederkehrenden Umgebungsprobleme und der Remote-Debugging-Workflow waren eine Erfahrung, die der Autor nicht wiederholen möchte
- Insbesondere arm64-MacBook, Remote-x86-VM, hohe Latenz, langsames Encoding und der spät sichtbar gewordene Dateipfad-Bug erhöhten die Implementierungsschwierigkeit erheblich
- Eine technischere WSC-Dokumentation soll später separat veröffentlicht werden
1 Kommentare
Hacker-News-Kommentare
Die invasivste, aber effektivste Methode, Defender auszuschalten, war, von einem Live-Linux-USB-Stick zu booten,
C:\ProgramData\Microsoft\Windows Defenderumzubenennen und an dieser Stelle eine leere Datei anzulegenZur Einordnung: WSC steht für Windows Security Center
Die Formulierung
the antivirus I was usinghat mich ziemlich verwirrt. Ich habe nicht verstanden, warum der Anbieter dieses Antivirenprogramms dem Autor einen DMCA-Takedown schicken sollteVermutlich ist gemeint, dass der Autor ein anderes Antivirenprogramm reverse-engineert und Teile davon in ein Open-Source-Projekt eingebaut hat. Da aber auch Titel wie
Impersonating WinDefendauftauchen, frage ich mich am Ende, ob der Autor auf irgendeine Weise gegen das Urheberrecht verstoßen hatDirekt vor dem zitierten Absatz steht die Erklärung, dass „das Projekt Third-Party-Code eines bereits existierenden Antivirus verwendete und diesen Antivirus zwang, sich bei WSC als Antivirus zu registrieren“
Dieser Code wirkt verflucht:
https://github.com/es3n1n/defendnot/blob/master/defendnot-lo...
Falls ihr wissen wollt, was tatsächlich passiert, hier:
https://github.com/es3n1n/defendnot/blob/master/cxx-shared/s...
In der Sprache D gibt es zum Beispiel ein Sprachkonzept für Statements, die am Ende eines Scopes ausgeführt werden
Kurz gesagt: Das ist nicht von einer KI geschrieben. Dieser Code verzögert einen Funktionsaufruf, bis ein Objekt den Scope verlässt. Die Implementierung erzeugt per C-Makro eine kürzere Syntax, die Teile der nötigen C-Lambda-/anonymen Funktionsdefinition weglässt, und generiert einen eindeutigen Variablennamen zur Verwaltung des verzögerten Aufrufs
Allerdings vermeidet die resultierende Syntax die übliche Konvention, C-Makros in Großbuchstaben zu schreiben, und sieht auf den ersten Blick wie ein Funktionsaufruf über einen Objektzeiger aus. Wenn man mit diesem Pattern nicht vertraut ist oder erwartet, dass Makros anders kenntlich gemacht werden, kann das verwirrend sein
Für manche ist es häufig und nützlich genug, dass man es in bestimmten Kontexten fast als Idiom ansehen kann. Eine technische Erklärung findet sich unter https://news.ycombinator.com/item?id=43959403#43960905; dort wird gut aufgeschlüsselt, wie das Makro funktioniert
Ich habe im Urlaub die virtuellen Desktops von Windows reverse-engineert, und das hat meinen Urlaub viel besser gemacht. Meine schönste Erinnerung vom letzten Jahr war die Erkenntnis, dass Reverse Engineering wirklich Spaß macht
Ich habe auch viel Interessantes gelernt; unter Windows gibt es unterhalb von RPC eine undokumentierte Messaging-Schicht: https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC....
Wenn das Profilbild eine Anime-Figur ist, weiß ich jedes Mal, dass der Beitrag gut sein wird. Für den Fall gespeichert, dass ich irgendwann wieder in eine eher miese Windows-Umgebung zurückmuss
Für alle, die sich wundern: WSC steht für Windows Security Center. Ich musste es auch nachschlagen
Warum sollte man WSC überhaupt abschalten wollen?
Wenn man EDR-Anbieter ist: Das ist ein verschleierter API-Aufruf, mit dem sich die Windows Firewall unterdrücken oder deaktivieren lässt. CrowdStrike etwa kann meiner Einschätzung nach sowohl die Windows Firewall nutzen als auch eine eigene Implementierung
netcat.exegehe nichtIch habe vor Kurzem https://nostarch.com/windows-security-internals gelesen, und durch diesen Artikel hat das deutlich mehr Sinn ergeben
Ich wusste schon grob, wie solche internen Abläufe unter Windows funktionieren, aber das Timing war gut. Das letzte Kapitel des Buchs geht ebenfalls ziemlich detailliert auf Tokens und SIDs ein, ähnlich wie es der Autor dieses Artikels behandelt