ICMP Exfil
Overview
A file is exfiltrated by embedding it in ICMP echo request payloads. A custom 4-byte header in each payload carries the sequence number and total chunk count. The file is a PNG image with one unredacted corner. Reassemble it to find the flag.
Identifying the Traffic
Most ICMP traffic in this PCAP is normal ping traffic (ICMP ID 0x1234).
The exfil stream uses ICMP ID 0x1337, filter in Wireshark:
icmp.type == 8 && icmp.ident == 0x1337
This reveals ~209 echo requests, all from the same source IP.
Payload Structure
Each ICMP echo request has a custom payload layout. Note that in tools like dpkt,
the ICMP .data field includes the id and seq fields (4 bytes) before the actual
payload content:
Bytes 0-1: ICMP ID (0x1337)
Bytes 2-3: ICMP sequence number
Bytes 4-5: File chunk sequence number (big-endian)
Bytes 6-7: Total chunk count (big-endian)
Bytes 8-40: 32 bytes of file data
Reassembly
import dpkt, struct, io
from PIL import Image
EXFIL_ID = 0x1337
PAYLOAD_DATA_SIZE = 32
chunks = {}
with open('icmp_exfil.pcap', 'rb') as f:
for ts, raw in dpkt.pcap.Reader(f):
eth = dpkt.ethernet.Ethernet(raw)
if not isinstance(eth.data, dpkt.ip.IP): continue
ip = eth.data
if ip.p != 1: continue
icmp = ip.data
if icmp.type != 8: continue
d = bytes(icmp.data)
if len(d) < 8: continue
if struct.unpack('>H', d[0:2])[0] != EXFIL_ID: continue
seq, total = struct.unpack('>HH', d[4:8])
chunks[seq] = d[8:8+PAYLOAD_DATA_SIZE]
reassembled = b''.join(chunks[k] for k in sorted(chunks.keys()))
# Trim to PNG IEND marker
iend = b'\x00\x00\x00\x00IEND\xaeB`\x82'
end = reassembled.find(iend)
if end != -1:
reassembled = reassembled[:end+len(iend)]
Image.open(io.BytesIO(reassembled)).save('recovered.png')
The recovered image is a redacted surveillance photo. Most of the frame is blacked out, but the bottom-right corner shows a pigeon wearing a small camera harness. The flag is watermarked across the unredacted area.
Flag: DEADROP{icmp_is_a_tunnel_now_apparently}
Key Takeaway
ICMP echo payloads are rarely inspected by firewalls. The 32 bytes of data per ping is a low-and-slow exfiltration technique that can transfer megabytes over hours without triggering volume-based alerts.