
Ingénierie inverse systématique du binaire lina de Cisco ASA pour découvrir et analyser les vulnérabilités de corruption mémoire, notamment CVE-2025-20333 et CVE-2025-20362, avec un accent sur la recherche de primitives d'exécution de code à distance.
linaCréé : 2026-08-12
Cible : lab_asav9-12-4-67/lina (ASAv 9.12(4)67, ELF x86-64, PIE ; base d'image Ghidra 0x100000 ; 112 687 fonctions, ~167 Mo mappés, 642 707 symboles)
Objectif de la piste : couverture RE systématique et complète du binaire lina — en complément de la RE ciblée pilotée par hypothèses menée jusqu'ici — pour traquer la primitive que le labo n'a pas trouvée (une RCE root non authentiquée en conditions réelles sur 20362+20333 est prouvée, elle existe donc).
Toute la RE précédente était ciblée (décompilations sur PC de faute, parcours de références croisées ancrés sur des chaînes, balayages de plages de binding). Elle a clos tous les périmètres audités (H4-1/2/3/4, réflexion tostring(userdata), %p SSH/SNMP/IKE, familles de dépassements alternatives, oracle de survie) — voir , . Ces clôtures sont par périmètre ; le d'un binaire de 112k fonctions est exactement là où doit vivre la primitive manquante de l'APT. Cette piste remplace « deviner la prochaine surface » par la .
../RCE_BLOCKERS.md../NEW_ROADS_TO_CODE_EXECUTION.mdPosition par rapport au chemin critique : le verrou dur de la chaîne connue reste P0 (fuite d'informations distante en direct) ; la sur-lecture readdir CIFS (Étape 19i, fenêtre de 4 octets) est la seule fuite confirmée empiriquement et reste la piste empirique de premier plan. LINA_FULL_RE est la parade systématique : trouver une fuite/primitive meilleure dans le code non audité, ou prouver qu'aucune n'existe.
0x55.. (lina) ou 0x7f.. (libc/tas) : émetteurs de chaînes de format (%p/%lx/%x sur des pointeurs), sur-lectures (longueur non bornée par des données initialisées), réflexion de résidus de tas, échos de tampons non initialisés.memcpy/memmove/strcpy/strcat/sprintf/vsprintf/classe gets + boucles de copie personnalisées), sur toutes les surfaces de protocole (pas seulement les liaisons Lua WebVPN déjà épuisées — voir ../LINA_ALT_OVERFLOW_FAMILIES_RE.md).csco_config) afin que les hits de triage puissent être classés selon qu'ils sont réellement atteignables depuis le réseau.(Différé par l'utilisateur : chasse au sink CVE-2025-20363 — l'OSINT indique qu'il consomme une fuite, jumeau de 20333 ; voir ../CVE-2025-20363_OSINT.md.)
| Étape | Quoi | Outillage | Sortie |
|---|---|---|---|
| 1. Corpus | Décompiler par lots les 112 687 fonctions sur disque, un .c par fonction, partitionné par adresse | Ghidra run_script_inline (Java, DecompInterface), par blocs + reprenable | corpus/<shard>/<addr>.c |
| 2. Triage mécanique | ripgrep du corpus pour les motifs de sinks (classes de fuite + dépassement ci-dessous) | scripts locaux, triage/ | tables de hits (CSV/MD) |
| 3. Filtre d'atteignabilité | ne conserver que les hits dans des fonctions atteignables depuis les points d'entrée réseau | graphe d'appels Ghidra (get_function_call_graph/script) + liste de graines de points d'entrée | liste de hits classés |
| 4. Analyse approfondie | RE ciblée des hits classés (le modèle existant de sous-agent ghidra-re) | ghidra-mcp | documents de constatations dans ce dossier |
L'étape 1 est du pur calcul (estim. heures–jours, sans surveillance, reprenable). Les étapes 2–3 sont peu coûteuses/locales. L'étape 4 est la seule étape lourde en humain/LLM et elle est bornée par l'entonnoir.
Research notes/LINA_FULL_RE/
README.md — ce fichier (plan maître + statut)
TRIAGE.md — catalogue de motifs de sinks + plan d'atteignabilité (spéc. étapes 2/3)
scripts/ — scripts de décompilation + triage + pilotes
corpus/ — sortie de l'étape 1 : fonctions décompilées, partitionnées (corpus/2c/02c6cc80.c)
_progress.txt — marqueur de progression reprenable (nombre de faits, dernière adresse)
_errors.txt — échecs de décompilation par fonction
triage/ — sorties des étapes 2/3 (tables de hits, listes classées)
findings/ — comptes rendus d'analyse approfondie de l'étape 4 (un MD par candidat confirmé)
| Étape | Statut | Notes |
|---|---|---|
| 1. Corpus | FAIT 2026-08-12 (~19:03 UTC-4) | 111 997/111 997 fonctions, 0 erreur, 548 Mo dans corpus/ ; a pris 26 214 s (~7,3 h) à 4,3 fn/s via scripts/decompile_all.py (GhidraMCP batch_decompile, limite de 20 fn/appel) |
| 2. Triage | FAIT 2026-08-13 | scripts/triage_stage2.py ; tables de hits par classe dans triage/*_hits.csv ; jointure classée dans triage/RANKED.md |
| 3. Atteignabilité | FAIT 2026-08-13 (relancé, graines corrigées) | graphe d'appels+références du corpus (427 198 arêtes) ; 26 291/111 997 atteignables (23,5 %) — pré-auth 26 278 / admin 13 / post-20362 0. Graines corrigées : registrar 0317b4e0, session 0317c0a0 (les anciens 030ab4e0/030ac0a0 n'étaient pas des débuts de fonction). Toujours une borne inférieure (vtables). |
| 4. Analyse approfondie | EN COURS 2026-08-17 | L1 CLÔTURÉ. Chemin C L2 GO (statique) : WebVPN UCTE create_type3_message copie les TargetInfo de type 2 de l'attaquant sans aucun bornage ; la fuite remonte via le Authorization: NTLM de type 3 jusqu'au serveur HTTP de l'attaquant (findings/L2_NTLM_C_PATH_TYPE3.md). ntlm.parseType2 de Lua est le jumeau dormant. Passe protocole O1/O5 CLÔTURÉE (statique) : les copies IKE/SSH/SNMP/EWS/PDTS sont dimensionnées par rapport à la destination, côté émission, ou déjà connues (031af6d0 / 02ff2f30). O1 « autres » 725 CLÔTURÉ (statique) : filtre pile/global/param+const → aucun nouveau GO de dépassement de destination ; 015a8b30 est un helper de type d'adresse sans bornage dont les appelants ne passent que des tailles AF 4/0x10 (findings/O1_OTHER_SWEEP.md). O2 CLÔTURÉ (statique) : 605 boucles de copie atteignables ; aucun nouveau GO de dépassement de destination. = → le même que le chemin C L2 GO (). Ensuite : sonde NTLM du labo (post-20362) — bat CIFS au niveau de la fenêtre si un qword / apparaît. Statique optionnel : O3/O4. |
Reprise/contrôle : le pilote ignore les fonctions dont le fichier de sortie existe déjà — relancez python3 scripts/decompile_all.py à tout moment pour continuer. Arrêt propre : touch corpus/STOP. Si Ghidra ou le plugin MCP redémarre, relancez simplement le pilote.
Contraintes du plugin découvertes (2026-08-12) : run_script_inline est désactivé (GHIDRA_MCP_ALLOW_SCRIPTS non défini) → le corpus n'utilise que les points de terminaison HTTP par lots ; batch_decompile prend ?functions=0x..,0x..,.. comme paramètre de requête GET (pas un corps JSON) et tronque silencieusement les réponses à 20 fonctions → taille de bloc du pilote = 20.
list_functions (vérifié : corpus/02/02c6cc80.c = luaH_get = RVA 0x2c6cc80). Remarque : le plugin HTTP GhidraMCP rapporte des adresses de type RVA, pas la VA Ghidra = RVA + 0x100000.../RCE_BLOCKERS.md / ../TODO.md lorsqu'un candidat « nouveau » chevauche une route clôturée.0x55.. vs 0x7f.. vs tas), et si elle bat la primitive readdir CIFS (Étape 19i) en fiabilité.FUN_02fd7270ucte_ntlm_authenticate_connectioncreate_type3_message0x7f..0x55..