Reverse engineers .NET malware samples using the dnSpy decompiler and debugger to read C#/VB.NET source, deobfuscate code protected by tools like ConfuserEx or SmartAssembly, and extract hardcoded C2 configurations, keys, and credentials. Use when a sample is identified as a .NET assembly (e.g. AgentTesla, AsyncRAT, RedLine Stealer, Quasar RAT) and needs decompilation, deobfuscation, or config extraction.
Reverse engineers .NET malware samples using the dnSpy decompiler and debugger to read C#/VB.NET source, deobfuscate code protected by tools like ConfuserEx or SmartAssembly, and extract hardcoded C2 configurations, keys, and credentials. Use when a sample is identified as a .NET assembly (e.g. AgentTesla, AsyncRAT, RedLine Stealer, Quasar RAT) and needs decompilation, deobfuscation, or config extraction.
Load the deobfuscated assembly in dnSpy for source-level analysis:
dnSpy Analysis Workflow:
━━━━━━━━━━━━━━━━━━━━━━━
1. File -> Open -> Select cleaned assembly
2. Navigate to the entry point:
- Assembly Explorer -> <namespace> -> Program class -> Main method
- Or: Right-click assembly -> Go to Entry Point
3. Key areas to examine:
- Entry point (Main) for initialization and execution flow
- Form classes for UI-based malware (RATs, stealers)
- Network/HTTP classes for C2 communication
- Crypto/encryption classes for data protection
- Resource access for embedded payloads
- Timer/Thread classes for persistence and scheduling
4. Navigation shortcuts:
Ctrl+G - Go to token/address
Ctrl+Shift+K - Search assemblies
F12 - Go to definition
Ctrl+R - Analyze (find usages)
F5 - Start debugging
F9 - Toggle breakpoint
Step 4: Extract Configuration and C2 Data
Locate hardcoded configuration in the decompiled source:
// Common .NET malware configuration patterns:// Pattern 1: Static class with hardcoded valuespublicstaticclassConfig {
publicstaticstring Host = "185.220.101.42";
publicstaticint Port = 4782;
publicstaticstring Key = "GhOsT_RaT_2025";
publicstaticstring Mutex = "AsyncMutex_6SI8OkPnk";
publicstaticbool Install = true;
publicstaticstring InstallFolder = "%AppData%";
}
// Pattern 2: Encrypted strings decrypted at runtimepublicstaticstringDecrypt(string input) {
byte[] data = Convert.FromBase64String(input);
byte[] key = Encoding.UTF8.GetBytes("SecretKey123");
for (int i = 0; i < data.Length; i++) {
data[i] ^= key[i % key.Length];
}
return Encoding.UTF8.GetString(data);
}
// Pattern 3: Resource-embedded configurationbyte[] configData = Properties.Resources.config;
string config = AES.Decrypt(configData, derivedKey);
# Python script to extract .NET resource stringsimport subprocess
import re
import base64
# Use monodis (Mono) or ildasm (.NET SDK) to dump IL
result = subprocess.run(
["monodis", "--output=il_dump.il", "suspect_cleaned.exe"],
capture_output=True, text=True
)
# Search for string literals in IL dumpwithopen("il_dump.il", errors="ignore") as f:
il_code = f.read()
# Find ldstr (load string) instructions
strings = re.findall(r'ldstr\s+"([^"]+)"', il_code)
for s in strings:
# Check for Base64 encoded stringstry:
decoded = base64.b64decode(s).decode('utf-8', errors='ignore')
iflen(decoded) > 3and decoded.isprintable():
print(f" Base64: {s[:40]}... -> {decoded[:100]}")
except:
pass# Check for URLs/IPsif re.match(r'https?://', s) or re.match(r'\d+\.\d+\.\d+\.\d+', s):
print(f" Network: {s}")
Step 5: Debug with dnSpy
Set breakpoints and debug the malware to observe runtime behavior:
dnSpy Debugging Workflow:
━━━━━━━━━━━━━━━━━━━━━━━
1. Set breakpoints on key methods:
- String decryption functions (to capture decrypted values)
- Network connection methods (to capture C2 URLs)
- File write operations (to see what is dropped)
- Registry modification methods (to see persistence)
2. Debug -> Start Debugging (F5)
- Select the assembly to debug
- Set command-line arguments if needed
- Configure exception handling (break on all CLR exceptions)
3. At each breakpoint:
- Inspect local variables (Locals window)
- Evaluate expressions (Immediate window)
- View call stack to understand execution context
- Step over (F10) / Step into (F11) / Step out (Shift+F11)
4. Capture decrypted strings:
- Set breakpoint after decryption function returns
- Read the return value from the Locals window
- Document all decrypted configuration values
Step 6: Document Findings
Compile analysis results into a structured report:
Common Intermediate Language; the bytecode format .NET assemblies compile to, which can be decompiled back to high-level C#/VB.NET
Metadata Token
Unique identifier for .NET types, methods, and fields within the assembly metadata tables; used for navigation in dnSpy
de4dot
Open-source .NET deobfuscator that identifies and removes protection from many commercial and malware-specific obfuscators
ConfuserEx
Popular open-source .NET obfuscator frequently used by malware authors for string encryption and control flow obfuscation
String Encryption
Obfuscation technique replacing string literals with encrypted data and runtime decryption calls to hide IOCs from static analysis
Resource Embedding
Storing configuration, payloads, or additional assemblies in .NET embedded resources, often encrypted with a key derived from assembly metadata
Assembly.Load
.NET method loading assemblies from byte arrays in memory, enabling fileless execution of embedded payloads
Tools & Systems
dnSpy/dnSpyEx: Open-source .NET assembly editor, decompiler, and debugger supporting C# and VB.NET decompilation
de4dot: Automated .NET deobfuscator supporting ConfuserEx, SmartAssembly, Dotfuscator, Reactor, and many other protectors
ILSpy: Open-source .NET decompiler providing C#, VB.NET, and IL views of assembly code
dotPeek: JetBrains' free .NET decompiler with symbol server and cross-reference navigation
Detect It Easy (DIE): Multi-format file analyzer identifying .NET framework version, obfuscator, and compiler information
Common Scenarios
Scenario: Analyzing an AgentTesla Information Stealer
Context: A phishing email delivers a .NET executable identified as AgentTesla. The sample needs analysis to determine what credentials it steals, how it exfiltrates data, and its C2 configuration.
Approach:
Run Detect It Easy to identify the obfuscator (commonly ConfuserEx or custom)
Deobfuscate with de4dot to restore readable class/method names and decrypt strings
Open in dnSpy and navigate to the entry point to understand initialization