3.2 KiB
3.2 KiB
name, description, domain, subdomain, tags, version, author, license, mitre_attack, d3fend, references
| name | description | domain | subdomain | tags | version | author | license | mitre_attack | d3fend | references | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| analyzing-dotnet-malware-internals | Reverses .NET/managed malware: decompiling MSIL back to C#, defeating common .NET protectors and string encryptors, and tracing reflection-based loaders to recover the real payload. Activates for requests to analyze a .NET sample, decompile MSIL, or unpack a managed loader. | cybersecurity | reverse-engineering |
|
1.0.0 | analyst-ai-pack | Apache-2.0 |
|
|
|
Analyzing .NET Malware Internals
When to Use
- A sample is a managed (.NET) assembly — confirmed by a CLR header /
mscoreeimport orBSJBmetadata signature. - You need readable C# from MSIL and want to defeat .NET-specific obfuscation.
- A loader uses reflection (
Assembly.Load) to run an in-memory payload you must recover.
Do not use native disassembly workflows (Ghidra for x86) as the primary tool — managed code decompiles far more cleanly with a .NET decompiler.
Prerequisites
- ILSpy / dnSpyEx for decompilation and (with dnSpyEx) managed debugging.
- de4dot or equivalent for known protectors; familiarity with common .NET obfuscators.
Workflow
Step 1: Confirm it is managed
Check for the CLR runtime header and the BSJB metadata magic:
python scripts/analyst.py identify sample.exe
Step 2: Decompile
Open in ILSpy/dnSpyEx and review the entry point, Main, and module initializer
(<Module>.cctor), which protectors often abuse.
Step 3: Handle obfuscation
Recognize and undo common schemes:
- String encryption — a decryptor method called everywhere; run/trace it to recover plaintext (de4dot can often static-decrypt).
- Control-flow flattening — follow the dispatcher state machine.
- Proxy methods / renaming — rely on decompiler analysis rather than names.
Step 4: Trace reflection loaders
Find Assembly.Load(byte[]) / Activator.CreateInstance; dump the byte array argument at
runtime (managed debugger breakpoint) to recover the real second-stage assembly, then recurse.
Step 5: Analyze the payload
Decompile the recovered stage; extract C2, configuration, and capabilities for the report.
Validation
- Decompiled C# is coherent (named or recovered) and the entry path is traced.
- Encrypted strings are recovered to plaintext.
- The reflection-loaded stage is dumped and itself decompiles.
Pitfalls
- Treating the loader as the payload — managed malware is frequently multi-stage.
- Ignoring the module initializer where protectors install hooks.
- Static-decrypting strings when the scheme is runtime-keyed; debug and dump instead.
References
- See
references/api-reference.mdfor the CLR identifier. - ECMA-335 and ILSpy (linked in frontmatter).