
Extrahiert den NetNTLMv2-Hash des aktuellen Benutzers über HTTP-Authentifizierungs-Proxying und vermeidet direkte SSPI-Aufrufe; v2 delegiert die Authentifizierung an den BITS-Dienst, um die Prozesszuordnung zu durchbrechen.
NTLM-Hash-Extraktion durch Authentifizierungs-Proxying auf HTTP-Ebene, null SSPI-Aufrufe aus dem Angreiferprozess.
HashSiphon extrahiert den NetNTLMv2-Hash des aktuellen Benutzers, indem es HTTP-Authentifizierungsabläufe manipuliert, anstatt SSPI-APIs direkt aufzurufen. Es werden zwei Varianten bereitgestellt: v1 leitet die NTLM-Authentifizierung über den HTTP-Stack von .NET innerhalb desselben Prozesses, und v2 delegiert die Authentifizierung vollständig an den BITS-Dienst (svchost.exe) in einer anderen PID, wodurch die Prozesszuordnung vollständig durchbrochen wird.
Jedes bekannte Tool zur Selbstextraktion von NTLM-Hashes – Internal Monologue, manuelle SSPI-Skripte und deren Derivate – ruft AcquireCredentialsHandle → InitializeSecurityContext → AcceptSecurityContext aus dem eigenen Prozess des Angreifers auf. EDRs hooken diese SSPI-Funktionen und markieren die Aufrufkette.
HashSiphon beschreitet einen grundlegend anderen Weg:
| Aspekt | Internal Monologue | HashSiphon v1 | HashSiphon v2 |
|---|
| SSPI-Aufrufe aus Angreifer-PID | 4+ direkte Aufrufe | 0 direkt (WinHTTP ruft intern auf) | 0 in jedem Prozess, den wir besitzen |
| Auth-Prozess | Angreifer-PID | Angreifer-PID (über HTTP-Stack) | svchost.exe (BITS-Dienst) |
| Security-API-Importe | SSPI-DLL-Importe erforderlich | Keine in unserem Code | Keine in unserem Code |
| Erkennungsoberfläche | SSPI-Hooks, API-Aufrufmuster | HTTP-Loopback-Verkehr | BITS-Job + Loopback-Verkehr |
| Prozesszuordnung | Angreifer-PID | Angreifer-PID | Durchbrochen, völlig andere PID |
Beide Varianten teilen denselben Kern: einen minimalen TCP-Server auf 127.0.0.1, der gerade genug HTTP spricht, um einen NTLM-Challenge-Response-Austausch durchzuführen, mit einer kontrollierten 8-Byte-Challenge, damit der erfasste Hash offline geknackt werden kann.
HashSiphon.ps1)┌──────────────────────────┐
│ PowerShell (PID X) │
│ │
│ ┌────────────────────┐ │ ┌──────────────────────┐
│ │ TCP Server (C#) │◄─┼──────────┤ HttpWebRequest + │
│ │ Loopback :random │ │ HTTP │ DefaultCredentials │
│ │ │──┼──────────► │
│ │ 1. Send 401+NTLM │ │ NTLM │ WinHTTP auto-auths │
│ │ 2. Send Type 2 │ │ Type │ using current user's │
│ │ 3. Capture Type 3 │ │ 1/2/3 │ credentials │
│ │ 4. Extract hash │ │ │ │
│ └────────────────────┘ │ └──────────────────────┘
└──────────────────────────┘
Add-Type, bindet an 127.0.0.1:0 (vom Betriebssystem zugewiesener Port)HttpWebRequest + CredentialCache.DefaultCredentialsHTTP 401 und WWW-Authenticate: NTLM, um die Aushandlung auszulösenKompromiss: WinHTTP ruft intern SSPI innerhalb derselben PID auf, keine direkten Importe, aber der Aufrufstack führt immer noch zu uns zurück.
HashSiphonV2.ps1)┌─────────────────────┐ ┌───────────────────────────┐
│ PowerShell (PID X) │ │ svchost.exe (PID Y) │
│ │ │ BITS Service │
│ ┌───────────────┐ │ HTTP │ │
│ │ TCP Server │◄─┼─────────┤ BITS downloads from our │
│ │ (Background │ │ NTLM │ server, auto-authenticates│
│ │ Runspace) │──┼─────────► using job owner's creds │
│ └───────────────┘ │ Type │ │
│ │ 1/2/3 │ SSPI calls happen HERE, │
│ Start-BitsTransfer─┼────────►│ not in PID X │
│ (Trigger only) │ COM │ │
└─────────────────────┘ └───────────────────────────┘
│
└── Our process: TcpListener + Start-BitsTransfer
Zero SSPI. Zero security API imports.
Start-BitsTransfer erstellt einen Download-Job, der auf http://127.0.0.1:<port>/hashsiphon.bin zeigtsvchost.exe, eine völlig andere PID) verbindet sich mit unserem ServerHTTP 200 mit einem Body zurück, damit BITS die Übertragung als erfolgreich betrachtetDurchbruch: Unser Prozess ruft niemals SSPI auf – nicht direkt, nicht über WinHTTP, überhaupt nicht. Die gesamte NTLM-Berechnung findet in svchost.exe statt. EDR-SSPI-Hooks sehen den Aufrufstack im BITS-Dienstprozess, nicht in unserem.
powershell -ExecutionPolicy Bypass -File HashSiphon.ps1
powershell -ExecutionPolicy Bypass -File HashSiphonV2.ps1
[*] Compiling HashSiphon v2 server...
[+] Server compiled
HashSiphon v2.0 - BITS Service Proxy Authentication
Auth by svchost.exe (BITS), not our process
[1] NTLM HTTP server ready on 127.0.0.1:52847
[2] Controlled challenge: 1122334455667788
[3] Triggering BITS transfer to our server...
[4] BITS transfer initiated
[+] User: ivan
[+] Domain: DESKTOP-ABCDEF
[+] NT response: 280 bytes (NTLMv2)
+----------------------------------------------------------+
| NetNTLMv2 HASH - Extracted via BITS service proxy! |
+----------------------------------------------------------+
| hashcat -m 5600 | john --format=netntlmv2 |
+----------------------------------------------------------+
ivan::DESKTOP-ABCDEF:1122334455667788:<NTProofStr>:<ClientBlob>
+----------------------------------------------------------+
| ATTRIBUTION ANALYSIS |
+----------------------------------------------------------+
| Our PID: 844 (PowerShell) |
| Auth by: BITS service (svchost.exe, PID 5500) |
| SSPI calls: Zero from PID 844 |
| Our APIs: TcpListener + Start-BitsTransfer only |
+----------------------------------------------------------+
Wenn BITS fehlschlägt (Dienst deaktiviert, Modul nicht verfügbar), fällt v2 automatisch darauf zurück, einen untergeordneten powershell.exe-Prozess mit Invoke-WebRequest -UseDefaultCredentials zu starten. Dies erreicht immer noch eine PID-Trennung, obwohl der untergeordnete Prozess sichtbarer ist als BITS.