
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 , . Diese Abschlüsse gelten pro Scope; der 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 .
../RCE_BLOCKERS.md../NEW_ROADS_TO_CODE_EXECUTION.mdPosition 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 wie beim L2-C-Pfad-GO (). Als Nächstes: NTLM-Probe im Labor (Post-20362) — übertrifft CIFS beim Fenster, wenn ein /-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.
list_functions zurückgegeben werden (verifiziert: corpus/02/02c6cc80.c = luaH_get = RVA 0x2c6cc80). Hinweis: Das GhidraMCP-HTTP-Plugin meldet Adressen im RVA-Stil, nicht die Ghidra-VA = RVA + 0x100000.../RCE_BLOCKERS.md / ../TODO.md, wenn ein „neuer“ Kandidat eine geschlossene Route überlappt.0x55.. vs. 0x7f.. vs. Heap) und ob sie die CIFS-readdir-Primitive (Schritt 19i) hinsichtlich Zuverlässigkeit übertrifft.create_type3_message0x7f..0x55..