In [1]:
#  solution to Maze of HITCON 2014 CTF
from telnetlib import Telnet
import terminal
from time import sleep
from IPython.html import widgets # Widget definitions
from IPython.display import display # Used to display widgets in the notebook
In [2]:
if "map_mem" not in globals():
    map_mem=dict()
w=widgets.HTMLWidget()
w2=widgets.HTMLWidget()
def show_maze2():
    html ="<table>"
    for i in range(-44,45):
        html+="<tr>"
        for j in range(-44,45):
            mx,my = j, i
            bg = {'@': '#000', '.': '#fff',  '':'#0f7' }[map_mem.get((mx,my), '')]
            html+='<td style="background-color: %s; width: 6px; height: 6px;">%c</td>'%(bg, ' ')
        html+="</tr>"
    html+="</table>"
    w2.value = html
    
def show_maze(d):    
    html ="<table>"
    for i in range(9):
        html+="<tr>"
        for j in range(9):
            try:
                mx,my = cx+j-4,cy+i-4
                bg = {'@': '#000', '.': '#fff', 'o':'#777' }[d[i][j]]
                if (mx,my) in dead:
                    bg="#f00"
                elif (mx,my) in old:
                    bg="#0f0"                
            except:
                bg = "#00f"
            t = d[i][j]
            if t=='o': t='.'
            if t in "@.":
                if (mx,my) in map_mem:
                    if map_mem[mx,my] != t:
                        raise xxxxxx
                else:
                    map_mem[mx,my] = t
            html+='<td style="background-color: %s;width: 18px; height: 18px;">%c</td>'%(bg, d[i][j])
        html+="</tr>"
    html+="</table>"
    w.value = html
In [3]:
import sys
progress = widgets.IntProgressWidget(value=0, max=1000)
progress.set_css("background", "black")
progress.set_css("width", "800px")
term = terminal.Terminal(24, 80)
X = Telnet("210.71.253.213", 8473)
r =  X.read_until("..........")    
term.write(r)
term.dump()
sleep(1)
def new_pos(cx,cy, d):
    if d ==0:
        return cx, cy-1
    if d ==1:
        return cx+1, cy
    if d == 2:
        return cx, cy+1
    if d ==3:
        return cx-1, cy
from collections import defaultdict
junction = set()
mem =defaultdict(int)
display(w)
display(progress)
display(w2)
direction = -1
ds = "ACBD"
rds = "BDAC"
stack =[]
old =set()
if 'dead' not in globals():
    dead=set()
cx, cy = 0,0
IDLE = 0.05
LOOPS = int(500/IDLE)
UPDATE = int(25/IDLE)
for cnt in range(LOOPS):
    sleep(IDLE)
    r = X.read_very_eager()    
    term.write(r)
    d = term.dump()
    if cnt%3==0:
        show_maze(d)
        progress.value=int(cnt*1000./LOOPS)
    nbhd = [d[3][4], d[4][5], d[5][4], d[4][3]]        
    while 1:
        direction +=1
        if direction >=4:
            break
        if nbhd[direction]=='.':
            nx,ny = new_pos(cx,cy,direction)
            if (nx,ny) not in old and (nx,ny) not in dead:
                break
    if direction == 4: 
            old.add((cx,cy))
            dead.add((cx,cy))
            if len(stack)==0:
                show_maze2()
                break
            cx, cy, direction = stack.pop()
            X.write("\x1b[%c"%rds[direction])
    else:
        stack.append((cx,cy,direction))
        X.write("\x1b[%c"%ds[direction])
        old.add((cx,cy))
        cx,cy,direction=nx,ny,-1    
    if cnt%UPDATE==0:
        show_maze2()
print "done"  
done
In [ ]: