$npx -y skills add meltedinhex/analyst-ai-pack --skill analyzing-dotnet-malware-internalsReverses .NET/managed malware: decompiling MSIL back to C#, defeating common
| 1 | # Analyzing .NET Malware Internals |
| 2 | |
| 3 | ## When to Use |
| 4 | |
| 5 | - A sample is a managed (.NET) assembly — confirmed by a CLR header / `mscoree` import or |
| 6 | `BSJB` metadata signature. |
| 7 | - You need readable C# from MSIL and want to defeat .NET-specific obfuscation. |
| 8 | - A loader uses reflection (`Assembly.Load`) to run an in-memory payload you must recover. |
| 9 | |
| 10 | **Do not use** native disassembly workflows (Ghidra for x86) as the primary tool — managed |
| 11 | code decompiles far more cleanly with a .NET decompiler. |
| 12 | |
| 13 | ## Prerequisites |
| 14 | |
| 15 | - ILSpy / dnSpyEx for decompilation and (with dnSpyEx) managed debugging. |
| 16 | - de4dot or equivalent for known protectors; familiarity with common .NET obfuscators. |
| 17 | |
| 18 | ## Workflow |
| 19 | |
| 20 | ### Step 1: Confirm it is managed |
| 21 | |
| 22 | Check for the CLR runtime header and the `BSJB` metadata magic: |
| 23 | |
| 24 | ```bash |
| 25 | python scripts/analyst.py identify sample.exe |
| 26 | ``` |
| 27 | |
| 28 | ### Step 2: Decompile |
| 29 | |
| 30 | Open in ILSpy/dnSpyEx and review the entry point, `Main`, and module initializer |
| 31 | (`<Module>.cctor`), which protectors often abuse. |
| 32 | |
| 33 | ### Step 3: Handle obfuscation |
| 34 | |
| 35 | Recognize and undo common schemes: |
| 36 | |
| 37 | - **String encryption** — a decryptor method called everywhere; run/trace it to recover |
| 38 | plaintext (de4dot can often static-decrypt). |
| 39 | - **Control-flow flattening** — follow the dispatcher state machine. |
| 40 | - **Proxy methods / renaming** — rely on decompiler analysis rather than names. |
| 41 | |
| 42 | ### Step 4: Trace reflection loaders |
| 43 | |
| 44 | Find `Assembly.Load(byte[])` / `Activator.CreateInstance`; dump the byte array argument at |
| 45 | runtime (managed debugger breakpoint) to recover the real second-stage assembly, then recurse. |
| 46 | |
| 47 | ### Step 5: Analyze the payload |
| 48 | |
| 49 | Decompile the recovered stage; extract C2, configuration, and capabilities for the report. |
| 50 | |
| 51 | ## Validation |
| 52 | |
| 53 | - Decompiled C# is coherent (named or recovered) and the entry path is traced. |
| 54 | - Encrypted strings are recovered to plaintext. |
| 55 | - The reflection-loaded stage is dumped and itself decompiles. |
| 56 | |
| 57 | ## Pitfalls |
| 58 | |
| 59 | - Treating the loader as the payload — managed malware is frequently multi-stage. |
| 60 | - Ignoring the module initializer where protectors install hooks. |
| 61 | - Static-decrypting strings when the scheme is runtime-keyed; debug and dump instead. |
| 62 | |
| 63 | ## References |
| 64 | |
| 65 | - See [`references/api-reference.md`](references/api-reference.md) for the CLR identifier. |
| 66 | - ECMA-335 and ILSpy (linked in frontmatter). |