
병렬 IDA Pro 바이너리 분석, AI 기반 함수 명명, Neo4j 지식 그래프, phantomrt 에뮬레이션/후킹/퍼징 엔진을 활용한 PE, ELF, NSO 형식의 자동 리버스 엔지니어링
바이너리를 통과하는 유령.
로컬에서 실행되는 AI 기반 리버스 엔지니어링 도우미: 병렬 IDA Pro 분석, AI 함수 이름 지정, 불편함 없는 터미널, 지금까지 파악한 모든 내용을 담은 Neo4j 지식 그래프, 그리고 Claude가 해당 그래프를 직접 검색하고 연결할 수 있게 해주는 MCP 서버.
그리고 이제 — phantomrt 덕분에 — 단순히 벽을 읽는 것을 넘어, 벽을 통과합니다: 이름 붙인 함수를 에뮬레이트, 후킹, 퍼징하고, 실제로 일어난 일을 그래프에 기록합니다.
bindPort - 리버스 쉘 페이로드를 HTTPS 또는 HTTP 프로토콜을 사용하여 특정 포트에서 수신 대기하는 서버로
설정합니다.
payload linux/meterpreter/reverse_tcp
bindPort - 직접 연결 페이로드를 수신 대기할 포트를 설정합니다.
payload windows/meterpreter/reverse_https
bindPort - 직접 연결 페이로드를 수신 대기할 포트를 설정합니다.
payload linux/x86/shell_reverse_tcp
bindPort - 직접 연결 페이로드를 수신 대기할 포트를 설정합니다.
payload windows/x64/meterpreter/reverse_tcp
bindPort - 직접 연결 페이로드를 수신 대기할 포트를 설정합니다.
payload java/meterpreter/reverse_tcp
bindPort - 직접 연결 페이로드를 수신 대기할 포트를 설정합니다.
payload python/meterpreter/reverse_tcp
◈ spectrIDA ▸ GameAssembly.dll
✓ 00 ✓ 01 ✓ 02 ✓ 03 ▸ 04 · 05 · 06 · 07 ✓ 08 ✓ 09 ✓ 10 ✓ 11 ✓ 12 ✓ 13 ▸ 14 · 15
14/16 shards │ 141,203 functions found ████████████████████████████░░░░ 89% ~4s remaining
---
## 개요
IDA Pro의 자동 분석은 단일 스레드로 동작합니다. 34MB 크기의 il2cpp DLL에서는 *몇 분*이 걸립니다. spectrIDA는 바이너리를 N개의 샤드로 분할하고, idalib을 통해 병렬로 실행한 후, 하나의 `.i64`로 병합합니다. 그런 다음 미세 조정된 8B 모델이 **모든 함수에 이름을 지정**합니다. 이 모든 작업을 사이버펑크 테마와 딱 적당한 양의 비꼼을 가진 하나의 터미널 UI에서 수행합니다.
이것이 1장이며, 독립적으로 작동합니다: 원하지 않으면 AI 없이도 순수한 속도만으로 사용할 수 있습니다.
2장은 출력을 세션보다 오래 지속되는 무언가로 바꿉니다 — MCP 클라이언트(Claude, [pi](https://pi.dev), MCP를 사용하는 모든 것)가 실제로 상주할 수 있는 Neo4j 그래프로, 더 이상 디컴파일러 출력을 하나씩 복사하여 채팅 창에 붙여넣지 않아도 됩니다:```
Binary ─▶ Parallel IDA Analysis ─▶ Demangle ─▶ AI Naming ─▶ Neo4j Graph ─▶ MCP Server ─▶ Claude
(N idalib shards) (free, real) (stripped (persists, (search/chain/
leftovers forever, rename, live)
only) across sessions)
3장(phantomrt)은 정적 도구가 절대 갖지 못하는 절반을 추가합니다. 즉, 코드를 실행합니다. OS 없이 함수를 에뮬레이션하거나(실행조차 할 수 없는 바이너리(예: Switch .nso)에서 작동), 라이브 프로세스에 후크를 걸거나 퍼징합니다. 그리고 평결(crashes / needs live state / clean)을 이름과 동일한 그래프 노드에 스탬프합니다.
아직 할 일 목록에 있는 것을 포함한 전체 요약은 2장과 3장에 있습니다.
Ghidra가 아닙니다. 한 가지 귀찮은 일(느린 분석 + 이름 지정)을 빠르게 처리하며, 사용하는 것이 정말 재미있습니다. 199회 다운로드가 증명합니다.
클라우드 없음. 텔레메트리 없음. 전적으로 사용자 머신에서 실행됩니다.
| task | time |
|---|---|
| Among Us DLL — 단일 스레드 IDA | ~4 hours |
| Among Us DLL — spectrIDA (16개 워커) | 67 seconds |
| 153,649개 함수 바이너리 — 전체 네이밍 패스 | overnight |
| 바이너리 개요 (이 바이너리는 무엇을 하나요?) | ~30 seconds |
측정에 사용된 하드웨어: AMD Ryzen 7 5800X3D (8C/16T), 32 GB RAM, RTX 4070 12 GB.
하드웨어가 다르면 병렬 분석 숫자(코어가 많을수록, 샤드가 많을수록, 더 빠름)가 변하고; 이름 지정 숫자는 대부분 GPU에 의해 제한됩니다. 4시간/67초 Among Us 수치는 2장 이전의 것이며 모든 릴리스에서 독립적으로 재검증되지 않습니다 — 자신의 머신과 바이너리에 대한 숫자를 원한다면 spectrida analyze를 직접 다시 실행하세요. 결과는 샤드 밀도와 바이너리 크기에 따라 다릅니다.
2장 개발 중 실제로 재검증된 수치, 동일한 하드웨어:
해당 NSO 행은 예전 Among Us의 "4시간 → 67초" 주장의 실제 등가물로, 이 릴리스에서 74,790개 함수를 가진 Switch 바이너리에서 새로 측정되었으며 AI 이름 지정은 포함되지 않았습니다 (디맹글링만 — populate=False). 병렬 단계(16코어, 약 55초)는 초기 샤드 검색을 수행하고; 병합 단계(약 143초)는 설계상 단일 스레드입니다 — IDA 데이터베이스 하나, 작성자 하나 — 따라서 작업 관리자에서 해당 부분을 보는 동안 15개의 코어가 잠자는 것을 본다면, 이는 버그 보고서가 아니라 물리학입니다.
여기서 정직한 숫자를 얻는 것은 그 자체로 작은 공포 이야기였습니다. NSO 지원의 첫 번째 버전은 깨끗하게 실행되고, 0으로 종료되며, 대략 75,000개의 함수가 있는 바이너리에 대해 자랑스럽게 727개의 함수를 반환했습니다 — 충돌이 아니라, 그냥 화려하게, 자신만만하게 틀렸으며, 이는 어쩐지 더 나쁩니다. IDA에는 기본 NSO 로더가 없어서, 파일이 조용히 일반 x86("metapc")으로 로드되었습니다. Switch는 출시 이후로 ARM64임에도 불구하고요. 모든 샤드가 순수 AArch64 명령어에 대해 x86 프롤로그 스캐너를 실행하고 우연히 일치하는 것을 "함수"라고 불렀습니다. 아키텍처를 수정하는 것만으로는 아무것도 고쳐지지 않았습니다. 바이너리가 메모리에서 또한 여전히 LZ4 압축되어 있었기 때문입니다 — 그래서 스캔된 것의 절반은 관대하게 말해 노이즈였습니다. 그리고 제대로 압축이 풀리고 AArch64로 플래그가 지정된 후에도, 각 샤드는 바이너리의 자신의 작은 조각 내에서만 호출 대상을 찾고 있었고, 샤드 경계를 넘는 모든 호출을 놓쳤습니다 — 이 크기의 바이너리에서는 대부분의 호출이 그렇습니다. 세 가지 버그, 하나의 숫자, 그리고 그 중 어느 것도 예외를 던지는 예의를 갖추지 못했습니다. (또한 IDA의 스택 프레임 분석을 건너뛰어 병합 단계를 줄여보려고 했습니다 — 아름다운 속도 향상과 Hex-Rays가 그 절반의 디컴파일을 정중히 거부하는 데이터베이스를 얻었습니다. 즉시 되돌렸습니다. 대신 훨씬 작고 훨씬 안전한 FLIRT-서명 건너뛰기를 유지했는데, 이는 어깨를 으쓱할 만한 약 3%의 가치가 있었고 아무것도 깨지 않았으며, 이쯤 되면 유지할 가치가 있는 성격 특성처럼 느껴졌습니다.)
이름 지정 정확도에 관하여: Ghidra 수준의 정답이 아니라, 의사 코드에서 추측하는 8B 모델입니다. 일반적인 헬퍼/게터는 대체로 잘 맞습니다; 깊은 게임 특화 로직은 동전 던지기에 가깝습니다. 잘못된 것은 다시 이름을 지정하세요 — 이것이 rename_function이 그래프로 바로 유지되는 이유입니다.
.i64로 병합합니다. 워커는 플래그, 설정 또는 환경 변수를 통해 구성 가능합니다..so/Linux)가 내장되어 제공됩니다; 새 형식을 추가하는 것은 단일 파일이며, 핵심 변경 사항이 없습니다. spectrida formats는 등록된 형식을 나열합니다. 새 바이너리 형식 추가를 참조하세요.N을 누르세요. 생각하는 것을 지켜보세요. 이름이 나타납니다.B를 눌러 목록의 모든 sub_* 함수에 이름을 지정하세요. 자리를 비우세요. 돌아오세요.O를 누르거나 spectrida overview file.i64를 실행하세요. 모델이 120개의 샘플링된 함수 이름을 읽고 바이너리가 무엇을 하는지, 서브시스템이 무엇인지, 그리고 보안 관련 사항을 알려줍니다. 153k 함수 IL2CPP 런타임을 30초 안에 정확히 식별했습니다.C는 호출자와 피호출자를 보여줍니다. 모델은 이름을 지정할 때 이를 컨텍스트로 사용합니다 — Player$$TakeDamage에 의해 호출되는 함수는 고립된 것보다 더 잘 이름이 지정됩니다.D는 Hex-Rays 의사 코드를 전환합니다.pip install spectrida
요구 사항: **IDA Pro 9.x** with idalib · **Python 3.10+** · **Ollama**```bash
# install Ollama (Windows)
winget install Ollama.Ollama
# pull the model (8.7 GB — go get coffee)
ollama pull hf.co/gdfhhjk/spectrida-re-gguf:latest
# first run — detects your IDA install and sets everything up
spectrida onboard
# or just try the demo right now
spectrida --demo
spectrida analyze GameAssembly.dll spectrida analyze GameAssembly.dll --workers 8 # custom worker count
spectrida open file.i64
spectrida overview file.i64 spectrida overview file.i64 --addr 0x10001000 --addr 0x10353fd0 # include specific functions
spectrida export file.i64 -f idc # IDA script — apply names to any install spectrida export file.i64 -f json # full dump with addresses + sizes spectrida export file.i64 -f csv # spreadsheet spectrida export file.i64 -f symbols # addr name pairs spectrida export file.i64 --named-only # skip sub_* functions
spectrida serve
spectrida onboard
---
## TUI 키
| 키 | 동작 |
|-----|--------|
| `N` | 선택한 함수 이름 지정 — AI가 결과를 실시간으로 스트리밍 |
| `R` | 이름 바꾸기 — AI 제안으로 미리 채워짐 |
| `D` | 디컴파일된 의사 코드 전환 (Hex-Rays) |
| `C` | 호출 체인 — 호출자와 피호출자 |
| `B` | 현재 목록의 모든 `sub_*` 함수 일괄 이름 지정 |
| `O` | 개요 — 전체 바이너리의 AI 요약 |
| `/` | 퍼지 검색 |
| `?` | 도움말 |
| `Q` | 종료 |
---
## 프로그래밍 API
TUI가 필요 없습니다 — 스크립트, Claude Code, 노트북 등에서 spectrIDA를 구동하세요:```python
import asyncio
from spectrida.api import open_i64
async def main():
async with open_i64("GameAssembly.i64") as db:
# list all 153k functions
funcs = await db.list_functions()
# name one function — returns name + reasoning + confidence
result = await db.name_function(0x10001000)
print(result["new_name"]) # init_atexit_handler
print(result["reasoning"]) # allocates array of 3 fn ptrs, calls _atexit...
# batch name everything (with live progress)
async def on_progress(done, total, r):
print(f" {done}/{total} {r['old_name']} -> {r['new_name']}")
await db.batch_name(limit=500, rename=True, progress_cb=on_progress)
# ask what the binary does
overview = await db.overview()
print(overview)
# export to IDA script
await db.export("names.idc", fmt="idc", named_only=True)
asyncio.run(main())
hf.co/gdfhhjk/spectrida-re-gguf — 리버스 엔지니어링용으로 파인튜닝된 Qwen3-8B 모델.
학습 데이터:
jtsylve/ida-mcp의 도구 호출 추적 — idalib을 사용한 헤드리스 IDA학습 접근법: 뉴런 타겟 SFT + GRPO. RE 관련 뉴런만 튜닝됨 — 기본 Qwen3 지식은 그대로 유지되며, 특정 스킬만 추가됩니다.
로컬에서 Ollama를 통해 실행됩니다. GGUF — CPU, GPU 또는 둘 다에서 작동합니다.
무언가를 리버싱하고 있습니다. 함수가 150,000개인 바이너리가 있습니다. 메타데이터에서 이름이 있는 함수는 아마 2,000개 정도일 것입니다. 나머지 148,000개는 sub_XXXXXXXX입니다. 네트워크 코드를 찾고 싶습니다. 아무것에 이름이 없기 때문에 grep으로 찾을 수 없습니다.
숙련된 리버서라면 시간당 약 50~100개의 함수에 이름을 붙일 수 있습니다. 그 속도라면 150,000개 함수에 대해 3년이 걸립니다.
spectrIDA는 하룻밤 사이에 이름을 붙입니다. 완벽하지는 않습니다 — 일반 함수에서는 약 70% 정확도, 모델이 인식하는 패턴에서는 훨씬 더 높습니다. 하지만 이제 148,000개의 sub_ 함수 대신 network_send_packet, serialize_player_state, validate_checksum과 같은 이름을 볼 수 있으며, 어디를 봐야 할지 알 수 있습니다.
숙련된 리버스 엔지니어를 대체하지는 않습니다. 지루한 80%를 처리하여 흥미로운 20%에 집중할 수 있게 해줍니다. 방향성을 제공하는 레이어입니다.
실제 사용 사례:
sub_140001234를 쳐다보며 더 나은 방법이 있을 텐데라고 생각한 모든 사람~/.spectrida/config.toml:```toml
[ida]
idalib = "C:/Program Files/IDA Professional 9.1"
output_dir = "~/.spectrida/output"
[ollama] base_url = "http://localhost:11434" model = "spectrida-re" # any ollama model name works
[pipeline] workers = 16
환경 변수 재정의: `SPECTRIDA_IDALIB` · `SPECTRIDA_MODEL` · `SPECTRIDA_WORKERS` · `SPECTRIDA_OLLAMA_URL`
---
## 새 바이너리 형식 추가하기
형식 지원은 if/elif 분기의 더미가 아닌 플러그인 시스템입니다. PE, NSO, ELF는 모두
`spectrida/analysis/formats/` 아래의 파일이며 자동으로 발견됩니다. 현재 등록된 내용을 보려면 `spectrida formats`
를 실행하세요.```bash
$ spectrida formats
ELF spectrida.analysis.formats.elf.ELFHandler
NSO spectrida.analysis.formats.nso.NSOHandler
PE spectrida.analysis.formats.pe.PEHandler
generic spectrida.analysis.formats.generic.GenericHandler
포맷 핸들러의 역할은 좁습니다 — 파일을 보고 소유 여부를 확인한 다음, 코드 레이아웃을 설명하는 것입니다. 그 외 모든 것(샤딩 전략, GPU 프롤로그 스캔, 여러 샤드를 하나의 .i64로 병합)은 한 번, 일반적으로 포맷 패키지 외부에서 처리됩니다. NSO는 완전한 예입니다. LZ4 압축 해제 + idaapi mem2base/add_segm 로직은 이미 nso_loader.py에 존재했습니다(2장의 역사에서 잘못된 아키텍처/여전히 압축된/로컬에서 블라인드된 진입점 버그에 대한 수정) — formats/nso.py는 기존의 검증된 모듈을 FormatHandler 계약을 통해 노출하는 얇은 어댑터일 뿐, 재작성이 아닙니다.
포맷을 추가하려면 spectrida/analysis/formats/에 새 파일 하나만 추가하면 되며, 다른 것은 필요 없습니다. parallel_analyze.py, shard_worker.py, 또는 레지스트리를 수정할 필요가 없습니다. 디렉터리를 스캔하여 HANDLER 인스턴스를 노출하는 모듈을 자동으로 찾기 때문입니다.```python
from spectrida.analysis.formats.base import FormatHandler, PreparedImage, Section
class MyFormatHandler(FormatHandler): name = "MYFMT"
@staticmethod
def sniff(header: bytes, path: str) -> bool:
return header[:4] == b"MYF0" # however you recognize the format
def prepare(self, path: str, workdir: str) -> PreparedImage:
# Format idalib already loads natively (ELF, PE, Mach-O)? Just parse
# the section/segment table — return the original path unchanged.
return PreparedImage(
binary_path=path,
image_base=0,
sections=[Section(name=".text", va=0x1000, raw_off=0x400,
raw_size=0x2000, vsize=0x2000, is_code=True)],
arch=None, # set "x86_64"/"arm64" only if IDA can't detect it itself
)
# Only needed if idalib has NO native loader for this format (NSO is the
# example): do any manual idaapi/ida_segment setup here, called right
# after idapro.open_database() succeeds, before analysis starts.
# def post_open(self) -> None: ...
HANDLER = MyFormatHandler()
전체 계약은 다음과 같습니다:
| 메서드 | 필수? | 기능 |
|---|---|---|
| `sniff(header, path)` | 예 | 매직 바이트/확장자 검사 — 이 핸들러가 파일을 소유합니까? |
| `prepare(path, workdir)` | 예 | `PreparedImage` 반환: idalib이 열어야 할 파일 + 섹션 테이블 |
| `post_open()` | 아니요 (기본값: 동작 없음) | 네이티브 IDA 로더가 없는 포맷을 위한 수동 세그먼트 설정 (`nso.py` 참조) |
| `make_shard_binary(image, dst, va_start, va_end)` | 아니요 (기본값: 정상 동작) | 샤드 외부 섹션 바이트를 0으로 설정하는 것이 포맷에 적합하지 않은 경우에만 재정의 (`nso.py` 참조 — 압축 파일은 절대 0으로 설정하지 마세요) |
| `code_range(image)` | 아니요 (기본값: 정상 동작) | "`is_code` 섹션의 최소/최대"가 올바른 답이 아닌 경우에만 재정의 |
| `read_bytes(image, va_start, va_end)` | 아니요 (기본값: 정상 동작) | `prepare()`가 이미 디스크 대신 메모리(NSO)에 관련 바이트를 보유하고 있는 경우 재정의 |
| `global_entry_points(image, text_start, text_end)` | 아니요 (기본값: None) | 샤드별 로컬 스캔이 실제 진입점을 놓칠 경우에만 재정의 — NSO는 AArch64 리프 함수가 로컬 프롤로그 스캔이 아닌 바이너리 내 다른 곳에서 보이는 BL 대상으로만 발견 가능하기 때문에 필요합니다 |
가장 간단한 핸들러(순수 헤더 구문 분석, 재정의 없음)를 위해 `formats/pe.py`를 확인하고, 전체 케이스(압축 해제 래핑 + 수동 세그먼트 설정 + 모든 재정의)를 위해 `formats/nso.py`를 확인하세요.
타사 패키지도 `spectrida.formats` 진입점 그룹을 통해 spectrIDA의 소스를 전혀 건드리지 않고 핸들러를 등록할 수 있습니다:```toml
# in a separate package's pyproject.toml
[project.entry-points."spectrida.formats"]
myformat = "spectrida_myformat_plugin:HANDLER"
Test coverage for the format system lives in tests/test_formats.py — pure Python, no IDA/idalib required, so it runs in CI.
Chapter 1 was a faster, funnier IDA. Chapter 2 is spectrIDA as a teammate: a persistent, queryable knowledge graph of every function it's ever named, and an MCP server so Claude (or any MCP client — pi works too) can search and reason through it directly, instead of you copy-pasting decompiler output into a chat window.```bash spectrida install mcp
That's it. It registers the server with Claude Code and pi automatically (pulling in `mcp` + `neo4j` if a bare `pip install spectrida` skipped them), writes their config, and tells you which restart you owe it.
**What Claude actually gets, once Neo4j is running (`spectrida` config `[graph]` section, or just point it at a local instance):**
- `search_functions` / `get_function` / `get_callees` / `get_callers` / `trace_chain` — fast, cached graph reads. `get_function` returns pseudocode **and** disassembly (exact instruction boundaries and operands — the layer pseudocode can't give you, which matters the moment you go from "what does this do" to "where exactly would I patch this") plus inline callers/callees, so Claude decides whether to chain deeper by looking at whether a callee is still `sub_*` right there in the response — no extra round trip just to find out there's nothing more to see.
- `get_full_pseudocode` / `rename_function` — live, authoritative reads/writes straight to the `.i64` when the cached snippet isn't enough or a name is finally figured out.
- `analyze_binary` — hand it a binary it's never seen (PE or NSO, parallel-sharded either way) and it runs the whole pipeline — analyze → demangle (Itanium *and* MSVC) → AI-name the genuinely stripped leftovers → push it all into the graph — as one background job you poll, so a multi-minute run never blocks the conversation.
- `doctor` / `start_all` — check or boot llama-server + Neo4j without leaving the chat. If llama-server itself isn't installed anywhere, `start_all` grabs it via winget (Windows) or brew (macOS) first — no separate llama.cpp download/setup needed.
It's not magic — a function that's still `sub_140001234` because nobody's looked at it yet is still `sub_140001234`. But the graph remembers everything the model *has* figured out, forever, across sessions, and Claude can walk it like a colleague who already read the codebase instead of staring at one function at a time.
**Still coming:**
- **Deep context naming** — follow call trees N levels deep, feed the full chain to the model. A function 3 hops from `encrypt_block` should know it's in the crypto path.
- **Deobfuscation** — TigressVM pattern detection and handler tracing
- **Actual patching** — the disassembly is in the graph now so an agent *can* plan a byte-level patch; turning "here's the exact instruction to change" into "and here's the write" is next.
---
## Chapter 3 — the ghost walks through walls
Chapters 1 and 2 read the binary and remember it. But reading a function tells you what it *is*, never what it *does* when you pull the trigger. Chapter 3 — [**phantomrt**](https://pypi.org/project/phantomrt/) — pulls the trigger.```bash
pip install "spectrida[atlas]"
이미 명명된 함수 spectrIDA를 받아서, 다음 세 가지 '무서운' 작업 중 하나를 수행합니다:
.nso 또는 Android .so처럼 실행할 수 없는
바이너리에서 작동하는 유일한 방법입니다.그런 다음 동일한 Neo4j 노드에 dyn_* 속성으로 판정 결과를 기록합니다. 그래프를 탐색하는 에이전트는 한 곳에서 이름 과 동작을 함께 볼 수 있습니다. 6개의 새로운 MCP 도구 —
emulate_function, hunt_crashes, live_trace, dynamic_overview, risk_functions,
learn_vm — 모두 하나의 그래프를 지원합니다. 추론 영역은 LLM이 주도하며; phantomrt
단순히 막연한 추측 대신 실제 런타임 사실을 추론에 사용할 수 있도록 보장합니다.```
spectrIDA (names it) ─▶ phantomrt (runs it) ─▶ graph (dyn_status / crash / live args) ─▶ the agent reasons
**그리고 위의 NSO 공포 이야기의 정신을 이어받아:** 첫 번째 실제 버그 사냥은 솔직히 *아무것도* 찾지 못했습니다. 그리고 그 이유는 크래시보다 더 흥미로웠습니다. 진짜 오래되고 진짜 취약한 FreeType을 대상으로 블라인드 퍼징은 0을 기록했습니다. 이후 커버리지 가이드 퍼징은 자랑스러운 **64,000개 엣지**를 커버했다고 보고했습니다. 하지만 이는 거짓말이었습니다. 바이너리가 PIE였고 ASLR이 실행 때마다 조용히 주소를 다시 섞었기 때문에 "새로운 커버리지"는 대부분 로더가 카드를 섞는 것에 불과했습니다. ASLR을 비활성화하자 정직한 숫자는 *실제* 727개 엣지로 떨어졌고 거기서 정체됩니다. 모든 시드가 TrueType 폰트였기 때문에 퍼저는 하나의 파서 안에 갇혀 버그가 실제로 존재하는 CFF/Type1/BDF 코드로 구조적으로 돌연변이를 일으킬 수 없었기 때문입니다. 해결책은 더 똑똑한 뮤테이터가 아니라 더 나은 시드였습니다. 에이전트가 실제 OpenType/Type1/BDF 샘플을 가져왔고, 단 한 번의 퍼징 반복 전에 커버리지가 727 → 4,013으로 뛰어올랐으며 제대로 탐색했습니다. 여전히 예산 내에서 크래시는 없었습니다. 이는 일반적으로 몇 시간이 걸리는 작업에 비해 단일 코어에서 3분 실행한 정직한 상태입니다. 기계는 진짜입니다. 자신의 *가짜* 숫자를 보고하지 않고 잡아냈습니다. 그게 핵심입니다.
**정직한 고스트 면책 조항:** phantomrt는 `0.1.0`입니다. 알파입니다. 견고한 동적 레이어이지 마법의 버그 오라클이 아닙니다. 장난감 타겟에서 심어진 버그를 즉시 찾았고, 실제 타겟에서는 막혔을 때(`needs_state`), 크래시가 단지 *후보*일 때(포인터가 실제로 입력에 의해 제어되는지 확인), 그리고 더 많은 시간과 더 나은 시드가 필요할 때 정직하게 알려줍니다. 스위치 바이너리는 라이브로 실행되지 않습니다. Frida는 실행할 수 있는 무언가가 필요하므로, 거기서는 에뮬레이션이 유일한 문이며 `needs_state`를 많이 볼 것입니다. 고장난 것이 아니라 정직한 것입니다.
의도적으로 무거운 추가 기능입니다(`torch`, `unicorn`, `frida`). 기본 `pip install spectrida`는 그중 아무것도 가져오지 않습니다. 소스는 [`phantomrt/`](https://github.com/ggfuchsi-oss/spectrida-reverse_engineering_stack/blob/HEAD/phantomrt/)에 있으며, 자체 고스트 풍미의 README는 [바로 거기](https://github.com/ggfuchsi-oss/spectrida-reverse_engineering_stack/blob/HEAD/phantomrt/README.md)에 있습니다.
*정적 고스트는 당신의 함수 이름을 지어줍니다. 이 녀석은 그것들을 자백하게 만듭니다.* 👻
---
## 라이선스
MIT. 원하는 대로 사용하세요. 작동하면 좋고, 작동하지 않으면 GGUF 양자화 탓으로 돌리세요.
악의, 커피, 그리고 RTX 4070으로 제작되었습니다.
모델은 마케팅 제로에 199회 다운로드되었습니다. 각 다운로드는 개발 속도를 0.01% 향상시킵니다.
(사실이 아닙니다. 하지만 거의 비슷합니다.) 👻
| binary | functions | task | time / result |
|---|
| test_small.dll (PE) | 189 | 병렬 분석, 4개 워커, CLI | 6.4s |
| test_small.dll (PE) | 164 | 전체 MCP 파이프라인 (분석 + 디맹글 + 그래프 쓰기) | 9.8s |
| main.nso — Mario Odyssey (NSO), 16 workers | 28,038 seed functions | 병렬 샤드 스캔 단계 | 54.5s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74,790 total functions | + 병합/전체 분석 단계 | 143.1s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74,790 total functions | 엔드투엔드 벽시계 시간 | 197.6s |
| main.nso — Mario Odyssey (NSO) | 74,790 | 디맹글링만으로 해결됨 (Itanium ABI, 무료, AI 없음) | 67,300 (90.0%) |
.idc 스크립트 또는 심볼 파일로 덤프합니다. .idc는 모든 AI 생성 이름을 한 번의 클릭으로 모든 IDA 설치에 적용합니다.from spectrida.api import open_i64. TUI를 건드리지 않고 스크립트, 노트북 또는 Claude Code에서 모든 것을 제어합니다.spectrida install mcp는 Claude Code 및/또는 pi에 직접 연결되며, 수동 JSON 편집이 필요 없습니다. 그러면 Claude는 Neo4j 기반 함수 그래프(이름, 의사 코드, 디스어셈블리, 호출자/피호출자)를 검색/읽기/연결하고 새로운 바이너리 자체에 대한 새 분석을 시작할 수 있습니다 — analyze_binary는 하나의 도구 호출로 전체 파이프라인(병렬 분석 → 디맹글 → AI 네이밍 → 그래프)을 백그라운드 작업으로 실행하고 폴링합니다. PE 및 NSO에서 작동합니다. 아래 2장을 참조하세요.spectrida --demo) — 설정 없이 전체를 시도해보세요. IDA도, Ollama도 필요 없습니다.