Neven Marić
Hidden Investigations CTF 2026

ForensicsHidden Investigations CTF 2026

Ghost in the Wire

A 30-packet PCAP hides a flag in ICMP Echo Requests: 26 anomalous packets from 10.13.37.1 each carry a single ASCII byte of the flag as their payload, sandwiched between normal-looking pings.

  • forensics
  • pcap
  • icmp
  • exfiltration
  • packet-analysis

What this one teaches

  • ICMP payloads can carry arbitrary data — 1-byte payloads with sequential sequence numbers are a classic exfiltration pattern.
  • Filtering by source/destination IP separates the exfiltration channel (10.13.37.x) from normal monitoring traffic.

Task description

Our network monitoring team detected anomalous ICMP traffic during a routine packet capture. Something is being exfiltrated through the wire — but the data blends in with normal network noise. Analyze the capture and extract the hidden message before the ghost disappears.

Approach

Analysis

We are given a packet capture file ghost_traffic.pcap (1,857 bytes) containing 30 IPv4 ICMP Echo Request (type=8, code=0) packets:

  • Packets 0–1 and 28–29: Normal multi-byte ping/monitoring payloads (AAAAAAAAAAAAAAAA, ping from server1, health check ok , monitor alive 001) sent from 192.168.1.100 to 10.0.0.5.
  • Packets 2–27: Anomalous ICMP Echo Request packets sent from 10.13.37.1 to 10.13.37.2 with ICMP ID 0x1337 and sequential ICMP sequence numbers 1 through 26. Each packet carries a 1-byte payload corresponding to a single character of the exfiltrated flag.

Solution

Extract and concatenate the ICMP data payloads from the packets between 10.13.37.1 and 10.13.37.2:

import struct

with open("ghost_traffic.pcap", "rb") as f:
    pcap = f.read()

pos = 24  # Skip 24-byte pcap global header
chars = []

while pos < len(pcap):
    ts_sec, ts_usec, incl_len, orig_len = struct.unpack("<IIII", pcap[pos:pos+16])
    pkt = pcap[pos+16:pos+16+incl_len]
    pos += 16 + incl_len

    ip = pkt[14:]  # Skip 14-byte Ethernet header
    src = ".".join(map(str, ip[12:16]))
    dst = ".".join(map(str, ip[16:20]))
    ihl = (ip[0] & 0x0F) * 4
    icmp_payload = ip[ihl + 8:]  # Skip IP header and 8-byte ICMP header

    if src == "10.13.37.1" and dst == "10.13.37.2":
        chars.append(icmp_payload.decode("ascii"))

print("".join(chars))

Output:

hiCTF{1cmp_3xf1l_d3t3ct3d}

Lessons

  • The 10.13.37.x (leet-speak) source/destination and ICMP ID 0x1337 are deliberate hints that this traffic is the exfiltration channel.
  • Even a single byte per ICMP packet is enough to exfiltrate a full flag when the sequence numbers provide ordering.
The flagRevealhiCTF{1cmp_3xf1l_d3t3ct3d}

This CTF was possibly solved, and the writeup most likely written by an LLM. Apologies for inconsistencies.