Race of a Lifetime (100)
Description
You are participating in a race around the world. The prize would be a personalized flag, together with a brand new car. Who wouldn’t want that? You are given some locations during this race, and you need to get there as quick as possible. The race organisation is monitoring your movements using the GPS embedded in the car. However, your car is so old and could never win against those used by the opposition. Time to figure out another way to win this race.
Write-up
There is console interface for GPS available on the UART. It shows your position on the map along with other textual information. The task was to travel to several destination points without exhausting number of moves and without exceeding transport speed (e.g. for airplane 7.5 pt/move).
Solution in Python with pwntools
:
from pwn import *
import math
GPS = {
"the Riscure office": (51.997838, 4.3853637),
"CDG": (49.0096906, 2.5457358),
"PVG": (31.1443439, 121.8060843),
"SFO": (37.6213129,-122.3811441),
"550 Kearny St, San Francisco, CA, United States": (37.7932696, -122.4065364),
}
def read_coords_begin(tty):
tty.recvuntil("Latitude:")
lat = float(tty.recvuntil("\t").strip())
tty.recvuntil("Longitude:")
lon = float(tty.recvuntil("\n").strip())
return (lat, lon)
def read_coords(tty):
tty.recvuntil("Location:")
location = tty.recvline().strip()
if location in GPS:
return GPS[location]
lat, lon = map(float, location.split(" "))
return (lat, lon)
def read_destination(tty):
tty.recvuntil("Head to ")
destination = tty.recvline().replace("to get the directions.", "").strip()
return destination
def enter_name(tty):
tty.recvuntil("Enter your name to start:")
tty.send("S0S1\n")
tty.recvline()
def create_track(start, end, max_speed=1.0, number=None):
track = []
if number is None:
d = math.sqrt(((end[0] - start[0]) ** 2) + ((end[1] - start[1]) ** 2))
number = int(math.ceil(d / max_speed))
for i in xrange(number):
lat = start[0] + ((end[0] - start[0]) * (i + 1) / number)
lon = start[1] + ((end[1] - start[1]) * (i + 1) / number)
track.append("%.6f %.6f" % (lat, lon))
print "FROM: %s TO: %s IN: %d" % (start, end, number)
return track
def move(tty, track):
for pos in track:
l = tty.recvuntil(">", timeout=1)
if l == '':
return False
print "SENDING: %s" % pos
tty.send(pos + "\n")
tty.recvline() # pos
l = tty.recvline()
if "Unexpected location." in l or "Too late." in l:
return False
return True
def foo():
tty = serialtube("/dev/tty.usbserial", baudrate=115200, timeout=0)
enter_name(tty)
start_pos = read_coords_begin(tty)
destination = read_destination(tty)
if not destination in GPS:
print "Not found: %s" % destination
end_pos = GPS[destination]
# -> riscure
track_to_riscure = create_track(start_pos, end_pos)
if not move(tty, track_to_riscure):
tty.interactive()
return
# get ECU
riscure_pos = end_pos
destination1_pos = read_coords(tty)
print "riscure -> cdg"
track_to_paris = create_track(riscure_pos, GPS["CDG"], max_speed=1.0)
if not move(tty, track_to_paris):
tty.interactive()
return
print "cdg -> pvg"
track_to_bejing = create_track(GPS["CDG"], GPS["PVG"], max_speed=7.5)
if not move(tty, track_to_bejing):
tty.interactive()
return
print "pvg -> destination1"
track_to_destination1 = create_track(GPS["PVG"], destination1_pos, number=8, max_speed=0.3)
if not move(tty, track_to_destination1):
tty.interactive()
return
## bring ECU
destination2_pos = read_coords(tty)
print "destination1 -> pvg"
track_to_bejing = create_track(destination1_pos, GPS["PVG"], max_speed=0.3)
if not move(tty, track_to_bejing):
tty.interactive()
return
print "pvg -> cdg"
track_to_paris = create_track(GPS["PVG"], GPS["CDG"], max_speed=7.5)
track_to_paris.append(track_to_paris[-1])
if not move(tty, track_to_paris):
tty.interactive()
return
print "cdg -> sfo"
track_to_sanfrancisco = create_track(GPS["CDG"], GPS["SFO"], number=16, max_speed=7.5)
if not move(tty, track_to_sanfrancisco):
tty.interactive()
return
print "sfo -> destination2"
track_to_destination2 = create_track(GPS["SFO"], destination2_pos, max_speed=0.3)
if not move(tty, track_to_destination2):
tty.interactive()
return
# go to riscure
print "destination2 -> sfo"
track_to_sanfrancisco = create_track(destination2_pos, GPS["SFO"], max_speed=0.3)
if not move(tty, track_to_sanfrancisco):
tty.interactive()
return
print "sfo -> cdg"
track_to_paris = create_track(GPS["SFO"], GPS["CDG"], number=16, max_speed=7.5)
if not move(tty, track_to_paris):
tty.interactive()
return
print "cdg -> riscure"
track_to_paris = create_track(GPS["CDG"], riscure_pos, max_speed=1.0)
if not move(tty, track_to_paris):
tty.interactive()
return
tty.interactive()
foo()