Lab 06 — Dynamic Analysis — Network¶
Hands-on lab · ← Back to the module concept
Setup¶
git clone https://github.com/plaintext-security/plaintext-labs
cd plaintext-labs/malware/06-dynamic-network
make up
make fetch-pcap # pulls a real malware-C2 capture from Malware-Traffic-Analysis.net into pcaps/
make demo # offline synthetic fallback (no download needed)
⚠ This lab analyzes a real capture of live malware C2 traffic. Handle it accordingly. - Analysis only. You read packets —
tshark, Wireshark, Suricata. You never execute anything and never replay the C2: do not connect to any host, IP, or domain seen in the capture. The attacker infrastructure may still be live. - Isolation. All work stays inside the isolated container; the lab network isinternal: true, so even the synthetic beacon's "C2 traffic" cannot leave the host. - Hygiene. The capture is fetched at lab time (password-protected zip) and is never committed —.gitignorecoverspcaps/,*.pcap,*.zip. The classic Malware-Traffic-Analysis.net (MTA) password isinfected; MTA changed its scheme for newer captures — the current password is on the site's about page. Override withPCAP_SOURCE=… ZIP_PASSWORD=… make fetch-pcap(register the source inlib/sources.tsv). - Offline fallback. No download / MTA unreachable? Skipmake fetch-pcap;make demoruns the bundled syntheticbeacon.pyagainst the local sink so you can build and test the same workflow with zero network.
Scenario¶
A host on your network has been flagged for repeated, regular outbound connections to an unfamiliar IP. The triage hypothesis is a Remote Access Trojan beaconing to its operator — the open-source RATs AsyncRAT (MITRE S1087) and QuasarRAT (MITRE S0262) are among the most common families you will meet, and both leave recognisable fingerprints on the wire. Before the SOC pushes a network block, the team lead wants the C2 characterised: which host and port, what protocol, what cadence, and — crucially — a durable signature that fires on the next victim.
You will work from a real labelled capture: make fetch-pcap downloads a RAT traffic-analysis exercise from Malware-Traffic-Analysis.net. Your job is to pull the C2 indicators out of it — the C2 IP and port, the beacon interval, and any protocol tells — then turn the highest-signal finding into a detection rule. AsyncRAT in particular is famous for an own-goal IOC: even when its C2 channel is TLS-encrypted, the server often presents a default self-signed certificate whose issuer/subject names the malware itself (e.g. an O=/CN= of AsyncRAT Server), so the encrypted channel announces exactly what it is. Read the real cert and the timing; that's the lab.
The capture = the real RAT C2 PCAP that
make fetch-pcapdrops inpcaps/(path printed by the target). In offline mode, the capture is the bundled syntheticbeacon.pytraffic captured at the local sink — same workflow, deterministic structure, no download. Treat the synthetic beacon as if you didn't know its source (readdata/beacon.pyonly after you've analysed its traffic).
Do¶
-
[ ] Stage the capture and open it. Run
make up, thenmake fetch-pcapto stage the real PCAP underpcaps/(or skip it and use the synthetic fallback). Confirm the file and its SHA-256 (pcaps/SHA256SUMS). Open it read-only:tshark -r /lab/pcaps/<file> -q -z io,phsfor a protocol hierarchy, and-q -z conv,tcpfor the conversation list. Which peer does the host talk to most, and on what port? -
[ ] Identify the C2 endpoint. From the conversations, isolate the suspected C2: its IP, its port (RATs love non-standard / high TCP ports, not 80/443), and roughly how many flows go to it. For the synthetic beacon, the "C2" is the local sink on
:8080. Record the candidate C2 IP:port. -
[ ] Measure the beacon interval. List the connection start times to the C2 endpoint and compute the deltas between them (
tshark … -e frame.time_epoch, or feed the sink log toparse_sink_log.py). A near-constant interval — low variance, possibly with jitter — is the beaconing tell. State the mean interval and how regular it is. -
[ ] Read the protocol tells.
- If the C2 is TLS: extract the certificate from the handshake and inspect issuer/subject (
tshark … -Y 'tls.handshake.type==11' -T fields -e x509sat.printableString -e x509ce.dNSName). Does the cert self-identify (AsyncRAT Server, a malware-namedO=/CN=, or an implausible self-signed cert)? Note the JA3/JA3S or cipher set if present. -
If the C2 is cleartext HTTP (the synthetic beacon): record the URI path, the non-browser User-Agent, any custom header (e.g. an
X-Session-Token), and the request body. -
[ ] Decode any encoded content. If a request carries an encoded payload in a body or header, decode it. (Hint: check for Base64 —
python3 -c "import base64,sys; print(base64.b64decode(sys.argv[1]))" <blob>.) What does it reveal about the implant (host ID, sequence, status)? -
[ ] Write a detection rule. Turn your single highest-signal finding into a Suricata rule, saved as
beacon-c2.rules. Key it on what's invariant for this family, not on content an operator can reshape: for a TLS RAT, atls.cert_subject/tls.cert_issuercontent match on the malware-named cert string (plus the destination port) is far more durable than any URI; for the cleartext beacon, match the URI pattern and the User-Agent together. Include protocol, direction, and your content matches. -
[ ] Write the network analysis report. In
network-report.md: the C2 endpoint (IP, port, protocol), the beacon interval and how you measured it, the protocol fingerprint (cert CN/issuer or URI+UA), any decoded payload, the MITRE ATT&CK techniques (T1071.001 Web Protocols and/or T1573 Encrypted Channel; cite S1087/S0262 for the family), and your rule with each condition explained.
Success criteria — you're done when¶
- [ ] The C2 endpoint (IP + port) is identified and recorded from the capture.
- [ ] The beacon interval is measured (mean + regularity) and documented.
- [ ] The protocol fingerprint is captured: a TLS cert issuer/subject (real PCAP) or the URI + User-Agent (synthetic fallback).
- [ ] Any encoded content is decoded.
- [ ]
beacon-c2.rulescontains a Suricata-compatible rule keyed on an invariant indicator. - [ ]
network-report.mdexists with the ATT&CK mapping (S1087/S0262 cited) and per-condition detection rationale.
Deliverables¶
beacon-c2.rules, network-report.md. Commit both. Lab artifacts — the pcaps/ capture and any extracted blobs — stay out of commits.
Automate & own it¶
Required. Extend parse_sink_log.py (provided in data/) so it doubles as a beacon-interval detector you can point at either source: it already reads the sink's JSON log; add a mode that reads tshark connection timestamps from the real PCAP (e.g. tshark -r file.pcap -T fields -e frame.time_epoch -e ip.dst -e tcp.dstport) and emits the same table of timestamp, endpoint, and time-delta. The delta column is the detector — flag any sequence whose delta coefficient-of-variation is under 20% as "consistent beacon interval (T1071.001 indicator)." AI drafts the tshark-parsing mode; you write the interval-variance logic yourself after reading the MITRE T1071 page, and you review every line.
AI acceleration¶
Give an AI your captured indicators (cert subject, port, interval, URI/UA) and ask it to write a Suricata rule. Then validate it: suricata -T -S /path/to/beacon-c2.rules (or check the OISF keyword docs). Identify and fix at least one syntax or logic error the AI introduced — a too-broad content match, a wrong flow: direction, or a keyword that doesn't exist — before committing.
Connects forward¶
The signature you write here is exactly the artifact Track 02 Defensive Operations deploys to a network IDS; the ATT&CK technique IDs connect this module to the ATT&CK-mapped detection work in that track's Module 08 (Detection as Code). The TLS-certificate reasoning recurs wherever encrypted C2 hides in plain sight.
Marketable proof¶
"I analyse real RAT C2 captures — beacon cadence, C2 endpoint, and the TLS-certificate fingerprint that betrays the family — and write durable network detection signatures from first principles."
Stretch¶
- Pull JA3/JA3S hashes from the real capture and check them against a public JA3 fingerprint set; note whether the RAT's TLS stack is distinctive enough to detect on the handshake alone.
- Capture the synthetic beacon with
tcpdumpinside the container, then diff your synthetic PCAP against the real one intshark— what does the real sample do that your model doesn't, and how would each difference change your rule?
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).