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.

TUI de Pi con el Qwen3.8-27B arrancando

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:

#PruebaQué demostró
1Inspección de la configDetectó doble ingesta (indexer + Universal Forwarder) y 3 desviaciones entre lo documentado y lo real
2Pipeline de datosDetectó 3 inputs muertos (perfmon/tasks/print) con forense de checkpoints
3Hardening del loggingMarker test en vivo de PowerShell 4104 + encontró un bug en mi propia nota
4Análisis de logs 24hCorrigió mi premisa (los EIDs de Sysmon), análisis completo y honesto
5Detección de IoCDetectó 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:

GUIDProductoAcción
{315DD779-…}UniversalForwarderDesinstalar
{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.

Diagrama: doble ingesta antes vs después

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.exe seguí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:

EventoEID real
ProcessAccess10
CreateRemoteThread8
FileCreateStreamHash15
PipeEvent17

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.

Sysmon64.exe -c mostrando ProcessAccess poblado

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: auditpol necesita el privilegio SeSecurityPrivilege. El error real era 0x522.
  • 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:enable

GUID entre comillas, en una shell elevada.

Tres trampas en una sola línea.

auditpol /get mostrando Creación del proceso

auditpol evento 4688 con CommandLine

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 (.../Operational en vez del clásico Windows 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:\Users que 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:

  1. Temperatura baja: --temp 0.3 en el llama-server (el default es 0.8). Menos creatividad, más determinismo.
  2. System prompt con reglas de trabajo, vía --append-system-prompt en 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:

AntesDespués
SalidaEnorme, divagabaConcisa y directa
Contexto usado97.4% (desbordó)49.7%
PremisasAsumíaVerificaba contra la realidad
Resultado1 hallazgo en 30 min4 hallazgos en cadena

Diagrama: determinismo antes vs después

0x09 - El balance

De 10 hallazgos:

HallazgoVeredicto
Doble ingestaresuelta (UF desinstalado)
Inputs muertostasks/print · perfmon (binario roto)
Sysmon → LSASSresuelto (ProcessAccess)
auditpol 4688resuelto (GUID + shell elevada)
Canal PS 400/403falso positivo
Regla T1099resuelto (exclusiones Electron)
Nota 07corregida
Fastly / %TEMP%benignos

Diagrama: pipeline auditoría → remediación

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.