intermediatecat/networking~2 min read

ICMP Covert Channels & Protocol Misuse

Decode hidden data payloads embedded in ICMP ping echo request/reply data fields and IP header ID fields using Wireshark and TShark.

// prerequisite reading

ICMP Protocol Overview

ICMP (Internet Control Message Protocol) is used for diagnostic error reporting (e.g., ping echo requests/replies, destination unreachable).

Standard ping packets contain an ICMP header followed by an arbitrary data payload (by default, 32 bytes on Windows or 56 bytes on Linux containing repeated pattern sequences like abcd... or timestamp data).

+----------------+----------------+-------------------------------------+
| IP Header (20B)| ICMP Header(8B)| Payload / Data Field (Variable B)   |
+----------------+----------------+-------------------------------------+
                                   ^ Attacker conceals exfiltrated bytes

1. Extracting ICMP Data Payloads with TShark

When malware or CTF challenges exfiltrate data via ICMP echo requests (Type 8):

# Filter ICMP Echo Request packets (icmp.type == 8) and print data payload field
tshark -r capture.pcap -Y "icmp.type == 8" -T fields -e data

Sample output (hex encoded bytes):

464c41477b
69636d705f
737465676f
7d0a

Concatenating & Decoding in Linux CLI

tshark -r capture.pcap -Y "icmp.type == 8" -T fields -e data | tr -d '\n' | xxd -r -p

Output exposes the extracted flag: FLAG{icmp_stego}.


2. IP Header Identification (ip.id) Covert Channel

Covert data can also be hidden inside standard IP header fields rather than the ICMP payload body:

  • ip.id (16-bit Identification field): Contains ASCII character codes or 16-bit integers sent in sequential packets.
  • ip.ttl (Time to Live field): Variations in TTL values encode secret bits.

Extracting ip.id Field Values

# Extract IP ID field values in hexadecimal
tshark -r capture.pcap -Y "icmp" -T fields -e ip.id

Python Reassembly Script

import pyshark

cap = pyshark.FileCapture('icmp_id.pcap', display_filter='icmp.type == 8')

chars = []
for pkt in cap:
    try:
        # Extract IP ID integer and convert to ASCII character
        ip_id = int(pkt.ip.id, 0)
        chars.append(chr(ip_id))
    except (AttributeError, ValueError):
        continue

print("Extracted Message:", "".join(chars))