关于 reverse-engineering-dotnet-malware-with-dnspy
这是使用 dnSpy 分析 .NET 恶意软件的逆向工程技能,面向恶意软件分析人员。内容涵盖反混淆、反编译、运行时调试及配置与 C2 信息提取,并强调在隔离环境中操作。
主要功能
- 01识别 .NET 程序集与混淆器
- 02使用 de4dot 解除常见混淆
- 03在 dnSpy 中反编译代码
- 04提取 C2 配置与指标
- 05通过断点观察运行时行为
适用场景
- 01分析 AgentTesla 等 .NET 恶意软件
- 02检查混淆程序集中的代码与字符串
- 03提取硬编码的 C2 地址和密钥
- 04观察解密及动态加载行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill reverse-engineering-dotnet-malware-with-dnspy安装后在 Claude Code 中输入/reverse-engineering-dotnet-malware-with-dnspy确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdscripts/agent.py详细介绍
使用 dnSpy 逆向分析 .NET 恶意软件
适用场景
- 某恶意软件样本被识别为 .NET 程序集(C#、VB.NET、F#),需要进行反编译
- 分析基于 .NET 的恶意软件家族(AgentTesla、AsyncRAT、RedLine Stealer、Quasar RAT)
- 对受 ConfuserEx、SmartAssembly 或自定义混淆器保护的 .NET 代码进行去混淆
- 从托管程序集中提取硬编码的 C2 配置、加密密钥和凭据
- 在运行时调试 .NET 恶意软件,以观察解密例程和动态行为
不要用于原生(非托管)PE 二进制文件;原生代码分析请使用 Ghidra 或 IDA。
前置条件
- 已安装 dnSpy 或 dnSpyEx(https://github.com/dnSpyEx/dnSpy——社区维护的分支)
- 用于自动化 .NET 去混淆的 de4dot(
https://github.com/de4dot/de4dot) - 作为替代反编译器用于交叉验证的 ILSpy
- 已安装 .NET SDK,用于在分析过程中重新编译修改后的程序集
- 用于在实时恶意软件上运行 dnSpy 调试器的隔离 Windows 虚拟机
- 用于识别所用 .NET 混淆器的 Detect It Easy (DIE)
工作流
步骤 1:识别 .NET 程序集和混淆器
验证样本是否为 .NET 二进制文件并检测其保护措施:
# Check if file is .NET assembly
file suspect.exe
# Output should contain "PE32 executable" with .NET metadata
# Detect obfuscator with Detect It Easy
diec suspect.exe
# Python-based .NET detection
python3 << 'PYEOF'
import pefile
pe = pefile.PE("suspect.exe")
# Check for .NET COM descriptor
if hasattr(pe, 'DIRECTORY_ENTRY_COM_DESCRIPTOR'):
print("[*] .NET assembly detected")
print(f" Runtime version: {pe.DIRECTORY_ENTRY_COM_DESCRIPTOR}")
else:
# Check for mscoree.dll import (alternative detection)
for entry in pe.DIRECTORY_ENTRY_IMPORT:
if entry.dll.decode().lower() == "mscoree.dll":
print("[*] .NET assembly detected (mscoree.dll import)")
break
else:
print("[!] Not a .NET assembly")
# Check section names for .NET indicators
for section in pe.sections:
name = section.Name.decode().rstrip('\x00')
if name in ['.text', '.rsrc', '.reloc']:
print(f" Section: {name} (typical .NET)")
PYEOF
步骤 2:使用 de4dot 去混淆
在手动分析之前,移除常见的 .NET 混淆:
# Run de4dot to identify and remove obfuscation
de4dot suspect.exe -o suspect_cleaned.exe
# Force specific deobfuscator
de4dot suspect.exe -p cf # ConfuserEx
de4dot suspect.exe -p sa # SmartAssembly
de4dot suspect.exe -p dr # Dotfuscator
de4dot suspect.exe -p rv # Reactor
de4dot suspect.exe -p bl # Babel.NET
# Verbose output for debugging
de4dot -v suspect.exe -o suspect_cleaned.exe
# Handle multi-file assemblies
de4dot suspect.exe suspect_helper.dll -o cleaned/
Common .NET Obfuscators:
━━━━━━━━━━━━━━━━━━━━━━━
ConfuserEx: String encryption, control flow, anti-debug, anti-tamper
SmartAssembly: String encoding, flow obfuscation, pruning
Dotfuscator: Renaming, string encryption, control flow
.NET Reactor: Native code generation, necrobit, anti-debug
Babel.NET: String encryption, resource encryption, code virtualization
Crypto Obfuscator: String encryption, anti-debug, watermarking
Custom: Malware-specific obfuscation (manual de4dot configuration needed)
步骤 3:在 dnSpy 中打开并分析代码
在 dnSpy 中加载去混淆后的程序集,进行源码级分析:
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
步骤 4:提取配置和 C2 数据
在反编译后的源码中定位硬编码配置:
// Common .NET malware configuration patterns:
// Pattern 1: Static class with hardcoded values
public static class Config {
public static string Host = "185.220.101.42";
public static int Port = 4782;
public static string Key = "GhOsT_RaT_2025";
public static string Mutex = "AsyncMutex_6SI8OkPnk";
public static bool Install = true;
public static string InstallFolder = "%AppData%";
}
// Pattern 2: Encrypted strings decrypted at runtime
public static string Decrypt(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 configuration
byte[] configData = Properties.Resources.config;
string config = AES.Decrypt(configData, derivedKey);
# Python script to extract .NET resource strings
import 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 dump
with open("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 strings
try:
decoded = base64.b64decode(s).decode('utf-8', errors='ignore')
if len(decoded) > 3 and decoded.isprintable():
print(f" Base64: {s[:40]}... -> {decoded[:100]}")
except:
pass
# Check for URLs/IPs
if re.match(r'https?://', s) or re.match(r'\d+\.\d+\.\d+\.\d+', s):
print(f" Network: {s}")
步骤 5:使用 dnSpy 调试
设置断点并调试恶意软件,以观察其运行时行为:
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
步骤 6:记录发现
将分析结果整理为结构化报告:
Analysis documentation should include:
- .NET assembly metadata (CLR version, target framework, compilation info)
- Obfuscator identified and deobfuscation method used
- Complete C2 configuration (hosts, ports, encryption keys, mutex names)
- Malware capabilities (keylogging, screen capture, file theft, etc.)
- Persistence mechanisms (registry, scheduled tasks, startup folder)
- Anti-analysis techniques (VM detection, debugger detection, sandbox evasion)
- Extracted IOCs (C2 IPs/domains, file hashes, mutex names, registry keys)
- YARA rule based on unique code patterns or strings
关键概念
| 术语 | 定义 |
|---|---|
| CIL/MSIL | 通用中间语言;.NET 程序集编译成的字节码格式,可被反编译回高级 C#/VB.NET |
| 元数据标记(Metadata Token) | 程序集元数据表中 .NET 类型、方法和字段的唯一标识符;用于在 dnSpy 中导航 |
| de4dot | 开源 .NET 去混淆器,可识别并移除许多商业及恶意软件专用混淆器的保护 |
| ConfuserEx | 流行的开源 .NET 混淆器,常被恶意软件作者用于字符串加密和控制流混淆 |
| 字符串加密 | 一种混淆技术,用加密数据和运行时解密调用来替换字符串字面量,以对静态分析隐藏 IOC |
| 资源嵌入 | 将配置、载荷或附加程序集存储在 .NET 嵌入资源中,通常使用由程序集元数据派生的密钥加密 |
| Assembly.Load | .NET 方法,可从内存中的字节数组加载程序集,从而实现嵌入载荷的无文件执行 |
工具与系统
- dnSpy/dnSpyEx:开源 .NET 程序集编辑器、反编译器和调试器,支持 C# 和 VB.NET 反编译
- de4dot:自动化 .NET 去混淆器,支持 ConfuserEx、SmartAssembly、Dotfuscator、Reactor 及许多其他保护器
- ILSpy:开源 .NET 反编译器,提供程序集代码的 C#、VB.NET 和 IL 视图
- dotPeek:JetBrains 的免费 .NET 反编译器,带符号服务器和交叉引用导航
- Detect It Easy (DIE):多格式文件分析器,可识别 .NET 框架版本、混淆器和编译器信息
常见场景
场景:分析 AgentTesla 信息窃取程序
背景:一封钓鱼邮件投递了一个被识别为 AgentTesla 的 .NET 可执行文件。需要对该样本进行分析,以确定它窃取哪些凭据、如何外传数据以及其 C2 配置。
方法:
- 运行 Detect It Easy 以识别混淆器(通常是 ConfuserEx 或自定义混淆器)
- 使用 de4dot 进行反混淆,以恢复可读的类/方法名并解密字符串
- 在 dnSpy 中打开并导航到入口点,以了解初始化过程
- 定位凭据收集模块(浏览器、电子邮件、FTP、VPN 密码窃取类)
- 找到外传方法(SMTP 电子邮件、FTP 上传、HTTP POST、Telegram bot API)
- 提取 C2 配置(SMTP 服务器、凭据、收件人电子邮件或 HTTP URL)
- 在解密函数上设置调试器断点,以一次性捕获所有解密后的字符串
陷阱:
- 未先使用 de4dot 就进行分析(ConfuserEx 会使手动分析极其困难)
- 未检查多阶段加载(初始 .NET 可执行文件可能会从资源中加载其他程序集)
- 遗漏存储在 .NET 资源中而非硬编码字符串中的配置
- 在未进行网络隔离的情况下运行调试器(AgentTesla 会立即尝试外传)
输出格式
.NET MALWARE ANALYSIS REPORT
================================
Sample: invoice_scanner.exe
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
Type: .NET Assembly (C#)
Framework: .NET Framework 4.8
Obfuscator: ConfuserEx v1.6
Deobfuscated: Yes (de4dot -p cf)
CLASSIFICATION
Family: AgentTesla v3
Type: Information Stealer / Keylogger
Compile Date: 2025-09-10
C2 CONFIGURATION
Exfil Method: SMTP (Email)
SMTP Server: smtp.yandex[.]com:587
SMTP User: exfil.account@yandex[.]com
SMTP Pass: Str0ngP@ssw0rd2025
Recipient: operator@protonmail[.]com
Interval: 30 minutes
Encryption: AES-256 with key "AgentTesla_2025_key"
CAPABILITIES
[*] Browser credential theft (Chrome, Firefox, Edge, Opera)
[*] Email client passwords (Outlook, Thunderbird)
[*] FTP client credentials (FileZilla, WinSCP)
[*] VPN credentials (NordVPN, OpenVPN)
[*] Keylogging (SetWindowsHookEx)
[*] Screenshot capture (every 30 seconds)
[*] Clipboard monitoring
PERSISTENCE
Method: Registry Run key + Scheduled Task
Registry: HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate
Task: \Microsoft\Windows\WindowsUpdate\Updater
EXTRACTED IOCs
SMTP Server: smtp.yandex[.]com
Exfil Email: exfil.account@yandex[.]com
Recipient: operator@protonmail[.]com
Mutex: AgentTesla_2025_Q3_MUTEX
Install Path: %AppData%\Microsoft\Windows\svchost.exe
评论
支持 Markdown