
Ingeniería inversa sistemática del binario lina de Cisco ASA para descubrir y analizar vulnerabilidades de corrupción de memoria, incluyendo CVE-2025-20333 y CVE-2025-20362, con un enfoque en encontrar primitivas de ejecución remota de código.
linaCreado: 2026-08-12
Objetivo: lab_asav9-12-4-67/lina (ASAv 9.12(4)67, ELF x86-64, PIE; base de imagen Ghidra 0x100000; 112,687 funciones, ~167 MB mapeados, 642,707 símbolos)
Meta de la vía: cobertura RE sistemática y completa del binario lina — complementaria a la RE dirigida por hipótesis realizada hasta ahora — para cazar la primitiva que el laboratorio no ha encontrado (el RCE root no autenticado salvaje en 20362+20333 está demostrado, por lo que existe).
Toda la RE anterior fue dirigida (descompilaciones en el PC de fallo, recorridos de xref anclados a strings, barridos de rangos de binding). Cerró todos los ámbitos auditados (H4-1/2/3/4, reflexión de tostring(userdata), %p en SSH/SNMP/IKE, familias alternativas de desbordamiento, oráculo de supervivencia) — ver ../RCE_BLOCKERS.md, ../NEW_ROADS_TO_CODE_EXECUTION.md. Esos cierres son por ámbito; el resto no auditado de un binario de 112k funciones es exactamente donde debe residir la primitiva que le falta al APT. Esta vía sustituye "adivinar la siguiente superficie" por cobertura.
Posición vs ruta crítica: el obstáculo duro de la cadena conocida sigue siendo P0 (fuga de información remota en vivo); la sobrelectura de readdir CIFS (paso 19i, ventana de 4 bytes) es la única fuga confirmada empíricamente y sigue siendo la vía empírica en primer plano. LINA_FULL_RE es la cobertura sistemática: encontrar una fuga/primitiva mejor en código no auditado, o demostrar que no existe ninguna.
0x55.. (lina) o 0x7f.. (libc/heap): emisores de format string (%p/%lx/%x sobre punteros), sobrelecturas (longitud no acotada por datos inicializados), reflejo de residuos del heap, ecos de buffers sin inicializar.memcpy/memmove/strcpy/strcat/sprintf/vsprintf/clase gets + bucles de copia personalizados), en todas las superficies de protocolo (no solo los bindings Lua de WebVPN ya agotados — ver ../LINA_ALT_OVERFLOW_FAMILIES_RE.md).csco_config) para que los hits del triaje puedan clasificarse por realmente alcanzables desde la red.(Diferido por el usuario: caza del sink CVE-2025-20363 — la OSINT dice que consume una fuga, hermano de 20333; ver ../CVE-2025-20363_OSINT.md.)
| Etapa | Qué | Herramientas | Salida |
|---|---|---|---|
| 1. Corpus | Descompilación en lote de las 112,687 funciones a disco, un .c por función, fragmentado por dirección | Ghidra run_script_inline (Java, DecompInterface), por lotes + reanudable | corpus/<shard>/<addr>.c |
| 2. Triaje mecánico | Aplicar ripgrep al corpus en busca de patrones de sumidero (clases de fuga y desbordamiento abajo) | scripts locales, triage/ | tablas de hits (CSV/MD) |
| 3. Filtro de alcanzabilidad | conservar los hits en funciones alcanzables desde los puntos de entrada de red | grafo de llamadas de Ghidra (get_function_call_graph/script) + lista de semillas de puntos de entrada | lista de hits clasificada |
| 4. Inmersión profunda | RE dirigida de los hits clasificados (el patrón existente del subagente ghidra-re) | ghidra-mcp | documentos de hallazgos en esta carpeta |
La etapa 1 es puro cómputo (est. horas–días, sin supervisión, reanudable). Las etapas 2–3 son baratas/locales. La etapa 4 es la única con carga intensiva de humano/LLM y está acotada por el embudo.
Research notes/LINA_FULL_RE/
README.md — this file (master plan + status)
TRIAGE.md — sink-pattern catalog + reachability plan (stage 2/3 spec)
scripts/ — decompile + triage + driver scripts
corpus/ — stage-1 output: decompiled functions, sharded (corpus/2c/02c6cc80.c)
_progress.txt — resumable progress marker (done count, last address)
_errors.txt — per-function decompile failures
triage/ — stage-2/3 outputs (hit tables, ranked lists)
findings/ — stage-4 deep-dive writeups (one MD per confirmed candidate)
| Etapa | Estado | Notas |
|---|---|---|
| 1. Corpus | COMPLETADO 2026-08-12 (~19:03 UTC-4) | 111,997/111,997 funciones, 0 errores, 548 MB en corpus/; tomó 26,214 s (~7.3 h) a 4.3 fn/s mediante scripts/decompile_all.py (GhidraMCP batch_decompile, límite de 20 fn/llamada) |
| 2. Triaje | COMPLETADO 2026-08-13 | scripts/triage_stage2.py; tablas de hits por clase en triage/*_hits.csv; unión clasificada en triage/RANKED.md |
| 3. Alcanzabilidad | COMPLETADO 2026-08-13 (re-ejecutado, semillas corregidas) | grafo call+ref del corpus (427,198 aristas); 26,291/111,997 alcanzables (23.5%) — preauth 26,278 / admin 13 / post20362 0. Semillas corregidas: registrar 0317b4e0, session 0317c0a0 (los antiguos 030ab4e0/030ac0a0 no eran inicios de función). Sigue siendo una cota inferior (vtables). |
| 4. Inmersión profunda | EN CURSO 2026-08-17 | L1 CERRADO. L2 C-path GO (estático): WebVPN UCTE create_type3_message copia el TargetInfo Tipo-2 del atacante sin acotar; la fuga viaja de vuelta al servidor HTTP del atacante en el Authorization: NTLM Tipo-3 (findings/L2_NTLM_C_PATH_TYPE3.md). Lua ntlm.parseType2 es el gemelo latente. Pasada de protocolo O1/O5 CERRADA (estático): las copias de IKE/SSH/SNMP/EWS/PDTS están acotadas al tamaño del destino, son del lado de envío o ya conocidas (031af6d0 / 02ff2f30). O1 “other” 725 CERRADO (estático): filtro stack/global/param+const → sin nuevo GO de desbordamiento de destino; 015a8b30 es un helper de addrtype sin acotar al que sus llamadores solo pasan tamaño AF 4/0x10 (findings/O1_OTHER_SWEEP.md). O2 CERRADO (estático): 605 bucles de copia alcanzables; sin nuevo GO de desbordamiento de destino. FUN_02fd7270 = ucte_ntlm_authenticate_connection → mismo create_type3_message que el C-path GO de L2 (findings/O2_SWEEP.md). Siguiente: sonda NTLM de laboratorio (post-20362) — supera a CIFS en ventana si aparece un qword 0x7f../0x55... Estático opcional: O3/O4. |
Reanudación/control: el driver omite las funciones cuyo archivo de salida ya existe — vuelva a ejecutar python3 scripts/decompile_all.py en cualquier momento para continuar. Detención ordenada: touch corpus/STOP. Si Ghidra o el plugin MCP se reinician, basta con volver a ejecutar el driver.
Restricciones del plugin descubiertas (2026-08-12): run_script_inline está deshabilitado (GHIDRA_MCP_ALLOW_SCRIPTS sin definir) → el corpus usa solo los endpoints HTTP por lotes; batch_decompile toma ?functions=0x..,0x..,.. como parámetro de consulta GET (no como cuerpo JSON) y trunca silenciosamente las respuestas a 20 funciones → tamaño de lote del driver = 20.