Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
[HITCON CTF 2018] EV3
import json
import operator
'''
Have to read documentation and see how opUI_DRAW worked
840501xxxxyyyyff
opcode text black xcord ycord char
Communication happens from localhost ethernet -> ev3
'''
# Taken from https://stackoverflow.com/questions/10664856/make-dictionary-with-duplicate-keys-in-python
class DictList(dict):
def __setitem__(self, key, value):
try:
# Assumes there is a list on the key
self[key].append(value)
except KeyError: # if fails because there is no key
super(DictList, self).__setitem__(key, value)
except AttributeError: # if fails because it is not a list
super(DictList, self).__setitem__(key, [self[key], value])
blk1=""
blk2=""
blk3=""
blk4=""
dict1 = DictList()
dict2 = DictList()
dict3 = DictList()
dict4 = DictList()
# btrfcomm && packetlogger.type==0x02 && data
with open('data_ev3_1.1') as f:
data = json.load(f)
for j in xrange(0, 4):
data_dump=""
stack=""
for i in xrange(0, len(data)):
tmp = "".join(data[i]["_source"]["layers"]["data"]["data.data"].split(":"))
if j ==0:
#print "[+] Retrieving block 1"
if '2884' in tmp:
meh = tmp.find('2884')
beep = tmp[meh+4:][:2]
xcord = tmp[meh-4:][:4]
if '00' in xcord[:2]:
xcord = tmp[meh-6:][:6]
xcord_int = int(xcord, 16)
beep_nice = beep.decode('hex')
if beep_nice in stack:
beep_nice = beep_nice+"#"
stack +=beep_nice
dict1[beep_nice] = xcord_int
#blk1 += beep_nice
#print data_dump
elif j == 1:
#print "[+] Retrieving block 2"
if '3684' in tmp:
meh = tmp.find('3684')
beep = tmp[meh+4:][:2]
xcord = tmp[meh-4:][:4]
if '00' in xcord[:2]:
xcord = tmp[meh-6:][:6]
xcord_int = int(xcord, 16)
beep_nice = beep.decode('hex')
if beep_nice in stack:
beep_nice = beep_nice+"#"
stack +=beep_nice
dict2[beep_nice] = xcord_int
#print data_dump
elif j == 2:
#print "[+] Retrieving block 3"
if '4484' in tmp:
meh = tmp.find('4484')
beep = tmp[meh+4:][:2]
xcord = tmp[meh-4:][:4]
if '00' in xcord[:2]:
xcord = tmp[meh-6:][:6]
xcord_int = int(xcord, 16)
beep_nice = beep.decode('hex')
if beep_nice in stack:
beep_nice = beep_nice+"#"
count +=1
stack +=beep_nice
dict3[beep_nice] = xcord_int
#print data_dump
elif j == 3:
#print "[+] Retrieving block 4"
if '5284' in tmp:
meh = tmp.find('5284')
beep = tmp[meh+4:][:2]
xcord = tmp[meh-4:][:4]
if '00' in xcord[:2]:
xcord = tmp[meh-6:][:6]
xcord_int = int(xcord, 16)
beep_nice = beep.decode('hex')
if beep_nice in stack:
beep_nice = beep_nice+"#"
stack +=beep_nice
dict4[beep_nice] = xcord_int
#print data_dump
print dict1
sorted_dict1 = sorted(dict1.items(), key=operator.itemgetter(1))
for i in xrange(0, len(sorted_dict1)):
blk1 += sorted_dict1[i][0]
sorted_dict2 = sorted(dict2.items(), key=operator.itemgetter(1))
for i in xrange(0, len(sorted_dict2)):
blk2 += sorted_dict2[i][0]
sorted_dict3 = sorted(dict3.items(), key=operator.itemgetter(1))
for i in xrange(0, len(sorted_dict3)):
blk3 += sorted_dict3[i][0]
sorted_dict4 = sorted(dict4.items(), key=operator.itemgetter(1))
for i in xrange(0, len(sorted_dict4)):
blk4 += sorted_dict4[i][0]
x = blk1.replace("#", '')
y = blk2.replace("#", '')
z = blk3.replace("#", '')
zz = blk4.replace("#", '')
print x+y+z+zz
#hitcon{m1nd5t0rm_communication_and_firmware_developer_kit}
#Human interaction was to include 'e' in firmwar due to 3 duplication issue. Didn't have time during CTF to optimize solver
import json
'''
Instruction opInput_Device (CMD, …)
Opcode 0x99
Now here we are looking at the read values from the sensor sent from ev3 to localhost ethernet
It seems like # for black and <space> for white will recreate the image
Example payload: 99 1d 00 02 00 02 01 60
length = 8 Bytes
99 = Opcode
1d = READY_SI
00 = Layer number 0
02 = Port Number of Sensor
00 = Type (default)
02 = Mode (default)
01 = Returned values (eh?)
Seems this payload is send as a request to read the values from sensor I think and the ev3 will respond it.
For reading response we can load the pklg into wireshark and use the following filter:
btrfcomm && packetlogger.type==0x03 && data
Select all packets (CTRL+SHIFT+M) and dump it using 'Export Packet Dissection -> As JSON -> ev3-scanner.json'
Hence, the communication weill be from LegoSyst -> localhost ethernet this case as values taken from robot will be sent of.
The response data variantions are minute :
00 c0 80
00 80 3f
+ + 45 (1st + is faster, 2nd is increment)
00 c0 80
00 80 3f
- - 45
00 c0 40
00 80 3f
+ + 45 (1st + is faster, 2nd is increment)
This looks like the ++45 means robot is making 180 degree U-Turn towards Right hand side
- - 45 is to nullify I think, making 180 degree U-Turn towards Left hand side
and c0 80 , c0 40 means White color read
80 3f means black color read
>>> int('c0', 16), int('80',16)
(192, 128)
>>> int('80', 16), int('3f',16)
(128, 63)
So, if the color is black then seems sensor value will be down, where intensity of reflected light will be higher on white surface.
----> 1
<----- 2
-------> 3
............
--------> 11
So, robot will traverse 11 times on the mattress.
'''
with open('ev3-scanner.json') as f:
data = json.load(f)
alert = 0
total_turn = 0
first_round = ""
second_round = ""
third_round = ""
fourth_round =""
fifth_round = ""
six_round =""
seven_round=""
eight_round = ""
nine_round = ""
ten_round = ""
eleven_round = ""
for i in xrange(0, len(data)):
tmp = "".join(data[i]["_source"]["layers"]["data"]["data.data"].split(":"))
if len(tmp) == 18:
i = 1
identifier1 = tmp[12:][0:2]
identifier2 = tmp[12:][2:4]
identifier3 = tmp[12:][4:6]
if identifier3 == '45': # Likely 180 U Turn
alert = 1
# break # start of the fucking turn
continue
elif identifier2 == 'c0' or identifier3 == '40' and identifier1 == '00': # Likely white
if alert == 1: # Turn has been taken
print "[+] Turn was taken"
alert = 0
total_turn += 1
if total_turn == 0:
first_round += " "
elif total_turn == 1:
second_round += " "
elif total_turn == 2:
third_round += " "
elif total_turn == 3:
fourth_round += " "
elif total_turn == 4:
fifth_round += " "
elif total_turn == 5:
six_round += " "
elif total_turn == 6:
seven_round += " "
elif total_turn == 7:
eight_round += " "
elif total_turn == 8:
nine_round += " "
elif total_turn == 9:
ten_round += " "
elif total_turn == 10:
eleven_round += " "
if total_turn == 0:
first_round += " "
elif total_turn == 1:
second_round += " "
elif total_turn == 2:
third_round += " "
elif total_turn == 3:
fourth_round += " "
elif total_turn == 4:
fifth_round += " "
elif total_turn == 5:
six_round += " "
elif total_turn == 6:
seven_round += " "
elif total_turn == 7:
eight_round += " "
elif total_turn == 8:
nine_round += " "
elif total_turn == 9:
ten_round += " "
elif total_turn == 10:
eleven_round += " "
elif identifier2 == '80' and identifier1 == '00': # Likely black
if alert == 1:
print "[+] Turn was taken"
alert = 0
total_turn += 1
if total_turn == 0:
first_round += "#"
elif total_turn == 1:
second_round += "#"
elif total_turn == 2:
third_round += "#"
elif total_turn == 3:
fourth_round += "#"
elif total_turn == 4:
fifth_round += "#"
elif total_turn == 5:
six_round += "#"
elif total_turn == 6:
seven_round += "#"
elif total_turn == 7:
eight_round += "#"
elif total_turn == 8:
nine_round += "#"
elif total_turn == 9:
ten_round += "#"
elif total_turn == 10:
eleven_round += " "
if total_turn == 0:
first_round += "#"
elif total_turn == 1:
second_round += "#"
elif total_turn == 2:
third_round += "#"
elif total_turn == 3:
fourth_round += "#"
elif total_turn == 4:
fifth_round += "#"
elif total_turn == 5:
six_round += "#"
elif total_turn == 6:
seven_round += "#"
elif total_turn == 7:
eight_round += "#"
elif total_turn == 8:
nine_round += "#"
elif total_turn == 9:
ten_round += "#"
elif total_turn == 10:
eleven_round +="#"
print "[+] Total turn taken was "+str(total_turn)
print first_round
print second_round[::-1]
print third_round
print fourth_round[::-1]
print fifth_round
print six_round[::-1]
print seven_round
print eight_round[::-1]
print nine_round
print ten_round[::-1]
print eleven_round
print "*************************************************************************************"
print len(first_round)
print len(second_round)
print len(third_round)
print len(fourth_round)
print len(fifth_round)
print len(six_round)
print len(seven_round)
print len(eight_round)
print len(nine_round)
print len(ten_round)
print len(eleven_round)
#hitcon{EV3GYROSUCKS}
#The ascii art isn't that proper but readable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.