Files
RE-AI/docs/MCP_SERVERS.md
John Smith f5e5e9e72c feat(re-lief): categorize_strings tool + catalog-driven string bucketing
Adds a keyword-bucketed strings dump to the re-lief MCP server, turning
the manual-grep step that today lives in the LLM's head into a
catalog-driven, deterministic lookup. Superset of extract_strings
(same {ascii, utf16le, totals, truncated} shape for backward compat)
plus a by_category block with 11 semantic categories (anti_debug,
hwid, crypto, network, registry, process, file, fingerprint,
activation, obfuscation, misc).

The categorization vocabulary lives in a new
data/drm-indicators.yaml::string_categories section. Two seed
categories (anti_debug, hwid) inherit their keyword lists from
existing catalog sections via a seed_from / seed_field YAML pointer
— when a future agent adds a new HWID API to hwid_apis.high_signal,
the categorizer picks it up on next MCP-server reload with zero
Python change. The YAML is the single source of truth for both the
indicator set that re-drm-fingerprint reads and the keyword set
that the categorizer reads.

Five skills (re-static-triage, re-malware-triage, re-drm-fingerprint,
re-vm-reverse, re-format-decode) had their manual-grep step replaced
with a call to re-lief.categorize_strings. No new workflow steps
were added — the categorizer IS the string scan.

ANTI-TAMPER-TAXONOMY.md gains a "Recognizing the patterns in
arbitrary binaries" section that documents Pattern A (encrypted-VM
bytecode interpreter: 7 section-name co-occurrence + W^X .idata +
.text virt>>raw + .ecode lazy-decrypt stub + vendor-tagged PDB +
late-bound export tail + 8+ HWID APIs) and Pattern B
(hardware-fingerprinting routine in a third-party launcher
activation library: ordinal-only exports + WinHTTP + OpenSSL +
HWID-vector APIs + split anti-debug surface) in vendor-neutral
category terms. No vendor / publisher / game / PDB-path literals
appear in any shipped file.

Tests: 7 new soft-skip tests in test_re_lief_categorize_strings.py
covering the result shape, the seed_from inheritance, the bundled
Activation64.dll high-signal hits, the legacy extract_strings
wrapper, and the GameAssembly full-section vs skip_sections paths.
All always-on tests (leakage, frontmatter, server registration,
smoke) continue to pass. ./verify.sh is green.
2026-06-05 16:01:49 -04:00

20 KiB

MCP Servers Reference

The RE-AI plugin ships 10 MCP servers. Each one exposes a set of tools to Claude Code via the standard Model Context Protocol stdio JSON-RPC transport.

Server Wraps Status
re-lief LIEF (in-process) always available
re-llm-decompile OpenAI-compatible HTTP needs a running endpoint
re-rizin rizin / rz-bin CLI needs rizin on PATH
re-capa capa (Mandiant) CLI needs pip install flare-capa
re-mitm2swagger mitmproxy + mitmproxy2swagger needs pip install mitmproxy mitmproxy2swagger
re-kaitai kaitai-struct-compiler + kaitaistruct needs kaitai-struct-compiler on PATH
re-gdb GDB + GEF needs gdb on PATH and ~/.gdb/gef.py
re-triton Triton (in-process) needs pip install triton
re-il2cpp Unity global-metadata.dat reader (pure Python) always available
re-winedbg Wine winedbg gdbserver + gdb client needs wine + winedbg on PATH (Linux/macOS)

Servers that are missing dependencies will report it cleanly from their check_<name>() tool rather than crashing. The plugin is usable in degraded mode with only the no-deps servers (re-lief, re-llm-decompile, and re-il2cpp).


re-lief

Pure Python (no system deps). Wraps LIEF for cross-format binary analysis: PE, ELF, MachO, COFF, DEX, ART, OAT in a single, normalized API. Also includes a Capstone fallback for disassembly.

Tools

Tool Description
check_lief Health check — return LIEF version, supported formats
parse_binary Auto-detect format and return normalized header
get_sections Section list with permissions, virtual vs raw size, entropy, W^X flag
get_imports_exports Symbol-level import/export tables
get_imphash PE import hash (MD5 of normalized import table)
get_overlay Appended data after the last section (PE)
get_authenticode PE signature details
list_dex_classes All classes in a Dalvik DEX file
list_dex_methods Methods of a DEX class by FQN
list_oat_art Methods in an OAT/ART file
disasm_capstone Capstone disassembly (works for any LIEF-parsed binary)
extract_strings ASCII + UTF-16LE strings, section-aware
categorize_strings ASCII + UTF-16LE strings, section-aware, bucketed into 11 keyword categories from data/drm-indicators.yaml::string_categories. Superset of extract_strings (same ascii / utf16le / totals / truncated shape, plus a by_category block).
normalize_for_diff Structural snapshot for cross-binary diffing

categorize_strings — keyword-bucketed strings dump

A superset of extract_strings: same {ascii, utf16le, totals, truncated} shape, plus a by_category block keyed by semantic category (anti_debug, hwid, crypto, network, registry, process, file, fingerprint, activation, obfuscation, misc). Categories are loaded from data/drm-indicators.yaml::string_categories at module import time; the anti_debug and hwid categories inherit their keyword lists from drm-indicators.yaml::anti_debug_indicators.checks[].name and hwid_apis.high_signal[].api respectively (a seed_from: pointer in the YAML). When the catalog is updated, the categorizer picks the new keywords up on next MCP server reload.

Why use it instead of extract_strings: the manual keyword-grep that the v2.4 skills did in the LLM's head is now a deterministic lookup. The categorization is consistent across runs (no LLM variance) and the result is JSON-serializable directly into the triage report.

Memory note: on a 500+ MB binary (e.g. a Unity IL2CPP GameAssembly.dll wrapped by an encrypted-VM bytecode interpreter), pass skip_sections=[".idata", ".xtls", ".xpdata", ".udata", ".xdata", ".didata", ".ecode", ".00cfg"] to skip the encrypted-VM bytecode regions. Note: on the bundled Input/rhinehartpcfg/ sample, the import-table strings live inside those sections, so skipping them blinds the categorizer to the imports. Use skip_sections for memory-bound runs; use the full section walk for completeness.

Replaces v1 code

The pefile + capstone code from backend/analysis/native.py was ported into parsers.py and disasm.py. LIEF supersedes pefile (same data for PE, plus ELF/MachO/DEX/ART/OAT). The string-extraction algorithm (ASCII + UTF-16LE, regex-driven) is salvaged from v1 and generalized.

LIEF API quirks (v0.16+)

  • The format enum is lief.Binary.FORMATS (not lief.FORMATS or lief.Formats)
  • Section is a base class; concrete sections are ELF.Section, PE.Section, MachO.Section — each with its own FLAGS constant
  • has_dynamic, has_relro, has_bind_now were dropped from the public API in 0.17. We work around this with getattr(elf, name, False)
  • LIEF 0.17.6 Binary has no .strings property. A common mistake is to do b = lief.parse(path); b.strings — it raises AttributeError. Use re-lief.categorize_strings (or re-lief.extract_strings / re-rizin.list_strings for the unfiltered flat list).

re-llm-decompile

HTTP-only (no system deps). Wraps any OpenAI-compatible chat-completions API — LLM4Decompile served via vLLM, Ollama with OPENAI_COMPAT=1, OpenAI itself, etc.

Tools

Tool Description
check_endpoint Hit /v1/models, return the list of available models
decompile_function Send disassembly to the LLM, return C-like pseudocode
explain_function Have the LLM explain disassembly (no rewrite)
rename_variables LLM proposes better names for compiler-generated symbols
summarize_binary Whole-binary summary from strings + imports + entry-point disasm

Configuration

Env var Default Purpose
LLM_DECOMPILE_ENDPOINT http://localhost:11434/v1 OpenAI-compatible base URL
LLM_DECOMPILE_MODEL llm4decompile Model name to request
LLM_DECOMPILE_API_KEY (empty) API key (use sk-... for OpenAI; empty for Ollama)

Choosing a model

  • LLM4Decompile 22B (Ref): best quality for Linux x86_64 binaries, ~44GB VRAM (or AWQ/GPTQ).
  • LLM4Decompile 6.7B (Ref): good middle ground, ~14GB VRAM.
  • Ollama + Qwen2.5-Coder 7B: general-purpose code model, lower decompile quality but good at explanation.
  • Claude / GPT (via this server): not recommended — call Claude directly through Claude Code.

re-rizin

Subprocess wrapper around the rizin CLI. 12 tools covering the most common static-analysis operations.

Tools

Tool Description
check_rizin Confirm rizin + rz-bin are installed
get_file_info rz-bin -I — arch, bits, type, pic, canary, nx
list_imports_exports rz-bin -i / -E — symbol tables
list_strings rz-bin -z/-zz/-zzz — ASCII / UTF-16 / all
analyze_function aa + afl — list all functions
disassemble_function pdf — full disassembly of one function
decompile_function pdc — pseudo-C decompile (lower quality than IDA/Ghidra)
get_xrefs axt / axf — cross-references
search_bytes /x — hex pattern search
find_crypto_constants Detect AES / SHA / CRC tables
emulate_esil aefi — ESIL emulation
get_cfg_graph agf — DOT-format CFG

Install

apt install rizin       # Debian/Ubuntu
brew install rizin       # macOS
scoop install rizin      # Windows

re-capa

Subprocess wrapper around capa (Mandiant). 4 tools for capability detection with MITRE ATT&CK and MBC mappings.

Tools

Tool Description
check_capa Version + rules path
detect_capabilities Full capa report (JSON or vverbose)
extract_mbc Just the Malware Behavior Catalog mappings
find_interesting High-confidence / unique matches only

Install

pip install flare-capa

re-mitm2swagger

Wraps mitmproxy (live capture) + mitmproxy2swagger (spec derivation). 8 tools.

Tools

Tool Description
check_mitm Confirm mitmdump is on PATH
start_capture Spawn mitmdump in the background
stop_capture Stop a previously-started capture
parse_flows Read a mitmproxy flow file
har_to_swagger Convert HAR → OpenAPI 3.0 spec (with path templating)
flow_to_swagger mitmproxy2swagger on a flow file → OAS
filter_flows Filter flows by method/host/path/status/content-type
extract_secrets Heuristically find tokens, JWTs, API keys

Path templating rules

har_to_swagger applies these in order:

  1. /<digits>/{id}
  2. /<uuid>/{uuid}
  3. /<base64-looking>/{token}
  4. /<sha1/256 hex>/{hash}

re-kaitai

Wraps the kaitai-struct-compiler (system) + kaitaistruct (Python). 6 tools for custom binary format reverse engineering.

Tools

Tool Description
check_compiler Confirm kaitai-struct-compiler is installed
list_known_formats List bundled .ksy formats
download_format Download a .ksy from the kaitai-formats gallery
compile_format Compile .ksy → Python at runtime
parse_with_format Parse a binary with a compiled or precompiled format
visualize Same as parse_with_format, named for intent
diff_parses Parse two files and return a structural diff

Install

brew install kaitai-struct-compiler   # macOS
scoop install kaitai-struct-compiler  # Windows
# Linux: download prebuilt from https://github.com/kaitai-io/kaitai_struct_compiler/releases
pip install kaitaistruct

re-gdb

Wraps GDB + GEF for dynamic analysis. 14 tools covering session lifecycle, breakpoints, stepping, memory, and GEF-specific commands.

Tools

Tool Description
check_gdb Confirm gdb + GEF
start_session Open a session, optionally load a binary
end_session Tear down a session
run_to_breakpoint Set a BP and run
step_count Single-step N times, return registers
read_memory x/N fmt ADDR
gef_heap GEF heap chunks
gef_canary GEF canary
gef_registers GEF registers
gef_vmmap GEF vmmap
gef_nearpc GEF nearpc
gef_pattern_create Cyclic pattern generator
gef_pattern_offset Find offset of a value in a pattern
attach_pid Attach to a running process

Safety

Never run unsigned binaries on a host you care about. Use a sandbox.

Cross-platform

The server uses pexpect (POSIX) or pywinpty (Windows) for the GDB subprocess. On Windows gdb is rough; prefer WSL.


re-triton

Wraps the Triton library for symbolic execution. 6 tools.

Tools

Tool Description
check_triton Confirm Triton is importable
emulate_function Concrete emulation (no sym)
symbolic_explore Symbolic execution through a function
solve_constraint Z3-based constraint solver
taint_analysis Taint tracking through a function
find_magic_bytes Solve for input that produces target bytes

Note

Triton operates on raw machine code, not files. Tools accept code_b64 (base64-encoded bytes) — the caller extracts the relevant bytes from the binary. Best-effort on Windows.


re-il2cpp

Pure-Python (no system deps). Reads Unity's global-metadata.dat to recover the C# class/method/field names that the IL2CPP compiler stripped from the game binary, AND walks the 7 binary record tables to return a structured class graph (parent types, method/field/property/event counts, type indices, tokens). Pairs with re-rizin for RVA cross-referencing. The optional resolve_method_rva tool parses GameAssembly.dll directly (requires pip install re-il2cpp[rva]).

Tools

Tool Description
check_il2cpp Read the metadata header — version, magic, file size
list_strings Pull strings from the unprotected C# symbol table (filter by substring)
search_strings Substring search of the symbol table (returns index + string)
list_namespaces Bucketed namespace list with class counts
list_classes Class FQN list (optionally filtered by namespace prefix)
get_type_definitions Walk the binary typeDefinitions table; return structured records (parent, type_index, method/field/property/event counts, flags, token)
get_methods Typed methods of a class (token, parameter count, return type index)
get_fields Typed fields of a class (token, type index)
get_parameters Typed parameters of a method in declaration order
get_properties Properties of a class (with has_getter / has_setter flags)
get_events Events of a class (with has_add / has_remove / has_raise flags)
get_images Assembly images (e.g. Assembly-CSharp.dll, UnityEngine.CoreModule.dll) with type ranges
resolve_method_rva Resolve a method FQN to its GameAssembly.dll RVA (requires lief)

Limitations

  • Type indices are returned as raw int32s. return_type_index and type_index in method/field records point into the runtime Il2CppType table; full name resolution requires reading s_Il2CppMetadataRegistration::types[] from GameAssembly.dll, which is a v2.3.0 follow-up. Cross-reference against get_type_definitions's type_index field for the most common case.
  • RVA resolution requires non-stripped GameAssembly.dll. Shipped Unity release builds strip the s_Il2CppCodeRegistrations symbol; for these, resolve_method_rva returns the structured data plus the IL2CPP mangled name to use with re-rizin.search_bytes.
  • Metadata versions 24-29 only (Unity 2019.4 - 2022.3 LTS). Unity 6 / metadata v30+ uses a different on-disk format and is not supported.
  • No mmap fallback to disk if the file is huge. Memory-maps the file at full size; 10.9 MB works fine, 500+ MB would be a problem (no game ships a global-metadata.dat that large today, but watch for it).

Example

# 1. Verify the file
re_il2cpp.check_il2cpp(metadata_path=".../global-metadata.dat")
# -> {version: 27, magic: "0xFAB11BAF", file_size_bytes: 10900000, ...}

# 2. Top-level inventory
re_il2cpp.list_namespaces(metadata_path="...", limit=20)

# 3. Classes in a specific game namespace
re_il2cpp.list_classes(metadata_path="...", namespace="Game")

# 4. Typed structure of a class
re_il2cpp.get_type_definitions(metadata_path="...", namespace="Game", limit=20)

# 5. Methods of a specific class
re_il2cpp.get_methods(metadata_path="...", class_fqn="Game.SaveGameManager")

# 6. Parameters of a method
re_il2cpp.get_parameters(metadata_path="...", method_fqn="Game.SaveGameManager.Save")

# 7. Resolve a method to its GameAssembly.dll RVA
re_il2cpp.resolve_method_rva(
    metadata_path=".../global-metadata.dat",
    gameassembly_path=".../GameAssembly.dll",
    method_fqn="Game.SaveGameManager.Save",
)
# -> {fqn, class_fqn, name, image_name, method_index,
#     pointer_table_rva, function_rva, rva_status, source}

# 8. Disassemble the function (if function_rva was returned)
re_rizin.disassemble_function(
    gameassembly_path, function="<function_rva from step 7>", max_insns=200,
)

re-winedbg

Drives the winedbg gdbserver (a debugger shim that ships with Wine) plus a GDB client subprocess, so a Linux or macOS host can attach to a Windows .exe and observe its behavior at runtime. Reuses re-gdb.gdb_mi.GDBSession for the gdb-client side. Runs the .exe in a per-session WINEPREFIX under ~/.cache/re-ai-wine/<session>/; the global ~/.wine is never touched, and end_session refuses to wineserver -k any prefix outside that cache root. 19 tools.

Tools

Tool Description
check_winedbg Confirm wine + winedbg + gdb are installed. Returns {status, wine_path, winedbg_path, gdb_path, *_version}. On Windows: status: ERROR, error: host_not_supported (re-winedbg is Linux/macOS only).
launch_under_wine Run a .exe under Wine (no debugger attached); returns the host-side PID for later attach_pid use.
start_winedbg_gdbserver Spawn winedbg --gdb <port> <exe>; the binary is paused at its entry point.
attach_winedbg_gdbserver Open a GDB client subprocess and target remote the gdbserver. Populates the per-module base-address cache from info sharedlibrary.
set_breakpoint By symbol, *<addr>, or <module>+0x<RVA> — RVA is resolved via the per-module base cache.
remove_breakpoint By breakpoint id.
continue_execution Resume; return the next stopped event as {reason, frame_addr, frame_func}.
step_into / step_over / step_out Single-step primitives (stepi / nexti / finish).
read_registers / write_register info registers parsed into a {name: hex} dict / set $reg = <val>.
read_memory / write_memory x/... / set {<type>}<addr> = <val>. Use write_memory for runtime NOP-out, hook install, or in-memory decryption-stub replacement.
info_modules info sharedlibrary parsed (drives the RVA cache).
info_threads info threads.
backtrace bt <n>.
gef_trace_breakpoint Server-side commands N; silent; printf "<fmt>", $<reg>; continue; end with a hit counter. Replaces the manual GDB-command workaround the v1 re-vm-reverse skill used.
end_session Close GDB client, stop the gdbserver, wineserver -k the per-session prefix (refuses to kill ~/.wine), kill the wine process tree. Idempotent.

Install

install.sh (POSIX) installs wine + winedbg via apt / dnf / brew on a best-effort basis. Set RE_AI_SKIP_WINE=1 to opt out. On Windows, re-winedbg is not useful (the user has the native Windows debuggers; winedbg is a Linux/macOS compatibility shim) and check_winedbg returns {status: ERROR, error: host_not_supported}.

# Linux (Debian / Ubuntu)
sudo apt-get install -y wine wine64 winedbg

# Linux (Fedora / RHEL)
sudo dnf install -y wine winedbg

# macOS
brew install --cask wine-stable

Per-session WINEPREFIX

Every start_winedbg_gdbserver / launch_under_wine call creates a fresh random WINEPREFIX under ~/.cache/re-ai-wine/<session-id>/ (overridable via the wine_prefix arg). The global ~/.wine is never touched, and end_session will refuse to wineserver -k any prefix that does not start with ~/.cache/re-ai-wine/. This guarantees we don't kill another Wine session the user has running.

Typical end-to-end

# 1. Confirm wine / winedbg / gdb are reachable
re_winedbg.check_winedbg()
# -> {status: "OK", wine_path: "/usr/bin/wine", winedbg_path: "/usr/bin/winedbg", ...}

# 2. Spawn winedbg gdbserver, paused at entry
re_winedbg.start_winedbg_gdbserver(exe="/path/to/Foo.exe", port=0, session="analyze")
# -> {port: 41357, command_line: "winedbg --gdb 41357 -- /path/to/Foo.exe", ...}

# 3. Connect gdb client + populate the module base cache
re_winedbg.attach_winedbg_gdbserver(session="analyze", host="127.0.0.1", port=41357, exe="/path/to/Foo.exe")

# 4. Set an RVA-resolved breakpoint
re_winedbg.set_breakpoint(session="analyze", target="GameAssembly.dll+0x1234567")

# 5. Continue to the breakpoint
re_winedbg.continue_execution(session="analyze", timeout_s=10)
# -> {event: {reason: "breakpoint-hit", frame_addr: "0x...", frame_func: "..."}}

# 6. Inspect state
re_winedbg.read_registers(session="analyze")
re_winedbg.read_memory(session="analyze", addr="0x...", count=32, fmt="hex")

# 7. Trace a hot handler (server-side printf + continue)
re_winedbg.gef_trace_breakpoint(
    session="analyze", target="*<dispatcher_addr>",
    register="$rcx", format="idx=%d\\n", max_hits=1000,
)
# -> {hits: [{n: 0, regs: {rcx: "0x2a"}}, {n: 1, regs: {rcx: "0x3b"}}, ...], truncated: false}

# 8. Tear down
re_winedbg.end_session(session="analyze")