extract the flag! Download:
83ff3b21362b514c20861c94fb3f68aed3e11ebf81c80f5e1f6ecfcc4ca8ed64.tar.xz
The challenge consisted of extracting a flag from a .pcapng-stream, captured while scanning a sheet of paper via USB.
There are quite some USB-packets to and from the scanner. Some of them obviously contain raw data.
As we’re not keen on klicking on each packet with raw data in wireshark and
extract the data manually, automating the task is desirable.
Fortunately there are some libraries for handling .pcapng.
I found pypcappy
to be the most usable (or usable at all for that matter).
from pypcappy import PcapNgFile
p = PcapNgFile('ctf.pcapng')
# make packets subscriptable
ps = [p for p in p.packets]
As we only want to extract the raw data, we try to find an easy criterium. Let’s take the packet size. Packets containing data are mostly larger than 1024, others smaller. So let’s filter those out:
# filter out packets containing data, skipping some
dt = [p for p in ps[700:] if len(p.data) >= 1024]
(I also filtered out a protocol-packet that was larger than 1024 byte.)
I used this little helper funktion:
def w(fn, ps):
with open(fn, 'bw') as o:
for p in ps:
# discard usb header
o.write (p.data[64:])
w('out_s0_sol.raw', dt)
I used GIMP as follows:
as they seem to have different orientation, I cut the raw data in half and had a look at both separately
# get first page
dt_s0 = dt[:int(len(dt)/2)]
# get second page
dt_s1 = dt[int(len(dt)/2):]
# write second page
w('out_s0_sol.raw', dt_s1)
The flag turns out to be at the second page with the following parameters:
The whole script:
from pypcappy import PcapNgFile
def w(fn, ps):
with open(fn, 'bw') as o:
for p in ps:
# discard usb header
o.write (p.data[64:])
p = PcapNgFile('ctf.pcapng')
# make packets subscriptable
ps = [p for p in p.packets]
# filter out packets containing data, skipping some
dt = [p for p in ps[700:] if len(p.data) >= 1024]
# get first page
dt_s0 = dt[:int(len(dt)/2)]
# get second page
dt_s1 = dt[int(len(dt)/2):]
# write second page (containing flag) to raw data
w('out_s0_sol.raw', dt_s1)
## Then
## - open GIMP
## - select the raw data
## - select type: Raw Image Data
## - in the dialog select
## - Image Type: RGB
## - Offset: something about 6000
## - Width: 3504
## - Height: more than double than width to be sure