Pipeline deterministico di estrazione, triage e backend del compilatore LLM locale basato su PyGhidra per la reimplementazione in C.
Grazie per aver scaricato la mia pipeline Ghidra + LLM.
Questo è il mio primo README. La ASL (American Sign Language) è la mia prima lingua, quindi il mio inglese non è perfetto. Ho fatto del mio meglio.
Amo una vecchia simulazione per PC a cui gioco fin da bambino, e voglio migliorarla sotto il cofano.
Guardare giochi open-source come OpenRA e OpenTTD mi ha insegnato questo: una reimplementazione amatoriale non consiste nell'ottenere il codice sorgente originale. Consiste nel costruire una nuova versione open-source del gioco che possa caricare le risorse dell'originale. Così chiunque può ampliarla o contribuire.
Per fare il lavoro uso due tipi di IA insieme:
Ogni funzione riceve un'etichetta. Questo fa risparmiare molto tempo, perché non spreco sforzi sul grande insieme di scorie del sistema operativo e del runtime.
|-----------|------------------------------------------------------------------------------------------------------------------
| Etichetta | Significato |
|---|---|
| KEEP | La logica propria del gioco (per esempio il modello di volo, il modello dei danni, TrackIR) |
| WRAP | Collante rivolto a Java che chiama API del sistema operativo o di input: mantieni la firma, scrivi un nuovo corpo. |
| (IL-2 1946 è un motore interessante: C++ e Java insieme.) | |
| REPLACE | Vecchio runtime C, allocatore, thunk: li fornisce il compilatore o il sistema operativo, quindi una nuova versione a 64 bit non ne ha bisogno |
| UNKNOWN | Non chiaro: esaminalo a mano |
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
Nel mio programma di test, circa il 44% delle funzioni erano REPLACE, quindi non hanno mai avuto bisogno di essere convertite.
All'inizio mi fidavo del fatto che lo pseudocodice C avesse tutte le risposte. È stato ingenuo. È l'interpretazione dell'assembly da parte di Ghidra, e tira a indovinare (tipi delle variabili, argomenti persi).
L'assembly è la verità grezza. Non ha tipi di variabili, ma contiene il comportamento esatto di ogni funzione. Quindi gli script leggono l'assembly e lo trasformano in un progetto in forma simile al C. Il C di Ghidra è mantenuto solo come suggerimento.
I miei primi test usavano gli LLM locali (Qwen 2.5 Coder, DeepSeek Coder V2 Lite, Mellum 2) per leggere direttamente l'assembly. Non ha mai funzionato in modo affidabile. Allucinavano, perché sono fatti per scrivere codice, non per leggere codice macchina grezzo.
Dopo molti esperimenti falliti ho diviso il lavoro:
NOTA: Come Python controlla la risposta
Controlli testuali: il nome della funzione, ogni chiamata, variabile globale e stringa dal progetto, i cicli, le dimensioni dei passi, le costanti confrontate, il valore di ritorno, e che non siano rimasti nomi di registri o nomi inventati.
controllo di compilazione con gcc: il codice viene compilato con gcc (solo sintassi, nulla viene eseguito). Questo è stato molto utile. In una fase iniziale i controlli testuali hanno superato le risposte di Mellum 2, ma nessuna di esse veniva compilata, a causa di un commento di intestazione scritto fuori da un commento. gcc intercetta ciò che i controlli testuali non riescono a vedere: variabili non dichiarate o ridichiarate, tipi errati e parentesi graffe o punti e virgola rotti. Una funzione è considerata PASS solo quando sia i controlli testuali sia la compilazione sono OK. gcc non dimostra che la logica sia corretta, quindi continuo a leggere il codice confrontandolo con il blueprint.
Se un controllo fallisce, l'LLM riceve l'elenco di ciò che è fallito e riprova una volta.
Python corregge da solo i piccoli errori, senza l'LLM: dichiara ogni variabile una volta, racchiude le righe di intestazione sciolte in un commento, fa sì che l'ultimo return restituisca il risultato corretto e aggiunge gli include e le dichiarazioni.
La checklist è arrivata dopo che ho visto gli LLM fallire su funzioni molto lunghe. Funziona come la checklist che un pilota usa prima del decollo e dell'atterraggio. Python la scrive a partire dalla funzione e verifica la risposta rispetto ad essa. Nei miei test le funzioni lunghe hanno iniziato a passare, e le esecuzioni sono diventate più veloci.
|-------------------|---------------------------------------|---------------------------------------------
| Cartella | Cosa fa | Leggi |
|---|---|---|
ghidra_pipeline | Dump, raggruppamento, triage, ruoli | ghidra_pipeline/INSTRUCTION.txt |
llm_pipeline | Blueprint e il runner LLM (v3) | llm_pipeline/INSTRUCTION_BLUEPRINT_LLM.txt |
| ------------------- | --------------------------------------- | --------------------------------------------- |
Inizia con ghidra_pipeline, poi passa a llm_pipeline quando sei pronto a usare i tuoi LLM locali.
Per prima cosa, analizza il tuo programma in PyGhidra ed esegui PyGhidra Scripts/decompile_full_dump.py.
I due file INSTRUCTION spiegano la configurazione delle cartelle. Poi:
Per prima cosa, analizza il tuo programma in PyGhidra ed esegui PyGhidra Scripts/decompile_full_dump.py.
I due file INSTRUCTION spiegano la configurazione delle cartelle. Poi:
python .\make_full_lite_v2.py --in . --out .\OUT
python .\triage_evidence_v2.py --lite .\OUT\LITE_AC
python .\build_roles_v2.py --triage .\OUT\TRIAGE
python .\blueprint_v3.py --group ".\SOURCE\LITE_AC\<GroupName>" --out ".\G_<GroupName>\BLUEPRINT_v3"
python .\run_blueprint_llm_v3.py --bp ".\G_<GroupName>\BLUEPRINT_v3" --out ".\G_<GroupName>\RUN1_v3_<model>" --model <model name>
Servono Ghidra con PyGhidra, Python 3, LM Studio (un modello caricato) e gcc (consigliato, usato come controllo di compilazione).