Umgehung der Windows Defender-Anwendungskontrolle mit Loki C2
Windows Defender Application Control (WDAC) ist eine Sicherheitslösung, die die Ausführung auf vertrauenswürdige Software beschränkt. Da es sich um eine Sicherheitsgrenze handelt, bietet Microsoft Bug-Bounty-Belohnungen für qualifizierte Umgehungen der Sicherheit an, was dies zu einem aktiven und wettbewerbsfähigen Forschungsfeld macht.
Typische Ergebnisse einer WDAC-Bypass-Bug-Bounty-Einreichung:
Ein Blick auf die von Microsoft in WDAC empfohlene Blockierliste zeigt, dass Legenden wie Jimmy Bayne (@bohops) und Casey Smith (@subTee) WDAC-Umgehungen entdeckt haben, die noch nicht behoben sind, aber ehrenvolle Erwähnungen erhalten haben. Darüber hinaus enthält das LOLBAS-Projekt weitere nicht behobene Umgehungen, die in der Blockierliste von Microsoft nicht berücksichtigt wurden. Ein Beispiel ist die Microsoft Teams-Anwendung, die trotz ihrer Dokumentation in LOLBAS weiterhin eine funktionierende WDAC-Umgehung ist.
Beim Auftreten von WDAC während der Red Team Operations konnten wir es erfolgreich umgehen und unsere Stage 2 Command and Control (C2) Payload mit den folgenden Techniken ausführen:
1. Verwenden Sie ein bekanntes LOLBIN wie MSBuild.exe
2. DLL-Sideloading einer vertrauenswürdigen Anwendung mit einer nicht vertrauenswürdigen DLL
3. Nutzen Sie eine benutzerdefinierte Ausschlussregel aus der WDAC-Richtlinie des Clients.
4. Finden Sie eine neue Ausführungskette in einer vertrauenswürdigen Anwendung, die die Bereitstellung von C2 ermöglicht.
Wie Ruben Boonen (@FuzzySec) in seinem Vortrag „Statikk Shiv: Leveraging Electron Applications for Post-Exploitation“ auf dem Wild West Hackin' Fest erklärte, fungieren Electron-Anwendungen als Webbrowser, die Desktop-Anwendungen mithilfe von Standard-Webtechnologien wie HTML, JavaScript und CSS rendern. Die JavaScript-Engine in Electron ist Node.js, die leistungsstarke APIs bereitstellt, die mit dem Host-Betriebssystem interagieren können. Diese APIs ermöglichen Aktionen wie das Lesen und Schreiben von Dateien, das Ausführen von Programmen und andere für native Anwendungen typische Vorgänge.
Während der Laufzeit liest eine Electron-Anwendung JavaScript-Dateien, interpretiert ihren Code und führt sie innerhalb des Electron-Prozesses aus. Die folgende Animation zeigt, wie die Microsoft Teams Electron-Anwendung zur Laufzeit eine JavaScript-Datei liest, die dann das child_process-Modul verwendet, um whoami.exe auszuführen.
In diesem Beispiel liest der Teams Electron-Prozess die JavaScript-Datei, die dann mit Hilfe des child_process- Moduls whoami.exe startet. Dieses Modul löst den Electron-Prozess dazu aus, seine exportierte API uv_spawn auszuführen, die für die Interaktion mit dem Betriebssystem verantwortlich ist, um einen neuen Prozess zu erstellen.
Die traditionelle Architektur einer Windows-Anwendung besteht aus:
Die EXE ruft exportierte Funktionen aus DLLs auf, um ihre Fähigkeiten zu erweitern. Bei Electron-Anwendungen ist diese Architektur jedoch umgekehrt. Anstatt dass die EXE APIs aus DLLs aufruft, stellt die Electron-EXE selbst API-Exporte bereit, die von Folgendem aufgerufen werden:
Dank dieser Struktur können Node.js-JavaScript und Knotenmodule auf eine Weise mit dem Betriebssystem interagieren, wie dies bei herkömmlichem JavaScript in einem Browser nicht möglich ist.
Im untenstehenden Bild betrachten wir die Teams Electron-Anwendung mit PE Bear, einem großartigen Tool von @hasherezade, das zeigt, dass die ausführbare Datei Teams Electron 2.977 exportierte APIs enthält. Diese große API-Oberfläche bietet umfangreiche Funktionen, die von Node.js JavaScript-Dateien und Node-Modulen zur Interaktion mit dem Betriebssystem genutzt werden können.
Da Electron-Anwendungen JavaScript zur Laufzeit ausführen, können Angreifer durch Modifizierung dieser JavaScript-Dateien beliebigen Node.js-Code in den Electron-Prozess einspeisen. Durch die Nutzung von Node.js- und Chromium-APIs kann JavaScript-Code mit dem Betriebssystem interagieren.
Die Fähigkeit, JavaScript-Dateien von vertrauenswürdigen Electron-Anwendungen so zu modifizieren, dass sie beliebigen JavaScript-Code von Node.js ausführen, wurde von mir nicht entdeckt. Die frühesten Referenzen, die ich finden kann, stammen aus dem Jahr 2022.
Anfang 2022 veröffentlichte Andrew Kisliakov den Blogbeitrag „ Microsoft Teams und andere Electron-Apps als LOLbins“. Andrew und @mrd0x haben ihre Ergebnisse zum LOLBAS-Projekt beigetragen.
Später im Jahr 2022 erkundeten Valentina Palmiotti (@chompie1337), Ellis Springe (@knavesec) und Ruben diesen Ansatz weiter, was zur Entwicklung eines internen Persistenzwerkzeugs führte, das seitdem in Red-Team-Operationen eingesetzt wird.
Ebenfalls 2022 veröffentlichte Michael Taggart das quASAR-Projekt, ein Tool zur Modifikation von Electron-Anwendungen zur Steuerung von Befehlen. In seinem Blog „Quasar: Compromising Electron Apps“ teilte er mit, dass sich im September 2022 ein Mitglied des Electron-Projekts an ihn wandte und erklärte, dass die Integritätsprüfung eine experimentelle Funktion sei und in Zukunft hoffentlich vollständig unterstützt werde.
Bei meinen persönlichen Experimenten mit neueren Electron-Anwendungen wie Signal habe ich festgestellt, dass es für einige Electron-Anwendungen jetzt Integritätsprüfungen gibt, die verhindern, dass ihre JavaScript-Dateien geändert werden. Dennoch bleiben viele aktiv verbreitete Electron-Anwendungen angreifbar.
Diese Technik wurde auch bei realen Angriffen beobachtet. Im Jahr 2022 hat ein Bedrohungsakteur die MiMi-Chat-Anwendung durch Modifizierung der gebündelten JavaScript-Dateien auf dem Verteilungsserver hintertrieben. Trend Micro identifizierte dies als Lieferkette-Angriff, bei dem die kompromittierte Electron-App an Endnutzer verteilt wurde und die Ausführung von bösartigem JavaScript-Code ermöglichte, der eine zweite C2-Nutzlast herunterlud und ausführen ließ.
Im April 2024 suchte ich, Bobby Cooke (@0xBoku), nach einer neuen Ausführungskette zur Vorbereitung einer bevorstehenden Red Team Operation für einen Kunden im Finanzsektor. In diesem Sektor gelten höhere Sicherheitsstandards und strengere Vorschriften, häufig werden zusätzliche Sicherheitsmaßnahmen wie WDAC eingesetzt. Während meiner Forschung bin ich auf eine weitere anfällige Electron-Anwendung gestoßen. Da es jedoch nicht von Microsoft signiert war, war es unwahrscheinlich, dass es die WDAC-Richtlinie des Clients umgehen konnte.
Anschließend wechselte ich zur Microsoft Teams-Altlast-Anwendung, die von Microsoft signiert ist und selbst die strengsten WDAC-Richtlinien umgehen kann. An diesem Punkt schloss sich Dylan Tran (@d_tranman) mir auf dieser Suche an, und wir begannen, nach einer Möglichkeit zu suchen, von der beliebigen Node.js JavaScript-Ausführung auf die Ausführung unseres Stage-2-C2-Shellcodes zu eskalieren.
Obwohl Node.js über dessen APIs mit dem Betriebssystem interagieren kann, fehlt ihm die volle Funktionalität von C, bei der Entwickler WINAPIs und NTAPIs direkt aufrufen können. Um diese Lücke zu schließen, entwickelten Entwickler Knoten-Module, die die Funktionen des Node.js-Frameworks erweitern. Diese Module, die aus C++-Code kompiliert werden, können WINAPIs aufrufen, mit Node.js APIs interagieren und JavaScript innerhalb von Electron-Anwendungen ausführen. Kompilierte Knoten-Module haben eine .node Die Erweiterung wird über ein DLL-Ladeereignis in Windows-Prozesse geladen.
Im Rahmen unserer Forschung haben wir verschiedene Electron-Anwendungen untersucht und deren signierte Knoten-Module analysiert. Wir entdeckten, dass mit diesen Modulen direkt über JavaScript interagiert werden konnte, so dass wir ihre integrierten Funktionen nutzen konnten.
Die Erstellung unserer eigenen Knoten-Module zur Ausführung von Shellcode ist zwar ein praktikabler Ansatz und eine Funktion von Loki C2, stellt aber ein Henne-Ei-Problem dar. Das Laden eines Knoten-Moduls aus JavaScript löst ein DLL-Ladeereignis aus, das durch WDAC-Richtlinien blockiert werden kann, die strenge Regeln gegen unsignierte DLLs durchsetzen. Glücklicherweise existiert eine große Anzahl signierter Knoten-Module in legitimen Electron-Anwendungen.
Dieser Ansatz zur Ausführung unserer Nutzlast sah vielversprechend aus, also teilten wir unsere Erkenntnisse mit Valentina und sie schloss sich uns bei diesem Vorhaben an. Mit ihrer Hilfe vertieften wir uns in die Umkehrung signierter Knoten-Module und suchten nach Schwachstellen oder eingebauten Funktionen, die uns die Ausführung von beliebigem Shellcode ermöglichen würden.
Ein Beispiel für ein Knoten-Modul mit nützlichen Funktionen ist windows_process_tree.node, ein von Microsoft signiertes Modul, das mit Visual Studio Code geliefert wird. Bei genauerer Betrachtung in PE Bear zeigen sich zwei exportierte Funktionen, wie unten dargestellt.
Im Gegensatz zu herkömmlichen DLLs listen Knoten-Module nicht alle verfügbaren Funktionen in der Exporttabelle auf. Die napi_register_module_v1 exportierte Funktion wird vom Electron-Prozess aufgerufen und ist dafür verantwortlich, das Modul zu laden und seine exportierte Funktionalität dem Electron-Prozess zugänglich zu machen. Das fungiert als Brücke und ermöglicht es JavaScript innerhalb des Electron-Prozesses, die Funktionen des Moduls aufzurufen und mit ihnen zu interagieren.
Eine einfache Möglichkeit, alle aufrufbaren Funktionen in einem Node-Modul aufzulisten, besteht darin, den unten stehenden Node.js-Code zu verwenden.
Wenn wir dieses Node.js-Skript in PowerShell ausführen, sehen wir, dass es zwei aufrufbare Funktionen in windows_process_tree.Knoten gibt. Sie sind getProcessList und getProcessCpuUsage.
Mit Persistenz ist es möglich, festzulegen, wie diese Funktionen von JavaScript aus aufgerufen werden sollen. Eine Einschränkung von Node.js ist, dass es keine integrierte API hat, um alle laufenden Prozesse auf dem System aufzulisten. Diese Einschränkung ist der Grund, warum Microsoft die Funktion getProcessList in diesem Modul eingeführt hat, um die Möglichkeiten der VS Code Electron-Anwendung zu erweitern.
Es ist möglich, diese Informationen direkt in JavaScript abzurufen, indem man das child_process-Modul verwendet, um PowerShell in einem Kindprozess auszuführen, der Details zu laufenden Prozessen zurückgibt. Im untenstehenden Bild erzeugt Loki C2 einen PowerShell-Kindprozess, um die Prozessliste abzurufen.
Dieser Ansatz birgt erhebliche operative Sicherheitsrisiken. Die Ausführung von PowerShell-Child-Prozessen ist leicht erkennbar und erhöht die Wahrscheinlichkeit, dass ein Vorgang als fehlerhaft markiert oder abgebrochen wird. Um dies zu vermeiden, nutzt Loki C2 signierte Knoten-Module wie windows_process_tree.node , um Node.js Funktionen zu erweitern.
Loki C2 beinhaltet den Befehl ps, der Prozessinformationen abruft, indem er das von Microsoft signierte Modul windows_process_tree.node lädt und die Funktion getProcessList aufruft, wie in der folgenden Abbildung zu sehen ist.
Der Loki C2 JavaScript-Code, der die Funktion getProcessList im Knoten windows_process_tree.Knoten aufruft, ist unten dargestellt. getProcessList liefert Prozessdaten im JSON-Format zurück, das Loki C2 in eine strukturierte Tabelle formatiert, um die Lesbarkeit zu verbessern.
Zu bestimmen, wie Funktionen innerhalb von Knoten-Modulen richtig aufgerufen werden, kann schwierig sein, da ihre internen Strukturen nicht dokumentiert sind. Durch die Nutzung von Tools wie Ghidra, entwickelt von der NSA, und die Zusammenarbeit mit erfahrenen Reverse Engineers wie Valentina haben wir diese Module erfolgreich analysiert und herausgefunden, wie man mit ihren Funktionen interagieren kann.
Valentina hat schließlich einen Weg gefunden, unseren Stage-2-C2-Shellcode auszuführen, ohne eine unsignierte DLL zu laden, aber ich überlasse es ihr, die Details preiszugeben. Gemeinsam arbeiteten Dylan, Valentina und ich an der Verfeinerung der Technik, um Stabilität für die bevorstehende Phishing-Kampagne zu gewährleisten.
Leider wurde unsere erste Phishing-E-Mail-Kampagne vom Blue Team gemeldet und blockiert. Nach diesem Rückschlag, Brett Hawkins (@h4wkst3r) Und ich begann, mich auf eine zweite Kampagne vorzubereiten. Als designierter Payload-Mitarbeiter wollte ich dieselbe Payload nicht wiederverwenden, da es für das blaue Team zu einfach gewesen wäre, uns zu verfolgen und unsere zweite Kampagne zu stoppen. Da wir jedoch nicht genügend Zeit hatten, Valentinas Technik auf eine neue Nutzlast anzuwenden, begann ich mit der Entwicklung einer neuen Nutzlast unter Verwendung eines alternativen Ansatzes.
In der Regel wird die Fähigkeit, beliebiges JavaScript in vertrauenswürdigen Electron-Anwendungen auszuführen, verwendet, um Befehle auszuführen, die einen C2-Agenten bereitstellen. Ohne Valentinas Technik würde dieser Ansatz jedoch bei WDAC scheitern, da er letztendlich die Ausführung eines unsignierten Programms erfordern würde, was höchstwahrscheinlich blockiert würde.
Da ich nur wenige Tage Zeit hatte, mich auf die zweite Kampagne vorzubereiten, kam mir der Gedanke: Was wäre, wenn ich ein komplettes C2-Framework in JavaScript entwickeln würde?
Wenn der C2-Agent selbst vollständig in JavaScript geschrieben wäre, könnte er selbst gegen die strengsten WDAC-Richtlinien einen C2-Kanal aufbauen. Von dort aus könnte eine Erkundung durchgeführt werden, um einen Weg zu finden, eine C2-Nutzlast der Stufe 2 bereitzustellen. Es gäbe keine Ereignisse zum Laden unsignierter DLLs – nur JavaScript, das innerhalb des vertrauenswürdigen Teams-Prozesses ausgeführt wird.
Wir benötigten lediglich genügend Funktionalität, um:
Mit all dem Node.js-Code, den ich während meiner Forschung geschrieben hatte, habe ich über Nacht einen C2-Proof-of-Concept zusammengestellt. Am nächsten Tag habe ich es Dylan gezeigt, und gemeinsam haben wir es rasch zu einem voll funktionsfähigen, JavaScript-basierten C2 ausgebaut. Unser C2 war zu Folgendem fähig:
Der JavaScript C2, der jetzt Loki C2 heißt, war in der zweiten Kampagne ein Erfolg. Seitdem haben wir Loki C2 weiter verfeinert und erweitert, mehr Funktionen hinzugefügt, die Stabilität erhöht und die Funktionen verbessert.
Mit all dem Electron-Wissen, das ich durch diese Forschung gewonnen habe, habe ich eine grafische Benutzeroberfläche für Loki C2 mit dem Electron-Framework gebaut.
In dem folgenden Video zeige ich Ihnen, wie Sie mit Loki C2 eine strenge WDAC-Richtlinie umgehen können. Die beiden folgenden Abschnitte erklären, was im Video passiert.
Für diese Demo wird WDAC über den App Control Policy Wizard VIA den App Control Policy Wizard auf einer aktuellen Windows Server 2025 EC2-Instanz in AWS bereitgestellt. Der Assistent bietet drei Basisrichtlinienvorlagen an:
Der Standard-Windows-Modus ist der strengste und erlaubt die Ausführung von:
In der Demo wird die Standard-Windows-Modus-Richtlinie ausgewählt. Der Standard-Audit-Modus ist deaktiviert, sodass WDAC die Richtlinie sofort durchsetzt. Zusätzlich sind die Optionen zur Zusammenführung mit empfohlenen Blocklisten aktiviert, wodurch die Regeln in der von Microsoft empfohlenen WDAC-Blockliste enthalten sind. Der App Control Wizard generiert eine XML- und CIP-Datei für die WDAC-Richtlinie, die dann mit CITool.exe auf dem Server deployt wird.
Sobald WDAC aktiv ist, versuche ich, Loki C2 Agent.exe auszuführen, aber WDAC blockiert dies, da die ausführbare Datei nicht von Microsoft signiert ist.
Um diese Einschränkung zu umgehen, kopiere ich den Inhalt des /resources/app/ -Verzeichniss von Loki Agent. Auf dem Desktop befindet sich ein Ordner namens „teams“, der eine legitime legacy Microsoft Teams-Anwendung enthält. Ein Blick in die Eigenschaften von Teams.exe bestätigt, dass es von Microsoft signiert ist.
Dann gehe ich zum /Ressourcen/-Verzeichnis der Teams-Anwendung und lösche alle bestehenden Dateien. Nach dem Löschen füge ich das zuvor kopierte Verzeichnis Loki C2 Agent /Ressourcen/App/ in ~/Desktop/teams/Ressourcen/App/ ein.
Mit dieser Modifikation führe ich Teams.exe aus, indem ich darauf klicke. Da die Teams-Anwendung von Microsoft signiert ist, wird sie von WDAC nicht blockiert. Im System Informer können wir sehen, dass der Teams-Prozess ohne WDAC-Eingriff erfolgreich erstellt wurde. Da ich jedoch das Verzeichnis Teams /Ressourcen/App/ durch den Code des Loki C2 Agents ersetzt habe, führt die Electron-basierte Teams-Anwendung nun das JavaScript des Loki C2 Agents innerhalb des vertrauenswürdigen Teams-Prozesses aus.
Der Teams-Prozess ruft erfolgreich den Loki C2-Client auf, und ich führe mehrere Befehle aus, um die Fernsteuerung des kompromittierten Servers zu demonstrieren.
Nachdem wir den ersten Zugang zu Loki C2 erhalten haben, haben wir mehrere Wege identifiziert, einen leistungsfähigeren C2-Agenten der Stufe 2 auszuführen, wie zum Beispiel Dragon, das interne C2, das von Shawn Jones (@anthemtotheego) und mir entwickelt wurde. Obwohl all die verschiedenen Eskalationsmethoden, die wir seit der ersten Entwicklung von Loki C2 entdeckt haben, in diesem Beitrag nicht veröffentlicht werden, planen wir, sie in zukünftigen Versionen zu behandeln.
Bei korrekter Implementierung umgeht diese Technik weiterhin erstklassige Endpoint Detection & Response (EDR)-Lösungen. Ohne ein stealthy Stage-2 C2 müssen Operatoren jedoch auf Befehlsausführung über Spawn setzen, das Befehle in Kindprozessen ausführt. Dadurch werden nach einem Angriff schnell entsprechende Erkennungen für führende EDRs ausgelöst.
Loki C2 entspricht der MITRE ATT&CK-Technik T1218.011 – Systembinäre Proxy-Ausführung: Elektronenanwendungen.
Nach der Suche im Internet habe ich diese Technik, Electron-Anwendungen auszuhöhlen und ihren Code durch ein C2 zu ersetzen, das öffentlich bekannt gegeben oder in freier Wildbahn verwendet wird, nicht gefunden. Nachdem Loki C2 jedoch mit vertrauenswürdigen Red-Teams geteilt wurde, hat eines bestätigt, dass sie interne ähnliche Funktionen entwickelt haben.
Trotz eines MITRE ATT&CK TTP, mehrerer Forschungsveröffentlichungen und eines LOLBAS-Eintrags bleibt diese Technik zur Aushöhlung der Electron-Anwendung selbst unentdeckt. Ich gehe davon aus, dass sich EDR-Lösungen nicht darauf konzentrieren, dies zu erkennen, sondern eher auf Indikatoren, die nach der Ausbeutung vorliegen, wie z. B. das Spawnen untergeordneter Prozesse zur Ausführung von Befehlen. Da wir Methoden entwickelt haben, um Stage 2 C2 bereitzustellen und gleichzeitig die üblichen Nachweisverfahren nach einem solchen Ausbeutung zu vermeiden, haben wir diese Technik in mehreren Einsätzen erfolgreich eingesetzt und dabei eine Erkennung vermieden.
Vor diesem Hintergrund sollten Sie sich, wenn Sie das nächste Mal hören, dass ein Anbieter „100 % MITRE-Abdeckung“ behauptet, fragen, was das wirklich bedeutet ...