MazX0p/mssqlbof

GitHub: MazX0p/mssqlbof

一个为 Microsoft SQL Server 打造的轻量级 TDS 7.4 BOF 套件,解决传统 SQL 工具在 Beacon 中引入额外 DLL 与脚本痕迹的问题。

Stars: 66 | Forks: 4

# mssqlbof 一个为 Microsoft SQL Server 打造的 Beacon 对象文件套件,通过 C 语言直接在 wire 上使用 TDS 7.4。不依赖 `msodbcsql.dll`、`sqloledb.dll`、.NET CLR 或 PowerShell。每个架构一个 COFF 文件,加载到任何支持标准 Beacon API 的 Beacon 中。 image ## 为什么 SQL Server 在几乎每一次渗透中都会出现。人们会使用的两个工具是 `SQLRecon` / `PowerUpSQL`(CLR + PowerShell)以及任何封装 `sqlcmd.exe` 的工具。它们都会让 `mscoree.dll`、PowerShell AMSI 事件或完整的 Microsoft ODBC 驱动驻留在 Beacon 内存中。其实这些都不必要:TDS 只是通过 TCP 传输的定长字节流,前有 Schannel 握手,而任何支持 Beacon 的 Beacon 已加载了 `ws2_32`、`secur32`、`schannel` 和 `bcrypt`。 因此 `mssqlbof` 手动用 C 实现 TDS,并直接使用操作员所需的任意 SSPI 或 BCrypt 原语。Beacon 仅加载一个约 48 KB 的对象文件,执行 SQL 后卸载。进程中不会引入其他内容。 ## 兼容性 | C2 | x64 | x86 | |---|---|---| | Cobalt Strike | 是 | 是 | | Havoc | 是 | 是 | | Sliver | 是 | 是 | | BruteRatel | 是 | 是 | | Nighthawk | 是 | 是 | | Outflank Stage1 | 是 | 是 | | AdaptixC2 | 是 | 是 | | Metasploit `execute_bof` | 是 | 是 | | PoshC2 | 是 | 是 | 每种架构一个对象文件。`mssql.x64.o` 在所有框架中是相同的二进制文件——我们仅使用标准 Beacon API(`BeaconPrintf`、`BeaconDataExtract` 等)以及 COFF 加载器在运行时解析的 `$` 动态导入模式。 ## 快速开始 ``` apt install gcc-mingw-w64 libssl-dev make ``` 生成 `build/mssql.x64.o` 和 `build/mssql.x86.o`。将其放入团队服务器,使用 C2 的 BOF 加载器加载即可。 ## 功能操作 所有操作都通过一个对象文件和 `--action ` 参数完成: ``` --action find LDAP enum of MSSQLSvc SPNs in the current forest --action info --host server/version/current user/sysadmin/db --action query --host --sql "..." arbitrary T-SQL, multi-row, multi-resultset --action links --host linked-server enumeration (single hop) --action exec --host --cmd "..." xp_cmdshell with auto enable + restore --action impersonate --host --discover list logins you can EXECUTE AS --action impersonate --host --login X --sql "..." run T-SQL as X via EXECUTE AS LOGIN --action privesc --host six-section privesc surface enumeration --action coerce --host --to "\\listener\x" xp_dirtree SMB auth coercion --action passwords --host dump sys.linked_logins + sys.credentials --action chain --host --via LINK --sql "..." EXEC (...) AT [LinkedServer] ``` `--action find` 在无主机模式下运行,通过 LDAP 与操作员的 DC 通信。 ## 身份验证 四种模式。所有模式均在真实域中通过 SQL Server 2019 与 COFFLoader 和 Adaptix C2 进行端到端验证。 ``` --auth sspi (default) current beacon thread token Kerberos if SPN exists, NTLM otherwise. Honors make_token / steal_token. --auth ntlm --domain D --user U --pass P explicit NTLM plaintext. Drives SSPI NTLM package, multi-leg. --auth ntlm --domain D --user U --hash pass-the-hash. Hand-rolled NTLMv2 (see below). No SSPI, no lsass, no make_token. --auth sql --user U --pass P SQL authentication. ``` `--hash` 接受 32 字符十六进制 NT 哈希,或 `secretsdump` 输出的 `LM:NT` 格式。 ### 为何哈希模式不只是 `SSPI + SEC_WINNT_AUTH_IDENTITY` `AcquireCredentialsHandleW(NULL, "NTLM", ...)` 仅接受凭据身份结构中的明文密码。NTLM 提供程序在内部推导 NT 哈希。若直接传入哈希,需要修补 lsass(类似于 Mimikatz 的 `sekurlsa::pth`),或运行 Beacon 于一个已被预身份验证的牺牲进程中。 我们采用的替代方案是完全跳过 SSPI 进行 PTH,并自行生成 NTLMSSP 消息。`src/tds/ntlm_pth.c` 构建 Type 1 NEGOTIATE,从 TDS 0xED 令牌解析服务器端的 Type 2 CHALLENGE,使用 `bcrypt.dll` 的 HMAC-MD5 提供者执行 NTLMv2 运算,并生成 Type 3 AUTHENTICATE,使 SQL Server 将其愉快地转发至 DC。 首次尝试因 `error 18452: login is from an untrusted domain` 失败。在线比对 Impacket 的握手过程后发现:我们发送的 LMv2 响应为 24 个零,且包含完整的 0xe288... Windows 协商标志。匹配 Impacket 的 LMv2 计算方式及其更小的 0xa2880205 标志集(无 `KEY_EXCH`、`SIGN`、`ALWAYS_SIGN`)后,服务器接受了该哈希。详细文章见 [`BLOG`](https://0xmaz.me/posts/Writing-a-TDS-7.4-BOF-for-SQL-Server-all-the-way-to-Pass-the-Hash/)。 ## `--action exec` 的权限提升 ``` --impersonate auto (default) try EXECUTE AS LOGIN, then TRUSTWORTHY hop --impersonate login EXECUTE AS LOGIN via an IMPERSONATE grant --impersonate trustworthy hop through dbo of a sysadmin-owned TRUSTWORTHY db --impersonate none fail if not sysadmin ``` `privesc` 在选择方法前枚举攻击面:包括 sysadmin 成员身份、IMPERSONATE 权限(目标登录的 sysadmin 状态)、由 sysadmin 拥有的 TRUSTWORTHY 数据库、链接服务器、服务器级权限以及 `xp_cmdshell` 状态。 ## 构建 ``` apt install gcc-mingw-w64 libssl-dev make # cross-compile BOFs to x64 + x86 make tds # Linux shared library of the TDS core (for fuzzing / tests) ``` Linux 共享库与 Windows 构建共享所有 TDS 源文件;仅 `tls_schannel.c` / `sspi.c` / `ntlm_pth.c` 替换为其 OpenSSL / stub 等效实现。 没有直接调用 libc 或 Win32。所有外部符号均通过 `src/common/dynimports.h` 中的 `$` 动态导入约定传递。可通过以下命令验证: ``` x86_64-w64-mingw32-objdump -t build/mssql.x64.o | grep UND ``` 应仅出现 `MSVCRT$*`、`WS2_32$*`、`SECUR32$*`、`BCRYPT$*`、`CRYPT32$*`、`SCHANNEL$*`、`WLDAP32$*`、`KERNEL32$*`、`ADVAPI32$*` 和 `__imp_Beacon*`。不包含 `msodbcsql.dll`、`sqloledb.dll` 或 `mscoree.dll`。 ## 操作安全(OPSEC) | 操作 | 超出 Beacon 基线的额外 DLL | 服务器端痕迹 | 备注 | |---|---|---|---| | `find` | `wldap32` | DC 事件 1644(罕见) | 仅 LDAP,不触碰 SQL | | `info` / `query` / `links` / `privesc` / `passwords` | `secur32` 或 `bcrypt`、`schannel`、`ws2_32` | 若启用 SQL 审计则记录 33205 | 纯 TDS,无 ODBC 指纹 | | `exec` | 同上 | 默认跟踪中的 `xp_cmdshell` + `sp_configure` | 较明显。使用 `--impersonate` 从低权限登录可避免以 NT SERVICE 身份落地 | | `impersonate` | 同上 | `EXECUTE AS` 审计 33205 与 33206 | | | `coerce` | 同上 | 尝试 `xp_dirtree` 会被记录 | 指向 `responder` / `ntlmrelayx` | | `chain` | 同上 | 链接服务器目标上记录 `EXEC AT` | 枢轴原语 | 所有 TLS 均为真实的 Schannel(而非 stub),并处理了 SQL Server PRELOGIN 封装的 quirks:握手在 TDS PRELOGIN 类型 0x12 包内运行,随后 LOGIN7 以原始 TLS 应用数据发出,服务器首先以明文回应该登录包。多阶段 SSPI 延续也以明文传输——若通过 TLS 加密它们,SRV02 会直接关闭连接。 ## 文档 | 文档 | 内容 | |---|---| | [`docs/PROTOCOL.md`](docs/PROTOCOL.md) | TDS 7.4 深入:数据包封装、PRELOGIN 选项流、LOGIN7 密码混淆、SQLBatch 中的 ALL_HEADERS、令牌流语法(COLMETADATA / ROW / NBCROW / DONE / LOGINACK / ENVCHANGE / `0xED` SSPI 延续)、TLS 握手 quirks、多阶段 NTLM 泵。 | | [`docs/OPERATOR.md`](docs/OPERATOR.md) | 端到端实验指南:构建、启动 Adaptix 监听器、在 Windows 主机上放置 Beacon、运行所有身份验证模式(包括 PTH)的所有操作,以及跨 C2 可移植性说明。 | | [`docs/OPSEC.md`](docs/OPSEC.md) | 每个操作的 on-wire 与内存占用:每个操作加载到 Beacon 的内容、在 SQL 审计中留下的痕迹,以及防御者可能观察到的信息。 | | [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) | C2 框架矩阵、SQL Server 版本矩阵,以及针对各目标验证的身份验证模式。 | | [`BLOG`](LINK_URL_5/>) | 调试叙事:Pass-the-Hash 实现过程,包括网络捕获、LMv2 零字节的误导项,以及与 Impacket 的 tshark 对比分析。 | ## 状态 `v0.1.2` — 多身份验证、PTH、11 个操作,实验室验证通过。 - 四种身份验证模式已工作:ssppi、ntlm-plaintext、ntlm-hash(PTH)、sql - 统一的 BOF 分发(`mssql.x64.o`)包含 11 个操作 - 四种 `exec` 权限提升方法:login、trustworthy、auto、none - 多阶段 SSPI 延续并处理 TDS EOM - 通过手工实现的 NTLMv2 + BCrypt 进行 Pass-the-Hash - 端到端完整验证:38 例 COFF 扫描 + 在域加入的 SQL Server 2019 上对 Adaptix C2 的扫描 已知边界情况: - 仅支持单跳链接服务器遍历;递归嵌套 `OPENQUERY` 链为 v0.2。 - 多阶段 SSPI 登录后的首个 SQLBatch 会丢弃数据。`do_connect` 中的初步 SELECT 可将其冲刷——副作用是每个操作都会记录 `[*] connected as ...` 行。根本原因在于 LOGINACK 后的读取路径,将在 v0.2 中修复。 ## 致谢 - [`Cobalt-Strike/bof_template`](https://github.com/Cobalt-Strike/bof_template):严格遵循该标准 Beacon API 表面。 - [`TrustedSec/COFFLoader`](https://github.com/trustedsec/COFFLoader):作为独立加载器用于交叉验证。 - `impacket` 的 `ntlm.py` 和 `mssqlclient.py`:我们比对时使用的参考实现。 - `[MS-TDS]` 与 `[MS-NLMP]`:所有手工实现均遵循这些规范。 - `Opus 4.6`:部分文档在 Opus 4.6 协助下起草。所有代码均为手写,并在实验室中完成端到端验证。 ## 许可证 MIT。
标签:AdaptixC2, BCrypt, BOF, BruteRatel, CISA项目, Cloudflare, Cobalt Strike, Havoc, MITRE ATT&CK, Nighthawk, ODBC, Outflank Stage1, PoshC2, PowerUpSQL, Schannel, Sliver, sqlcmd, SQLRecon, SQL Server, SSPI, StruQ, T1059, T1190, T1552, T1555, TCP, TDS 7.4, 内存加载, 客户端加密, 开源, 攻击诱捕, 数据展示, 数据库, 无AMSI, 无CLR, 无DLL, 无PowerShell, 横向移动, 欺骗防御, 端点可见性, 红队, 编程规范