C2 Beacon
Overview
C2 beaconing traffic over HTTP to port 8080. Commands are encoded with base64+XOR. One server response contains a polyglot file: a valid PNG that is also a valid ZIP archive containing the flag.
Step 1: Identify the Beacon
Filter to the C2 channel:
tcp.dstport == 8080
Plot timestamps of POST requests to measure the interval. The beacon fires every ~30 seconds with up to 5 seconds of jitter, a classic C2 pattern.
Step 2: Decode Commands
Each POST body has the form d=<encoded>&t=<type>. The encoding is:
1. XOR each byte with 0x4A
2. base64 encode
To decode:
import base64
XOR_KEY = 0x4A
def decode(s):
return bytes(b ^ XOR_KEY for b in base64.b64decode(s)).decode()
# Example: decode the 'd' parameter from each POST body
Decoded commands reveal the agent checking in, receiving tasking, executing
whoami and ipconfig, then receiving a file.
Step 3: Extract the Polyglot
The fifth beacon response is much larger than the others (~11KB). To get it
out: in Wireshark, right-click any packet in the conversation to 203.0.113.42
and choose Follow > TCP Stream. In the stream dialog, set Show and save
data as: Raw, switch the direction dropdown to show only the server side
(203.0.113.42 -> 10.10.14.52), then click Save as response.bin.
Strip the HTTP headers and find the PNG:
with open('response.bin', 'rb') as f:
data = f.read()
body = data[data.find(b'\r\n\r\n')+4:]
png_start = body.find(b'\x89PNG')
payload = body[png_start:]
with open('extracted.png', 'wb') as f:
f.write(payload)
The file starts with the PNG magic bytes \x89PNG.
It opens as a valid PNG showing an agent status screen. However, it is also a valid ZIP archive , the ZIP end-of-central-directory record is appended after the PNG IEND marker:
# Both of these work on the same file:
eog extracted.png
unzip extracted.png
Unzipping reveals exfil_doc.txt, an intelligence report on the aftermath of
the March 2024 breach. The flag is the verification token at the bottom.
import zipfile, io
zf = zipfile.ZipFile(io.BytesIO(open('extracted.png','rb').read()))
print(zf.read('exfil_doc.txt').decode())
Flag: DEADROP{c2_traffic_analysis_and_a_polyglot_bonus}
Key Takeaway
Polyglot files exploit the fact that different file parsers read from different positions: PNG readers stop at IEND, ZIP readers search from the end of the file for the end-of-central-directory record. The same bytes satisfy both.