Pular para o conteúdo
Categoria: Forense8 min de leitura

Hunting de Living-off-the-Land Binaries no Windows com KQL

Por Lucas Andrade ·

Queries KQL prontas para Microsoft Defender e Sentinel cacando abuso de LOLBins como rundll32, mshta e certutil em ambientes reais.

Hunting de Living-off-the-Land Binaries no Windows com KQL

Um atacante competente nao precisa largar seu proprio binario no disco da vitima: ele usa o que ja esta ali. Rundll32, mshta, certutil, bitsadmin e regsvr32 sao ferramentas legitimas assinadas pela propria Microsoft, o que leva muitos EDR a tratar suas execucoes como ruido. Essa tecnica se chama Living off the Land, os binarios em si LOLBins, catalogados no projeto publico LOLBAS. A equipe Basilisk passou os ultimos seis meses analisando 47 incidentes e em 31 deles havia pelo menos um LOLBin na kill chain. Este post entrega as consultas KQL que rodamos no Microsoft Defender for Endpoint e no Sentinel para transformar essas execucoes em deteccoes acionaveis sem afogar o SOC em falsos positivos.

O que sao LOLBins e por que passam batido

Um LOLBin e um programa pre-instalado e assinado que carrega uma funcao secundaria nao prevista e util ao atacante: download, execucao de codigo, persistencia ou evasao de application control. Como a assinatura vem da Microsoft, allowlists ingenuas nao disparam, e um nome de processo pelado como indicador nao vale nada. A deteccao se desloca assim de qual binario para qual linha de comando, qual processo pai, qual comportamento posterior. Por isso a linha de comando do processo (ProcessCommandLine) e o campo mais importante de qualquer consulta de hunting, seguido de InitiatingProcessFileName e das conexoes de rede do mesmo processo.

Primeiro entender a baseline

Antes de escrever qualquer regra, e preciso entender a baseline do ambiente. Rodamos um hunt amplo sobre DeviceProcessEvents agrupando por FileName e contando execucoes em 30 dias por host, identificando o normal daquela frota. Num cliente com 8.200 endpoints, mshta.exe aparecia so em 0,4% das maquinas, todas do marketing rodando um relatorio legado. Isso significa que qualquer execucao de mshta fora desse grupo merece um alerta P2. Essa abordagem de raridade estatistica e a base do hunting moderno e dialoga com Threat Hunting com Sigma e Elastic: Do Indicador a Regra de Deteccao, onde mostramos o caminho do indicador cru ate a regra Sigma versionada no Git.

Rundll32 com linha de comando suspeita

A consulta base que recomendamos para rundll32 e: DeviceProcessEvents | where FileName =~ 'rundll32.exe' | where ProcessCommandLine has_any ('javascript:', 'shell32.dll,Control_RunDLL', 'mshtml,RunHTMLApplication', '.cpl,', 'url.dll,OpenURL') | where InitiatingProcessFileName !in~ ('explorer.exe', 'svchost.exe') | project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName. Testada contra a tecnica T1218.011 do MITRE ATT&CK, pegou 9 de 10 execucoes do beacon do Cobalt Strike em modo SMB pivot. O ajuste fino vem de excluir processos pai legitimos por departamento, algo que documentamos em Adversary Emulation com Caldera e MITRE ATT&CK em Lab Corporativo. Preste atencao especial a rundll32 sem argumento de DLL, sinal forte de process hollowing.

Certutil: o canivete suico

Certutil merece capitulo proprio. Baixa arquivos (-urlcache), decodifica base64 (-decode) e calcula hashes. Nossa consulta cacadora e: DeviceProcessEvents | where FileName =~ 'certutil.exe' | where ProcessCommandLine has_any ('-urlcache', '-decode', '-decodehex', '-ping', 'http://', 'https://') | where ProcessCommandLine !contains 'CertificateServices' | extend Stage = case(ProcessCommandLine has '-decode', 'staging', ProcessCommandLine has 'http', 'download', 'recon'). Em 2025 vimos certutil usado como segunda etapa em campanhas que comecaram com phishing de macro, fluxo que descrevemos do lado ofensivo em Initial Access Simulado: Macros, LNK e ISO em Lab Windows 11 Isolado e que o time azul precisa correlacionar com eventos 4688 do AD.

Mshta e regsvr32: scriptlets remotos

Para mshta e regsvr32 (T1218.010) a logica muda. Mshta executando URL quase sempre e malicioso fora de sistemas de ajuda: DeviceProcessEvents | where FileName =~ 'mshta.exe' | where ProcessCommandLine has_any ('http://','https://','.hta','javascript:','vbscript:') gera taxa de falso positivo abaixo de 2% na maioria das frotas. Regsvr32 com /i: e uma URL (a tecnica Squiblydoo) voce pega igual via ProcessCommandLine has_any ('/i:http','scrobj.dll'). Ambos se beneficiam muito da correlacao com a camada de rede, porque uma chamada localmente inofensiva vira alerta real por uma conexao de saida.

Correlacao multi-tabela com a rede

Combine o achado de processo com DeviceNetworkEvents na mesma janela de 60 segundos por um join em DeviceId e o ID do processo, para confirmar que a conexao veio de fato do processo suspeito: DeviceProcessEvents | where FileName =~ 'mshta.exe' | join kind=inner (DeviceNetworkEvents) on DeviceId, InitiatingProcessId | where NetworkTimestamp between (Timestamp .. Timestamp + 60s). Esse tipo de correlacao multi-tabela separa hunting de mero log mining e conecta com Lateral Movement em Lab: SMB, WMI e WinRM com Foco em Deteccao, onde atacantes encadeiam LOLBins via WMI remoto e a visao de rede fornece o contexto decisivo.

O trio: bitsadmin, msiexec e wmic

Bitsadmin, msiexec /i http e wmic remoto formam o trio que mais escapa das regras default. Para msiexec, nossa heuristica favorita usa ProcessVersionInfoOriginalFileName para detectar binarios renomeados, algo que ferramentas como Sliver fazem por padrao: where FileName =~ 'msiexec.exe' and ProcessVersionInfoOriginalFileName !~ 'msiexec.exe'. Veja a perspectiva do operador em Construindo Infra de C2 com Sliver em Lab Isolado para Estudo Defensivo. Pegue bitsadmin via ProcessCommandLine has_any ('/transfer','/create','/addfile'), e wmic via process call create e /node: para execucao remota.

PowerShell e comandos codificados como vizinhos

LOLBins raramente aparecem sozinhos; quase sempre ha uma etapa PowerShell logo ao lado. Cace comandos codificados com DeviceProcessEvents | where FileName in~ ('powershell.exe','pwsh.exe') | where ProcessCommandLine has_any ('-enc','-EncodedCommand','-e ','FromBase64String','IEX','Invoke-Expression','-w hidden','-nop'). A verdadeira mina de ouro, porem, e o module logging: habilite telemetria ScriptBlock (evento 4104) via DeviceEvents e procure ali o payload em claro que -enc esconde na linha de comando. Um rundll32 ou mshta cujo pai e um PowerShell codificado e um carregador de beacon quase certo e merece severidade alta imediata em vez de arquivamento silencioso.

Correlacionar o drop de payload via DeviceFileEvents

Um download de certutil sem o arquivo que ele escreve depois e so metade da historia. Junte a execucao com DeviceFileEvents para ver o payload de fato depositado: faca join em DeviceId e InitiatingProcessId e filtre eventos FileCreated frescos em %TEMP%, %APPDATA% ou C:\Users\Public. Enriqueca o hit com o SHA256 do arquivo e busque contra suas fontes de threat intel; um executavel sem assinatura recem-escrito por um LOLBin e um achado que justifica isolar o host. E exatamente essa cadeia de processo, rede e arquivo que transforma um indicador fraco numa historia solida para o relatorio de incidente.

Operacionalizar no Sentinel e Sigma

No Sentinel materializamos esses hunts como Analytics Rules com entity mapping em Account e Host, frequencia de 5 minutos e supressao de 1 hora por entidade, o que mantem o ruido gerenciavel. Cada regra recebe uma tag de tatica/tecnica MITRE para a cobertura ficar mensuravel. Sempre exportamos a logica para Sigma por portabilidade de SIEM, a mesma filosofia de Purple Team na Pratica: Construindo Ciclo de Feedback Red x Blue. Assim roda a mesma deteccao seja o cliente em Defender, Elastic ou Splunk, e o red team valida direto contra ataques emulados.

Domando falsos positivos e pegadinhas

O erro mais comum e querer eliminar os LOLBins; eles fazem parte do OS e sao usados legitimamente. SCCM chama msiexec de rotina, distribuicao de software usa bitsadmin, jobs de backup lancam certutil para hashing. Ajuste por processo pai e contexto, nunca por binario sozinho. Outra pegadinha: has versus contains no KQL; has e tokenizado e mais rapido mas nao casa substrings, o que deixa buracos em linhas de comando concatenadas. Meca a taxa de falso positivo de cada regra antes de armar e documente cada excecao com justificativa.

Checklist

Antes de subir qualquer regra de LOLBin: (1) baseline coletada por pelo menos 30 dias; (2) filtro em ProcessCommandLine, nao so FileName; (3) exclusoes de processo pai documentadas por departamento; (4) correlacao de rede onde fizer sentido; (5) binarios renomeados cobertos via OriginalFileName; (6) tag MITRE setada; (7) supressao por entidade configurada; (8) exportado para Sigma; (9) validado contra um ataque emulado; (10) taxa de falso positivo medida e abaixo do limiar.

FAQ

Basta bloquear os LOLBins via WDAC? Raramente, porque muitos sao criticos para o negocio; melhor bloquear as invocacoes perigosas (como certutil -urlcache) mais deteccao. Por que nao alertar todo download de certutil? Em ambientes grandes isso gera centenas de hits diarios de automacao legitima; so a combinacao de processo pai raro, URL externa e arquivo destino sem assinatura torna o alerta confiavel. Preciso de P1 para essas tabelas? DeviceProcessEvents e DeviceNetworkEvents pertencem ao Defender for Endpoint P2, e chegam ao Sentinel via data connector.

Como lidar com LOLBins de persistencia? schtasks.exe e sc.exe sao eles mesmos LOLBins quando criam tarefas ou servicos novos apontando para um script ou caminho incomum. Cace-os com DeviceProcessEvents | where FileName in~ ('schtasks.exe','sc.exe') | where ProcessCommandLine has_any ('/create','create','binPath=') | where ProcessCommandLine has_any ('powershell','cmd /c','\Users\','\Temp\','http'). E se o atacante renomear o binario? Por isso voce nunca filtra so por FileName; a combinacao de ProcessVersionInfoOriginalFileName, a assinatura da linha de comando e o processo pai sobrevive ao rename, enquanto um filtro so de nome fica cego.

Fechando com pratica imediata: rode isto no seu tenant hoje: DeviceProcessEvents | where Timestamp > ago(30d) | where FileName in~ ('rundll32.exe','mshta.exe','certutil.exe','regsvr32.exe','bitsadmin.exe','msiexec.exe') | summarize Total=count(), Hosts=dcount(DeviceName) by FileName, bin(Timestamp, 1d) | order by Timestamp desc. A saida e seu mapa de baseline. Tudo que quebrar esse padrao por 3 desvios padrao vira candidato a regra. Voce nao elimina um LOLBin, voce o observa com disciplina, e times que tratam a baseline como produto vivo detectam intrusoes em horas em vez de meses.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly