
Assistente di reverse engineering basato su IA che collega IDA Pro con modelli linguistici tramite MCP.
Semplice server MCP per consentire il vibe reversing in IDA Pro.
https://github.com/user-attachments/assets/6ebeaa92-a9db-43fa-b756-eececce2aca0
I binari e il prompt per il video sono disponibili nel repository mcp-reversing-dataset.
idapyswitch per passare alla versione più recente di Pythonida-pro-mcp --config per ottenere la configurazione JSON per il tuo client.Nota: È necessario avere idalib attivato globalmente e uv installato:
# windows
uv run "C:\Program Files\IDA Professional 9.3\idalib\python\py-activate-idalib.py"
# macos
uv run "/Applications/IDA Professional 9.3.app/Contents/MacOS/idalib/python/py-activate-idalib.py"
Per installare l'ultima versione di IDA Pro MCP in Claude Code:
claude plugin marketplace add mrexodia/claude-marketplace
claude plugin uninstall ida-pro-mcp@mrexodia
claude plugin install ida-pro-mcp@mrexodia
Per installare l'ultima versione di IDA Pro MCP in Codex:
codex plugin marketplace add mrexodia/codex-marketplace
codex plugin remove ida-pro-mcp@mrexodia
codex plugin add ida-pro-mcp@mrexodia
Per installare l'ultima versione di IDA Pro MCP in Kimi Code, esegui questo comando slash nella chat:
/plugins install https://github.com/mrexodia/ida-pro-mcp/tree/main
/reload
Questo installa il server MCP idalib e la skill idapython. I plugin vengono copiati in
$KIMI_CODE_HOME/plugins/managed/, quindi uv deve essere nel tuo PATH. La prima sessione dopo
l'installazione è più lenta, perché uv risolve le dipendenze prima che il server risponda.
Nota: il plugin MCP non è più raccomandato e verrà eventualmente deprecato. Usa invece idalib-mcp.
Se vuoi configurare manualmente il server MCP dalla GUI di IDA:
pip uninstall ida-pro-mcp
pip install https://github.com/mrexodia/ida-pro-mcp/archive/refs/heads/main.zip
Configura i server MCP e installa il plugin IDA:
ida-pro-mcp --install
Importante: Assicurati di riavviare completamente IDA e il tuo client MCP affinché l'installazione abbia effetto. Alcuni client (come Claude) girano in background e devono essere chiusi dall'icona della tray.
I LLM sono inclini ad allucinazioni e devi essere specifico con i tuoi prompt. Per il reverse engineering la conversione tra interi e byte è particolarmente problematica. Di seguito un esempio minimale di prompt, sentiti libero di avviare una discussione o aprire un issue se ottieni buoni risultati con un prompt diverso:
Your task is to analyze a crackme in IDA Pro. You can use the MCP tools to retrieve information. In general use the following strategy:
- Inspect the decompilation and add comments with your findings
- Rename variables to more sensible names
- Change the variable and argument types if necessary (especially pointer and array types)
- Change function names to be more descriptive
- If more details are necessary, disassemble the function and add comments with your findings
- NEVER convert number bases yourself. Use the `int_convert` MCP tool if needed!
- Do not attempt brute forcing, derive any solutions purely from the disassembly and simple python scripts
- Create a report.md with your findings and steps taken at the end
- When you find a solution, prompt to user for feedback with the password you found
Questo prompt è stato solo il primo esperimento, per favore condividi se hai trovato modi per migliorare l'output!
Un altro prompt di @can1357:
Your task is to create a complete and comprehensive reverse engineering analysis. Reference AGENTS.md to understand the project goals and ensure the analysis serves our purposes.
Use the following systematic methodology:
1. **Decompilation Analysis**
- Thoroughly inspect the decompiler output
- Add detailed comments documenting your findings
- Focus on understanding the actual functionality and purpose of each component (do not rely on old, incorrect comments)
2. **Improve Readability in the Database**
- Rename variables to sensible, descriptive names
- Correct variable and argument types where necessary (especially pointers and array types)
- Update function names to be descriptive of their actual purpose
3. **Deep Dive When Needed**
- If more details are necessary, examine the disassembly and add comments with findings
- Document any low-level behaviors that aren't clear from the decompilation alone
- Use sub-agents to perform detailed analysis
4. **Important Constraints**
- NEVER convert number bases yourself - use the int_convert MCP tool if needed
- Use MCP tools to retrieve information as necessary
- Derive all conclusions from actual analysis, not assumptions
5. **Documentation**
- Produce comprehensive RE/*.md files with your findings
- Document the steps taken and methodology used
- When asked by the user, ensure accuracy over previous analysis file
- Organize findings in a way that serves the project goals outlined in AGENTS.md or CLAUDE.md
Live stream che discute il prompting e mostra analisi di malware reali:
I modelli linguistici di grandi dimensioni (LLM) sono strumenti potenti, ma a volte possono avere difficoltà con calcoli matematici complessi o mostrare "allucinazioni" (inventare fatti). Assicurati di dire all'LLM di usare lo strumento MCP int_convert e potresti anche aver bisogno di math-mcp per certe operazioni.
Un'altra cosa da tenere a mente è che gli LLM non daranno buoni risultati su codice offuscato. Prima di provare a usare un LLM per risolvere il problema, dai un'occhiata al binario e dedica un po' di tempo a rimuovere (automaticamente) le seguenti cose:
Dovresti anche usare uno strumento come Lumina o FLIRT per provare a risolvere tutto il codice delle librerie open source e la STL del C++, questo migliorerà ulteriormente l'accuratezza.
Puoi eseguire un server SSE per connetterti all'interfaccia utente in questo modo:
uv run ida-pro-mcp --transport http://127.0.0.1:8744/sse
Dopo aver installato idalib puoi anche eseguire un server MCP headless. Puoi avviare con un binario iniziale:
uv run idalib-mcp --host 127.0.0.1 --port 8745 path/to/executable
Oppure avviare senza un binario e aprire file arbitrari in seguito con idb_open(...):
uv run idalib-mcp --host 127.0.0.1 --port 8745
Per client basati su stdio, usa:
uv run idalib-mcp --stdio
I worker del database sono persistenti: ognuno viene eseguito come processo separato che
sopravvive al supervisor che lo ha generato. Quando un nuovo supervisor (via stdio
o HTTP) chiama idb_open per un binario che è già aperto sotto un worker su questo host,
il supervisor adotta quel worker in modo trasparente — non esiste una
modalità "condivisa" separata da abilitare. I worker si terminano automaticamente quando nessuna richiesta
li ha contattati per un intervallo di inattività.
Nota: La funzionalità idalib è stata contribuita da Willi Ballenthin.
idalib-mcp è un supervisor che mantiene ogni database aperto nel proprio processo worker idalib. I worker si registrano in una directory di scoperta locale all'host e sopravvivono al supervisor che li ha generati; qualsiasi supervisor successivo che desidera lo stesso percorso adotta il worker in esecuzione. Un worker termina da solo quando nessuna richiesta lo ha contattato per il suo TTL di inattività (default 1 ora). Chiama idb_close per rilasciare un worker immediatamente (liberando un posto verso --max-workers); le istanze GUI/worker adottate vengono scollegate, non terminate.
idb_open sceglie il backend tramite il suo parametro mode:
prefer_headless (default): genera un worker idalib (o ne adotta uno che ha già il file aperto).force_headless: stessa cosa, ma non adotta mai una GUI in esecuzione anche se ha il file.prefer_gui: adotta una GUI in esecuzione per il file; altrimenti genera un worker idalib.force_gui: adotta una GUI in esecuzione per il file; altrimenti avvia un nuovo processo GUI di IDA.Ogni chiamata a uno strumento deve portare un argomento database esplicito. Non esiste un "database corrente" implicito — i chiamanti nominano la sessione su cui vogliono operare.
uv run idalib-mcp --stdio --max-workers 4
Flusso tipico:
idb_open("/path/to/binary_a.exe", preferred_session_id="binary_a")
idb_open("/path/to/library.dll", preferred_session_id="library")
decompile("main", database="binary_a")
xrefs_to("ImportantExport", database="library")
database deve essere l'ID di sessione restituito da idb_open (o mostrato in idb_list); non vengono accettati nomi di file o percorsi.
idb_open(input_path, mode="prefer_headless", run_auto_analysis=True, build_caches=True, init_hexrays=True, preferred_session_id=""): Apre un binario, riscalda i sottosistemi (cache delle stringhe, Hex-Rays) e restituisce il suo ID di sessione. Se un worker o una GUI per questo percorso è già in esecuzione sull'host, quell'istanza viene adottata e preferred_session_id viene ignorato.idb_list(): Elenca le sessioni aperte e le istanze GUI di IDA in esecuzione. Ogni voce ha adopted (True se questo supervisor la gestisce, False per GUI/worker scoperti ma non ancora aperti tramite idb_open), backend (worker o gui), is_active e PID.idb_close(database, save=True): Salva (opzionalmente), deregistra la sessione e termina il suo worker posseduto, liberando un posto verso --max-workers. Le istanze GUI/worker adottate vengono scollegate, non terminate.Controlli dei worker:
--max-workers N: massimo numero di worker di database simultanei (0 = illimitato, default 4).IDA_MCP_MAX_WORKERS: valore di default per --max-workers dall'ambiente.Risorse rappresentano stato navigabile (dati di sola lettura) seguendo la filosofia MCP.
Stato IDB principale:
ida://idb/metadata - Info del file IDB (percorso, architettura, base, dimensione, hash)ida://idb/segments - Segmenti di memoria con permessiida://idb/entrypoints - Punti di ingresso (main, callback TLS, ecc.)Stato UI:
ida://cursor - Posizione corrente del cursore e funzioneida://selection - Intervallo di selezione correnteInformazioni sui tipi:
ida://types - Tutti i tipi localiida://structs - Tutte le strutture/unioniida://struct/{name} - Definizione della struttura con campiRicerca:
ida://import/{name} - Dettagli dell'import per nomeida://export/{name} - Dettagli dell'export per nomeida://xrefs/from/{addr} - Riferimenti incrociati da un indirizzolookup_funcs(queries): Ottiene funzione/i per indirizzo o nome (rilevamento automatico, accetta lista o stringa separata da virgole).int_convert(inputs): Converte numeri in diversi formati (decimale, esadecimale, byte, ASCII, binario).list_funcs(queries): Elenca funzioni (paginato, filtrato).list_globals(queries): Elenca variabili globali (paginato, filtrato).imports(offset, count): Elenca tutti i simboli importati con nomi di modulo (paginato).decompile(addr): Decompila la funzione all'indirizzo dato.disasm(addr): Disassembla la funzione con dettagli completi (argomenti, stack frame, ecc.).xrefs_to(addrs): Ottiene tutti i riferimenti incrociati verso indirizzo/i.xrefs_to_field(queries): Ottiene i riferimenti incrociati verso campi di struct specifici.callees(addrs): Ottiene le funzioni chiamate dalla funzione/i a indirizzo/i.add_bookmark(addr, name, prefix): Aggiunge o sostituisce il segnalibro IDA a un indirizzo; imposta prefix="" per nessun prefisso.set_comments(items): Imposta commenti a indirizzo/i sia nella vista disassemblaggio che nella vista decompilatore.patch_asm(items): Applica patch alle istruzioni assembly a indirizzo/i.declare_type(decls): Dichiara tipo/i C nella libreria dei tipi locali.define_func(items): Definisce funzione/i a indirizzo/i. Opzionalmente specifica end per limiti espliciti.define_code(items): Converte byte in istruzione/i codice a indirizzo/i.undefine(items): Annulla la definizione di elemento/i a indirizzo/i, riconvertendo in byte grezzi. Opzionalmente specifica end o size.get_bytes(addrs): Legge byte grezzi a indirizzo/i.get_int(queries): Legge valori interi usando ty (i8/u64/i16le/i16be/etc).get_string(addrs): Legge stringa/e con terminazione null.get_global_value(queries): Legge valore/i di variabili globali per indirizzo o nome (rilevamento automatico, valori in fase di compilazione).stack_frame(addrs): Ottiene le variabili dello stack frame per funzione/i.declare_stack(items): Crea variabile/i di stack a offset specificati.delete_stack(items): Elimina variabile/i di stack per nome.read_struct(queries): Legge valori dei campi di strutture a indirizzo/i specifici.search_structs(filter): Cerca strutture per pattern di nome.Gli strumenti del debugger sono nascosti per impostazione predefinita. Abilita con il parametro ?ext=dbg:
http://127.0.0.1:13337/mcp?ext=dbg
Controllo:
dbg_start(): Avvia il processo debugger.dbg_exit(): Esci dal processo debugger.dbg_continue(): Continua l'esecuzione.dbg_run_to(addr): Esegui fino all'indirizzo.dbg_step_into(): Esegui passo-istruzione.dbg_step_over(): Esegui passo sopra.Breakpoint:
dbg_bps(): Elenca tutti i breakpoint.dbg_add_bp(addrs): Aggiunge breakpoint.dbg_delete_bp(addrs): Elimina breakpoint.dbg_toggle_bp(items): Abilita/disabilita breakpoint.Registri:
dbg_regs(): Tutti i registri, thread corrente.dbg_regs_all(): Tutti i registri, tutti i thread.dbg_regs_remote(tids): Tutti i registri, thread specifici.dbg_gpregs(): Registri general-purpose, thread corrente.dbg_gpregs_remote(tids): Registri GP, thread specifici.dbg_regs_named(names): Registri nominati, thread corrente.dbg_regs_named_remote(tid, names): Registri nominati, thread specifico.Stack e memoria:
dbg_stacktrace(): Stack di chiamata con informazioni su modulo/simbolo.dbg_read(regions): Legge memoria dal processo in debug.dbg_write(regions): Scrive memoria nel processo in debug.py_eval(code): Esegue codice Python arbitrario nel contesto di IDA (restituisce dict con result/stdout/stderr, supporta valutazione stile Jupyter).analyze_funcs(addrs): Analisi completa delle funzioni (decompilazione, assembly, xrefs, callees, callers, stringhe, costanti, blocchi di base).find_regex(queries): Cerca stringhe con regex case-insensitive (paginato).find_bytes(patterns, limit=1000, offset=0): Trova pattern di byte nel binario (es. "48 8B ?? ??"). Limite massimo: 10000.find_insns(sequences, limit=1000, offset=0): Trova sequenze di istruzioni nel codice. Limite massimo: 10000.find(type, targets, limit=1000, offset=0): Ricerca avanzata (valori immediati, stringhe, riferimenti a dati/codice). Limite massimo: 10000.basic_blocks(addrs): Ottiene blocchi di base con successori e predecessori.set_type(edits): Applica tipo/i a funzioni, globali, locali o variabili di stack.infer_types(addrs): Inferisce tipi a indirizzo/i usando Hex-Rays o euristiche.export_funcs(addrs, format): Esporta funzione/i nel formato specificato (json, c_header o prototypes).callgraph(roots, max_depth): Costruisce grafo delle chiamate dalla funzione radice con profondità configurabile.rename(batch): Operazione di rinomina batch unificata per funzioni, globali, locali e variabili di stack (accetta dict con chiavi opzionali func, data, local, stack).patch(patches): Applica patch a multiple sequenze di byte contemporaneamente.put_int(items): Scrive valori interi usando ty (i8/u64/i16le/i16be/etc).Caratteristiche principali:
[{..., error: null|string}, ...]cursor: {next: offset} o {done: true} (limite default: 1000, massimo imposto: 10000 per prevenire overflow di token)build_strlist ripetute in progetti grandiAggiungere nuove funzionalità è un processo estremamente semplice e snello. Tutto ciò che devi fare è aggiungere una nuova funzione @tool ai file API modulari in src/ida_pro_mcp/ida_mcp/api_*.py e la tua funzione sarà disponibile nel server MCP senza alcun boilerplate aggiuntivo! Di seguito un video in cui aggiungo la funzione get_metadata in meno di 2 minuti (incluso il test):
https://github.com/user-attachments/assets/951de823-88ea-4235-adcb-9257e316ae64
Per testare il server MCP stesso:
npx -y @modelcontextprotocol/inspector
Questo aprirà un'interfaccia web su http://localhost:5173 e ti permetterà di interagire con gli strumenti MCP per i test.
Per i test creo un collegamento simbolico al plugin IDA e poi invio una richiesta JSON-RPC POST direttamente a http://localhost:13337/mcp. Dopo aver abilitato i collegamenti simbolici puoi eseguire il seguente comando:
uv run ida-pro-mcp --install
Genera il changelog dei commit diretti su main:
git log --first-parent --no-merges 1.2.0..main "--pretty=- %s"
idb_save(session_id, path=""): Salva l'IDB di una sessione su disco. Inoltrato come strumento worker regolare (database=<id> iniettato) — stessa firma in entrambi i backend.server_health(database=<id>) (inoltrato). idb_list() riporta is_active dal probe TCP/RPC del supervisor.