Team Name: HATS SG
First time actually solving something under HATS SG. Always just went for the meetups and became useless cause I was too noob. Who knew? Suddenly got arrowed to do the robotics challenges because of my background in robotics.
Do you hear the robot sing
Network Packet Analysis
The first thing I saw was a
.pklg file after which I basically flipped as this was nowhere near my area of expertise.
The video shows a EV3 robot playing audio saying
congratulations the flag...
.pklg logs the communication from the computer (MacBook OSX) to a LEGO Mindstorms NXT EV3. After looking at a writeup from previous year’s Hitcon, I found the guides to the LEGO Developer Kits.
I analyzed the bytes
.pklg with the help of a Wireshark add-on and extracted the following information:
Packet 982 signifies end of download Packet 991 loads the program and start program All packets from the MacBook to the EV3 do not contain any instructions to play sound Packet 1-970: Boot and Download program and other files to EV3 Packet 500: Begin transfer of file fl.rsf Packet 698: Begin transfer of file ag.rsf
No instructions were sent to the EV3 brick to play any sound. Based on my knowledge of EV3, sound can only be played either by frequencies, musical notes, sound files. Sound files have to be parsed through their sound editor which later converts it to a
.rsf (robot sound file). I would guess that the bytes in the
.rsf are just frequencies.
Extracting the RSF File
Anyways, looks like our best bet was to extract
ag.rsf. We filtered the packets using the following filter
(ev3.sys_cmd=0x092 || ev3.sys_cmd=0x093) && bluetooth.dst == 00:16:53:61:30:c1 which basically restricts the packets to those that are related to the download to the EV3 brick. The bytes of each filtered packet was then extracted manually. A script written by my teammate was used to combine these bytes into a
.rsf files while extracting the system commands.
import binascii combine = '' for i in range(1,97): with open(str(i),'rb') as f: content = binascii.hexlify(f.read()) content = content[12:] combine += content with open('output.rsf','wb') as f: f.write(combine)
.rsf was opened in the
LEGO Mindstorms Education EV3 application. When played, we hear a very high-pitched, indistinct sound but it does sound like a audio sped up by 5x. We import the file into Audacity as unsigned 8-bit raw data with no endianness. We then slow down the speed by 5x and increase the volume (as necessary).
fl.rsf, we hear
congratulations, the flag contains no spaces and all lowercase. This is when we knew we got it. We then did the same process for
ag.rsf and the audio file literally read out the flag.
Finally something I am remotely familiar with. The video shows a robot writing the word
.rbf file is a robot block code file used in EV3 to give the robot instructions. Using an online decompiler, we can obtain a line version of LEGO code that we see in the LEGO Mindstorms programming app. We can remove all the extra lines and the beginning characters of lines to make the lines more consistent using a simple text editor since the code isn’t that long. The decompiled and shortened commands can be found in EV3 Arm Commands.
Each motor has a port (A,B,C), a speed (Negative and positive numbers) and the distance in which it should move. By the order of movements in the video, I deduced the ports
A: Arm swivelling, B: Lowering the pen, C: Base movement. With that, we can write a simple python script to plot out exactly where the marker wrote stuff. We can assume the arm swivelling is linear (along y-axis) because of its relatively large radius of turning and we can take the base movement as translations along the x-axis. We only draw lines when the pen is lowered. The values were then plotted using the library
matplotlib in the script below.
import matplotlib.pyplot as plt with open('commands.txt','r') as f: content = f.readlines() plotX =  plotY =  fig, ax = plt.subplots() penAngle = 35 x = 0 y = 0 for i in content: items = i.strip().split(' | ') if items.startswith("Motor"): #base movement if int(items.split(' ')) > 0: x += float(items.split(' ')) * 50 else: x -= float(items.split(' ')) * 50 elif items == 'port_motor: B': #Arm controller if int(items.split(' ')) > 0: penAngle += int(items.split(' ')) else: penAngle -= float(items.split(' ')) else: #Swivel/Turret motion if int(items.split(' ')) > 0: y += int(items.split(' ')) else: y -= int(items.split(' ')) if penAngle != 0: #Plot all points once pen leaves canvas ax.plot(plotX,plotY) plotX.clear() plotY.clear() else: #Append points plotX.append(x) plotY.append(y) plt.show()
This script would display an image of the “writings” the robot did.