DEFCON1 (reverse, 300p, 5 solves)

description

DEFCON is the website controlling the security level of the room. The 5 different levels allows to warn the population of the risk of a potential nuclear war. Levels ranges from 5 (peacetime) to 1 (maximum alert). Try level 1.

solution

DEFCON website is pretty graphic website with lots of data, bet relevant part is "DEFCON LEVEL CONSOLE", where clicking on each level shows a popup with title "UNAUTHORIZED ACTION", text "The server requires a password for this action." and a single input field (password).

Using Chrome Developer Tools, inspecting button, following "Event Listeners" and searching defcon-1 in JavaScript files, shows how password is validated.

<div id="console">
	<button id="defcon-1">1</button>
	<button id="defcon-2">2</button>
	<button id="defcon-3">3</button>
	<button id="defcon-4">4</button>
	<button id="defcon-5">5</button>
</div>
async function validate() {
  if (modalLevel === "defcon-1") {
    return check1($("#modal-password").val());
  } else if (modalLevel === "defcon-2") {
    return await check2($("#modal-password").val());
  } else if (modalLevel === "defcon-3") {
    return check3($("#modal-password").val());
  } else if (modalLevel === "defcon-4") {
    return check4($("#modal-password").val());
  } else if (modalLevel === "defcon-5") {
    return check5($("#modal-password").val());
  } else {
    return false;
  }
}

Looking further at the level 1 validation in http://defcon.challs.malice.fr/static/js/scripts.js, reveals that it is validated elsewhere (different JavaScript file).

function check1(pwd) {
  return checkcheck1(pwd);
}

Real validation happens in http://defcon.challs.malice.fr/static/js/x.js.

checkcheck1 = function(pwd) {
	var _1, i, pos, pwd, walls;
	if (!((pwd.length === 2703))) {
		return false;
	}
	pos = new sliceType([75, 79]);
	walls = new sliceType$1([new sliceType([0, 1]), new sliceType([0, 2]), ... // long, long, loong line
	i = 0;
	while (true) {
		if (!(i < pwd.length)) { break; }
		_1 = pwd.charCodeAt(i);
		if (_1 === (117)) {
			pos = new sliceType([(0 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 0]) - 1 >> 0, (1 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 1])]);
		} else if (_1 === (100)) {
			pos = new sliceType([(0 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 0]) + 1 >> 0, (1 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 1])]);
		} else if (_1 === (108)) {
			pos = new sliceType([(0 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 0]), (1 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 1]) - 1 >> 0]);
		} else if (_1 === (114)) {
			pos = new sliceType([(0 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 0]), (1 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 1]) + 1 >> 0]);
		} else {
			return false;
		}
		if (in$1(pos, walls) || out_lab(pos)) {
			return false;
		}
		i = i + (1) >> 0;
	}
	if (!(((0 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 0]) === 34)) || !(((1 >= pos.$length ? ($throwRuntimeError("index out of range"), undefined) : pos.$array[pos.$offset + 1]) === 79))) {
		return false;
	}
	$global.alert($externalize("Well Done! Send the flag encoded with Sha512 to get your points!", $String));
	return true;
};
main = function() {
	$global.checkcheck1 = $externalize(checkcheck1, funcType);
};

So the idea is, that one must input 2703 character long string, containing u (up), d (down), l (left), r (right), which will solve the provided maze (walls), starting in position 75,79 and reaching position 34,79. Therefore a maze solving algorithm should be used.

Extract the maze walls (producing walls.txt where each line contains y,x coordinates of a wall).

$ wget http://defcon.challs.malice.fr/static/js/x.js
$ grep 'walls = ' x.js | sed 's/, new/X/g' | tr 'X' '\n' | sed -e 's/$1//g' -e 's/[^0-9,]*//g' > walls.txt
$ head -3 walls.txt
0,1
0,2
0,0

Write a maze solver, construcing maze from walls.txt and solving it with Breadth First Search algorithm from Labyrinth Algorithms.

#!/usr/bin/env python
import io, sys
from collections import deque

def maze2graph(maze):
    height = len(maze)
    width = len(maze[0]) if height else 0
    graph = {(i, j): [] for j in range(width) for i in range(height) if not maze[i].get(j)}
    for row, col in graph.keys():
        if row < height - 1 and not maze[row + 1].get(col):
            graph[(row, col)].append(("d", (row + 1, col)))
            graph[(row + 1, col)].append(("u", (row, col)))
        if col < width - 1 and not maze[row].get(col + 1):
            graph[(row, col)].append(("r", (row, col + 1)))
            graph[(row, col + 1)].append(("l", (row, col)))
    return graph

def find_path_bfs(maze, start, goal):
    queue = deque([("", start)])
    visited = set()
    graph = maze2graph(maze)
    while queue:
        path, current = queue.popleft()
        if current == goal:
            return path
        if current in visited:
            continue
        visited.add(current)
        for direction, neighbour in graph[current]:
            queue.append((path + direction, neighbour))
    return "no path"

walls = {} 
with io.open('walls.txt') as fh:
	for rline in fh:
		line = rline.strip().split(',')
		y, x = int(line[0]), int(line[1])
		if y not in walls:
			walls[y] = {}
		walls[y][x] = 1

o = find_path_bfs(walls, (75, 79), (34, 79))
print(len(o), o)

Run the maze solver.

$ python defcon1.py
(2703, 'uurrddrrrrrruurrddrrddllddllddlluuuullddddllllddddllddddrruurrddrrrrddddrrddddrruurruulluuuuuulluuuurrddrruuuurrrruulluuuurruurruulllllluulllllluullllddddlllluuuulluulluulllllluuuullllddddrrddrrrrrrddddrrddllddrrrrddddlluullddllddllddrrddrrrrddlllllluullddddlluullddllllllddllddrrddddrrddrrrruulluurrrrddrruurrrrrrddrruurrrrddllddlllllluullddllllddllllddlluullddddrrddllddrrddllddlluulllluurrrruulllluullddddddddrrddddllddrrrrddddrrrrrrrruuuuuuuulluurruurrddddddddddrrrrrruurrddrruuuurrddddrrddrrrrrrrrrruurruullllllddlllluuuurrrruurrrruurrrruuuuuuuurrrrddrruurrrruuuullddlluulluuuurruuuuuuuulluuuurrrruurruuuuuuuurruurrddrruuuurrrrrrrrrrrrddddddrrddddddddlluuuuuulluulluullddddddrrddddrrddddllddlluuuuuulllluullddllllllddddrrddllllddrrddddrruurrrruuuurrrrddllddddrrddrrddllllddddrruurrddddrrddlllllluulllluuuullddddddddrruurrddrrrrrrddddddddddllddrrrrrruurrddddrrrruurrrrrrrrddddllllddrrddllddddlluuuulluuuullllllllddlllluullddllddrrddrrrrrrrrrrrrddddrrrrrrddddllllddddlluuuuuulluulluullddlluullddddrrrrddddddddrrrrrrddllllllddrrddllddrrddllddrrddrruuuurrddddrruurrrrddrrrrrruurrrruurruurruurruurrddrrrrrrrrddddlllluullddlluullddddrrrrrrrrddrrrrrruulluuuuuuuulluulluuuurrddrruuuulllluullddddddllddlllllluuuulluurrrruurrddrruuuuuuuurrrrddrruurrddddllddrrrrddrrddddddrruuuuuuuuuuuuuuuulluuuullddllddlllllllluuuurruulllluurrrrrrrrddrruurruurrrruulllllllluulluulluurrrrrrrrrrrruuuuuuuullddlluulluurrrruurruuuuuuuullddddddllddlllluuuuuurruulluurruurrddrruuuurruulllllllluulllluuuurrrrrruulllluuuullddllllddllllddddllddlllluullllddllddlluuuulluurrrrrruurruurrddddrruurruuuulllllluuuulluuuurrddrrddrruuuuuurruurrrrrruuuurrddrrddllddllddddddllddrrrrrruuuulluurruurrrrrrddllddllddrrrrrruurruuuuuuuurruuuullllddddddlluuuulllluurruurruurruurruullllddllddllddllllddlluullllddrrddddlllluullddlluuuulllllluuuurrrrddrrrrrruuuurrrruuuuuurruulluuuuuulluulluurrrrrrddrrddllddrrddddddddllddddrrrruuuuuurrddrrrrrrrruurruuuullddlluullddddlluuuullddlluuuurrrrrruuuurrrrddllddrrrruuuuuulllluulluuuulluuuuuuuurrrrrrrruulluurruuuuuullddddlllllluulluurruurrrruulluullllllddddddddllddddddrrddddlluullddddrrrrrrddddddrrddllddlluuuuuuuullddddddlluullddlluullddllddlluuuulluurruurrddrrrrrrrruulluuuullddddlluulluuuuuurruuuulllllluurrrruulluulluurruullllllddddrrddddlluullddlllluuuurrrruulluullddlluullllllddllddddrrddddddllddddllllllddrrrrddrrddlllluullllddlluuuuuulllluurrrruulllllluurrrrrruulluurrrrrrddddllddrrrrddrruuuulluurruuuulllllllluurruullllllddlluullllddddddlllluuuullddddllddllddrrrrrrddddlluullddddrrrrrrddddddrrddrrrrrruuuuuurrddddddddddddllddlluulluuuullddddlllluulluullddddlllluuuuuuuurrrrrrrruulluulllluulluulluulluurrrruuuuuurruulluullllllddrrddddddllddddddrrddllllllllddddrrrrrrrrrrddllddrrddddddllllddddrruurrrrd')

Trying this in DEFCON website, returns "Well Done! Send the flag encoded with Sha512 to get your points!" Therefore, the flag is sha512 of maze path.

echo -n uurrd... | sha512
7452d6d91da700d0d686e75dd28fa80a0c64f81a402fcba2b9c4f81cd18eb46e5c052cd0cd1f601b5f117ad94ec68505f7f8fde8adb4e34157f55873239205ae

Flag is 7452d6d91da700d0d686e75dd28fa80a0c64f81a402fcba2b9c4f81cd18eb46e5c052cd0cd1f601b5f117ad94ec68505f7f8fde8adb4e34157f55873239205ae.