
Reverse engineering sistematico del binario lina di Cisco ASA per scoprire e analizzare vulnerabilità di corruzione della memoria, incluse CVE-2025-20333 e CVE-2025-20362, con particolare attenzione all'individuazione di primitive di esecuzione remota di codice.
linaCreato: 2026-08-12
Target: lab_asav9-12-4-67/lina (ASAv 9.12(4)67, ELF x86-64, PIE; base immagine Ghidra 0x100000; 112.687 funzioni, ~167 MB mappati, 642.707 simboli)
Obiettivo del track: copertura RE sistematica e completa del binario lina — complementare alla RE mirata e guidata da ipotesi fatta finora — per cacciare la primitiva che il laboratorio non ha trovato (RCE root non autenticata selvaggia su 20362+20333 è provata, quindi esiste).
Tutta la RE precedente era mirata (decompilazioni fault-PC, cammini xref ancorati a stringhe, sweep sui binding-range). Ha chiuso ogni scope verificato (H4-1/2/3/4, riflessione tostring(userdata), %p SSH/SNMP/IKE, famiglie di overflow alternative, oracolo di sopravvivenza) — vedi , . Quelle chiusure sono per-scope; il di un binario da 112k funzioni è esattamente dove deve vivere la primitiva mancante dell'APT. Questo track sostituisce "indovina la prossima superficie" con .
../RCE_BLOCKERS.md../NEW_ROADS_TO_CODE_EXECUTION.mdPosizione vs percorso critico: il gate duro della catena nota rimane P0 (infoleak remoto live); l'over-read CIFS readdir (Step 19i, finestra di 4 byte) è l'unica leak confermata empiricamente e resta il track empirico in primo piano. LINA_FULL_RE è la copertura sistematica: trovare una leak/primitiva migliore nel codice non verificato, o dimostrare che non esiste.
0x55.. (lina) o 0x7f.. (libc/heap): emettitori format-string (%p/%lx/%x su puntatori), over-read (lunghezza non limitata da dati inizializzati), riflessione di residui heap, echo di buffer non inizializzati.memcpy/memmove/strcpy/strcat/sprintf/vsprintf/gets + loop di copia custom), su tutte le superfici di protocollo (non solo i binding Lua WebVPN già esauriti — vedi ../LINA_ALT_OVERFLOW_FAMILIES_RE.md).csco_config) così gli hit del triage possono essere classificati in base a effettivamente raggiungibili dal wire.(Differito dall'utente: caccia al sink CVE-2025-20363 — l'OSINT dice che consuma una leak, gemello di 20333; vedi ../CVE-2025-20363_OSINT.md.)
| Fase | Cosa | Strumenti | Output |
|---|---|---|---|
| 1. Corpus | Decompilazione batch di tutte le 112.687 funzioni su disco, un .c per funzione, shardate per indirizzo | Ghidra run_script_inline (Java, DecompInterface), a chunk e riprendibile | corpus/<shard>/<addr>.c |
| 2. Triage meccanico | ripgrep del corpus per i pattern di sink (classi di leak + overflow sotto) | script locali, triage/ | tabelle degli hit (CSV/MD) |
| 3. Filtro di raggiungibilità | tenere gli hit in funzioni raggiungibili dai punti di ingresso di rete | call-graph Ghidra (get_function_call_graph/script) + lista seed dei punti di ingresso | lista hit classificata |
| 4. Deep-dive | RE mirata degli hit classificati (il pattern esistente del subagent ghidra-re) | ghidra-mcp | documenti di findings in questa cartella |
La fase 1 è puro compute (stimato ore–giorni, non presidiata, riprendibile). Le fasi 2–3 sono economiche/locali. La fase 4 è l'unica fase ad alto impiego di umano/LLM ed è delimitata dall'imbuto.
Research notes/LINA_FULL_RE/
README.md — questo file (piano master + stato)
TRIAGE.md — catalogo dei pattern di sink + piano di raggiungibilità (spec fasi 2/3)
scripts/ — script di decompilazione + triage + driver
corpus/ — output fase 1: funzioni decompilate, shardate (corpus/2c/02c6cc80.c)
_progress.txt — marcatore di avanzamento riprendibile (conteggio completato, ultimo indirizzo)
_errors.txt — fallimenti di decompilazione per funzione
triage/ — output fasi 2/3 (tabelle hit, liste classificate)
findings/ — writeup di deep-dive fase 4 (un MD per candidato confermato)
| Fase | Stato | Note |
|---|---|---|
| 1. Corpus | COMPLETATO 2026-08-12 (~19:03 UTC-4) | 111.997/111.997 funzioni, 0 errori, 548 MB in corpus/; ha richiesto 26.214 s (~7,3 h) a 4,3 fn/s via scripts/decompile_all.py (GhidraMCP batch_decompile, cap 20 fn/chiamata) |
| 2. Triage | COMPLETATO 2026-08-13 | scripts/triage_stage2.py; tabelle hit per classe in triage/*_hits.csv; join classificato in triage/RANKED.md |
| 3. Raggiungibilità | COMPLETATO 2026-08-13 (rieseguito, seed corretti) | grafo call+ref del corpus (427.198 archi); 26.291/111.997 raggiungibili (23,5%) — preauth 26.278 / admin 13 / post20362 0. Seed corretti: registrar 0317b4e0, session 0317c0a0 (i vecchi 030ab4e0/030ac0a0 non erano start di funzione). Ancora un limite inferiore (vtable). |
| 4. Deep-dive | IN CORSO 2026-08-17 | L1 CHIUSO. L2 C-path GO (statico): WebVPN UCTE create_type3_message copia il TargetInfo Type-2 dell'attaccante senza clamp; la leak viaggia sul Type-3 Authorization: NTLM di ritorno al server HTTP dell'attaccante (findings/L2_NTLM_C_PATH_TYPE3.md). Lua ntlm.parseType2 è il gemello dormiente. Pass protocolli O1/O5 CHIUSO (statico): le copie IKE/SSH/SNMP/EWS/PDTS sono dimensionate sulla destinazione, lato send, o già note (031af6d0 / 02ff2f30). O1 "other" 725 CHIUSO (statico): filtro stack/global/param+const → nessun nuovo dest-overflow GO; 015a8b30 è un helper addrtype senza clamp i cui chiamanti passano solo AF size 4/0x10 (findings/O1_OTHER_SWEEP.md). O2 CHIUSO (statico): 605 copy-loop raggiungibili; nessun nuovo dest-overflow GO. FUN_02fd7270 = ucte_ntlm_authenticate_connection → stessa del C-path GO L2 (). Prossimo: sonda NTLM in laboratorio (post-20362) — batte CIFS sulla finestra se appare una qword /. Statico opzionale: O3/O4. |
Ripresa/controllo: il driver salta le funzioni il cui file di output esiste già — riesegui python3 scripts/decompile_all.py in qualsiasi momento per continuare. Stop pulito: touch corpus/STOP. Se Ghidra o il plugin MCP si riavviano, basta rieseguire il driver.
Vincoli del plugin scoperti (2026-08-12): run_script_inline è disabilitato (GHIDRA_MCP_ALLOW_SCRIPTS non impostato) → il corpus usa solo gli endpoint HTTP batch; batch_decompile accetta ?functions=0x..,0x..,.. come parametro query GET (non body JSON) e tronca silenziosamente le risposte a 20 funzioni → dimensione chunk del driver = 20.
list_functions (verificato: corpus/02/02c6cc80.c = luaH_get = RVA 0x2c6cc80). Nota: il plugin HTTP GhidraMCP riporta indirizzi in stile RVA, non VA Ghidra = RVA + 0x100000.../RCE_BLOCKERS.md / ../TODO.md quando un candidato "nuovo" si sovrappone a una rotta chiusa.0x55.. vs 0x7f.. vs heap) e se batte la primitiva CIFS readdir (Step 19i) in affidabilità.create_type3_message0x7f..0x55..