Analyzing a .NET RAT Configuration
Why RAT Configuration Extraction Matters
Remote Access Trojans (RATs) are the most common category of .NET malware. Every RAT must store operational parameters -- the C2 server address, encryption keys, mutex names, persistence paths -- somewhere in its binary. Extracting this configuration is one of the highest-value analysis tasks because it produces immediate, actionable intelligence:
| Config Field | Intelligence Value | How It Helps |
|---|---|---|
| C2 Host / Port | Network IOC | Block at firewall/proxy, create detection rules |
| Encryption Key | Decryption capability | Decrypt captured C2 traffic for full visibility |
| Mutex Name | Host IOC | Detect running infections across the enterprise |
| Install Path | File IOC | Sweep endpoints for installed copies |
| Registry Key | Persistence IOC | Identify and remove persistence mechanisms |
| Campaign ID / Version | Attribution data | Link samples to campaigns and threat actors |
| Anti-Analysis Flags | Operational context | Understand what defenses the attacker anticipated |
Analyst Tip: A single extracted RAT config can generate a dozen or more IOCs. This is often faster and more reliable than dynamic analysis for producing actionable intelligence.
Common .NET RAT Configuration Patterns
Through analyzing hundreds of .NET RAT samples, several recurring configuration patterns emerge. Recognizing these patterns lets you locate the config quickly, even in unfamiliar families.
Pattern 1: Static Fields in a Settings Class (AsyncRAT, Quasar)
The simplest pattern. Config values are stored as static fields in a dedicated class. In unobfuscated samples, you can read them directly:
// AsyncRAT-style Settings class (decompiled from dnSpyEx)
internal static class Settings
{
public static string Host = "185.196.x.x";
public static string Port = "8808";
public static string Key = "VGhpcyBpcyBhIHRlc3Q=";
public static string Mutex = "AsyncMutex_6a1f3b2c";
public static string InstDir = "%AppData%";
public static string InstFile = "svchost.exe";
public static string Version = "0.5.8";
public static bool Install = true;
public static bool AntiVM = true;
}
How to find it: Search (Ctrl+Shift+K) in dnSpyEx for strings like "Host", "Port", "Mutex", "Settings", or "Config". The class usually stands out as a collection of static string fields.
Pattern 2: Encrypted Config in Resources (Agent Tesla, Formbook)
More sophisticated RATs encrypt the entire configuration and store it as an embedded resource. A decryption routine extracts it at runtime:
// Agent Tesla-style encrypted config extraction
byte[] encryptedConfig = Resources.ResourceManager.GetObject("CONFIG");
byte[] key = Encoding.UTF8.GetBytes("hardcoded_key_here");
byte[] iv = Encoding.UTF8.GetBytes("hardcoded_iv_here");
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
byte[] decrypted = aes.CreateDecryptor().TransformFinalBlock(
encryptedConfig, 0, encryptedConfig.Length);
// decrypted contains: "host|port|mutex|key|installpath"
string[] parts = Encoding.UTF8.GetString(decrypted).Split('|');
}
How to find it: Look for Resources.ResourceManager calls near the beginning of Main(), or search for encryption-related classes (AES, RijndaelManaged, DES).
Pattern 3: Constructor-Based Config (NanoCore, njRAT)
Config values are decrypted in a constructor, often using a per-field decryption call:
// NanoCore-style per-field decryption
public ClientSettings()
{
this.Host = Crypto.Decrypt("a3F2X09iZnVzY2F0ZWQ=");
this.Port = Crypto.Decrypt("ODgwOA==");
this.Mutex = Crypto.Decrypt("TmFub0NvcmVfYWJj");
this.GroupName = Crypto.Decrypt("RGVmYXVsdA==");
this.InstallPath = Crypto.Decrypt("JUFwcERhdGEl");
}
How to find it: Search for class constructors that call the same method repeatedly with string/byte arguments. The decryption method will have many "Used By" references.
Pattern 4: Base64 + Multi-Layer Encoding (RedLine)
Some RATs stack multiple encoding layers:
// RedLine-style multi-layer config decryption
string encoded = "encrypted_blob_here";
byte[] step1 = Convert.FromBase64String(encoded); // Base64 decode
byte[] step2 = Xor(step1, key); // XOR decrypt
string step3 = Encoding.UTF8.GetString(step2); // UTF8 decode
string[] config = step3.Split(new[] { "|||" }); // Split fields
Pattern 5: Reflectively Loaded Config (Multi-Stage Loaders)
In multi-stage .NET malware, the configuration may be embedded in a second-stage assembly that is loaded via Assembly.Load():
// Stage 1: Loader decrypts and loads Stage 2
byte[] stage2Bytes = DecryptResource("embedded_payload");
Assembly stage2 = Assembly.Load(stage2Bytes);
// Config is inside stage2, not in the initial loader
Type configType = stage2.GetType("Namespace.Settings");
Analyst implication: If you cannot find a config in the initial binary, it may be in a reflectively loaded second stage. Use DotDumper or debugging to extract the loaded assembly, then analyze that for the config.
Step-by-Step Config Extraction with dnSpyEx
Step 1: Identify the Config Storage Mechanism
Open the sample in dnSpyEx and look for config indicators:
Search targets (Ctrl+Shift+K):
- String search: "Host", "Port", "Mutex", "Install", "Key", "C2"
- Type search: "Settings", "Config", "Options", "ClientConfig"
- Method search: "Decrypt", "Deobfuscate", "GetConfig"
- Resource search: Check Resources node in Assembly Explorer
Step 2: Determine if Config is Encrypted
| Observation | Config State | Next Step |
|---|---|---|
| Readable strings visible in Settings class | Plaintext | Read values directly |
| Base64-looking strings in fields | Encoded | Decode Base64 (may be multi-layer) |
| Fields set by method calls with byte arrays | Encrypted | Identify encryption algorithm |
| No obvious config class visible | Hidden / in resource | Check resources, or trace from Main() |
Step 3: Extract Encrypted Config via Debugging
When the config is encrypted, let the malware decrypt it for you:
1. Locate the decryption method (the one called for each config field)
2. Set a breakpoint on the RETURN statement of that method
3. Start debugging (F5)
4. When breakpoint hits, check the return value in Locals window
5. Record: [encrypted_input] -> [decrypted_output]
6. Continue (F5) to the next call
7. Repeat until all config values are collected
Alternatively, set a breakpoint after the config class is fully initialized and inspect all fields at once:
1. Find where the config class is used (e.g., first network call)
2. Set breakpoint on that line
3. When it hits, examine the config object's fields in Locals/Watch
4. All decrypted values will be visible at this point
Step 4: Document the Configuration
Produce a structured report with all extracted values:
=== RAT Configuration Extract ===
Sample: d41d8cd98f00b204e9800998ecf8427e (MD5)
Family: AsyncRAT v0.5.8
Obfuscator: None detected
| Field | Value |
|---------------|------------------------------------------|
| C2 Server | 185.196.x.x:8808 |
| Protocol | TCP (raw socket, custom protocol) |
| Mutex | AsyncMutex_6a1f3b2c |
| Install Path | %AppData%\svchost.exe |
| Persistence | HKCU\...\Run\svchost |
| AES Key | VGhpcyBpcyBhIHRlc3Q= (Base64) |
| Campaign ID | campaign_2024_q4 |
| Anti-VM | Enabled |
| Anti-Debug | Disabled |
Automated Config Extraction Tools
For known RAT families, automated extractors save significant time:
MWCP (Malware Configuration Parser) by DCSO/FireEye
# Install the framework
pip install mwcp
# Run against a sample (with appropriate parser)
mwcp parse AsyncRAT suspect.exe
# Output: JSON with extracted C2, keys, mutexes
RATDecoders by Kevin Breen
pip install malwareconfig
# Extract config from known RAT family
malwareconfig -f suspect.exe
# Automatically identifies the family and extracts config fields
CAPE Sandbox
CAPE sandbox has built-in config extractors for 100+ malware families:
- Submit the sample to CAPE
- CAPE identifies the family during dynamic analysis
- Config is automatically extracted and presented in the report
- Extracted payloads (from Assembly.Load) are also captured
DotDumper for Multi-Stage Extraction
For samples that reflectively load their payload:
# DotDumper monitors Assembly.Load and dumps everything
DotDumper.exe -file loader.exe -log output.json
# Output includes:
# - Each assembly loaded via Assembly.Load (saved as files)
# - Decrypted strings
# - Network connection attempts
# - File write operations
Family-Specific Config Extraction Tips
| RAT Family | Config Location | Encryption | Key Extraction Tip |
|---|---|---|---|
| AsyncRAT | Static Settings class | AES-256 or plaintext | Search for "Settings" class, key is often in "Key" field |
| Agent Tesla | Encrypted resource blob | AES-CBC | Key/IV hardcoded near ResourceManager call |
| Quasar RAT | Settings class, encrypted fields | AES-128 | Key derived from hardcoded passphrase via PBKDF2 |
| NanoCore | Plugin DLLs in resources | DES or custom | Decrypt the main resource, then parse plugin configs |
| njRAT | Plaintext in source | Usually none | Look for string fields in Form1 class |
| RedLine | Encrypted string block | XOR + Base64 | XOR key is typically short (4-8 bytes) |
| Remcos | Encrypted resource "SETTINGS" | RC4 | First byte of resource is key length, followed by key |
Pivoting from Extracted Configs
Once you have extracted a config, use the IOCs to expand your investigation:
C2 IP Address -> Passive DNS -> Other domains on same IP -> Additional samples
Mutex Name -> Enterprise sweep -> Identify all infected hosts
AES Key -> Decrypt captured PCAP traffic -> See C2 commands
Install Path -> EDR telemetry search -> Track lateral movement
Campaign ID -> VirusTotal/MalwareBazaar -> Find related samples
MITRE ATT&CK Mapping for .NET RATs
| Behavior | Technique ID | Technique Name |
|---|---|---|
| Remote access / control | T1219 | Remote Access Software |
| Keylogging | T1056.001 | Keylogging |
| Screen capture | T1113 | Screen Capture |
| Clipboard data theft | T1115 | Clipboard Data |
| Credential harvesting | T1555 | Credentials from Password Stores |
| Exfiltration over C2 | T1041 | Exfiltration Over C2 Channel |
| Registry Run key persistence | T1547.001 | Registry Run Keys / Startup Folder |
| File and directory discovery | T1083 | File and Directory Discovery |
| System information discovery | T1082 | System Information Discovery |
| Reflective code loading | T1620 | Reflective Code Loading |
