Crystal from the past
Description
- Hey, Nux! Look at this crystal! It's almost as nice as a V8 engine!
- What?
- It looks like... a chrome... thingy.
- What are you talking about. Let me see.
- NO! ITS MINE! I... MUST... DRAW!
One of Nux’s weirdo friend found a mesmerizing crystal in the desert. After taking it with him, he got posessed with it. He tells weird jokes no one understands, and draws a lot on his shitty computer using an unrecognizeable graphic tablet as old as mankind. However, he won’t let you see the drawings, thus, you installed a packet sniffer on his computer.
You managed to get a pcap of one of his drawing. He starts every session by calibrating the graphic tablet. This is achieved by drawing a horizontal and a vertical line, pushing the tip of the pen (draw force calibration), and tilting the pen around.
Your task is to recover the picture he drew.
- Author: Csf3r3ncz1
 - Difficulty: medium
 - Attachments: calibration.pcap, challenge.pcap
 
Solution
I started this challenge with looking at the given calibration.pcap file inside Wireshark. I noticed the USB descriptor but since google didn’t gave me an understandable protocol description easily, I tried to understand the sent bytes in a logical manner. We knew the following from the description:
- Our guy starts with a horizontal line
 - Followed by a vertical line
 - Then some other calibration stuff
 
This meant to me, I am looking for an x and a y variable sent, signaling the pen’s position, and some other stuff, which might be handy later, e.g. force and tilt. I exported the captured data from Wireshark, and started working. (Yes I knew about PyShark, but I couldn’t make it to work, since it failed to load the data from me from the packets.) This is the script I came up with, which loads the data, and then plots it to a diagram.
#!/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
file = open('./calibration.data', 'r')
#file = open('./chall.data', 'r')
data = []
#Read data from capture
for line in file.readlines():
	if ('02' in line):
		raw = line.strip('\n')
		cut = [raw[i+2:i+4] + raw[i:i+2] for i in range(0, len(raw), 4)]
		d = {
			'idk': int('0x' + cut[0],16),
			'x': int('0x' + cut[1],16),
			'y': int('0x' + cut[2],16),
			'force': int('0x' + cut[3],16),
			'tilt': int('0x' + cut[4],16)
		}
		data.append(d)
#Plot the data
for item in data:
	print(item)
	plt.scatter(item['x'], item['y'])
plt.show()

From here I started working with the real data, however on the first render it looked quite a mess. Of course, up until now I only used the x and y variables, so I figured I would tinker a little bit with the other values. This setup gave me a clear enough diagram, so I could read the flag:
for item in data:
	print(item)
	if item['x'] < 14700 and item['y'] < 9700:
		if item['tilt'] > 200 and item['force'] > 0:
			plt.scatter(item['x'], item['y'])
The acquired flag is:
cd21{HIDDEN}