All investigations
Case 03 Network & Detection TDX Arena — IR Expert 08 / 13 / 2025

Pig Rules

As a SOC analyst at the Flying Piglet post office, the task was to detect a planned hacktivist campaign without flooding on benign RDP traffic. Port-based filtering was too coarse. The real discriminator was sitting in the TCP header — a static Window Size of 1024 bytes across every malicious SYN. That non-default value became the basis of a targeted Snort signature, authored, tested, and validated in Snorby with a low false positive rate.

Executive Summary

Inbound RDP traffic on TCP 3389 contained both legitimate administrative connections and hacktivist probing. Detecting the malicious subset required a discriminator more specific than port number alone. Broad packet capture surfaced a recurring TCP header anomaly: every malicious packet carried a static Window Size of exactly 1024 bytes. Normal TCP sessions negotiate and adjust this value dynamically; a fixed value is a strong signal of crafted traffic — brute-force tools, malware, or command-and-control clients often set Window Size as a hard-coded constant rather than letting the OS calculate it.

A custom Snort rule was authored against that specific header field (window:1024), configuration-tested with snort -T, deployed, and validated in the Snorby web UI. Alerts fired only for traffic matching the anomaly; the legitimate RDP baseline did not trigger. False positive rate stayed low throughout validation.

Findings & Analysis

Target port
TCP 3389 (RDP)
Detected consistent inbound RDP traffic. RDP is legitimate administrative protocol; the presence of unsolicited inbound traffic on 3389 pointed at probing, but port alone was not specific enough to isolate malicious from benign.
Packet-level signature
TCP Window Size = 1024
Recurring, abnormal TCP header field on the malicious stream. Normal sessions adjust Window Size dynamically based on receive buffer and congestion — a fixed value indicates crafted packets, not a negotiated TCP session. This became the discriminator.
Source IP
172.29.0.1
Attacker source consistently matched every packet carrying the anomalous Window Size. Linking the header anomaly to a single source confirmed the pattern as a targeted attack rather than random background noise — one tool, one host, one signature.
Detection technique
Signature-based NIDS
(Snort, window:1024)
Custom Snort rule matching TCP traffic with Window Size 1024. Targets the packet-level anomaly directly rather than filtering by port, source, or destination — which means the rule continues to fire even if the attacker rotates source IP or moves off port 3389, as long as they keep crafting packets with the same Window value.
IOC quick reference
  • Port: TCP 3389 (RDP)
  • Header signature: TCP Window Size = 1024
  • Source IP: 172.29.0.1
  • Snort SID: 1000002
  • Rules file: /etc/snort/rules/local.rules

Tools & Technologies

tcpdump
Live packet capture on eth0. Used both as a broad listener to surface the anomaly and as a filtered listener to confirm the signature before committing to a Snort rule. BPF filter on tcp[14:2] = 1024 reads the 16-bit Window field at byte offset 14 of the TCP header — faster than post-capture analysis and confirms the pattern at wire level.
Snort IDS
Rule engine for signature-based detection. The window: option is the specific keyword that matches against the TCP Window Size field — most Snort rules target payloads, so targeting a header field is the less-obvious design choice that made this rule specific.
Snorby
Web UI for Snort alert review. Used to validate the custom rule was firing on the right traffic only — not just that it was firing. The Sensors tab provided event counts and matching packet details for defensibility in reporting.
nano
Direct edit of /etc/snort/rules/local.rules to add the custom rule. No IDE overhead; Snort reads the file on startup and a reload picks up changes.
Linux shell utilities
Service control, rule deployment, traffic inspection, and configuration testing. snort -T -c validates configuration syntax before activation — cheaper to catch a malformed rule at test time than after deployment.

Investigation Process

Five steps. The defining move is step 2 — not authoring the rule, but recognizing the anomaly that makes the rule possible. Detection engineering rewards the analyst who sees the signature before the tool is told to look for it.

Step 01 Establish environment & read on-box guidance Snort VM confirmed
whoami pwd ls cat README hostname -I

Why: Confirm identity, working directory, and the challenge's own on-box documentation. The README specified where custom rules go (/etc/snort/rules/local.rules) and how to invoke Snort in test mode. Reading it up front is faster than reverse-engineering the expected paths.

Step 02 Capture and filter live traffic Window Size 1024
# Broad capture — surface the anomaly sudo tcpdump -i eth0 tcp # BPF filter — confirm the signature at wire level sudo tcpdump -i eth0 tcp and 'tcp[14:2] = 1024'

Why: Broad capture first to see what traffic actually looks like — hypotheses about malicious behavior survive or die against the real packet stream. Observed recurring SYN packets from 172.29.0.1 with a static TCP Window Size of 1024. The BPF filter confirmed it at wire level: reading the 16-bit Window field at offset 14 of the TCP header isolated the malicious stream cleanly. That this value is fixed across every malicious packet — rather than adjusted per-session — is the anomaly.

Why a static Window Size is an anomaly

TCP Window Size controls how much unacknowledged data a receiver will accept. Real sessions negotiate it during the handshake and adjust it dynamically based on the receiver's buffer state and the network's congestion signals — values drift as the session progresses. A fixed value across every SYN from the same source, every time, is a strong signal that packets are being crafted by a tool rather than originating from a real TCP stack. Brute-forcers, scanners, and C2 clients commonly hard-code Window Size to avoid the cost of a full stack implementation. 1024 specifically is a common choice because it's a round power of two and small enough to keep crafted packets compact. Using it as a signature works precisely because legitimate RDP clients almost never emit it.

Step 03 Author the Snort rule SID 1000002 added
nano /etc/snort/rules/local.rules # Added: alert tcp any any -> any any (msg:"TCP Window = 1024 (may not fire)"; \ sid:1000002; rev:1; window:1024;)

Why: Rule targets the window: keyword directly — the TCP Window Size field, not a payload pattern. any any -> any any is intentional: port and IP are not part of the signature, the crafted-packet anomaly is. That means the rule continues to fire even if the attacker rotates source IP or moves off port 3389, as long as the crafted Window Size persists. sid:1000002 is in the local SID range reserved for custom rules, avoiding collision with shipped signatures.

Step 04 Configuration test and run Validated
# Syntax check before deploying sudo snort -T -c /etc/snort/snort.conf # Run quietly and capture alerts sudo snort -c /etc/snort/snort.conf -q

Why: -T validates every loaded configuration file and rule syntactically without processing live traffic — catching a malformed rule here costs a second; catching it after a live deploy costs whatever alerts it missed in the meantime. -q suppresses per-packet noise so the alert stream is readable in a terminal session.

Step 05 Validate in Snorby Flag recovered
# Snorby → Sensors tab # Confirmed: alerts only on malicious RDP traffic matching the signature # Benign RDP baseline did not trigger # FLAG retrieved from alert detail

Why: A rule that fires is not the same as a rule that fires correctly. Snorby's alert detail provides timestamps, matching packet data, and aggregate event counts — enough to confirm the rule is scoped to the malicious stream and that benign RDP is not being picked up. Low false positive rate confirmed. The challenge flag was retrieved from the alert metadata itself.

Recommendations

Deploy the validated rule to production
The window:1024 signature fired cleanly against the malicious stream without false positives on the benign baseline. Rules that pass that bar in lab validation should graduate to production IDS with the same SID, so detection history remains continuous across environments.
Monitor RDP end-to-end, not just at a single layer
A header-level signature catches crafted traffic. It does not catch legitimate-looking authenticated RDP abuse. Pair the rule with authentication log monitoring (failed login spikes, unusual source IP geography) and firewall-level rate limiting on 3389 — defense in depth is what makes a detection rule durable.
Correlate Snort alerts into the SIEM
Individual alerts are useful; correlated alerts answer questions. Forward Snort events into Splunk or the equivalent SIEM so the window:1024 hits cross-reference with Windows authentication logs, firewall deny logs, and endpoint telemetry from the same source IP. That cross-view turns "someone crafted bad RDP packets" into "someone crafted bad RDP packets and then authenticated successfully from a different IP."
Review detection rules periodically against attack evolution
A fixed Window Size of 1024 works now because attacker tooling uses it. When tool authors randomize Window Size or adopt TCP stack fingerprint normalization to evade exactly this kind of detection, the rule stops working and needs replacement. Scheduled rule reviews are not administrative overhead; they are maintenance of a living detection.
Segment RDP to trusted management networks
No detection rule replaces not exposing RDP to the public internet. Restrict 3389 to management networks, require VPN or an identity-aware proxy, and enforce MFA on any account that can log in via RDP. The rule handles what gets past those controls; the controls prevent the rule from ever needing to fire.

Technical Note

Header-field detection vs. payload detection

Most Snort rules target payloads — substring matches, regex against the application data, content within a packet's body. That's where novel attack signatures typically live, and it's where the engine's strengths show. But payload detection assumes a payload worth inspecting, and plenty of attack traffic never gets that far: scan packets, crafted SYNs, probes designed to find a service and disappear. For those, header-field detection is the right primitive. Snort exposes it through keywords like window:, flags:, and ttl: — matching against fields the attacker's tool controls directly, rather than fields negotiated by a real TCP stack.

The trade-off is specificity. Header-field rules are fast and cheap at runtime, but they're also easy to evade once an attacker knows the rule exists. A fixed Window Size of 1024 is a signature because it's anomalous; the moment attacker tooling randomizes Window Size, the rule becomes blind. That's why header-field detection works best as one layer in a stack — precise, low-overhead, and explicit about its own expiration date. The operational value isn't that it's permanent. It's that it turns a live investigation into a deployable artifact while the attacker is still using the version of the tool you observed.

References

  1. MITRE ATT&CK — Remote Desktop Protocol. T1021.001 (Remote Services: RDP) is the lateral-movement technique this rule's target traffic maps to. attack.mitre.org/techniques/T1021/001
  2. CISA Advisory AA23-136A — #StopRansomware: BianLian. FBI and CISA joint advisory on the BianLian group explicitly warns organizations to "strictly limit the use of RDP and other remote desktop services" — context for why RDP detection engineering continues to be operationally relevant. cisa.gov/aa23-136a
  3. Snort 2 Users Manual — Rule Options. Reference for the window: keyword and other TCP header-level options used to build non-payload detection rules. snort.org/documents
  4. Note on the specific signature. No publicly documented real-world campaign uses a fixed TCP Window Size of exactly 1024 in RDP traffic. The signature observed in this exercise is likely constructed for the lab rather than reflecting an in-the-wild pattern. The detection methodology — building a precise rule from an observed header anomaly, validating, deploying — transfers directly to real-world packet-crafted attack detection.