Our once-venerable president has committed the unspeakable crime of dine-and-dashing the pizza during our own club meetings. He's on the run as we speak, but we're not sure where he's headed.

Luckily, he forgot that we had planted a packet sniffer on his laptop, and we were able to retrieve the following capture when we raided his apartment:

https://storage.googleapis.com/utctf/capture.pcapng

He's too smart to email his plans to himself, but I'm certain he took them with him somehow. Can you help us figure out which country he's fleeing to?

by antony

Local download. This challenge was a good example of utilizing both my USB PCAP parsing tool (Gallimaufry) as well as my stego tool (stegoVeritas). It's also a good example of how you can go down the COMPLETELY wrong path initially... It happens.

 

When first opening the pcap, we quickly discover it's mostly USB traffic. Note, it's not ALL USB traffic, as there are DNS lookups for Twitch and TLS communications. However, I guessed that we likely were not supposed to break TLS, though did wonder for a while if we were supposed to find the twitch stream. However, since it was mostly USB, I opened it up in Gallimaufry:

 


In [1]: from Gallimaufry.USB import USB

In [2]: pcap = USB("./capture.pcapng")
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.
Expected 1 Descriptors. Found 0.

In [3]: pcap.devices
Out[3]:
[<Logitech, Inc. Gaming Mouse G300 v70.0.2 USB2.0.0 bus_id=2 address=9>,
 <Sony Corp. DualShock 4 [CUH-ZCT2x] v1.0.0 USB2.0.0 bus_id=2 address=6>,
 <Razer USA, Ltd Unknown... v2.0.0 USB2.0.0 bus_id=2 address=5>,
 <VirtualBox USB Tablet v1.0.0 USB1.1.0 bus_id=2 address=4>,
 <Linux Foundation 1.1 root hub v4.1.8 USB1.1.0 bus_id=2 address=1>,
 <Alcor Micro Corp. Flash Drive v1.0.6 USB2.0.0 bus_id=1 address=2>,
 <Linux Foundation 2.0 root hub v4.1.8 USB2.0.0 bus_id=1 address=1>]

In [4]: print(pcap.summary)
PCAP: /home/gallimaufry/work/ctf/utctf2019/for/rogue-leader/capture.pcapng
Total Packets: 66341

Devices
-------

    Logitech, Inc. - Gaming Mouse G300
    ----------------------------------
    bus_id: 2
    device_address: 9
    device_version: 70.0.2
    bluetooth_version: 2.0.0
    packets: 2842

    Configurations
    --------------

    Sony Corp. - DualShock 4 [CUH-ZCT2x]
    ------------------------------------
    bus_id: 2
    device_address: 6
    device_version: 1.0.0
    bluetooth_version: 2.0.0
    packets: 61746

    Configurations
    --------------

    Razer USA, Ltd - Unknown...
    ---------------------------
    bus_id: 2
    device_address: 5
    device_version: 2.0.0
    bluetooth_version: 2.0.0
    packets: 418

    Configurations
    --------------

    VirtualBox - USB Tablet
    -----------------------
    bus_id: 2
    device_address: 4
    device_version: 1.0.0
    bluetooth_version: 1.1.0
    packets: 2

    Configurations
    --------------

    Linux Foundation - 1.1 root hub
    -------------------------------
    bus_id: 2
    device_address: 1
    device_version: 4.1.8
    bluetooth_version: 1.1.0
    packets: 2

    Configurations
    --------------

    Alcor Micro Corp. - Flash Drive
    -------------------------------
    bus_id: 1
    device_address: 2
    device_version: 1.0.6
    bluetooth_version: 2.0.0
    packets: 192

    Configurations
    --------------

    Linux Foundation - 2.0 root hub
    -------------------------------
    bus_id: 1
    device_address: 1
    device_version: 4.1.8
    bluetooth_version: 2.0.0
    packets: 2

    Configurations
    --------------

 

So we have a few different devices here. At the beginning, my mind was set on the flag being in the Mouse or DualShock devices, as they had the most data. I actually wrote a DualShock4 parser for Gallimaufry, which worked only to discover that they were simply creating data (pressing buttons in a circle, moving the sticks around, etc). That was a bit longer of a detour than I had hoped for, but if you're interested you can use the DS4 parser now at part of Gallimaufry.

 

That detour aside, I looked again and realized there was a Flash Drive USB. Really should have started there... Since the pcap didn't catch any Configuration packets, I tried out different configuration and endpoint numbers to discover the address of "1.2.1" is where the host was sending data to. Basically, you'll see a bunch of SCSI 'ready' packets, then a SCSI 'write' packet (saying "Hey i'd like to write data to you here"), followed by a URB_BULK out. It's those URB_BULK out packets that we're interested in.

 

You can extract all the bulk transfer data with something like this

 

cap_datas = [packet['_source']['layers']['usb.capdata'] for packet in pcap.pcap_filter(bus_id=1, device_address=2, endpoint_number=1) if 'usb.capdata' in packet['_source']['layers']]

 

Writing those out, run the file command to see what we got:

 

raw.bin.gpg: GPG symmetrically encrypted data (AES256 cipher)

 

File can be found here. That one looks interesting. It's encrypted, but where's the key? I recalled that there was a keyboard in the USB device list as well, and figured they may have leaked it through there. Since we don't have the descriptors, we'll have to "manually" extract the keystrokes by instantiating a Keyboard class.

 

from Gallimaufry.Classes.HID.Keyboard import Keyboard
keyboard = Keyboard(pcap.devices[2].pcap)
keyboard.keystrokes
# 'gpgg  -c ffllaaggsgs.ppnng\nutNOTflag{try_haarrdeerr}\nutNOTflag{try_hardeerr}\ncp flaggss.png.gpg /media/usseerer/USB/\n'

 

There are a few extra characters in there, but you can see the password they typed in. Using that as the pgp decryption key, we uncover a png. At this point, I ran stegoVeritas on it and discovered that they hid the flag in the LSB plane graphically (i.e.: the image transforms found it).

 

utflag{t3x45_1s_my_f4v0r1te_c0untry}