Automatisierung der Erkennung möglicher DLL-Abfangpfade (DLL-Hijacks)

Hallo Khabrovites. Rekrutierung für den neuen Stream des Kurses „Pentest. Penetrationstestpraxis " . Im Vorfeld des Kursbeginns teilen wir Ihnen die Übersetzung von interessantem Material mit.







Einführung



In diesem Artikel werden wir uns mit dem Konzept des DLL-Hijacking befassen und wie es verwendet werden kann, um auf Windows-Systemen eine Persistenz des Benutzerlandes zu erreichen. Diese Methode wird in MITRE ATT & CK unter "Abfangen der DLL-Suchreihenfolge (T1038) " beschrieben.



DLL-Spoofing kann von Angreifern für viele verschiedene Zwecke verwendet werden. Dieser Artikel konzentriert sich jedoch auf das Erreichen der Ausfallsicherheit mithilfe von Autostart-Anwendungen. Da beispielsweise Slack- und Microsoft-Teams beim Start (standardmäßig) gestartet werden, kann ein Angreifer durch DLL-Spoofing in einer dieser Anwendungen dauerhaft auf sein Ziel zugreifen, wenn sich ein Benutzer anmeldet.



Nachdem ich das Konzept der DLLs, der DLL-Suchreihenfolge und des DLL-Spoofing vorgestellt habe, werde ich Sie durch den Prozess der Automatisierung der DLL-Abhörerkennung führen . In diesem Artikel wird das Erkennen von DLL-Abfangpfaden in Slack, Microsoft Teams und Visual Studio Code beschrieben.



Schließlich entdeckte ich mehrere DLL-Abfangpfade, die von verschiedenen Anwendungen verwendet wurden, untersuchte die Grundursache und stellte fest, dass Anwendungen, die bestimmte Windows-API-Aufrufe verwenden, für das Abfangen von DLLs anfällig sind, wenn sie nicht ausgeführt werden C:\Windows\System32\.



Ich möchte meinem Kollegen Josiah Massari ( @Airzero24) dafür danken, dass er als erster einige dieser DLL-Hooks entdeckt, ihre Methodik erklärt und mich dazu inspiriert hat, die Erkennung zu automatisieren.



Was ist eine DLL?



Eine DLL ist eine Bibliothek mit Code und Daten, die von mehr als einem Programm gleichzeitig verwendet werden können. ( Quelle ) Die



Funktionalität einer DLL kann von einer Windows-Anwendung mit einer der Funktionen verwendet werden LoadLibrary*. Anwendungen können auf DLLs verweisen, die speziell für diese Anwendungen entwickelt wurden, oder auf Windows-DLLs, die sich bereits in System32 auf der Festplatte befinden. Entwickler können DLLs von System32 laden, um Funktionen zu verwenden, die bereits in Windows in ihren Anwendungen implementiert sind, ohne diese Funktionen von Grund auf neu schreiben zu müssen.



Beispielsweise kann ein Entwickler, der HTTP-Anforderungen stellen muss, die WinHTTP ( winhttp.dll) - Bibliothek verwenden, anstatt HTTP-Anforderungen mithilfe von Raw-Sockets zu implementieren.



DLL-Suchreihenfolge und Abfangen



Da DLLs als Dateien auf der Festplatte vorhanden sind, fragen Sie sich möglicherweise, woher eine Anwendung weiß, woher die DLL geladen werden soll. Microsoft hat die DLL-Suchreihenfolge hier detailliert dokumentiert .



Ab Windows XP SP2 ist der sichere DLL-Suchmodus standardmäßig aktiviert ( HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode). Wenn der abgesicherte Modus aktiviert ist, lautet die DLL-Suchreihenfolge wie folgt:



  1. Das Verzeichnis, aus dem die Anwendung geladen wurde.
  2. Systemverzeichnis. Verwenden Sie die Funktion GetSystemDirectory , um den Pfad zu diesem Verzeichnis abzurufen .
  3. 16-Bit-Systemverzeichnis. Es gibt keine Funktion, die einen Pfad zu diesem Verzeichnis bereitstellt, aber es wird gesucht.
  4. Windows-Verzeichnis. Verwenden Sie die Funktion GetWindowsDirectory , um den Pfad zu diesem Verzeichnis abzurufen .
  5. Aktuelles Verzeichnis.
  6. , PATH. , , App Paths. App Paths DLL.


Ein System kann mehrere Versionen derselben DLL enthalten. Anwendungen können die Auswahl des Speicherorts steuern, von dem die DLL geladen werden soll, indem sie den vollständigen Pfad angeben oder einen anderen Mechanismus wie ein Manifest verwenden. ( Quelle )



Wenn die Anwendung nicht angibt, von wo die DLL geladen werden soll, verwendet Windows die oben gezeigte Standard-DLL-Suchreihenfolge. Die erste Position in der DLL-Suchreihenfolge (das Verzeichnis, aus dem die Anwendung geladen wird) ist für Angreifer von Interesse.



Wenn der Anwendungsentwickler beabsichtigt, die DLL von zu ladenC:\Windows\System32, aber nicht explizit in die Anwendung geschrieben, wird die im Anwendungsverzeichnis platzierte schädliche DLL vor der legitimen DLL von System32 geladen. Das Laden einer schädlichen DLL wird als DLL-Spoofing (oder Abfangen) bezeichnet und von Angreifern verwendet, um bösartigen Code in vertrauenswürdige / signierte Anwendungen zu laden.



Verwenden von DLL-Spoofing zum Erreichen von Ausfallsicherheit



DLL-Spoofing kann verwendet werden, um Ausfallsicherheit zu erreichen, wenn eine anfällige Anwendung / ein anfälliger Dienst gestartet und eine schädliche DLL an einem anfälligen Ort abgelegt wird. Ein Kollege von mir @Airzero24entdeckte DLL-Spoofing in Microsoft OneDrive, Microsoft Teams und Slack as userenv.dll.



Diese Programme wurden zum Ziel des Abfangens, da sie standardmäßig so konfiguriert sind, dass sie beim Start von Windows gestartet werden. Dies ist unten im Task-Manager zu sehen: Für





den Autostart konfigurierte Windows-Anwendungen



Um das DLL-Spoofing zu testen, habe ich einen DLL-Shellcode-Loader erstellt, mit dem Cobalt Strike Beacon gestartet wurde. Ich habe die schädliche DLL in umbenannt userenv.dllund in das betroffene Anwendungsverzeichnis kopiert. Ich habe die Anwendung gestartet und meinen neuen Beacon-Rückruf gesehen.





Cobalt Strike Beacon durch DLL-Interception



mitIm Prozess-Explorer kann ich überprüfen, ob meine schädliche DLL tatsächlich von einer anfälligen Anwendung geladen wurde.





Prozess-Explorer zeigt geladene schädliche DLL an



Automatische Erkennung des DLL-Abhörpotentials



Nachdem ich das zuvor bekannte DLL-Hijacking bestätigt hatte, wollte ich sehen, ob ich andere DLL-Spoofing-Funktionen finden konnte, die ausgenutzt werden konnten.



Den in meiner Kasse verwendeten Code finden Sie hier .



Am Beispiel von Slack



Um diesen Prozess zu starten, habe ich Process Monitor (ProcMon) mit den folgenden Filtern ausgeführt:



  • Prozessname -slack.exe
  • Ergebnis enthältNOT FOUND
  • Der Weg endet mit .dll.




Finden Sie fehlende DLLs in ProcMon.



Dann startete ich Slack und untersuchte ProcMon auf DLLs, die Slack suchte, aber nicht finden konnte.





Mögliche von ProcMon entdeckte DLL-Abfangpfade



Ich habe diese Daten aus ProcMon als CSV-Datei exportiert, um das Parsen in PowerShell zu vereinfachen.



Mit meiner aktuellen Shellcode Loader-DLL konnte ich die DLL-Namen, die von Slack erfolgreich geladen wurden, nicht einfach herausfinden. Ich habe eine neue DLL erstellt, die verwendet GetModuleHandleExwird GetModuleFileName, um den Namen der geladenen DLL zu ermitteln und in eine Textdatei zu schreiben .



Mein nächstes Ziel war es, die CSV-Datei für DLL-Pfade in der Liste zu analysieren, diese Liste anzuzeigen, meine Test-DLL in den angegebenen Pfad zu kopieren, den Zielprozess zu starten, den Zielprozess zu stoppen und die Test-DLL zu löschen. Wenn die Test-DLL erfolgreich geladen wurde, schreibt sie ihren Namen in die resultierende Datei.



Wenn dieser Prozess abgeschlossen ist, werde ich eine Liste möglicher DLL-Hijacks (ich hoffe) in eine Textdatei schreiben lassen.



Die ganze Magie in meinem DLLHijackTest-Projekt wird von einem PowerShell-Skript ausgeführt . Es akzeptiert den Pfad zu der von ProcMon generierten CSV-Datei, den Pfad zu Ihrer schädlichen DLL, den Pfad zu dem Prozess, den Sie ausführen möchten, und alle Argumente, die Sie an den Prozess übergeben möchten.





Get-PotentialDLLHijack-Parameter





Get-PotentialDLLHijack.ps1



Nach einigen Minuten überprüfe ich die in meiner "böswilligen" DLL aufgeführte Textdatei auf mögliche DLL-Hijacks. Ich habe die folgenden möglichen Abfangpfade für Slack gefunden:



PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\slack\slack.exe"
C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL


Am Beispiel von Microsoft Teams



Wir führen den oben beschriebenen Prozess erneut durch:



  1. Verwenden Sie ProcMon, um potenzielle DLL-Abfangpfade zu identifizieren, und exportieren Sie diese Daten als CSV-Datei.
  2. Bestimmen Sie den Pfad zum Starten des Prozesses.
  3. Definieren Sie alle Argumente, die Sie an den Prozess übergeben möchten.
  4. Führen Sie Get-PotentialDLLHijack.ps1mit den entsprechenden Argumenten aus.


Ich habe die folgenden möglichen Abfangpfade für Microsoft-Teams gefunden:



PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Microsoft\Teams\Update.exe" -ProcessArguments '--processStart "Teams.exe"'
C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll


Hinweis : Zum Abschluss musste ich kleine Änderungen am PowerShell-Skript vornehmen Teams.exe, da mein Skript versucht, den zu startenden Prozess zu beenden. In diesem Fall ist dies der Fall Update.exe.


Verwenden Sie Visual Studio Code als Beispiel



Durch Wiederholen des obigen Vorgangs habe ich die folgenden möglichen Abfangpfade für Visual Studio Code gefunden:



PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Programs\Microsoft VS Code\Code.exe"
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll


Freigeben von DLLs



Ich habe festgestellt, dass Slack, Microsoft Teams und Visual Studio Code die folgenden DLLs gemeinsam nutzen:



  • WINSTA.dll
  • LINKINFO.dll
  • ntshrui.dll
  • srvcli.dll
  • cscapi.dll


Ich fand das interessant und wollte verstehen, was dieses Verhalten verursacht.



Methodik: Grundlegendes zum Abfangen gemeinsam genutzter DLLs



Ich sah Tracy Stapel , wenn sie Last versucht Lasches WINSTA.dll, LINKINFO.dll, ntshrui.dll, srvcli.dllund cscapi.dll.



DLL mit verzögertes Laden



bemerkte ich Ähnlichkeiten in Tracy - Stack beim Laden WINSTA.dll, LINKINFO.dll, ntshrui.dllund srvcli.dll.





Stack-Trace, wenn Code.exe versucht, WINSTA.dll





einen Stack-Trace beim Teams.exeLaden zu laden LINKINFO.dll,





Stack-Trace, wenn Slack versucht,ntshrui.dll



einen Stack-Trace zu laden , enthält ständig einen Aufruf _tailMerge_<dllname>_dll, delayLoadHelper2gefolgt von LdrResolveDelayLoadedAPI. Dieses Verhalten war für alle drei Anwendungen gleich.



Ich habe festgestellt, dass dieses Verhalten mit dem verzögerten Laden der DLL zusammenhängt . Vom Trace-Stack beim BootenWINSTA.dllIch konnte sehen, dass das Modul für dieses verzögerte Laden verantwortlich war wtsapi32.dll.



Ich öffnete wtsapi32.dllin Ghidra und benutzte Search -> For Strings -> Filter: WINSTA.dll. Ein Doppelklick auf die gefundene Zeile führt Sie zu ihrer Position im Speicher.





Die Zeile " WINSTA.dll" inwtsapi32.dll



Wenn Sie mit der rechten Maustaste auf eine Stelle im Speicher klicken, können Sie Verweise auf diese Adresse finden.





Links zuWINSTA.dll



Wenn Sie den Links folgen, sehen Sie, dass die Zeichenfolge WINSTA.dllan eine Struktur mit dem Namen übergeben wird ImgDelayDescr. In der Dokumentation zu dieser Struktur können wir bestätigen, dass sie mit dem verzögerten Laden von DLLs zusammenhängt.



typedef struct ImgDelayDescr {
   DWORD        grAttrs;        // 
   RVA          rvaDLLName;     // RVA   dll 
   RVA          rvaHmod;        // RVA  
   RVA          rvaIAT;         // RVA IAT
   RVA          rvaINT;         // RVA INT
   RVA          rvaBoundIAT;    // RVA   IAT
   RVA          rvaUnloadIAT;   // RVA    IAT
   DWORD        dwTimeStamp;    // 0,   ,
                                // O.W. / DLL,   (Old BIND)
   } ImgDelayDescr, * PImgDelayDescr;


Diese Struktur kann an übergeben werden __delayLoadHelper2, die LoadLibrary/ GetProcAddresszum Laden der angegebenen DLL und zum Korrigieren der importierten Funktionsadresse in der IAT (Lazy Load Import Address Table) verwendet.



FARPROC WINAPI __delayLoadHelper2(
   PCImgDelayDescr pidd,  //     ImgDelayDescr
   FARPROC * ppfnIATEntry //     IAT  
);


Indem ImgDelayDescrwir andere Verweise auf unsere Struktur finden , können wir einen Anruf finden __delayLoadHelper2, der dann anruft ResolveDelayLoadedAPI. Ich habe den Funktionsnamen, die Typen und die Variablen umbenannt, um das Verständnis zu erleichtern.





__delayLoadHelper2und ResolveDelayLoadedAPIbei Ghidra



Excellent! Dies stimmt mit dem überein, was wir in unserem ProcMon-Stack-Trace gesehen haben, als Slack versuchte zu laden WINSTA.dll.





__delayLoadHelper2 und ResolveDelayLoadedAPIin ProcMon.



Dieses Verhalten wurde einheitlich für WINSTA.dll, LINKINFO.dll, ntshrui.dllund srvcli.dll. Der Hauptunterschied zwischen jeder Lazy-Load-DLL war die "übergeordnete" DLL. In allen drei Anwendungen:



  • wtsapi32.dll aufgeschoben geladen WINSTA.dll
  • shell32.dll faul geladen LINKINFO.dll
  • LINKINFO.dll aufgeschoben geladen ntshrui.dll
  • ntshrui.dll aufgeschoben geladen srvcli.dll


Haben Sie etwas Interessantes bemerkt? Es sieht so aus, als würde es shell32.dllherunterladen LINKINFO.dll, welche herunterladen ntshrui.dll, welche schließlich herunterladen srvcli.dll. Dies bringt uns zu unserer letzten gemeinsamen potenziellen DLL-Spoofing-Option - cscapi.dll.



DLL-Ersetzung in NetShareGetInfo und NetShareEnum



Ich folgte der Stapelverfolgung, als Slack versuchte zu laden cscapi.dllund einen Anruf sah LoadLibraryExW, der anscheinend von kam srvcli.dll. Ich habe den





Stack-Trace beim Bootencscapi.dll in Ghidra



geöffnet und verwendet . Ein Doppelklick auf die gefundene Zeile und das Folgen der Links führt zum erwarteten Anruf. ruft LoadLibrary auf, um die Funktion, die den Aufruf enthält, umzubenennen und den Links zu folgen. Ich habe zwei Stellen, an denen die Funktion verwendet wird:srvcli.dllSearch -> For Strings -> Filter: cscapi.dllLoadLibrary





srvcli.dllcscapi.dll



LoadLibrary







NetShareEnum-Downloads cscapi.dll





NetShareGetInfo-Downloadscscapi.dll



Ich habe dies mit PoC-Programmen überprüft, die aufgerufen haben NetShareEnumund NetShareGetInfo:





NetShareEnum.exeDownloads cscapi.dll





NetShareGetInfo.exeherunterladencscapi.dll



Ergebnisse



Die folgenden DLL-Spoofing-Pfade sind in Slack verfügbar:



C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL


Die folgenden DLL-Spoofing-Pfade sind in Microsoft Teams verfügbar:



C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll


Die folgenden DLL-Spoofing-Pfade sind in Visual Studio Code verfügbar:



C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll


Darüber hinaus stellte ich fest, dass Programme DLLs in der Form verwenden NetShareEnumund NetShareGetInfobereitstellen, die cscapi.dllaufgrund des fest codierten Aufrufs ersetzt werden können LoadLibrary. Ich habe dieses Verhalten mit Ghidra und PoC überprüft.



Fazit



Zur Erinnerung: Das Abfangen von DLLs ist eine Methode, mit der Angreifer die Codeausführung in signierten / vertrauenswürdigen Anwendungen stören können. Ich habe Tools erstellt, mit denen die Erkennung von DLL-Abfangpfaden automatisiert werden kann. Mit diesem Tool habe ich DLL-Abfangpfade in Slack, Microsoft Teams und Visual Studio Code entdeckt.



Ich habe festgestellt, dass sich die DLL-Abfangpfade dieser drei Anwendungen überschneiden, und die Ursache untersucht. Ich habe meine Methode zum Verständnis dieses Zufalls hervorgehoben. Ich habe etwas über das verzögerte Laden von DLLs gelernt und zwei API-Aufrufe entdeckt, die es ermöglichen, DLLs in jedem Programm abzufangen, das sie aufruft:



  • NetShareEnum Ladungen cscapi.dll
  • NetShareGetInfo Ladungen cscapi.dll


Vielen Dank, dass Sie sich die Zeit genommen haben, diesen Artikel zu lesen. Ich hoffe, Sie haben ein oder zwei Dinge über Windows-APIs, Ghidra, ProcMon, DLLs und DLL-Interception gelernt!



Links



Ein großes Hallo an meine Kollegen Daniel Heinsen ( @hotnops), Lee Christensen ( @tifkin_) und Matt Hand ( @matterpreter) für ihre Hilfe bei Ghidra / ProcMon!






Überprüfen öffentlicher PoCs zur Verwendung beim Pentesting






Weiterlesen:






All Articles