CTF Malware & Network Analysis
Obfuscated Scripts
- •Replace
eval/bashwithechoto print underlying code - •Extract base64/hex blobs and analyze with
file - •Common deobfuscation chain: base64 decode → gzip decode → reverse → base64 decode
Debian Package Analysis
ar -x package.deb # Unpack debian package tar -xf control.tar.xz # Check control files # Look for postinst scripts that execute payloads
Custom Crypto Protocols
- •Stream ciphers may share keystream state for both directions
- •Concatenate ALL payloads chronologically before decryption
- •Look for hardcoded keys in
.rodata - •ChaCha20 keystream extraction: Send large nullbytes payload (0 XOR anything = anything)
- •Alternative: Pipe ciphertext from pcap directly into the binary
PCAP Analysis
tshark -r file.pcap -Y "tcp.stream eq X" -T fields -e tcp.payload
Look for C2 communication patterns on unusual ports (e.g., port 21 not for FTP).
Hex-Encoded Payloads
- •Convert hex to bytes, try common transformations: subtract 1, XOR with key
JavaScript Deobfuscation
// Replace eval with console.log eval = console.log; // Then run the obfuscated code // Common patterns unescape() // URL decoding String.fromCharCode() // Char codes atob() // Base64
PowerShell Analysis
# Common obfuscation -enc / -EncodedCommand # Base64 encoded IEX / Invoke-Expression # Eval equivalent [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encoded))
PE Analysis
peframe malware.exe # Quick triage pe-sieve # Runtime analysis pestudio # Static analysis (Windows)
Sandbox Evasion Checks
Look for:
- •VM detection (VMware, VirtualBox artifacts)
- •Debugger detection (IsDebuggerPresent)
- •Timing checks (sleep acceleration)
- •Environment checks (username, computername)
- •File/registry checks for analysis tools
Network Indicators
# Extract IPs/domains
strings malware | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
strings malware | grep -E '[a-zA-Z0-9.-]+\.(com|net|org|io)'
# DNS queries
tshark -r capture.pcap -Y "dns.qry.name" -T fields -e dns.qry.name | sort -u
C2 Traffic Patterns
- •Beaconing: regular intervals
- •Domain generation algorithms (DGA)
- •Encoded/encrypted payloads
- •HTTP(S) with custom headers
- •DNS tunneling
Junk Code Detection
Pattern: Obfuscation adds meaningless instructions around real code
Identification:
- •NOP sleds, push/pop pairs that cancel
- •Arithmetic that results in zero/identity
- •Dead writes (register written but never read before next write)
- •Unconditional jumps to next instruction
Filtering technique:
# Identify real calls by looking for patterns
# junk, junk, junk, CALL target, junk, junk
# Extract call targets, ignore surrounding noise
def extract_real_calls(disassembly):
calls = []
for instr in disassembly:
if instr.mnemonic == 'call' and not is_junk_target(instr.operand):
calls.append(instr)
return calls
.NET DNS-based C2
Pattern: Deobfuscated .NET malware with DNS C2
Analysis with dnSpy:
- •Find network functions (TcpClient, DnsClient, etc.)
- •Identify encoding/encryption wrappers
- •Look for command dispatch (switch on opcode)
AsmResolver for programmatic analysis:
using AsmResolver.DotNet;
var module = ModuleDefinition.FromFile("malware.dll");
foreach (var type in module.GetAllTypes()) {
foreach (var method in type.Methods) {
// Analyze method body
}
}
AES-CBC in Malware
Common key derivation:
- •MD5/SHA256 of hardcoded string
- •Derived from timestamp or PID
- •Password-based (PBKDF2)
Analysis approach:
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import hashlib # Common pattern: key = MD5(password) password = b"hardcoded_password" key = hashlib.md5(password).digest() # IV often first 16 bytes of ciphertext iv = ciphertext[:16] ct = ciphertext[16:] cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(cipher.decrypt(ct), 16)
Password Rotation in C2
Pattern: C2 uses rotating passwords based on time/sequence
Analysis:
- •Find password generation function
- •Identify rotation trigger (time-based, message count)
- •Sync your decryptor with the rotation
def get_current_password(timestamp):
# Password changes every hour
hour_bucket = timestamp // 3600
return hashlib.sha256(f"seed_{hour_bucket}".encode()).digest()
Malware Configuration Extraction
Common storage locations:
- •.data section (hardcoded)
- •Resources (PE resources, .NET resources)
- •Registry keys written at install
- •Encrypted config file dropped to disk
Extraction tools:
# PE resources wrestool -x -t 10 malware.exe -o config.bin # .NET resources monodis --mresources malware.exe # Strings in .rdata/.data objdump -s -j .rdata malware.exe
Identifying Encryption Algorithms
By constants:
- •AES:
0x637c777b,0x63636363(S-box) - •ChaCha20:
expand 32-byte kor0x61707865 - •RC4: Sequential S-box initialization
- •TEA/XTEA:
0x9E3779B9(golden ratio)
By structure:
- •Block cipher: Fixed-size blocks, padding
- •Stream cipher: Byte-by-byte, no padding
- •Hash: Mixing functions, rounds, constants
.NET Malware Analysis (C2 Extraction)
Tools: ILSpy, dnSpy, dotPeek
LimeRAT C2 extraction (Whisper Of The Pain):
- •Open .NET binary in dnSpy
- •Find configuration class with Base64 encoded string
- •Identify decryption method (typically AES-256-ECB with derived key)
- •Key derivation: MD5 of hardcoded string → first 15 + full 16 bytes + null = 32-byte key
- •Decrypt: Base64 decode → AES-ECB decrypt → reveals C2 IP/domain
from Crypto.Cipher import AES
import hashlib, base64
key_source = '${8\',`d0}n,~@J;oZ"9a'
md5 = hashlib.md5(key_source.encode()).hexdigest()
# Key = md5[:30] + md5 + '\x00' (32 bytes total as hex → 16 bytes binary)
key = bytes.fromhex(md5[:30] + md5 + '00')[:32]
cipher = AES.new(key, AES.MODE_ECB)
plaintext = cipher.decrypt(base64.b64decode(encrypted_b64))
Telegram Bot API for Evidence Recovery
Pattern (Stomaker): Malware uses Telegram bot to exfiltrate stolen data.
Recover exfiltrated data via bot token:
# If you have the bot API token from malware source:
import requests
TOKEN = "bot_token_here"
# Get updates (message history)
r = requests.get(f"https://api.telegram.org/bot{TOKEN}/getUpdates")
# Download files sent to bot
file_id = "..."
r = requests.get(f"https://api.telegram.org/bot{TOKEN}/getFile?file_id={file_id}")
file_path = r.json()['result']['file_path']
requests.get(f"https://api.telegram.org/file/bot{TOKEN}/{file_path}")
RC4-Encrypted WebSocket C2 Traffic
Pattern (Tampered Seal): Malware uses WSS over non-standard port with RC4 encryption.
Decryption workflow:
- •Identify C2 port from malware source (not standard 443)
- •Remap port with
tcprewriteso Wireshark decodes TLS - •Add RSA key for TLS decryption → reveals WebSocket frames
- •Find RC4 key hardcoded in malware binary
- •Decrypt each WebSocket payload with RC4 via CyberChef
Malware communication patterns:
- •Registration message: hostname, OS, username, privileges
- •Exfiltration: screenshots, keylog data, file contents
- •Commands: reverse shell, file download, process list
PyInstaller + PyArmor Unpacking
# Step 1: Extract PyInstaller archive python pyinstxtractor.py malware.exe # Look for main .pyc file in extracted directory # Step 2: If PyArmor-protected, use unpacker # github.com/Svenskithesource/PyArmor-Unpacker # Three methods available; choose based on PyArmor version # Step 3: Clean up deobfuscated source # Remove fake/dead-code functions (confusion code) # Identify core encryption/exfiltration logic