
Systematisches Reverse Engineering des Cisco-ASA-lina-Binärs zur Entdeckung und Analyse von Speicherkorruptions-Schwachstellen, einschließlich CVE-2025-20333 und CVE-2025-20362, mit Fokus auf die Suche nach Primitive für die Remote-Codeausführung.
lina mit vollständiger AbdeckungErstellt: 2026-08-12
Ziel: lab_asav9-12-4-67/lina (ASAv 9.12(4)67, ELF x86-64, PIE; Ghidra-Image-Basis 0x100000; 112.687 Funktionen, ~167 MB gemappt, 642.707 Symbole)
Ziel des Tracks: systematische, vollständige RE-Abdeckung der lina-Binärdatei — als Ergänzung zur bisherigen hypothesengetriebenen, gezielten RE — um die Primitive zu jagen, die das Labor noch nicht gefunden hat (wilde, unauthentifizierte Root-RCE auf 20362+20333 ist bewiesen, sie existiert also).
Die gesamte bisherige RE war gezielt (Fault-PC-Dekompilierungen, Xref-Läufe über String-Anker, Binding-Range-Sweeps). Sie hat jeden geprüften Scope geschlossen (H4-1/2/3/4, tostring(userdata)-Reflektion, SSH/SNMP/IKE %p, alternative Overflow-Familien, Survival-Orakel) — siehe ../RCE_BLOCKERS.md, ../NEW_ROADS_TO_CODE_EXECUTION.md. Diese Abschlüsse gelten pro Scope; der nicht geprüfte Rest einer Binärdatei mit 112k Funktionen ist genau der Ort, an dem die fehlende Primitive der APT leben muss. Dieser Track ersetzt „nächste Oberfläche raten“ durch Abdeckung.
Position vs. kritischer Pfad: Das harte Gate der bekannten Kette bleibt P0 (Live-Remote-Infoleak); der CIFS-readdir-Overread (Schritt 19i, 4-Byte-Fenster) ist der einzige empirisch bestätigte Leak und bleibt der vordergründige empirische Track. LINA_FULL_RE ist die systematische Absicherung: einen besseren Leak/eine bessere Primitive im nicht geprüften Code finden — oder beweisen, dass es keine gibt.
0x55..-Qword (lina) oder ein 0x7f..-Qword (libc/Heap) emittieren kann: Format-String-Emitter (%p/%lx/%x auf Zeiger), Overreads (Länge nicht durch initialisierte Daten begrenzt), Reflektion von Heap-Resten, Echos uninitialisierter Puffer.memcpy/memmove/strcpy/strcat/sprintf/vsprintf/gets-Klasse + eigene Kopierschleifen), über alle Protokolloberflächen hinweg (nicht nur die bereits ausgeschöpften WebVPN-Lua-Bindungen — siehe ../LINA_ALT_OVERFLOW_FAMILIES_RE.md).csco_config), damit Triage-Treffer danach eingestuft werden können, ob sie tatsächlich vom Netz aus erreichbar sind.(Vom Nutzer zurückgestellt: Sink-Jagd zu CVE-2025-20363 — laut OSINT konsumiert sie einen Leak, Schwester von 20333; siehe ../CVE-2025-20363_OSINT.md.)
| Stufe | Was | Werkzeuge | Ausgabe |
|---|---|---|---|
| 1. Korpus | Batch-Dekompilierung aller 112.687 Funktionen auf die Platte, eine .c-Datei pro Funktion, nach Adresse shardiert | Ghidra run_script_inline (Java, DecompInterface), gechunkt + fortsetzbar | corpus/<shard>/<addr>.c |
| 2. Mechanische Triage | Korpus mit ripgrep nach Sink-Mustern durchsuchen (Leak- + Overflow-Klassen unten) | lokale Skripte, triage/ | Treffertabellen (CSV/MD) |
| 3. Erreichbarkeitsfilter | nur Treffer in Funktionen behalten, die von Netzwerk-Einstiegspunkten aus erreichbar sind | Ghidra-Call-Graph (get_function_call_graph/Skript) + Seed-Liste der Einstiegspunkte | nach Rang sortierte Trefferliste |
| 4. Deep-Dive | gezielte RE der sortierten Treffer (das bestehende ghidra-re-Subagent-Muster) | ghidra-mcp | Findings-Dokumente in diesem Ordner |
Stufe 1 ist reine Rechenarbeit (geschätzt Stunden bis Tage, unbeaufsichtigt, fortsetzbar). Stufen 2–3 sind günstig/lokal. Stufe 4 ist die einzige stark personen-/LLM-lastige Stufe und wird durch den Trichter begrenzt.
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)
| Stufe | Status | Anmerkungen |
|---|---|---|
| 1. Korpus | FERTIG 2026-08-12 (~19:03 UTC-4) | 111.997/111.997 Funktionen, 0 Fehler, 548 MB in corpus/; dauerte 26.214 s (~7,3 h) bei 4,3 fn/s über scripts/decompile_all.py (GhidraMCP batch_decompile, Limit: 20 fn/call) |
| 2. Triage | FERTIG 2026-08-13 | scripts/triage_stage2.py; Treffertabellen pro Klasse in triage/*_hits.csv; sortierter Join in triage/RANKED.md |
| 3. Erreichbarkeit | FERTIG 2026-08-13 (erneut ausgeführt, Seeds korrigiert) | Korpus-Call-+Ref-Graph (427.198 Kanten); 26.291/111.997 erreichbar (23,5 %) — Preauth 26.278 / Admin 13 / Post-20362 0. Seeds korrigiert: Registrar 0317b4e0, Session 0317c0a0 (die alten 030ab4e0/030ac0a0 waren keine Funktionsanfänge). Immer noch eine untere Schranke (vtables). |
| 4. Deep-Dive | IN BEARBEITUNG 2026-08-17 | L1 GESCHLOSSEN. L2 C-Pfad GO (statisch): WebVPN-UCTE create_type3_message kopiert die Typ-2-TargetInfo des Angreifers ohne Clamp; der Leak reist über Typ-3 Authorization: NTLM zurück zum HTTP-Server des Angreifers (findings/L2_NTLM_C_PATH_TYPE3.md). Lua ntlm.parseType2 ist der schlafende Zwilling. O1/O5-Protokolldurchlauf GESCHLOSSEN (statisch): IKE/SSH/SNMP/EWS/PDTS-Kopien sind auf Zielgröße begrenzt, sendeseitig oder bereits bekannt (031af6d0 / 02ff2f30). O1 „andere“ 725 GESCHLOSSEN (statisch): Stack/Global/param+const-Filter → kein neues Dest-Overflow-GO; 015a8b30 ist ein Addrtype-Helfer ohne Clamp, dessen Aufrufer nur AF-Größe 4/0x10 übergeben (findings/O1_OTHER_SWEEP.md). O2 GESCHLOSSEN (statisch): 605 erreichbare Kopierschleifen; kein neues Dest-Overflow-GO. FUN_02fd7270 = ucte_ntlm_authenticate_connection → dieselbe create_type3_message wie beim L2-C-Pfad-GO (findings/O2_SWEEP.md). Als Nächstes: NTLM-Probe im Labor (Post-20362) — übertrifft CIFS beim Fenster, wenn ein 0x7f../0x55..-Qword auftaucht. Optional statisch: O3/O4. |
Fortsetzen/Steuerung: Der Treiber überspringt Funktionen, deren Ausgabedatei bereits existiert — python3 scripts/decompile_all.py kann jederzeit erneut ausgeführt werden, um fortzufahren. Sauberer Stopp: touch corpus/STOP. Falls Ghidra oder das MCP-Plugin neu startet, einfach den Treiber erneut ausführen.
Festgestellte Plugin-Einschränkungen (2026-08-12): run_script_inline ist deaktiviert (GHIDRA_MCP_ALLOW_SCRIPTS nicht gesetzt) → das Korpus nutzt nur die HTTP-Batch-Endpunkte; batch_decompile akzeptiert ?functions=0x..,0x..,.. als GET-Query-Parameter (nicht als JSON-Body) und kürzt Antworten stillschweigend auf 20 Funktionen → Chunk-Größe des Treibers = 20.