
자동 바이너리 비교를 위한 MCP 서버
[Русская версия](https://github.com/xteardx/diaphora-mcp/blob/master/README.ru.md)
# Diaphora MCP
AI 어시스턴트에서 IDA로 분석된 두 바이너리를 비교합니다. Diaphora MCP는 저장된 IDA 데이터베이스를 내보내고, [Diaphora](https://github.com/joxeankoret/diaphora)를 실행하며, AI가 대응하는 함수와 그 호출 그래프를 검사할 수 있게 합니다.
기본 인터페이스는 비교에 초점을 맞춘 **10개의 도구**를 제공합니다. Diaphora가 매치를 제공하면, AI가 실제 코드를 읽고 변경 사항을 설명합니다.
[빠른 시작](#quick-start) · [예제](#examples) · [도구](#tools) · [문제 해결](#troubleshooting)
```text
old.i64 + new.i64 → headless export → SQLite exports + diff results
↓
summary → matched code → call graph
```
## 요구 사항
- Python 3.10+, `idat.exe`/`idat64`가 포함된 IDA Pro, 그리고 설치된 Diaphora 플러그인.
- 두 바이너리가 분석되어 `.i64`/`.idb` 데이터베이스로 저장되어 있어야 합니다.
- Codex, Claude Code 또는 Cursor와 같은 로컬 MCP 클라이언트.
- 의사코드를 원하는 경우에만 호환되는 Hex-Rays 디컴파일러.
IDA와 Diaphora는 별도로 설치됩니다. Diff 스키마 검증은 현재 Diaphora **3.4.1**을 대상으로 하며, 다른 스키마는 호환성 업데이트가 필요할 수 있습니다. Diff에 사용되는 Python 인터프리터에는 Diaphora의 독립 실행형 의존성이 설치되어 있어야 합니다.
## 빠른 시작
### 1. 설치 및 출력 디렉터리 생성
```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. MCP 서버 연결
클라이언트의 MCP 구성에 다음 항목을 추가하세요. 저장소, IDA 및 Diaphora 경로를 설치 경로로 바꾸세요. 이 프로젝트를 설치한 환경의 Python 실행 파일을 사용하세요.
```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"
}
}
}
}
```
클라이언트는 stdio를 통해 서버를 실행합니다. 별도로 시작할 웹 서비스는 없습니다. 코드나 환경을 변경한 후에는 MCP 서버를 재시작하세요. 연결에 성공하면 아래 나열된 10개의 도구가 노출됩니다.
### 3. 어시스턴트에게 파일 비교 요청
```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.
```
매번 **새로운 실행 디렉터리**를 선택하세요. 기존에 생성된 대상은 절대 덮어쓰지 않습니다.
## 예제
다음 JSON 블록은 셸 명령이 아니라 **MCP 도구 인수**입니다. 어시스턴트는 명명된 도구를 직접 호출할 수 있습니다. 경로와 `0x401000`은 예시이며, 자신의 실행에서 반환된 경로와 주소를 사용하세요.
### 1. 두 IDA 데이터베이스 내보내기 및 비교
도구: **`batch_export_and_diff`**. Old가 항상 첫 번째 입력이고 new가 두 번째입니다.
```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
}
```
이렇게 하면 Hex-Rays 없이도 어셈블리 세부 정보를 유지합니다. 필요한 내보내기 프로필을 선택하세요:
| 세부 정보 | `use_decompiler` | `summaries_only` | 용도 |
| --- | --- | --- | --- |
| 매칭 요약 | `false` | `true` | 빠른 첫 번째 패스; 상세 코드 없음 |
| 어셈블리 | `false` | `false` | 디컴파일러 없이 디스어셈블리 비교 |
| 어셈블리 + 의사코드 | `true` | `false` | 호환되는 Hex-Rays 디컴파일러를 사용한 코드 리뷰; 느림 |
항상 응답에서 출력 경로를 가져오세요:
```text
OLD_SQLITE = steps.export1.output
NEW_SQLITE = steps.export2.output
RESULTS = steps.diff.output
```
이 예제에서 생성된 파일은 `run-001` 아래의 `old.diaphora.sqlite`, `new.diaphora.sqlite`, `old_vs_new.diaphora`입니다. 동일한 입력 기본 이름은 서로 다른 `old_`/`new_` 내보내기 이름을 생성합니다. 나중에 함수를 검사하려면 `cleanup=false`로 유지하세요.
### 2. 요약 가져오기 및 변경된 매치 검사
도구: **`get_diff_summary`**.
```json
{
"results_path": "C:/diaphora-outputs/run-001/old_vs_new.diaphora"
}
```
도구: **`get_diff_results`**. 이 페이지는 낮은 비율의 부분 매치부터 시작합니다.
```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`은 Diaphora 매치 카테고리를 선택하는 것이지, 동작 변경을 보장하는 것이 아닙니다. 지원되는 모든 카테고리에는 `match_type="all"`을 사용하세요. 응답에는 카테고리 개수, 필터링된 총계, 매치, 매치되지 않은 행, `next_offset` 및 `next_unmatched_offset`이 포함됩니다.
계속하려면 반환된 다음 오프셋을 동일한 필터와 정렬을 유지한 채 다음 호출에 복사하세요. 예를 들어 `50`과 `50`이면 `offset=50`과 `unmatched_offset=50`을 사용하세요. `null` 다음 오프셋은 해당 목록이 끝났다는 의미이므로 더 이상 진행하지 마세요. 두 목록은 독립적으로 진행됩니다. 페이지 크기는 양수여야 하며 최대 5000으로 제한됩니다. 가장 강한 매치부터 검사하려면 `sort_order="desc"`를 사용하세요.
### 3. 매치된 함수와 그 그래프 비교
도구: **`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"
}
```
응답에는 `function_old`, `function_new`, 사용 가능한 어셈블리/의사코드, 측정된 차이점, 동일성 증거가 포함됩니다. `address` 대신 `name`을 사용할 수 있습니다. 두 선택자가 모두 제공되면 주소가 우선합니다. 이름으로 선택할 때는 주소를 생략하세요.
도구: **`get_changed_callgraph`**는 위와 동일한 인수를 받습니다. 변경 사항을 보고하기 전에 대응하는 호출자/피호출자 주소를 변환하며, 확인되지 않은 이웃과 확인된 엣지 차이를 구분합니다.
16진수 입력을 명확히 하려면 **`0x` 접두사가 붙은 주소**를 선호하세요. 사용 가능한 경우 `match_results_path`를 제공하세요. 이는 리베이스 및 이름이 변경된 함수를 처리합니다. 주소가 같다고 해서 동일성이 확립되는 것은 아닙니다. 모호하거나 누락된 매치는 삭제로 간주되지 않고 미해결로 남습니다. 수동으로 쌍을 검증한 경우 `address2` 또는 `name2`를 명시적으로 제공할 수 있습니다.
### 4. 함수 찾기 및 코드 읽기
도구: **`search_export_db`**. `name_pattern`은 SQL LIKE를 사용합니다: `%`는 임의의 시퀀스와 일치합니다.
```json
{
"db_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"name_pattern": "%parse%",
"min_instructions": 20,
"limit": 20
}
```
도구: **`get_function_pseudocode`**는 이름과 달리 사용 가능한 의사코드 **및 어셈블리**를 반환합니다.
```json
{
"db_path": "C:/diaphora-outputs/run-001/old.diaphora.sqlite",
"address": "0x401000"
}
```
의사코드가 비어 있으면 호환되는 디컴파일러를 사용하여 `use_decompiler=true`와 `summaries_only=false`로 새 실행 디렉터리에 내보내기를 다시 실행하세요. `db_path`와 함께 `get_export_info`를 사용하여 내보내기 메타데이터를 검사하세요.
### 5. 이미 가지고 있는 내보내기 비교
도구: **`diff_diaphora_dbs`**. 이는 IDA 내보내기를 건너뛰고 기존의 공식 SQLite 내보내기를 비교합니다.
```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"
}
```
새 내보내기 하나에는 `idb_path`, 새로운 `output_path`, `export_mode="headless"`와 함께 `export_idb_to_diaphora`를 사용하세요.
## 도구
| 도구 | 목적 |
| --- | --- |
| `export_idb_to_diaphora` | 저장된 IDA 데이터베이스 하나 내보내기 |
| `batch_export_and_diff` | 두 데이터베이스를 내보내고 비교 |
| `diff_diaphora_dbs` | 기존 내보내기 비교 |
| `get_diff_summary` | 매치 통계 및 제한된 예시 |
| `get_diff_results` | 필터링, 정렬, 페이지네이션된 결과 |
| `get_export_info` | 내보내기 메타데이터 및 개수 |
| `search_export_db` | 함수 검색 |
| `get_function_pseudocode` | 어셈블리/의사코드 읽기 |
| `compare_functions` | 해결된 old/new 쌍 비교 |
| `get_changed_callgraph` | 매핑된 호출자/피호출자 비교 |
정확한 시그니처는 MCP `tools/list`를 통해 확인할 수 있습니다. [도구 참조](https://github.com/xteardx/diaphora-mcp/blob/master/docs/TOOLS.md)를 참조하세요.
## 내보내기 모드 및 구성
| 모드 | 동작 |
| --- | --- |
| `headless` | IDA를 헤드리스로 실행하고 diff 스키마를 검증; 비교에 권장 |
| `auto` | 활성 GUI 브리지를 시도한 후 헤드리스 폴백 |
| `gui` | 올바른 열린 GUI 세션 필요; 헤드리스 폴백 없음 |
`batch_export_and_diff`는 `headless`가 필요합니다.
| 환경 변수 | 의미 |
| --- | --- |
| `IDAT_PATH` | IDA 헤드리스 실행 파일의 절대 경로 |
| `DIAPHORA_DIR` | Diaphora 스크립트가 포함된 디렉터리 |
| `DIAPHORA_OUTPUT_ROOT` | 새 내보내기 및 diff 결과에 대해 허용된 기존 루트 |
| `DIAPHORA_PYTHON` | 선택적 diff 인터프리터; 기본값은 MCP 서버의 인터프리터 |
| `DIAPHORA_ENABLE_LEGACY_TOOLS` | 정확히 `1`이면 이전 21개 도구 인터페이스 활성화 |
레거시 매칭, 기능 점수, 보안 트리아지, 보고서, 메타데이터 및 진단은 옵트인으로 유지됩니다. 활성화하려면 구성의 `env` 객체에 다음 항목을 추가하고 재시작하세요:
```json
{
"DIAPHORA_ENABLE_LEGACY_TOOLS": "1"
}
```
이 도구들은 휴리스틱을 사용합니다. 그 점수는 의미적 동등성, 보안 수정 또는 인과 관계를 증명하지 않습니다. [구성](https://github.com/xteardx/diaphora-mcp/blob/master/docs/CONFIGURATION.md) · [GUI 설정](https://github.com/xteardx/diaphora-mcp/blob/master/GUI_INSTRUCTIONS.md).
## 문제 해결
| 증상 | 조치 |
| --- | --- |
| 대상이 이미 존재함 | 새로운 실행 디렉터리 또는 출력 파일 이름 사용 |
| 허용된 루트 외부의 출력 | `DIAPHORA_OUTPUT_ROOT` 아래의 대상을 선택하세요; 먼저 루트를 생성하세요 |
| 결과 도구에 IDA 데이터베이스를 전달함 | 상황에 맞게 반환된 `.diaphora.sqlite` 내보내기 또는 `.diaphora` 결과를 사용하세요 |
| 누락/모호한 대응 항목 | old/new 순서와 매핑을 확인하세요; 후보를 수동으로 검사하세요 |
| 비어 있는 어셈블리/의사코드 | 내보내기 프로필을 확인하세요; 새로운 상세 내보내기를 얻으세요 |
| 내보내기/diff가 오래 걸림 | MCP 클라이언트 타임아웃을 늘리세요; 로컬 `logs/`를 검사하세요; 요약 전용 첫 번째 패스를 고려하세요 |
| IDA 세션에 의해 IDB가 잠김 | 세션을 닫거나 단일 내보내기에는 일치하는 GUI 내보내기 모드를 사용하세요 |
| 지원되지 않는 스키마 | 지원되는 Diaphora 버전으로 다시 내보내세요; 보고된 누락된 테이블/컬럼을 참조하세요 |
매칭은 여전히 휴리스틱입니다. 높은 비율은 증거이지 증명이 아닙니다. 매치되지 않은 함수는 확인된 추가/삭제가 아닙니다. 바이너리, IDB, 내보내기 및 로그를 Git에 포함하지 마세요. [워크플로](https://github.com/xteardx/diaphora-mcp/blob/master/docs/WORKFLOWS.md), [제한 사항](https://github.com/xteardx/diaphora-mcp/blob/master/docs/LIMITATIONS.md), [보안](https://github.com/xteardx/diaphora-mcp/blob/master/SECURITY.md)을 참조하세요.
## 개발
```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
```
회귀 테스트 스위트는 합성 데이터베이스와 모킹된 IDA 프로세스를 사용합니다. 실제 IDA 내보내기에는 로컬 통합 검증이 필요합니다. [기여](https://github.com/xteardx/diaphora-mcp/blob/master/CONTRIBUTING.md) · [에이전트 지침](https://github.com/xteardx/diaphora-mcp/blob/master/AGENTS.md).