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
Running sports | jordan Release Dates