Skip to main content

reverser-dotnet-malware

.NET malware analysis — dnSpy/ILSpy decompilation, de-obfuscation (ConfuserEx, .NET Reactor, Babel, Crypto Obfuscator), behavioral analysis of managed assemblies, PowerShell cradle extraction, and config decryption for common .NET RAT families.

跳到安装

来源信息

仓库
BitterSecurity/Decepticon
最近来源活动
2026年6月29日 01:38
检测到的 SKILL.md 语言
英语
星标
5,522
分支
1,048

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
reverser-dotnet-malware
description
.NET malware analysis — dnSpy/ILSpy decompilation, de-obfuscation (ConfuserEx, .NET Reactor, Babel, Crypto Obfuscator), behavioral analysis of managed assemblies, PowerShell cradle extraction, and config decryption for common .NET RAT families.
allowed-tools
Bash Read Write
metadata
{"when_to_use":"dotnet .net malware dnspy ilspy de4dot deobfuscate confuserex reactor obfuscation managed assembly csharp vbnet msil cil rat stealer loader","subdomain":"reverser","tags":".NET, malware, deobfuscation, dnSpy, ILSpy, de4dot","mitre_attack":"T1027.002, T1140, T1059.001"}
# .NET Malware Analysis Analyze .NET malware from initial triage through full decompilation, de-obfuscation, config extraction, and behavioral mapping. ## Quick Reference ```bash # Identify .NET assembly file <TARGET> python3 -c "import pefile; pe=pefile.PE('<TARGET>'); print('CLR:', pe.OPTIONAL_HEADER.DATA_DIRECTORY[14].VirtualAddress)" # Fast metadata check monodis --assembly <TARGET> strings -n 10 <TARGET> | grep -iE 'System\.Reflection|Assembly\.Load|FromBase64|Invoke|WebClient|DownloadString' # De-obfuscate with de4dot de4dot <TARGET> -o <TARGET>.cleaned.exe # Decompile to C# project ilspycmd -p -o ./decompiled/ <TARGET> # Extract embedded resources python3 -c " import dnfile dn = dnfile.dnPE('<TARGET>') for r in dn.net.resources: print(f'{r.name} offset={r.offset} size={r.size}') " ``` ## MITRE ATT&CK Mapping | Technique | ID | How It Appears | |---|---|---| | Software Packing | T1027.002 | ConfuserEx, .NET Reactor, SmartAssembly, Babel packing | | Deobfuscate/Decode | T1140 | Base64 decode + Assembly.Load, XOR decryption of payloads | | PowerShell | T1059.001 | Cradle execution: `powershell -enc <base64>` from managed code | | Obfuscated Files | T1027 | String encryption, control flow flattening, anti-tamper | | Reflective Code Loading | T1620 | Assembly.Load(byte[]) for in-memory stage loading | ## 1. Identify .NET Assembly Confirm the sample is managed code before committing to .NET tooling. ```bash # Check PE headers for CLR data directory (index 14) python3 << 'EOF' import pefile, sys pe = pefile.PE("<TARGET>") clr_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[14] if clr_dir.VirtualAddress > 0: print(f"[+] .NET assembly confirmed — CLR RVA: {hex(clr_dir.VirtualAddress)}") # Check runtime version import struct clr_offset = pe.get_offset_from_rva(clr_dir.VirtualAddress) pe.__data__.seek(clr_offset + 8) major, minor = struct.unpack('<HH', pe.__data__.read(4)) print(f" Runtime: v{major}.{minor}") else: print("[-] Not a .NET assembly") sys.exit(1) EOF # Alternative quick checks file <TARGET> # Look for "Mono/.Net assembly" exiftool <TARGET> | grep -i "assembly\|\.net\|framework" ``` ## 2. Detect Obfuscator Identify what protection was applied before attempting decompilation. ```bash # de4dot auto-detects most obfuscators de4dot --detect-only <TARGET> # Output example: "Detected .NET Reactor 6.x" # Detect It Easy (DIE) for packer/protector identification diec <TARGET> # Manual signature checks strings <TARGET> | grep -iE 'ConfuserEx|Reactor|SmartAssembly|Babel|Crypto Obfuscator|Dotfuscator|Eazfuscator|AgileDotNet' # Check for anti-tamper / anti-debug module initializers monodis --method <TARGET> | grep -i "cctor\|InitializeComponent\|Module" # Entropy per section — high entropy in .text = packed/encrypted python3 << 'EOF' import pefile, math pe = pefile.PE("<TARGET>") for s in pe.sections: data = s.get_data() if len(data) == 0: continue counts = [data.count(bytes([b])) for b in range(256)] total = len(data) ent = -sum((c/total)*math.log2(c/total) for c in counts if c) name = s.Name.decode().rstrip('\x00') print(f" {name:10s} entropy={ent:.2f} {'PACKED' if ent > 7.2 else 'normal'}") EOF ``` ## 3. De-obfuscate Strip protections layer by layer. ```bash # de4dot — handles ConfuserEx, .NET Reactor, SmartAssembly, Babel, etc. de4dot <TARGET> -o <TARGET>.cleaned.exe # If de4dot detects "Unknown obfuscator", try force mode: de4dot <TARGET> --strtyp delegate --strtok 0x06000042 -o <TARGET>.cleaned.exe # For ConfuserEx specifically: # 1. Remove anti-tamper first (patches module cctor) de4dot <TARGET> --un-name "!^<Module>$&!^<" -o step1.exe # 2. Then full clean de4dot step1.exe -o <TARGET>.cleaned.exe # For .NET Reactor: # Use .NET Reactor Slayer or NETReactorSlayer NETReactorSlayer.CLI <TARGET> # Verify result decompiles cleanly ilspycmd <TARGET>.cleaned.exe | head -50 ``` ## 4. Decompile and Analyze Full source recovery from cleaned assembly. ```bash # ILSpy command-line — full project decompilation ilspycmd -p -o ./decompiled/ <TARGET>.cleaned.exe # Search decompiled source for key behaviors grep -rn "WebClient\|HttpClient\|WebRequest" ./decompiled/ grep -rn "Registry\|RegistryKey\|SetValue" ./decompiled/ grep -rn "Process\.Start\|ProcessStartInfo" ./decompiled/ grep -rn "Assembly\.Load\|Activator\.CreateInstance" ./decompiled/ grep -rn "FromBase64String\|Convert\.FromBase64" ./decompiled/ grep -rn "RijndaelManaged\|AesManaged\|DES\|TripleDES\|RC4" ./decompiled/ grep -rn "Socket\|TcpClient\|NetworkStream" ./decompiled/ grep -rn "Clipboard\|Screenshot\|Keylog\|GetAsyncKeyState" ./decompiled/ # Extract hardcoded C2 / config grep -rn "http://\|https://\|ftp://\|\b[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\b" ./decompiled/ # Dump embedded resources (payloads, configs, second stages) python3 << 'EOF' import dnfile, os dn = dnfile.dnPE("<TARGET>.cleaned.exe") os.makedirs("resources", exist_ok=True) for res in dn.net.resources: if hasattr(res, 'data') and res.data: path = f"resources/{res.name}" open(path, 'wb').write(res.data) print(f"[+] Extracted: {path} ({len(res.data)} bytes)") EOF ``` ## 5. PowerShell Cradle Extraction .NET loaders frequently spawn encoded PowerShell. ```bash # Find encoded PowerShell invocations in decompiled source grep -rn "\-enc\|\-EncodedCommand\|\-e " ./decompiled/ # Decode base64 PowerShell payloads python3 << 'EOF' import base64, sys encoded = "<BASE64_PAYLOAD>" decoded = base64.b64decode(encoded).decode('utf-16-le') print(decoded) # Write to file for further analysis with open("decoded_ps.ps1", "w") as f: f.write(decoded) EOF # Look for staged downloads grep -iE 'DownloadString|DownloadFile|DownloadData|Invoke-Expression|IEX|Net\.WebClient' decoded_ps.ps1 ``` ## 6. Config Extraction for Known Families ```bash # AsyncRAT config extraction python3 << 'EOF' import base64, hashlib from Crypto.Cipher import AES # AsyncRAT stores config as encrypted strings in Settings class # Key is derived from a hardcoded passphrase via PBKDF2 passphrase = "<EXTRACTED_KEY>" # From Settings.Key in decompiled source salt = b"<EXTRACTED_SALT>" # From Settings.aession key = hashlib.pbkdf2_hmac('sha1', passphrase.encode(), salt, 50000, dklen=32) # Each config field is Base64(IV + AES-CBC(data)) config_fields = { "Host": "<ENC_HOST>", "Port": "<ENC_PORT>", "Mutex": "<ENC_MUTEX>", } for name, enc in config_fields.items(): raw = base64.b64decode(enc) iv, ct = raw[:16], raw[16:] cipher = AES.new(key, AES.MODE_CBC, iv) pt = cipher.decrypt(ct) pt = pt[:-pt[-1]] # PKCS7 unpad print(f" {name}: {pt.decode()}") EOF # QuasarRAT — config in Settings class, AES-encrypted # njRAT — config in plain text fields, base64-encoded # AgentTesla — SMTP exfil config in Settings resource ``` ## 7. Behavioral Analysis with dnSpy ``` # dnSpy interactive workflow (Windows GUI): # 1. Load cleaned assembly: File → Open → <TARGET>.cleaned.exe # 2. Set breakpoints on: # - EntryPoint (Main method) # - Any method calling WebClient/HttpClient # - Any method calling Process.Start # - Any method calling Assembly.Load # 3. Debug → Start (F5) — dnSpy hosts the CLR # 4. Step through, watch locals for decrypted strings/URLs # 5. Memory window: watch for in-memory PE headers (4D 5A) # Headless: dump method bodies via Mono.Cecil python3 << 'EOF' # pip install dnfile import dnfile dn = dnfile.dnPE("<TARGET>.cleaned.exe") for row in dn.net.mdtables.MethodDef: if row.ImplFlags.miIL: print(f" Token 0x{row.row_index:08X} {row.Name} RVA={hex(row.RVA)}") EOF ``` ## Tools & Resources | Tool | Purpose | Install | |---|---|---| | dnSpy | .NET debugger + decompiler (GUI) | github.com/dnSpy/dnSpy | | ILSpy / ilspycmd | .NET decompiler (GUI + CLI) | github.com/icsharpcode/ILSpy | | de4dot | .NET de-obfuscator | github.com/de4dot/de4dot | | dotPeek | JetBrains .NET decompiler | jetbrains.com/decompiler | | dnlib / dnfile | .NET metadata parsing (Python/C#) | pip install dnfile | | Mono.Cecil | .NET assembly manipulation | nuget Mono.Cecil | | NETReactorSlayer | .NET Reactor unpacker | github.com/SychicBT/NETReactorSlayer | | Detect It Easy | Packer/protector identification | github.com/horsicq/Detect-It-Easy | | AsmResolver | .NET PE/metadata library | github.com/Washi1337/AsmResolver | ## Detection Signatures | Indicator | Description | Sigma/YARA | |---|---|---| | `Assembly.Load(byte[])` | Reflective loading of in-memory .NET payload | YARA: `$s1 = "Assembly" ascii wide` + `$s2 = "Load" ascii wide` | | `FromBase64String` + `Assembly.Load` | Base64 decode → reflective load chain | Sigma: process_creation with CommandLine containing `-enc` | | `WebClient.DownloadString` | Stage 2 download via .NET HTTP client | Network: HTTP GET to non-standard port | | ConfuserEx metadata | `ConfusedBy` attribute in assembly | YARA: `$conf = "ConfusedByAttribute"` | | High entropy .text section | Packed/encrypted .NET payload | YARA: `math.entropy(0, filesize) > 7.0` | | `csc.exe` compilation at runtime | Dynamic code compilation via CodeDom | Sysmon: Event ID 1, process `csc.exe` with parent not devenv/msbuild | ## Error Handling & Edge Cases | Issue | Resolution | |---|---| | de4dot crashes on sample | Try older de4dot fork, or manually patch anti-tamper (NOP the module cctor) | | Mixed mode assembly (native + managed) | Use dnSpy for managed parts, IDA/Ghidra for native stubs | | AOT/NativeAOT compiled | Not a traditional .NET assembly — treat as native PE, use Ghidra | | .NET 5+ single-file bundle | Extract with `dotnet-dump` or manually parse bundle header at end of PE | | Heavily virtualized (KoiVM/EazVM) | Use specialized devirtualizers: OldRod (KoiVM), EazFixer (Eazfuscator) | | Anti-debug in module initializer | Patch `<Module>.cctor` or use dnSpy's "Edit IL" to NOP checks | | Resource encryption | Dump at runtime with dnSpy breakpoints on `ResourceManager.GetObject` | ## Decision Gate ``` IF sample is .NET assembly (CLR header present): → Run de4dot to identify + strip obfuscation → Decompile with ILSpy/dnSpy → Extract configs for known RAT families → Map behaviors to ATT&CK techniques → Extract IOCs (C2, mutex, registry keys) ELSE IF .NET single-file or AOT: → Extract bundled assemblies first, then proceed above ELSE: → Not .NET — use reverser/malware-triage or reverser/ghidra ```
在 GitHub 查看