Files
RE-AI/CHANGELOG.md
John Smith 895514bd93 docs(anti-tamper-taxonomy): Pattern B references license-activation bucket
Post-run follow-up to the 2026-06-06-r01 stress test
(Output/2026-06-06-r01/gap-analysis.md). The C1 catalog refactor
split 'activation' into 'ue-component-activation' and
'license-activation'; ANTI-TAMPER-TAXONOMY.md's Pattern B fire
rule was still reading 'activation.count' which now points to
the (much smaller) license-activation bucket. The 615
false-positive hits in P3R.exe's UE component vocabulary no
longer trip the Pattern B threshold of 50 strings.

CHANGELOG.md [2.5.1] entry: full release notes for the Cycle 2
post-run follow-up (14 tool-bug fixes + 6 catalog refactors
+ 1 new leak category + 1 KSY backport, no new MCP servers,
no new skills).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 15:57:00 -04:00

27 KiB
Raw Permalink Blame History

Changelog

All notable changes to RE-AI will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[2.5.1] - 2026-06-06

Cycle 2 — post-run follow-up to the 2026-06-06-r01 multi-target stress test (Output/2026-06-06-r01/cross-target.md, Output/2026-06-06-r01/gap-analysis.md). 14 tool-bug fixes + 6 catalog refactors + 1 new leak category + 1 KSY backport. No new MCP servers added; no new skills added.

Fixed

  • re-winedbg.start_winedbg_gdbserver — dropped the unused _pick_free_port-based TCP-port path; switched stdin from DEVNULL to PIPE so Wine 11.0's stdio-based gdbserver works. The peeked port is still reported in the response for diagnostic purposes. (servers/re-winedbg/src/re_winedbg/winedbg.py)
  • re-gdb.gdb_mi.GDBSession._drain — replaced the getattr(..., "set_blocking", None) or .setblocking chain with a pair of getattr(default=None) probes; the prior form raised AttributeError on Python 3.14 where setblocking is gone. (servers/re-gdb/src/re_gdb/gdb_mi.py)
  • re-capa._run_capa — default timeout bumped from 300s to 900s with auto-scaling by file size (900s for >= 10 MB inputs); resolves the default-rules-path lookup so the bundled rules are passed via --rules even when the caller passes rules="". (servers/re-capa/src/re_capa/capa_runner.py)
  • re-capa.find_interesting — new heuristic: a namespace is "interesting" iff it has >= min_score rules AND at least one rule in that namespace has an ATT&CK or MBC mapping. The prior version returned 0 hits on every binary because the namespace threshold was too coarse.
  • re-rizin.search_bytes — added _sanitize_hex_pattern() that strips spaces, normalizes case, and removes non-hex chars before passing to rizin's /x. The prior form silently returned 0 matches for 0F 31 (the canonical RDTSC anti-debug probe) and 0F 84 (the universal JE rel32). Verified: 6 RDTSC hits in Core/Activation64.dll, 196K JE-rel32 hits in the proprietary-engine main exe.
  • re-rizin.analyze_function — added _auto_timeout_s(path, base=600): 600s base, +60s per 100 MB above 100 MB, cap at 1800s. The prior 120s default timed out on every binary > 300 MB.
  • re-rizin.disassemble_function — replaced the f"s {function}" seek command with multiple flag-resolution paths before pdf @ <addr>. The prior form returned 0 instructions for entry0 on stripped binaries (the function name doesn't resolve to a flag until after aaa, and auto_level=1 only runs aa).
  • re-lief.get_authenticode — added _safe_str() that decodes LIEF 0.17.x's bytes issuer / serial_number to str (UTF-8 with latin-1 fallback) so the dict is JSON-encodable. The prior form raised TypeError: Object of type bytes is not JSON serializable on 4/4 binaries × 3 targets = 12 errors.
  • re-llm-decompile.get_model — default changed from llm4decompile (not in the user's Ollama registry) to deepseek-v4-flash:cloud (the cloud model the user has available). The auto-fallback to llama3.2:3b produced HTTP 500 on decompile prompts.
  • re-llm-decompile._pick_fallback_model — fidelity-aware preference list: code-specialized models first (deepseek-coder, qwen2.5-coder, codellama, codeqwen, starcoder, wizardcoder), then larger / coder-flavored chat models, then general purpose.
  • re-triton._probe_arch_enum + _make_triton_context — probe triton.ARCH (Quarkslab 0.x) and fall back to triton.CPU / triton.cpus (Quarkslab 1.x). Replace triton.TritonContext(arch) with getattr(triton, "TritonContext", triton.Triton)(arch) for the same 0.x / 1.x compatibility. The prior form returned supported_archs: [] and raised AttributeError: module 'triton' has no attribute 'TritonContext'.
  • re-kaitai.parse_with_format — after compile_format: call importlib.invalidate_caches(), pop the cached entry from sys.modules, then re-import. The prior form returned stale results on a second call with the same ksy_path because Python's import cache held the first-parse module.
  • data/ksy/unityfs.ksy — file-header layout corrected: inserted bundle_format_version strz + file_size s8, deleted the phantom platform / has_directory_info / reserved fields, removed the has_directory_info param coercion on the inner bundle_header sub-type. Fixed compressed_block_info.uncompressed_size from s8 to u4 (per the upstream AssetStudio / UABE references; the 8-byte read was walking into flags and num_blocks).
  • data/ksy/unityfs.ksyendian: le was wrong; the on-disk Addressables bundle has 00 00 00 07 at offset 8 (version=7 BE), not 07 00 00 00 (version=117M LE). Changed to endian: be. (The 2026-06-06-r01 plan instructed the opposite based on speculation; the live file is the source of truth and it is big-endian.)
  • data/ksy/unity_addressables.ksy — the Cycle 2 plan instructed flipping this file's endian: be → le based on the same wrong assumption. Reverted — the original endian: be was correct. Also fixed compressed_block_info.uncompressed_size: s8 → u4.

Changed

  • C1data/drm-indicators.yaml::string_categories.activation split into activation (kept for backward-compat) + ue-component-activation (Unity component-lifecycle noise) + license-activation (the real license-gate vocabulary). ANTI-TAMPER-TAXONOMY.md::Pattern B now references license-activation.count (was activation.count). 615 false-positive hits in P3R.exe are now suppressed.
  • C2fingerprint split into custom-fingerprint (high-signal HW-fingerprint literals) + windows-com-api-name (standard COM / typelib property names; 48 FPs in P3R.exe are now suppressed).
  • C3telemetry_leak gets exclude_keywords: for asian / Asian / Asia / albanian / Albanian / width / Width / East_Asian_Width / Caucasian_Albanian / stasianwidth / sesasianwidth. 13 Unicode-UCD FPs in P3R.exe are now suppressed.
  • C4hwid (seeded from hwid_apis.high_signal) gets exclude_keywords: for cl /Zi /Fd, ossl_static.pdb, /Fdopenssl. 1 OpenSSL-static-link FP in P3R.exe is now suppressed.
  • C5obfuscation gets exclude_keywords: for __TBB_ / tbb:: / tbb::task / TBB_internal / C:\ci\builds\ / C:/ci/builds/ / C:\BuildBot\ / /ci/builds/. 41 TBB / CI-build FPs in tbb12.dll are now suppressed.
  • C6anti_debug_indicators.checks[].confirmation: field added; enum string_only / import_only / requires_disasm / requires_xref. The 4 byte-pattern checks (RDTSC, INT 2D, INT 3, exception-hooking decoy) are now requires_disasm so the string-table presence of "RDTSC" alone no longer fires the bucket. The exception-hooking and scattered-bit register storage checks are requires_disasm and requires_xref respectively. Pending: the consumer-side re-drm-fingerprint change to consult confirmation: is deferred to a follow-up (the catalog now has the metadata; the consumer wiring is a small change).
  • L1 — new publisher-internal-diagnostic-hostname leak detector added to servers/re-leak-scan/src/re_leak_scan/ patterns.py. The pattern matches an internal-TLD anchor (.internal, .corp, .lan, .local, .intra, .private, .home.arpa) + a diagnostic-product stem (jenkins, jira, grafana, prometheus, kibana, splunk, sentry, bitbucket, gerrit, artifactory, nexus, sonarqube, vault, consul, etcd, datadog, newrelic, pagerduty) to keep the false-positive rate low (the public jenkins.io does not match). Discovered in target-B's pers.exe::PASystemInfoScanner.SenderInfomation (a .NET WPF class that does a DNS lookup of a publisher-internal .io TLD staging relay and conditionally sends the un-hashed machine fingerprint to it). Risk: HIGH.
  • servers/re-lief/src/re_lief/categorizers.py — added load_excludes() (returns {category_name: [exclude, ...]})
    • categorize() now honors the exclude list. Backward- compatible: existing call sites that don't add exclude_keywords: to their YAML entries see no behavior change. New YAML schema fields: exclude_keywords: (per category, optional) and confirmation: (per anti_debug_indicators.checks[] entry, optional).

[2.5.0] - 2026-06-05

Added

  • re-lief.categorize_strings — new MCP tool. Superset of extract_strings (same {ascii, utf16le, totals, truncated} shape for backward compatibility) plus a by_category block bucketing the strings into 11 keyword categories (anti_debug, hwid, crypto, network, registry, process, file, fingerprint, activation, obfuscation, misc). The anti_debug and hwid categories inherit their keyword lists from data/drm-indicators.yaml::anti_debug_indicators.checks[].name and hwid_apis.high_signal[].api via a seed_from: YAML pointer — when the catalog is updated, the categorizer picks the new keywords up on next MCP-server reload. Other categories have their keyword lists inline in the YAML under the new string_categories: section. New skip_sections parameter for memory-bound runs on >100 MB Unity IL2CPP binaries.
  • data/drm-indicators.yaml::string_categories — new section with 11 categories and the seed_from: / seed_field: schema extension that lets a category inherit from another catalog list. This is the first consumer of the catalog in re-lief (the prior consumers were all in the skills); the YAML remains the single source of truth for both the indicator set and the keyword set.
  • servers/re-lief/src/re_lief/categorizers.py — new module that loads the catalog (with a small pre-processor to neutralize the regex-literal \.X strings the catalog has used for plain-text LLM consumption), resolves seed_from: pointers via dotted-path walking, and exposes categorize(matches, categories, samples_per_category) for the parser. Cached via lru_cache; restart the MCP server to pick up YAML edits.
  • tests/test_re_lief_categorize_strings.py — new soft-skip smoke test that asserts the result shape, the seed_from: inheritance works, and the bundled sample (Input/<target-A>/Core/Activation64.dll) populates crypto / network / anti_debug / hwid / activation as expected. Mirrors the test_re_lief_imports.py soft-skip pattern.
  • ANTI-TAMPER-TAXONOMY.md — new "Recognizing the patterns in arbitrary binaries" section — documents Pattern A (encrypted-VM bytecode interpreter + the .ecode lazy-decrypt stub + the late-bound export tail + 7-section-name co-occurrence) and Pattern B (hardware-fingerprinting routine in a third-party launcher activation library with ordinal-only exports + WinHTTP + OpenSSL + HWID-vector APIs) in vendor-neutral category terms. No vendor / publisher / game / PDB-path literals. The "How to detect the patterns" subsection ties the patterns to the new re-lief.categorize_strings tool's by_category output.

Changed

  • servers/re-lief/src/re_lief/parsers.py::extract_strings_for_binary is now a thin wrapper around the new categorize_strings (passes categories=[], include_misc=False, max_per_category=200). Output shape is unchanged; no caller-side migration required.
  • 5 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.
  • re-static-triage description gains "categorize the strings" in the trigger-phrase list (frontmatter is still under the 200-char cap and well above the 40-char floor).
  • servers/re-lief/README.md gets a categorize_strings row and a "Categorization vocabulary" paragraph explaining the seed_from: pointer and the catalog-as-source-of-truth invariant.

Vendor neutrality

  • All 11 category names (anti_debug, hwid, crypto, network, registry, process, file, fingerprint, activation, obfuscation, misc) are generic and pass the tests/test_no_vendor_leakage.py grep. The string_categories keywords (1,000+ substrings in data/drm-indicators.yaml) are all from generic Windows API names, OpenSSL source paths, and standard protocol substrings — no vendor or PDB literal appears. The new ANTI-TAMPER-TAXONOMY.md section uses only category names ("encrypted-VM bytecode interpreter", "hardware-fingerprinting routine", "third-party launcher activation library") and the observable composition that defines them.

[2.4.0] - 2026-06-05

Added

  • 10th MCP server: 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's GDBSession for the gdb-client side; each session gets its own WINEPREFIX under ~/.cache/re-ai-wine/<session>/ (the global ~/.wine is never touched). 19 vendor-neutral tools.
  • re-winedbg.gef_trace_breakpoint — server-side commands N; silent; printf "<fmt>", $<reg>; continue; end with a hit counter and a structured {hits: [{n, regs}], truncated: bool} return. Replaces the manual GDB-command workaround in re-vm-reverse Stage 4 (line 67 of the v1 skill explicitly called for this tool).
  • install.sh wine + winedbg install path — best-effort install of wine + winedbg on apt / dnf / brew hosts. Opt-out via RE_AI_SKIP_WINE=1. Always a warning, never a fatal error (mirrors the existing 5-minute install-script design — missing optional tools never block the install).
  • install.bat — new wine / winedbg discovery block; warns the user that re-winedbg requires WSL on Windows hosts.
  • scripts/check_deps.py::check_wine() — new dependency row in the install report.
  • tests/test_re_winedbg.py — soft-skip tests for check_winedbg, the GDB-CLI parsers (parse_sharedlibrary, parse_registers, parse_stopped), the wineserver_kill safety guard, and a behavioural launch_under_wine smoke test (skipped without RE_AI_WIN32_FIXTURE).
  • Skill re-dynamic-analysis extended with a "Windows .exe on Linux (via Wine + winedbg)" section walking through check_winedbgstart_winedbg_gdbserverattach_winedbg_gdbserverset_breakpoint (with RVA + symbol + absolute forms) → continue_execution / step_* / read_registers / read_memory / info_modulesgef_trace_breakpointwrite_memoryend_session. Frontmatter unchanged (description is still 318 chars, well above the 40-char floor).
  • Skill re-vm-reverse Stage 4 updated to use re-winedbg.gef_trace_breakpoint on Windows targets; the v1 manual step_count loop is retained as the Linux-ELF fallback path. The "Limitations" bullet at the old line 139 is updated to match.
  • tests/test_plugin_manifest.py::test_mcp_json_includes_re_winedbg — new manifest test (mirrors test_mcp_json_includes_re_il2cpp).
  • tests/test_servers_import.py — new re-winedbg row in the parametrized expected-tools list (19 tools).
  • verify.sh and verify.bat — updated inline assertion from len(d)==9 to len(d)==10 and added "re-winedbg" in d to the check. The opening echo / print now reads "10 servers with the 8 originals + re-il2cpp + re-winedbg".

Changed

  • The MCP-server count is now 10 (was 9). The "8 originals + re-il2cpp" invariant in verify.sh / verify.bat is updated to "8 originals + re-il2cpp + re-winedbg".
  • Bumped .claude-plugin/plugin.json and root pyproject.toml to 2.4.0.
  • Bumped servers/re-winedbg/pyproject.toml to 0.1.0.
  • install.sh final-echo / install.bat final-echo — "9 servers" → "10 servers".

Vendor neutrality

  • The new server's tool names, docstrings, README, and skill extensions are vendor-neutral: no commercial anti-tamper product, publisher, or game title appears in any shipped file. The winedbg / wine / wineserver / WINEPREFIX / WINEDBG_PATH / WINE_PATH / WINESERVER_PATH / re-winedbg strings are tool / env-var / server-slug identifiers, not commercial names. tests/test_no_vendor_leakage.py continues to pass.

[2.3.0] - 2026-06-04

Added

  • re-il2cpp.get_assembly_types(metadata_path, image_name) — new MCP tool that walks the typeDef range owned by a single IL2CPP image. Enumerates the publisher's Assembly-CSharp.dll (or any other assembly) end-to-end and returns the same shape as get_type_definitions but scoped to one image. Returns all 2,697 Assembly-CSharp.dll types that the string-table scan in list_classes can't surface.
  • data/ksy/unity_raw.ksy — new KSY for the Unity raw asset bundle format (the level* and sharedassets* files in this target use this format, not UnityFS).
  • skills/re-il2cpp-static-triage/SKILL.md — new condensed 30-second triage skill focused on the recoverable class graph; explicitly does NOT promise to read function bodies. Complements the longer re-il2cpp-decompile skill.
  • unityfs.ksy directory-block parsing (v0.2 of the spec) — bundle_header.directory, directory_entry, and per-block records (compressed_block_info.blocks) added. The synthetic-parse test exercises the full file → bundle_header → compressed_block_info → blocks → directory → entries chain.
  • Behavioral test coverage for re-capa, re-lief, re-triton, and re-kaitai (4 new tests/test_re_*.py files). pytest tests/: 36 passed / 11 skipped (the +1 is the synthetic-parse test, which skips on hosts without kaitaistruct).
  • docs/the-il2cpp-game-binary-triage.md — refreshed end-to-end smoke test report of every MCP server + key skill against the bundled Unity IL2CPP sample. Confirms the IL2CPP class-graph recovery pipeline (re-il2cpp), binary header / section / import analysis (re-lief + re-rizin), capa capability detection (re-capa), and asset-bundle format handling (re-kaitai).

Fixed

  • servers/re-capa/ ships without sigs/capa.sig; every real call fails until the sig is dropped into both .venv-re-ai/lib/python3.11/site-packages/sigs/ and servers/re-capa/.venv/lib/python3.11/site-packages/sigs/. install.sh now downloads the sig from mandiant/capa into both venvs.
  • data/ksy/unityfs.ksy is uncompilable: every strz field needed encoding: UTF-8; the bundle_header call site needed a bool coercion; the magic field needed a YAML \0 escape. All fixed; the spec now compiles cleanly against kaitai 0.10.
  • servers/re-triton/pyproject.toml pinned triton>=0.6, which resolved to the Triton GPU compiler (PyPI) instead of the binary-analysis framework the plugin needs. Repinned to the correct source-build URL. install.sh pulls the source build. (The GPU-compiler / Quarkslab-Triton name collision is also defended in servers/re-triton/src/re_triton/server.py — a missing Quarkslab Triton now returns a structured {"status": "ERROR", "error": "triton_unavailable", ...} per-tool instead of crashing the MCP server.)
  • re-capa.find_interesting and re-capa.extract_mbc did not pass the rules argument through to detect_capabilities. Now accepted and forwarded.
  • re-lief.get_imports_exports on stripped binaries returned blank name fields (the LIEF import loop was one level too shallow). Now walks the inner imp.entries loop, so per-function names are recovered.
  • unityfs.ksy declared endian: be but real UnityFS is little-endian. Switched to endian: le; the synthetic-parse test uses LE encoding.
  • re-kaitai.list_known_formats used a hard-coded tuple of names that drifted out of sync with what kaitaistruct actually ships. Now globs the package directory.
  • re-il2cpp.list_classes with empty namespace did not surface Assembly-CSharp.dll types (the publisher's game code is in the root namespace). The new get_assembly_types(image_name) tool fills the gap.

[2.0.0] - 2026-06-04

Changed

  • Complete rewrite as a Claude Code plugin (skills + MCP servers). The v1 FastAPI + React + SQLite + ChromaDB + WebSocket agent loop architecture has been removed entirely. Claude Code is the agent now.
  • Cross-platform packaging: Linux (apt/brew) and Windows (winget/scoop) installers with parallel Python and system-tool provisioning.

Added

  • 8 MCP servers: re-rizin, re-capa, re-lief, re-llm-decompile, re-mitm2swagger, re-kaitai, re-gdb, re-triton.
  • 12 skills: re-static-triage, re-decompile, re-api-reverse, re-format-decode, re-dynamic-analysis, re-symbolic-exec, re-malware-triage, re-vuln-research, re-report, plus re-vm-reverse, re-mba-deobfuscate, re-drm-fingerprint for anti-tamper / VM-pack analysis.
  • data/drm-indicators.yaml companion data file with KUSER offsets, PEB fields, HWID-vector API catalog, section heuristics, VM dispatcher patterns, MBA identity catalog, anti-debug catalog, and pattern indicators (vendor-neutral) for the encrypted-VM / VM-pack / legacy disc-protection categories.
  • Plugin manifest at .claude-plugin/plugin.json and MCP registry at .mcp.json with ${CLAUDE_PLUGIN_ROOT} resolution.
  • install.sh / install.bat (idempotent, all warnings non-fatal) and verify.sh / verify.bat smoke tests.
  • scripts/check_deps.py dependency report.
  • Test suite: manifest, frontmatter, server import, and smoke tests for every MCP server.

Decisions

  • Sogen (momo5502/sogen) NOT added as an MCP server. License is GPL-2.0 which conflicts with the MIT plugin; setup cost (hundreds-of-MB emulation root) is non-trivial; the methodology from the third-party anti-tamper analysis post is achievable with existing servers (re-rizin + re-triton + re-gdb). If demand materializes, isolate as GPL-2.0 in servers/experimental/re-sogen/.
  • No vendor-specific anti-tamper skill was created. The post's methodology is packaged as three generic skills (re-vm-reverse, re-mba-deobfuscate, re-drm-fingerprint) that apply to VM-based and anti-tamper-protected binaries generally, so they remain useful as new protection schemes appear.

Removed

  • backend/ (FastAPI + custom agent loop + tool registry + RAG + planning engine)
  • frontend/ (React 19 + Vite 8 SPA)
  • tests/ (old pytest suite that tested the deleted backend)
  • dev.bat and start.bat (Windows-only batch files)
  • re-ai.db* (SQLite working-tree residue)
  • .chroma/ and .test_chroma* (ChromaDB working-tree residue)
  • All v1 skills/*.md files (content absorbed into v2 skills and docs)

Migrated (content preserved)

  • The 5-step static analysis workflow and indicator-triage table from skills/static_analysis_workflow.md are absorbed into skills/re-static-triage/SKILL.md.
  • The pefile + capstone analysis code from backend/analysis/native.py is ported and generalized to LIEF in servers/re-lief/.
  • The pefile caveats and capstone arch/mode mapping from skills/pefile.md and skills/capstone.md are moved to docs/MCP_SERVERS.md (planned for v1).

[2.2.0] - 2026-06-04

Added

  • re-il2cpp walks all 7 binary tables in global-metadata.dat: typeDefinitions, methods, fields, parameters, properties, events, images. 7 new tools exposed: get_type_definitions, get_methods, get_fields, get_parameters, get_properties, get_events, get_images. Tools return structured records with parent, type index, token, member counts — the same data that Il2CppDumper produces, but as JSON via MCP.
  • re-il2cpp.resolve_method_rva resolves a Namespace.ClassName.MethodName FQN to its GameAssembly.dll RVA by parsing the runtime registration structures. For non-stripped builds it returns the function RVA directly; for stripped builds (the default for shipped Unity games) it returns the structured data plus the IL2CPP mangled name to use with re-rizin.search_bytes. Requires pip install re-il2cpp[rva] (LIEF is an optional dep).
  • re-il2cpp sub-version detection for v24 (24.1, 24.2, 24.4) via the same tree Il2CppDumper uses (Metadata.cs:67-83).
  • re-il2cpp lief>=0.16,<0.18 declared as an optional rva extra — the table-walk tools work without LIEF; only the RVA resolver needs it.
  • 9 new soft tests in tests/test_re_il2cpp_check.py covering each new tool against the bundled Unity IL2CPP sample (one of which soft-skips if LIEF is not installed).
  • Bumped .claude-plugin/plugin.json and root pyproject.toml to 2.2.0. Bumped servers/re-il2cpp/pyproject.toml to 0.2.0.

Changed

  • re-il2cpp-decompile skill updated: Step 4 recommends the new get_type_definitions for structured class graphs; Step 5 adds the typed get_methods / get_fields / get_parameters flow; Step 6 uses resolve_method_rva as the primary path with re-rizin.search_bytes demoted to a fallback for stripped binaries; the Limitations section drops the "does not walk" bullet and adds the "type_index not fully resolved" caveat.
  • re-il2cpp is still 9 MCP servers / 13 skills (this is a feature add, not a count change).

[2.1.0] - 2026-06-04

Added

  • 9th MCP server: re-il2cpp — pure-Python mmap-based reader for Unity global-metadata.dat (versions 24-29). Exposes check_il2cpp, list_strings, search_strings, list_namespaces, list_classes. No system dependencies; safe in degraded mode.
  • 13th skill: re-il2cpp-decompile — orchestrates re-il2cpp + re-rizin to triage a Unity IL2CPP game, recover C# class/method/field names, and cross-reference GameAssembly.dll RVAs.
  • data/ksy/unityfs.ksy — starter Kaitai Struct spec for UnityFS asset bundle header (used by re-format-decode).
  • tests/test_re_il2cpp_check.py — 3 soft smoke tests against the bundled Unity IL2CPP global-metadata.dat; tests skip when the sample is absent.
  • docs/ARCHITECTURE.md diagram updated to reflect 13 SKILL.md files and 9 MCP servers.

Changed

  • Bumped .claude-plugin/plugin.json and pyproject.toml to 2.1.0.
  • Updated version counts and component indexes across README.md, docs/SKILLS.md, docs/MCP_SERVERS.md, docs/ARCHITECTURE.md, docs/MIGRATION_FROM_V1.md, docs/TROUBLESHOOTING.md, verify.sh, and verify.bat to 9 MCP servers / 13 skills.
  • Fixed verify.sh and verify.bat stale inline assertion (len(d)==8) — they now check the mcpServers key, require the 8 originals to be a subset, and require re-il2cpp to be present.

Known limitations

  • re-il2cpp reads only the string table of global-metadata.dat; walking the binary typeDefinitions / methods / fields tables is left for a future enhancement.
  • re-il2cpp supports metadata versions 24-29 (Unity 2019.4 - 2022.3 LTS). Unity 6 / metadata v30+ uses a different on-disk format.

[1.x] - 2024 to 2026-06-04

Legacy v1 release history (FastAPI + React + SQLite + ChromaDB architecture) — not preserved in this repository.