
Servidor MCP para diffing binario automatizado.
[Versión en ruso](https://github.com/xteardx/diaphora-mcp/blob/master/README.ru.md)
# Diaphora MCP
Compara dos binarios analizados con IDA desde tu asistente de IA. Diaphora MCP exporta las bases de datos de IDA guardadas, ejecuta [Diaphora](https://github.com/joxeankoret/diaphora) y permite que la IA inspeccione las funciones correspondientes y sus grafos de llamadas.
La interfaz predeterminada tiene **10 herramientas** centradas en la comparación. Diaphora proporciona las coincidencias; la IA lee el código real y explica los cambios.
[Inicio rápido](#quick-start) · [Ejemplos](#examples) · [Herramientas](#tools) · [Solución de problemas](#troubleshooting)
```text
old.i64 + new.i64 → headless export → SQLite exports + diff results
↓
summary → matched code → call graph
```
## Requisitos
- Python 3.10+, IDA Pro con `idat.exe`/`idat64`, y un plugin Diaphora instalado.
- Ambos binarios analizados y guardados como bases de datos `.i64`/`.idb`.
- Un cliente MCP local, como Codex, Claude Code o Cursor.
- Un descompilador Hex-Rays compatible solo si quieres pseudocódigo.
IDA y Diaphora se instalan por separado. La validación del esquema de diff actualmente apunta a Diaphora **3.4.1**; otros esquemas pueden necesitar actualizaciones de compatibilidad. El intérprete de Python usado para el diff debe tener instaladas las dependencias independientes de Diaphora.
## Inicio rápido
### 1. Instalar y crear un directorio de salida
```powershell
git clone https://github.com/xTeardx/diaphora-mcp.git
cd diaphora-mcp
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e .
New-Item -ItemType Directory -Force C:\diaphora-outputs | Out-Null
```
### 2. Conectar el servidor MCP
Añade esta entrada a la configuración MCP de tu cliente. Reemplaza las rutas del repositorio, IDA y Diaphora con las rutas de tu instalación. Usa el ejecutable de Python del entorno donde instalaste este proyecto.
```json
{
"mcpServers": {
"diaphora": {
"command": "C:/src/diaphora-mcp/.venv/Scripts/python.exe",
"args": ["C:/src/diaphora-mcp/diaphora_mcp_server.py"],
"env": {
"IDAT_PATH": "C:/Program Files/IDA Professional 9.3/idat.exe",
"DIAPHORA_DIR": "C:/Program Files/IDA Professional 9.3/plugins/diaphora",
"DIAPHORA_OUTPUT_ROOT": "C:/diaphora-outputs"
}
}
}
}
```
El cliente lanza el servidor por stdio; no hay un servicio web separado que iniciar. Reinicia el servidor MCP después de cambiar su código o entorno. Una conexión exitosa expone las 10 herramientas listadas a continuación.
### 3. Pide a tu asistente que compare los archivos
```text
Use Diaphora to compare C:/analysis/old.i64 (old) against
C:/analysis/new.i64 (new). Save output under C:/diaphora-outputs/run-001.
Export headlessly with assembly detail, keep the exports, show a summary,
then inspect partial matches and explain the code changes in the interesting
functions. Use the result mapping when comparing functions and call graphs.
```
Elige un **directorio de ejecución nuevo** cada vez. Los destinos generados existentes nunca se sobrescriben.
## Ejemplos
Los siguientes bloques JSON son **argumentos de herramientas MCP**, no comandos de shell. Tu asistente puede llamar directamente a las herramientas nombradas. Las rutas y `0x401000` son ejemplos; usa las rutas y direcciones devueltas por tu propia ejecución.
### 1. Exportar y comparar dos bases de datos de IDA
Herramienta: **`batch_export_and_diff`**. El antiguo es siempre la primera entrada, el nuevo la segunda.
```json
{
"idb1_path": "C:/analysis/old.i64",
"idb2_path": "C:/analysis/new.i64",
"output_dir": "C:/diaphora-outputs/run-001",
"export_mode": "headless",
"use_decompiler": false,
"summaries_only": false,
"cleanup": false,
"limit": 100,
"unmatched_limit": 50
}
```
Esto conserva el detalle de ensamblador sin requerir Hex-Rays. Selecciona el perfil de exportación que necesites:
| Detalle | `use_decompiler` | `summaries_only` | Uso |
| --- | --- | --- | --- |
| Resúmenes de coincidencias | `false` | `true` | Primera pasada rápida; sin código detallado |
| Ensamblador | `false` | `false` | Comparar desensamblado sin un descompilador |
| Ensamblador + pseudocódigo | `true` | `false` | Revisión de código con un descompilador Hex-Rays compatible; más lento |
Toma siempre las rutas de salida de la respuesta:
```text
OLD_SQLITE = steps.export1.output
NEW_SQLITE = steps.export2.output
RESULTS = steps.diff.output
```
Para este ejemplo, los archivos generados son `old.diaphora.sqlite`, `new.diaphora.sqlite` y `old_vs_new.diaphora` bajo `run-001`. Nombres base de entrada iguales producen nombres de exportación distintos `old_`/`new_`. Mantén `cleanup=false` para la inspección posterior de funciones.
### 2. Obtener un resumen e inspeccionar coincidencias modificadas
Herramienta: **`get_diff_summary`**.
```json
{
"results_path": "C:/diaphora-outputs/run-001/old_vs_new.diaphora"
}
```
Herramienta: **`get_diff_results`**. Esta página comienza con coincidencias parciales de menor ratio.
```json
{
"results_path": "C:/diaphora-outputs/run-001/old_vs_new.diaphora",
"match_type": "partial",
"min_ratio": 0.0,
"limit": 50,
"offset": 0,
"unmatched_limit": 50,
"unmatched_offset": 0,
"sort_by": "ratio",
"sort_order": "asc"
}
```
`partial` selecciona una categoría de coincidencia de Diaphora, no una garantía de cambio de comportamiento. Usa `match_type="all"` para todas las categorías compatibles. La respuesta incluye recuentos por categoría, el total filtrado, coincidencias, filas no coincidentes, `next_offset` y `next_unmatched_offset`.
Para continuar, copia los siguientes offsets devueltos en la siguiente llamada, manteniendo los mismos filtros y orden. Por ejemplo, si son `50` y `50`, usa `offset=50` y `unmatched_offset=50`. Un siguiente offset `null` significa que esa lista ha terminado; deja de avanzarla. Las dos listas progresan de forma independiente. Los tamaños de página deben ser positivos y están limitados a 5000. Usa `sort_order="desc"` para inspeccionar primero las coincidencias más fuertes.
### 3. Comparar una función coincidente y su grafo
Herramienta: **`compare_functions`**.
```json
{
"db1_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"db2_path": "C:/diaphora-outputs/run-001/new.diaphora.sqlite",
"address": "0x401000",
"match_results_path": "C:/diaphora-outputs/run-001/old_vs_new.diaphora"
}
```
La respuesta contiene `function_old`, `function_new`, ensamblador/pseudocódigo disponible, diferencias medidas y evidencia de identidad. Puedes usar `name` en lugar de `address`. Si se proporcionan ambos selectores, la dirección tiene prioridad; omítela cuando selecciones por nombre.
Herramienta: **`get_changed_callgraph`** acepta los mismos argumentos anteriores. Traduce las direcciones correspondientes de llamadores/llamados antes de informar cambios, y separa los vecinos no resueltos de las diferencias de aristas confirmadas.
Prefiere **direcciones con prefijo `0x`** para hacer explícita la entrada hexadecimal. Proporciona `match_results_path` cuando esté disponible: maneja el reajuste de base y las funciones renombradas. Direcciones iguales por sí solas no establecen identidad. Las coincidencias ambiguas o ausentes permanecen sin resolver en lugar de considerarse eliminaciones. Si has verificado manualmente un par, puedes proporcionar `address2` o `name2` explícitamente.
### 4. Encontrar una función y leer su código
Herramienta: **`search_export_db`**. `name_pattern` usa SQL LIKE: `%` coincide con cualquier secuencia.
```json
{
"db_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"name_pattern": "%parse%",
"min_instructions": 20,
"limit": 20
}
```
Herramienta: **`get_function_pseudocode`** devuelve el pseudocódigo disponible **y el ensamblador**, a pesar de su nombre.
```json
{
"db_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"address": "0x401000"
}
```
Si el pseudocódigo está vacío, vuelve a ejecutar la exportación en un directorio de ejecución nuevo con `use_decompiler=true` y `summaries_only=false`, usando un descompilador compatible. Usa `get_export_info` con `db_path` para inspeccionar los metadatos de la exportación.
### 5. Comparar exportaciones que ya tienes
Herramienta: **`diff_diaphora_dbs`**. Esto omite la exportación de IDA y compara las exportaciones SQLite oficiales existentes.
```json
{
"db1_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"db2_path": "C:/diaphora-outputs/run-001/new.diaphora.sqlite",
"output_path": "C:/diaphora-outputs/another-diff.diaphora"
}
```
Para una nueva exportación, usa `export_idb_to_diaphora` con `idb_path`, un `output_path` nuevo y `export_mode="headless"`.
## Herramientas
| Herramienta | Propósito |
| --- | --- |
| `export_idb_to_diaphora` | Exportar una base de datos de IDA guardada |
| `batch_export_and_diff` | Exportar ambas bases de datos y compararlas |
| `diff_diaphora_dbs` | Comparar exportaciones existentes |
| `get_diff_summary` | Estadísticas de coincidencias y ejemplos acotados |
| `get_diff_results` | Resultados filtrados, ordenados y paginados |
| `get_export_info` | Metadatos y recuentos de la exportación |
| `search_export_db` | Buscar funciones |
| `get_function_pseudocode` | Leer ensamblador/pseudocódigo |
| `compare_functions` | Comparar un par antiguo/nuevo resuelto |
| `get_changed_callgraph` | Comparar llamadores/llamados mapeados |
Las firmas exactas se pueden descubrir a través de MCP `tools/list`. Consulta [Referencia de herramientas](https://github.com/xteardx/diaphora-mcp/blob/master/docs/TOOLS.md).
## Modos de exportación y configuración
| Modo | Comportamiento |
| --- | --- |
| `headless` | Lanza IDA sin interfaz y valida el esquema de diff; recomendado para comparaciones |
| `auto` | Prueba el puente GUI activo, luego el fallback sin interfaz |
| `gui` | Requiere la sesión GUI abierta correcta; sin fallback sin interfaz |
`batch_export_and_diff` requiere `headless`.
| Variable de entorno | Significado |
| --- | --- |
| `IDAT_PATH` | Ruta absoluta al ejecutable sin interfaz de IDA |
| `DIAPHORA_DIR` | Directorio que contiene los scripts de Diaphora |
| `DIAPHORA_OUTPUT_ROOT` | Raíz permitida existente para nuevas exportaciones y resultados de diff |
| `DIAPHORA_PYTHON` | Intérprete de diff opcional; por defecto el intérprete del servidor MCP |
| `DIAPHORA_ENABLE_LEGACY_TOOLS` | Exactamente `1` habilita la interfaz anterior de 21 herramientas |
La coincidencia heredada, las puntuaciones de características, el triaje de seguridad, los informes, los metadatos y los diagnósticos siguen siendo opcionales. Para habilitarlos, añade la siguiente entrada al objeto `env` de la configuración y reinicia:
```json
{
"DIAPHORA_ENABLE_LEGACY_TOOLS": "1"
}
```
Estas herramientas usan heurísticas; sus puntuaciones no prueban equivalencia semántica, correcciones de seguridad ni causalidad. [Configuración](https://github.com/xteardx/diaphora-mcp/blob/master/docs/CONFIGURATION.md) · [Configuración de GUI](https://github.com/xteardx/diaphora-mcp/blob/master/GUI_INSTRUCTIONS.md).
## Solución de problemas
| Síntoma | Acción |
| --- | --- |
| El destino ya existe | Usa un directorio de ejecución o nombre de archivo de salida nuevos |
| Salida fuera de la raíz permitida | Elige un destino bajo `DIAPHORA_OUTPUT_ROOT`; crea la raíz primero |
| Base de datos de IDA pasada a una herramienta de resultados | Usa las exportaciones `.diaphora.sqlite` devueltas o los resultados `.diaphora`, según corresponda |
| Contraparte ausente/ambigua | Comprueba el orden antiguo/nuevo y el mapeo; inspecciona el candidato manualmente |
| Ensamblador/pseudocódigo vacío | Comprueba el perfil de exportación; obtén una nueva exportación detallada |
| La exportación/diff tarda mucho | Aumenta el tiempo de espera del cliente MCP; inspecciona los `logs/` locales; considera una primera pasada solo de resúmenes |
| IDB bloqueada por una sesión de IDA | Cierra la sesión o usa el modo de exportación GUI correspondiente para una sola exportación |
| Esquema no compatible | Vuelve a exportar con la versión de Diaphora compatible; consulta las tablas/columnas faltantes reportadas |
La coincidencia sigue siendo heurística; un ratio alto es evidencia, no prueba. Las funciones no coincidentes no son adiciones/eliminaciones confirmadas. Mantén los binarios, IDBs, exportaciones y logs fuera de Git. Consulta [Flujos de trabajo](https://github.com/xteardx/diaphora-mcp/blob/master/docs/WORKFLOWS.md), [Limitaciones](https://github.com/xteardx/diaphora-mcp/blob/master/docs/LIMITATIONS.md) y [Seguridad](https://github.com/xteardx/diaphora-mcp/blob/master/SECURITY.md).
## Desarrollo
```powershell
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m compileall -q .
git diff --check
```
La suite de regresión usa bases de datos sintéticas y procesos de IDA simulados. La exportación real de IDA requiere validación de integración local. [Contribuir](https://github.com/xteardx/diaphora-mcp/blob/master/CONTRIBUTING.md) · [Instrucciones para agentes](https://github.com/xteardx/diaphora-mcp/blob/master/AGENTS.md).