Saltar al contenido
Categoria: Forense8 min de lectura

Hunting de Living-off-the-Land Binaries en Windows con KQL

Por Lucas Andrade ·

Consultas KQL listas para Microsoft Defender y Sentinel para cazar abuso de LOLBins como rundll32, mshta y certutil en entornos reales.

Hunting de Living-off-the-Land Binaries en Windows con KQL

Un atacante competente no necesita dejar caer su propio binario en el disco de la victima: usa lo que ya esta ahi. Rundll32, mshta, certutil, bitsadmin y regsvr32 son herramientas legitimas firmadas por la propia Microsoft, lo que hace que muchos EDR traten sus ejecuciones como ruido. Esta tecnica se llama Living off the Land, los binarios mismos LOLBins, catalogados en el proyecto publico LOLBAS. El equipo Basilisk paso los ultimos seis meses analizando 47 incidentes y en 31 de ellos habia al menos un LOLBin en la kill chain. Este post entrega las consultas KQL que usamos en Microsoft Defender for Endpoint y Sentinel para convertir esas ejecuciones en detecciones accionables sin ahogar al SOC en falsos positivos.

Que son los LOLBins y por que se cuelan

Un LOLBin es un programa preinstalado y firmado que carga una funcion secundaria no prevista y util para el atacante: descarga, ejecucion de codigo, persistencia o evasion de application control. Como la firma viene de Microsoft, las allowlists ingenuas no disparan, y un nombre de proceso pelado como indicador no vale nada. La deteccion se desplaza asi de que binario hacia que linea de comando, que proceso padre, que comportamiento posterior. Por eso la linea de comando del proceso (ProcessCommandLine) es el campo mas importante de cualquier consulta de hunting, seguido de InitiatingProcessFileName y de las conexiones de red del mismo proceso.

Primero entender el baseline

Antes de escribir una regla hay que entender el baseline del entorno. Lanzamos un hunt amplio sobre DeviceProcessEvents agrupando por FileName y contando ejecuciones en 30 dias por host, identificando lo normal en esa flota. En un cliente con 8.200 endpoints, mshta.exe aparecia solo en 0,4% de las maquinas, todas de marketing corriendo un reporte legado. Esto significa que cualquier ejecucion de mshta fuera de ese grupo merece una alerta P2. Este enfoque de rareza estadistica es la base del hunting moderno y dialoga con Threat Hunting con Sigma y Elastic: Del Indicador a la Regla de Deteccion, donde mostramos el paso del indicador crudo a regla Sigma versionada en Git.

Rundll32 con linea de comando sospechosa

La consulta base que recomendamos para rundll32 es: 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. En pruebas contra la tecnica T1218.011 de MITRE ATT&CK detecto 9 de 10 ejecuciones del beacon de Cobalt Strike en modo SMB pivot. El ajuste fino llega excluyendo procesos padre legitimos por departamento, algo que documentamos en Adversary Emulation con Caldera y MITRE ATT&CK en Laboratorio Corporativo. Presta especial atencion a rundll32 sin argumento de DLL, senal fuerte de process hollowing.

Certutil: la navaja suiza

Certutil merece capitulo propio. Descarga archivos (-urlcache), decodifica base64 (-decode) y genera hashes. Nuestra consulta cazadora es: 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'). En 2025 vimos certutil usado como segunda etapa en campanas que arrancaron con phishing de macro, flujo que describimos del lado ofensivo en Initial Access Simulado: Macros, LNK e ISO en un Lab Windows 11 Aislado y que el equipo azul debe correlacionar con eventos 4688 del AD.

Mshta y regsvr32: scriptlets remotos

Para mshta y regsvr32 (T1218.010) la logica cambia. Mshta ejecutando URL casi siempre es malicioso fuera de sistemas de ayuda: DeviceProcessEvents | where FileName =~ 'mshta.exe' | where ProcessCommandLine has_any ('http://','https://','.hta','javascript:','vbscript:') genera una tasa de falsos positivos bajo 2% en la mayoria de las flotas. Regsvr32 con /i: y una URL (la tecnica Squiblydoo) lo cazas igual via ProcessCommandLine has_any ('/i:http','scrobj.dll'). Ambos se benefician enormemente de la correlacion con la capa de red, porque una llamada localmente inocua se vuelve alerta real por una conexion saliente.

Correlacion multi-tabla con la red

Combina el hallazgo de proceso con DeviceNetworkEvents en la misma ventana de 60 segundos mediante un join sobre DeviceId y el ID de proceso, para confirmar que la conexion vino realmente del proceso sospechoso: DeviceProcessEvents | where FileName =~ 'mshta.exe' | join kind=inner (DeviceNetworkEvents) on DeviceId, InitiatingProcessId | where NetworkTimestamp between (Timestamp .. Timestamp + 60s). Este tipo de correlacion multi-tabla separa el hunting del simple log mining y conecta con Movimiento Lateral en Lab: SMB, WMI y WinRM con Foco en Deteccion, donde los atacantes encadenan LOLBins via WMI remoto y la vista de red aporta el contexto decisivo.

El trio: bitsadmin, msiexec y wmic

Bitsadmin, msiexec /i http y wmic remoto son el trio que mas seguido evade las reglas default. Para msiexec, nuestra heuristica favorita usa ProcessVersionInfoOriginalFileName para detectar binarios renombrados, algo que herramientas como Sliver hacen por defecto: where FileName =~ 'msiexec.exe' and ProcessVersionInfoOriginalFileName !~ 'msiexec.exe'. Mira la perspectiva del operador en Construyendo Infra de C2 con Sliver en Lab Aislado para Estudio Defensivo. Caza bitsadmin via ProcessCommandLine has_any ('/transfer','/create','/addfile'), y wmic via process call create y /node: para ejecucion remota.

PowerShell y comandos codificados como vecinos

Los LOLBins rara vez aparecen solos; casi siempre hay una etapa PowerShell justo al lado. Caza comandos codificados con DeviceProcessEvents | where FileName in~ ('powershell.exe','pwsh.exe') | where ProcessCommandLine has_any ('-enc','-EncodedCommand','-e ','FromBase64String','IEX','Invoke-Expression','-w hidden','-nop'). La verdadera mina de oro, sin embargo, es el module logging: habilita telemetria ScriptBlock (evento 4104) via DeviceEvents y busca ahi el payload en claro que -enc esconde en la linea de comando. Un rundll32 o mshta cuyo padre es un PowerShell codificado es un cargador de beacon casi seguro y merece severidad alta inmediata en vez de un archivado silencioso.

Correlacionar el drop de payload via DeviceFileEvents

Una descarga de certutil sin el archivo que escribe despues es solo media historia. Une la ejecucion con DeviceFileEvents para ver el payload realmente depositado: haz join sobre DeviceId e InitiatingProcessId y filtra eventos FileCreated frescos en %TEMP%, %APPDATA% o C:\Users\Public. Enriquece el hit con el SHA256 del archivo y buscalo contra tus fuentes de threat intel; un ejecutable sin firma recien escrito por un LOLBin es un hallazgo que justifica aislar el host. Es exactamente esta cadena de proceso, red y archivo la que convierte un indicador debil en una historia solida para el informe de incidente.

Operacionalizar en Sentinel y Sigma

En Sentinel materializamos estos hunts como Analytics Rules con entity mapping en Account y Host, frecuencia de 5 minutos y supresion de 1 hora por entidad, lo que mantiene el ruido manejable. Cada regla lleva un tag de tactica/tecnica MITRE para que la cobertura sea medible. Siempre exportamos la logica a Sigma para portabilidad de SIEM, la misma filosofia de Purple Team en la Practica: Construyendo Ciclo de Feedback Red vs Blue. Asi corre la misma deteccion sin importar si el cliente usa Defender, Elastic o Splunk, y el red team la valida directamente contra ataques emulados.

Domar falsos positivos y trampas

El error mas comun es querer eliminar los LOLBins; son parte del OS y se usan legitimamente. SCCM llama msiexec de rutina, la distribucion de software usa bitsadmin, los jobs de backup lanzan certutil para hashing. Ajusta por proceso padre y contexto, nunca por binario solo. Otra trampa: has versus contains en KQL; has es tokenizado y mas rapido pero no matchea substrings, lo que deja huecos en lineas de comando concatenadas. Mide la tasa de falsos positivos de cada regla antes de armarla y documenta cada excepcion con justificacion.

Checklist

Antes de desplegar cualquier regla de LOLBin: (1) baseline recolectado sobre al menos 30 dias; (2) filtro sobre ProcessCommandLine, no solo FileName; (3) exclusiones de proceso padre documentadas por departamento; (4) correlacion de red donde tenga sentido; (5) binarios renombrados cubiertos via OriginalFileName; (6) tag MITRE puesto; (7) supresion por entidad configurada; (8) exportado a Sigma; (9) validado contra un ataque emulado; (10) tasa de falsos positivos medida y bajo umbral.

FAQ

Basta con bloquear los LOLBins via WDAC? Rara vez, porque muchos son criticos para el negocio; mejor bloquear las invocaciones peligrosas (como certutil -urlcache) mas deteccion. Por que no alertar cada descarga de certutil? En entornos grandes eso produce cientos de hits diarios de automatizacion legitima; solo la combinacion de un proceso padre raro, una URL externa y un archivo destino sin firma hace confiable la alerta. Necesito P1 para estas tablas? DeviceProcessEvents y DeviceNetworkEvents pertenecen a Defender for Endpoint P2, y llegan a Sentinel via el data connector.

Como manejo los LOLBins de persistencia? schtasks.exe y sc.exe son ellos mismos LOLBins cuando crean tareas o servicios nuevos que apuntan a un script o a una ruta inusual. Cazalos con 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'). Y si el atacante renombra el binario? Por eso nunca filtras solo por FileName; la combinacion de ProcessVersionInfoOriginalFileName, la firma de la linea de comando y el proceso padre sobrevive al rename, mientras que un filtro de solo nombre queda ciego.

Cerrando con practica inmediata: corre esto en tu tenant hoy: 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. La salida es tu mapa de baseline. Todo lo que rompa ese patron por 3 desviaciones estandar se vuelve candidato a regla. No eliminas un LOLBin, lo observas con disciplina, y los equipos que tratan el baseline como producto vivo detectan intrusiones en horas en vez de meses.

Related posts

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