[Part 3] Extracting Leftover Data from USB Packets - ACS-IXIA_CTF - Jerry Paints & Exfiltration

Today I'm going to explain Jerry Paints and Exfiltration from the Forensics category.

Let's start with Jerry Paints. It was a 100 points challenge. Unfortunately I can't show you the prompt again because the challenges were made unavailable.

We were given 5 pcap files. I just downloaded them and straight up jump into wireshark. Opening the first file 1.pcapng in wireshark, we see it's something about some USB communication.

The challenge prompt was something about Tom & Jerry.

A mouse and a cat. Talking about USB it might be a pretty good reference to a mouse. So let's check out the USB Protocol documentation (page 61). We get a really nice table:

Byte Bits Description
0 0 Button 1
1 Button 2
2 Button 3
4 to 7 Device specific
1 0 to 7 X displacement
2 0 to 7 Y displacement
3 to n 0 to 7 Device specific

Also notice:

Devices may append additional data to these boot reports, but the first 8 bytes of keyboard reports and the first 3 bytes of mouse reports must conform to the format defined by the Boot Report descriptor in order for the data to be correctly interpreted by the BIOS. The report may not exceed 8 bytes in length.

Okay, so looking at the leftover data and using the hints about Tom & Jerry we can deduce that we are facing a Mouse USB Packets. So let's try to carve out of the pcaps the leftover data. We can use tshark for that:

tshark -r 1.pcapng -T fields -e usb.capdata

This will give you something like this:

I personally don't like those empty new lines, so let's get rid of them using sed and redirect everything into a file.

tshark -r 1.pcapng -T fields -e usb.capdata | sed -r '/^\s*$/d' > data1.txt

To decode this get the X, Y coordinates out of this leftover data we can write an awk script.

#!/usr/bin/awk -f

function comp(v) {
    if (v > 127) {                  # so we could get negative values too
        v -= 256;

    return v

BEGIN { FS=":" }                    # delimiter

    x += comp(strtonum("0x"$3));    # calculation
    y += comp(strtonum("0x"$4))


    print x, y                      # printing the values

Nice. Now let's run it.

Now redirect this into a file and let's use gnuplot and then plot <filename> inside the gnuplot command line. Doing that we will get:

Kind of looks like we're on the right track, doing that for every pcap in order, we get some similar plots. After some fiddling around with it and rotating the plots around, we can deduce something readable.


Now let's continue with Exfiltration, around 150 points challenge. Once again we are give a pcap file. This time a really large one. During the CTF I started looking at this challenge just after a hint was leaked which really helped me solving this. The hint was: Why are there so many ICMP packets?!

Let's just go straight up and analyze the ICMP packets in wirehsark. So filtering after the protocol we get:

Urgh. This is a lot of stuff. Let's carve out the ICMP packets into another pcap. You can do that with wireshark filters. After doing that and opening the new pcap, let's sort after the destination, so just clicking on the destination column. We get:

Now let's just scroll through them and see if we can find something interesting. It looked like only some bytes of the data section were changing. Anyway. After some scrolling we see something readable byte-by-byte, meaning in every packet there would be another byte forming a sentence. Like this:

Look at the last but one byte, it spells: i_wonder_whats_in_here.html. So this must be a file. Rushing to the very first packets we see in the same spot (last but one byte) in the first 2 packets PK. This should tell you something.

PK is the begininng of the magic header for zip files. So this must be a zip file. We can extract the data from all these packets and then write a python script to extract the last but one byte from every packet's data. So let's see the script.


f = open('hex', 'r')

data = f.read()

lines = data.split('\n')

s = ""
for line in lines:
    if len(line) > 3:
        s += str(line[-4]) + str(line[-3])

bytez = s.decode('hex')
print bytez

I extracted the data in string form, so I should get the 4th and 3rd characters from the end. That would represent the last but one byte. Redirecting the output to a file, we indeed get a zip file. After unzipping we see the i_wonder_whats_in_here.html.

And we get the flag.

FLAG: ACS_IXIA_CTF{fnflne_pncsbdd}