CONTEXTO PERSONAL Soy analista de seguridad sin experiencia laboral previa en un SOC, estudiando para el CySA+.
Este post es 100% real y local: una instancia de Splunk en mi propio Windows, Sysmon como telemetría de endpoint con un Qwen3.8-27B corriendo en mi GPU (RTX 5060 Ti 16GB) actuando de analista.
No hay datos de terceros ni infraestructura ajena. Todo lo que cuento lo ejecuté yo, lo verificó el modelo y lo confirmé con evidencia real.
La pregunta no era ¿Puede un LLM local hacer de analista SOC?.
La pregunta es ¿Puede un LLM local de 27B, sin mandar ni un byte a la nube, auditar mi Splunk y luego arreglar lo que él mismo ha encontrado roto?
La respuesta, después de una tarde entera de iterar, fue un sí con matices que valen un post completo.
0x00 - De dónde salió todo
Estudiando para el CySA+ me di cuenta de que podía leer mil libros, pero nada se compara a montar un SOC real en casa y tener a un mentor que no duerme.
En posts anteriores ya monté el stack: Splunk (licencia dev), Sysmon como telemetría, Obsidian como cerebro, y un Qwen 35B como mentor para el análisis de logs.
Pero esta vez quería algo más ambicioso, no un mentor que me explica, sino un agente que actúa por ejemplo haciendo:
- Audite mi instalación real de Splunk y Sysmon
- Detecte lo que está mal (que lo hay, siempre lo hay)
- Remedie los hallazgos editando configs, proponiendo comandos, desinstalando lo redundante etc…
Para eso necesitaba un modelo con contexto largo y una forma de darle herramientas.
Elegí el Qwen3.8-27B que es reciente (híbrido Gated DeltaNet, cuantizado IQ2_M, 128K de contexto) corriendo en llama-server en el puerto 8086, orquestado por Pi Agent.
0x01 - Las 5 pruebas de auditoría
No iba a confiarle mi Splunk a un modelo sin haberlo puesto a prueba.
Le preparé 5 auditorías reales contra mi propia instancia:
| # | Prueba | Qué demostró |
|---|---|---|
| 1 | Inspección de la config | Detectó doble ingesta (indexer + Universal Forwarder) y 3 desviaciones entre lo documentado y lo real |
| 2 | Pipeline de datos | Detectó 3 inputs muertos (perfmon/tasks/print) con forense de checkpoints |
| 3 | Hardening del logging | Marker test en vivo de PowerShell 4104 + encontró un bug en mi propia nota |
| 4 | Análisis de logs 24h | Corrigió mi premisa (los EIDs de Sysmon), análisis completo y honesto |
| 5 | Detección de IoC | Detectó que sus propias queries contaminaban el log (lo aisló con regex) |
El veredicto tras las cinco fue claro: razona a nivel de analista senior.
Corrigió mis premisas tres veces, depuró una docena de bugs por su cuenta y fue honesto cuando no podía confirmar algo.
Pero había un “pero” enorme…
0x02 - El desbordamiento
En una auditoría, la exhaustividad es oro.
En una remediación, es veneno.
Cuando le pasé el primer hallazgo para arreglar, el modelo se puso a hacer forense a saco sin descanso, probó typeperf para verificar los contadores, leyó el spec de Splunk, intentó reproducir el fallo ejecutando el binario directamente… y se quedó sin contexto.
↑92k ↓71k R4.2M CH98.4% 97.4%/131k (auto)
Llegó al 97.4% de los 128K tokens persiguiendo el sourcename de un log de Windows Update que era irrelevante para el fix.
Fue su primera auto-compactación.
El LLM sabía la respuesta, pero no sabía parar.
Le puse la regla “detente en cuanto tengas la causa raíz con evidencia” en el system prompt del modelo.
0x03 - La doble ingesta
El hallazgo más importante era que estaba duplicando datos por tanto el indexer ya recogía todos los logs localmente, pero además tenía un Universal Forwarder instalado en la misma máquina reenviándoselos otra vez.
Doble gasto de licencia, el doble de ruido.
El modelo lo diagnosticó con precisión.
Y aquí hizo algo que me salvó de un desastre, identificó dos GUIDs en el registro MSI y me advirtió explícitamente:
| GUID | Producto | Acción |
|---|---|---|
{315DD779-…} | UniversalForwarder | Desinstalar |
{BA7E981D-…} | Splunk Enterprise (el indexer) | NO TOCAR |
Un modelo menos cuidadoso habría dado un msiexec /x genérico y me habría hecho borrar el indexer con todos mis datos. Él lo marcó excluido.
No es que depende 100% de su criterio pero la configuración de un Splunk es compleja, realmente cuando llegas a un sitio ya está “todo montado”.
La desinstalación fue una mini-aventura porque el msiexec /x ... /qn directo devolvía un -1 fantasma (msiexec es asíncrono y PowerShell no captura bien su exit code) y no puedes estar todo el tiempo probando si sincronizas.
La solución fue Start-Process msiexec -Wait -PassThru, que devolvió ExitCode: 0 y limpió servicio + directorio + registro.
0x04 - Contadores en inglés en un Windows español
Tres inputs de Splunk llevaban muertos desde la instalación: win_perfmon, win_tasks y win_print.
Cero datos desde el 25 de julio.
El modelo destapó tres causas raíz distintas:
- win_tasks / win_print: los canales de eventos de Windows (
.../Operational) estaban deshabilitados (sin.evtx). Fix:wevtutil sl "..." /e:true. - win_perfmon: doble bug. Faltaba el parámetro
object(que el spec de Splunk marca como requerido) y los contadores estaban en inglés (% Processor Time) en un Windows en español.
Lo más impresionante: lo demostró con typeperf.
En un sistema español, el contador no se llama \Processor(_Total)\% Processor Time... se llama \Procesador(_Total)\% de tiempo de procesador.
Hasta el objeto está localizado.
La solución: useEnglishOnly = 1, que fuerza a Splunk a usar la API en inglés.
El fix de config era correcto, pero el binario
splunk-perfmon.exeseguía muriendo al muestrear (exit=1 silencioso).Lo dejó documentado como “requiere debugging de binario” en vez de inventar que estaba arreglado.
0x05 - Sysmon y la ceguera ante LSASS
El hallazgo de seguridad más grave mi Sysmon no detectaba acceso a LSASS.
Un Mimikatz podría volcar credenciales y yo no me enteraría hasta que lanzase Mimikatz desde un Kali como hice en mi TFG.
El modelo propuso habilitar ProcessAccess con un filtro a lsass.exe.
Correcto en esencia, pero aquí descubrí que arrastraba un error de numeración de EID (y yo también, propagándolo en mis prompts) decía “EID 8 = ProcessAccess” y “EID 17 = FileCreateStreamEvent”, cuando en Sysmon v15:
| Evento | EID real |
|---|---|
| ProcessAccess | 10 |
| CreateRemoteThread | 8 |
| FileCreateStreamHash | 15 |
| PipeEvent | 17 |
Y “FileCreateStreamEvent” ni siquiera existe.
Aquí se aprende que hay que contrastar los números técnicos contra la realidad.
Aquí la realidad era el XML real de la config (la de SwiftOnSecurity, que trae el bloque ProcessAccess vacío a propósito).
El fix final fue poblar ese bloque:
<ProcessAccess onmatch="include">
<TargetImage condition="is">C:\Windows\System32\lsass.exe</TargetImage>
</ProcessAccess>Y aquí pasó algo que merece un post por sí solo… el LLM se puso a regenerar el XML entero de 123KB a mano para añadir dos líneas.
Tardó 30 minutos.
Lo corté y lo resolví con un -replace de una línea + verificación del hash.
Las operaciones mecánicas son para scripts, no para el LLM.
0x06 - auditpol
Quería habilitar auditpol para el evento 4688 (creación de procesos con línea de comandos).
Un comando aparentemente trivial que escondía tres capas de error:
- Elevación:
auditpolnecesita el privilegioSeSecurityPrivilege. El error real era0x522. - Localización: el nombre
"Process Creation"no resolvía — en Windows español la subcategoría se llama “Creación del proceso”. Solución: usar el GUID. - Sintaxis de PowerShell: el GUID
{0CCE922B-…}sin comillas falla, porque en PowerShell las llaves{}son bloques de script.
El comando que funcionó:
auditpol /set /subcategory:"{0CCE922B-69AE-11D9-BED3-505054503030}" /success:enable /failure:enableGUID entre comillas, en una shell elevada.
Tres trampas en una sola línea.
0x07 - Los falsos positivos
Lo mejor de toda la jornada llegó al final, con dos hallazgos que resultaron ser falsos positivos y fue el propio modelo quien lo destapó, corrigiendo errores de auditorías anteriores:
- Canal PowerShell 400/403: la auditoría previa decía que estaba “deshabilitado” pero el modelo verificó y estaba habilitado y registrando (526 eventos). El error original fue mirar el canal equivocado (
.../Operationalen vez del clásicoWindows PowerShell). - Regla T1099: el modelo determinó que la etiqueta “inyección de procesos” no venía de ProcessAccess, sino de FileCreateTime (EID 2) con una regla demasiado amplia que marcaba a cualquier proceso bajo
C:\Usersque tocara un.tmp. VS Code, Obsidian y Hermes (Agente de LLM) eran falsos positivos. Fix: exclusiones específicas de Electron.
Un analista senior LLM que corrige sus propias premisas con evidencia es exactamente lo que se busca, al menos en la etapa de dejar a punto Splunk para futuros labs.
De paso detectó que sus propias invocaciones de PowerShell ya estaban generando los eventos 400 que “faltaban” la prueba viva de que el canal funcionaba y que el LLM es una máquina en ciberseguridad y yo me siento sinceramente abrumado.
0x08 - El determinismo
Tras ver al modelo desbordar el contexto, decidí atacar el problema de raíz haciendo pequeños cambios en el server de llamacpp:
- Temperatura baja:
--temp 0.3en elllama-server(el default es 0.8). Menos creatividad, más determinismo. - System prompt con reglas de trabajo, vía
--append-system-prompten el arranque de Pi, como he comentado antes.
Eres un agente técnico de ciber-seguridad en Windows. Trabaja DIRECTO y DETERMINISTA.
(1) Responde solo a lo pedido, sin divagar.
(2) En REMEDIACIÓN detente al tener la causa raíz CON EVIDENCIA y propón el fix.
(3) En AUDITORÍA sé exhaustivo.
(4) Para operaciones mecánicas usa un script, no regeneres contenido a mano.
(5) Verifica números técnicos (EIDs, puertos, GUIDs) antes de afirmarlos.
(6) Usa evidencia real, nunca inventes.
(7) Sé conciso.
Resultados:
| Antes | Después | |
|---|---|---|
| Salida | Enorme, divagaba | Concisa y directa |
| Contexto usado | 97.4% (desbordó) | 49.7% |
| Premisas | Asumía | Verificaba contra la realidad |
| Resultado | 1 hallazgo en 30 min | 4 hallazgos en cadena |
0x09 - El balance
De 10 hallazgos:
| Hallazgo | Veredicto |
|---|---|
| Doble ingesta | resuelta (UF desinstalado) |
| Inputs muertos | tasks/print · perfmon (binario roto) |
| Sysmon → LSASS | resuelto (ProcessAccess) |
| auditpol 4688 | resuelto (GUID + shell elevada) |
| Canal PS 400/403 | falso positivo |
| Regla T1099 | resuelto (exclusiones Electron) |
| Nota 07 | corregida |
| Fastly / %TEMP% | benignos |
Lecciones
- Un 27B local ya es un analista SOC competente lo peor el cuello de botella es del contexto (128K) pero no la inteligencia.
- La exhaustividad es oro en auditoría pero veneno en remediación hay que decirle que debe parar.
- El modelo (y yo) arrastramos errores de EID por tanto hay que verificar contra la realidad y eso fue lo que los destapó.
- Insertar 2 líneas en un XML de 123KB no justifica 30 minutos de razonamiento, lo sé… fue perezoso.
- Los errores “simples” esconden capas → Elevación + localización + sintaxis = tres trampas en un
auditpol. - El determinismo se configura si es necesario y aquí el System prompt + temperatura baja = un agente que va al grano.
La IA no sustituye tu criterio y tratar de entender qué pasa, pero sin duda es un gran avance si sabes qué ocurre y no dejas que todo lo haga un agente.
Con un LLM local bien configurado y con tu sistema auditándolo, es brutal para un analista que está empezando, es mi mentor y mi compañero aquí solo en casa.
Y todo sin que un solo log salga de tu máquina 100% privacidad.
El SOC de casa no es un sueño.