| check_dotnetA | Return .NET runtime + re-dotnet-cli + ilspycmd availability. Reports WARN (not ERROR) if either binary is not found —
this lets Claude Code load the plugin in degraded mode and
surface a useful message instead of crashing. The :func:runner._cli_binary / :func:runner._decompiler_binary
fallback chains search $RE_DOTNET_CLI_PATH /
$RE_DOTNET_DECOMPILER_PATH first, then
<server>/bin/, then $PATH. |
| parse_assemblyA | Enumerate TypeDef rows in path. Returns the assembly header (name, version, target framework,
entry point) plus a one-row-per-type summary. This is the
.NET cousin of re-lief.parse_binary and re-il2cpp
.get_assembly_types — the analyst's first call on a
.NET-style launcher or mod-loader. Output shape:: {
"header": {
"path": "...",
"assembly_name": "...",
"assembly_version": "...",
"target_framework": "...",
"corlib": "...",
"is_mixed_mode": bool,
"entry_point": "Namespace.Type::Method",
"file_kind": "assembly" | "netmodule",
"type_count": N,
"method_count": N,
"field_count": N,
},
"types": [
{"fqn": "...", "namespace": "...", "name": "...",
"is_public": bool, "method_count": N, "field_count": N,
"property_count": N, "event_count": N, "nested_type_count": N,
"base_type": "..."},
...
],
"truncated": false
}
|
| decompile_typeA | Decompile a single class to C# via ilspycmd. Args:
path: path to a .dll / .exe .NET assembly
fqn: fully-qualified type name (e.g. MyGame.PlayerController).
Discover candidates with :func:parse_assembly first. Returns:: {"path": "...", "fqn": "...", "code": "C# source..."}
On decompiler failure (e.g. an obfuscated control-flow pattern
ilspycmd refuses to lift, or ilspycmd not installed), returns
code: null and a non-null error field. ilspycmd is the
industry-standard CLI for ILSpy; for protected binaries the next
step is re-decompile (which calls into de4dot for unpacking)
before re-running this tool. |
| decompile_methodA | Decompile a single method to C# via ilspycmd. Args:
path: path to a .dll / .exe .NET assembly
fqn: "Namespace.Type::MethodName" (the :: separator
matches the C++ convention; do not use . between
type and method name — those are both parts of the
type FQN) Returns:: {"path": "...", "fqn": "...", "code": "C# method body..."}
|
| list_stringsA | Extract user-visible strings from the .NET #US heap. Two modes: "field-default" (default): walks every type's
const string field-default values. Best for the
pure-.NET path where most strings live in static readonly
fields.
"ldstr" (v2.8.1, A11): walks every method body's IL
stream and captures every ldstr operand. Best for the
Mono path (CD's MonoLauncher is the canonical example) where
most useful strings live in ldstr operands, not
field-defaults.
The C# CLI subcommand is list-strings for field-default
and list-ldstr for ldstr (both implemented in
:mod:Re.Dotnet.Cli.Ops.MetadataOps). On encrypted /
obfuscated #US heaps the CLI returns count: 0 silently —
that's a legitimate "heap unreadable" signal, not a regression. Args:
path: path to a .dll / .exe .NET assembly
mode: "field-default" (default) or "ldstr"
limit: maximum strings to return (default 500) Returns:: {"path": "...", "mode": "...", "count": N, "truncated": bool,
"strings": [{"fqn": "...", "kind": "...", "il_offset": N,
"string": "..."}, ...]}
|
| get_entry_pointA | Return the managed entry point (<Module>::.cctor or Main). Useful for "what does the launcher do first?" — point a
decompiler at the entry point before reading the rest of the
class graph. |
| get_methodsA | List the methods of one type (Mono / .NET pure assembly). Pure routing: the C# CLI already implements list-methods
in :mod:Re.Dotnet.Cli.Ops.MetadataOps (uses
System.Reflection.Metadata via the .NET 10 runtime). This
MCP wrapper is the v2.8.1 (A12) addition that exposes the
Mono path the r03-stress run flagged as missing. A12 note (v2.8.0): on Mono assemblies (e.g. CD's MonoLauncher)
this tool did not exist; callers had to fall back to
decompile_type + regex on the C# source. The MCP wrapper
fixes the routing gap; the underlying CLI subcommand is
already battle-tested on the IL2CPP path
(re-il2cpp.get_methods uses the same code path). Args:
path: path to a .dll / .exe .NET or Mono assembly
fqn: fully-qualified type name (e.g. MyGame.PlayerController)
limit: max rows to return (default 500) Returns:: {"path": "...", "fqn": "...", "type_fqn": "...",
"count": N,
"methods": [{"name": "...", "signature": "...",
"is_public": bool, "is_static": bool,
"is_virtual": bool, "is_abstract": bool,
"is_final": bool, "is_special_name": bool,
"rva": N, "token": "..."}, ...]}
|
| get_fieldsA | List the fields of one type (Mono / .NET pure assembly). Same routing pattern as :func:get_methods. The CLI
subcommand is list-fields in
:mod:Re.Dotnet.Cli.Ops.MetadataOps. A12 (v2.8.1): added so the CD-3 patch coordinates (which
need the field name _isSteam) can be discovered without
decompile_type first. Args:
path: path to a .dll / .exe .NET or Mono assembly
fqn: fully-qualified type name
limit: max rows to return (default 200) Returns:: {"path": "...", "fqn": "...", "type_fqn": "...",
"count": N,
"fields": [{"name": "...", "field_type": "...",
"is_public": bool, "is_static": bool,
"is_read_only": bool, "is_literal": bool,
"constant": "..."}, ...]}
|
| classify_dotnet_protectionA | Walk a .NET assembly for canonical obfuscation patterns. Returns category-only labels (type-name-renaming,
control-flow-flattening, string-encryption,
managed-anti-debug, resource-encryption,
native-aot-stub). Never names a specific commercial
obfuscator. The walker uses the re-dotnet Python helper
:mod:re_dotnet.protection_classifier (pure-Python
IL/Metadata subset; no need for the .NET CLI binary
to be built). The CLI is only used for type-name listing
(already covered by :func:parse_assembly). Args:
path: path to a .dll / .exe .NET assembly
max_per_category: per-category cap (default 50) Returns:: {
"path": "...",
"matches": [{"category": "...", "evidence": "...",
"evidence_member": "..."}, ...],
"by_category": {"type-name-renaming": 12, "string-encryption": 4, ...}
}
|
| detect_managed_anti_debugA | Scan IL method bodies for managed anti-debug primitives. Looks for IsDebuggerPresent, Debugger.IsAttached,
Debug.Assert, Debugger.Break, and the curated
indirect-check set (timing traps, process-name blacklists,
registry probes). Returns {method_fqn, primitive,
evidence_il_offset} per hit. The category is
"managed-anti-debug"; no vendor is named. Args:
path: path to a .NET assembly
max_per_method: cap per method (default 500; a single
method with 500+ anti-debug calls is itself a
signal — the cap is for safety, not for
normality) Returns:: {
"path": "...",
"hits": [{"method_fqn": "...", "primitive": "...",
"evidence_il_offset": N}, ...],
"by_primitive": {"IsDebuggerPresent": 4, ...}
}
|
| run_il_simplificationA | Run a d810-ng-style IL simplification pass set on one method. Currently supported passes: constant_fold — replace arithmetic on constants with
the constant result.
dead_branch_elim — remove branches that are provably
dead after constant folding.
opaque_predicate_eval — evaluate predicates whose
truth is provable from prior dataflow.
string_decrypt — replace
ldstr; call Get<name>(); ret patterns with the
literal string. The decryption function name is
auto-detected from the assembly's #Strings heap.
Args:
path: path to a .NET assembly
method_fqn: "Namespace.Type::MethodName"
passes: optional override; default is
["constant_fold", "dead_branch_elim",
"opaque_predicate_eval", "string_decrypt"]. Returns:: {
"path": "...",
"method_fqn": "...",
"passes_applied": [...],
"before_il_size": N,
"after_il_size": M,
"il_before": "...",
"il_after": "..."
}
|