Skip to content Skip to navigation

Maze (PPC - 200)

Category: 

Task:

Universal dangerous positive: 194.226.244.125:1024. Send me your password: "3k8bbz032mrap75c8iz8tmi7f4ou00". Flag format is "RUCTF_.*"

Solution:

 "Universal dangerous positive" hints us, that there is UDP protocol. So lets connect to given ip and send password:

UDP_IP = "194.226.244.125"
UDP_PORT = 1024
message = "3k8bbz032mrap75c8iz8tmi7f4ou00"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(1)

sock.sendto(message, (UDP_IP, UDP_PORT))
print sock.recv(100000)

This code prints:

Hello stranger!
You can go down(1280) with password: g5op3e6wxcy71m24dgcmhq714nd799
You can go right(1025) with password: 084399ptmy7u4bxwy003x2ko2oa06n

Ok, we have a maze, each cell of maze is defined by port and password. When we send correct password to port it responds with information about it's neighbors. So we have to write some code

First thing: maze's answers recognition (it's ugly, but it works):

res = sock.recv(100000)
print res

#Parse the answer
mess = []
dirs = []
while True:
        #looking for direction:
	ind1 = res.find("can go ")
	if -1 == ind1:
		break
	ind1 = ind1 + len("can go ")
	dirs.append(res[ind1:ind1+1])
	#looking for password
	ind = res.find("password: ")
	if -1 == ind :
		break
	ind = ind + len("password: ")
	mess.append(res[ind: ind+30])
	res = res[ind+30:]

 Now we have array with password and corresponding array with directions (with first letters of them). We need some maze-solving algorithm, for example right-hand methond: 

#declare in the begining
order = ["r","d","l","u"] #right-hand alg order
direction = 3

#and do this in cycle:

#Compute next turn (right-hand method)
next_dir = (direction + 1) % 4
next_i = -1
while True:
	for i in xrange(0, len(dirs), 1):
		if dirs[i] == order[next_dir]:
			next_i = i
			break
	if -1 != next_i:
		break
	next_dir = (next_dir - 1) %4

message = mess[next_i]

#update port and coordinates

if next_dir == 0:
	UDP_PORT +=1
if next_dir == 2:
	UDP_PORT -=1
if next_dir == 1:
	UDP_PORT +=256
if next_dir == 3:
	UDP_PORT -=256
direction = next_dir

 So we choose next direction, trying to turn to the right every time when it possible and then update message and port to new values. As you can see, each time you go left and right port simply dec/increments, but when you go up and down it changes by 256... it's obvious from first server answer. (All other answer does not specify port, only passwords.)

Last thing we need.. some cool gui to draw this maze.. i used pygui... and there is result:

And full code of solving script:

#!/usr/bin/python
import socket
from time import sleep
import sys
from GUI import Application, ScrollableView, Document, Window, Cursor, rgb
from GUI.StdColors import black, red, white
from GUI.Files import FileType
from GUI.Geometry import pt_in_rect, offset_rect, rects_intersect

class MazeView(ScrollableView):
	hero_x = 0
	hero_y = 0
	maze_walls = [[0 for x in xrange(256)] for x in xrange(256)] 

	offset = 10
	multi = 4

	def add_point(self, p_x ,p_y):

		self.maze_walls[p_x][p_y]=1

	def move_hero(self, p_x ,p_y):
		self.hero_x = p_x
		self.hero_y = p_y
		self.invalidate_rect(( self.offset + (p_x - 3) * self.multi, self.offset + (p_y -3) * self.multi, self.offset + (p_x+3) * self.multi, self.offset + (p_y+3) * self.multi ))
		self.update()

	def draw(self, canvas, update_rect):
		#canvas.erase_rect(update_rect)
		#draw main wall
		canvas.fill_frame_rect((self.offset-self.multi,self.offset-self.multi,self.offset+257*self.multi,self.offset+257*self.multi))
		canvas.fillcolor = white
		canvas.pencolor = white
		canvas.fill_frame_rect((self.offset,self.offset,self.offset+256*self.multi,self.offset+256*self.multi))
		#draw hero
		canvas.fillcolor = red
		canvas.pencolor = red
		canvas.fill_frame_rect((self.offset + self.hero_x*self.multi, self.offset + self.hero_y*self.multi ,self.offset + self.hero_x*self.multi + self.multi,self.offset + self.hero_y*self.multi+ self.multi))
		#draw inner walls
		canvas.fillcolor = black
		canvas.pencolor = black

		for k in xrange(self.hero_x-5,self.hero_x+5,1):
			for l in xrange(self.hero_y-5,self.hero_y+5,1):
				if k < 0 or l <0 or k>= 256 or l >=256 : continue
				if 1 == self.maze_walls[k][l]:
					if True == pt_in_rect((self.offset + k*self.multi, self.offset + l*self.multi), update_rect):
						canvas.fill_frame_rect((self.offset + k*self.multi, self.offset + l*self.multi,self.offset + k*self.multi + self.multi,self.offset + l*self.multi+ self.multi))


win = Window(size = (258*4+20, 258*4+20))
view = MazeView(extent = (512*4, 512*4))
win.place(view, left = 0, top = 0, right = 0, bottom = 0, sticky = 'nsew')
win.show()

UDP_IP = "194.226.244.125"
order = ["r","d","l","u"] #right-hand alg order

message = "3k8bbz032mrap75c8iz8tmi7f4ou00"
UDP_PORT = 1024
direction = 3
cur_x = 0
cur_y = 0

while True: # ti recover after disconnect
	try:
		sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		sock.settimeout(1)
		while True: 
			sock.sendto(message, (UDP_IP, UDP_PORT))
			print "Current position: " + str(cur_x) + ", " + str(cur_y)
			res = sock.recv(100000)
			print res

			#Parse the answer
			mess = []
			dirs = []
			while True:
				#looking for direction:
				ind1 = res.find("can go ")
				if -1 == ind1:
					break
				ind1 = ind1 + len("can go ")
				dirs.append(res[ind1:ind1+1])
				#looking for password
				ind = res.find("password: ")
				if -1 == ind :
					break
				ind = ind + len("password: ")
				mess.append(res[ind: ind+30])
				res = res[ind+30:]

			view.move_hero(cur_x,cur_y)

			if (dirs.count('r') == 0):
				view.add_point(cur_x+1,cur_y)

			if (dirs.count('l') == 0):
				view.add_point(cur_x-1,cur_y)

			if (dirs.count('u') == 0):
				view.add_point(cur_x,cur_y-1)

			if (dirs.count('d') == 0):
				view.add_point(cur_x,cur_y+1)

			#Compute next turn (right-hand method)
			next_dir = (direction + 1) % 4
			next_i = -1
			while True:
				for i in xrange(0, len(dirs), 1):
					if dirs[i] == order[next_dir]:
						next_i = i
						break
				if -1 != next_i:
					break
				next_dir = (next_dir - 1) %4

			message = mess[next_i]

			#update port and coordinates

			if next_dir == 0:
				cur_x += 1
				UDP_PORT +=1
			if next_dir == 2:
				cur_x -= 1
				UDP_PORT -=1
			if next_dir == 1:
				cur_y +=1
				UDP_PORT +=256
			if next_dir == 3:
				cur_y -= 1
				UDP_PORT -=256

			direction = next_dir
	except Exception, e:
		print e

 

 

Attachments: