Skip to content

Latest commit

 

History

History

misc_150

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

number_place (misc 150)

###ENG PL

In the task we get hint about sudoku and address of remote server which sends us inputs in form:

.418.5..9..9.7..58.3............26..3...6..25...5...97.....69.2.1..4......7......

It's quite clear that this is definition of sudoku grid and we need to solve it to get the flag. In some later stages the inputs were also containing roman numbers, binary numbers and base-64 decoded numbers.

So we grabbed first sudoku solver from internet, coded data parsing and communication with the server and used the script:

import base64
import socket
import re
from time import sleep


def findNextCellToFill(grid, i, j):
    for x in range(i, 9):
        for y in range(j, 9):
            if grid[x][y] == 0:
                return x, y
    for x in range(0, 9):
        for y in range(0, 9):
            if grid[x][y] == 0:
                return x, y
    return -1, -1


def isValid(grid, i, j, e):
    rowOk = all([e != grid[i][x] for x in range(9)])
    if rowOk:
        columnOk = all([e != grid[x][j] for x in range(9)])
        if columnOk:
            # finding the top left x,y co-ordinates of the section containing the i,j cell
            secTopX, secTopY = 3 * (i / 3), 3 * (j / 3)
            for x in range(secTopX, secTopX + 3):
                for y in range(secTopY, secTopY + 3):
                    if grid[x][y] == e:
                        return False
            return True
    return False


def solveSudoku(grid, i=0, j=0):
    i, j = findNextCellToFill(grid, i, j)
    if i == -1:
        return True
    for e in range(1, 10):
        if isValid(grid, i, j, e):
            grid[i][j] = e
            if solveSudoku(grid, i, j):
                return True
            # Undo the current cell for backtracking
            grid[i][j] = 0
    return False


def stringify(arrays):
    return "".join("".join([str(c) for c in x]) for x in arrays)


def solve(s):
    arrays = [[int(c) for c in s[i * 9:(i + 1) * 9]] for i in range(9)]
    solveSudoku(arrays)
    result = stringify(arrays)
    return result


def parse_bin(s):
    bins = re.findall("\(.+?\)", s)
    for found in bins:
        s = s.replace(found, str(int(found[1:-1], 2)))
    return s


def parse_base64(s):
    bins = re.findall("\[.+?\]", s)
    for found in bins:
        s = s.replace(found, str(base64.b64decode(found[1:-1])))
    return s


def parse_roman(s):
    s = s.replace('<I>', '1')
    s = s.replace('<II>', '2')
    s = s.replace('<III>', '3')
    s = s.replace('<IV>', '4')
    s = s.replace('<V>', '5')
    s = s.replace('<VI>', '6')
    s = s.replace('<VII>', '7')
    s = s.replace('<VIII>', '8')
    s = s.replace('<IX>', '9')
    return s


def parse(s):
    s = s.replace('.', '0')
    s = parse_roman(s)
    s = parse_bin(s)
    s = parse_base64(s)
    return s


def main():
    url = '35.161.87.33'
    port = 10101
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((url, port))
    while True:
        sleep(1)
        received = s.recv(9999)[:-1]
        print(received)
        received = parse(received)
        result = solve(received)
        print(result)
        s.sendall(result + "\n")


main()

Finally we got ECTF{jk_w3_41n7_s0rrY}

###PL version

W zadaniu dostajemy hint na temat sudoku oraz adres serwera który wysyła dane w formie:

.418.5..9..9.7..58.3............26..3...6..25...5...97.....69.2.1..4......7......

Jest dość jasne, że to opis planszy sudoku a my mamy ją rozwiązać aby dostać flagę. W dalszych poziomach dane zawierały również liczby rzymskie, liczby binarne oraz liczby enkodowane jako base-64.

W związku z tym ściągnęliśmy pierwszy lepszy solver sudoku z internetu, napisalismy parser dla danych oraz komunikacje z serwerem:

import base64
import socket
import re
from time import sleep


def findNextCellToFill(grid, i, j):
    for x in range(i, 9):
        for y in range(j, 9):
            if grid[x][y] == 0:
                return x, y
    for x in range(0, 9):
        for y in range(0, 9):
            if grid[x][y] == 0:
                return x, y
    return -1, -1


def isValid(grid, i, j, e):
    rowOk = all([e != grid[i][x] for x in range(9)])
    if rowOk:
        columnOk = all([e != grid[x][j] for x in range(9)])
        if columnOk:
            # finding the top left x,y co-ordinates of the section containing the i,j cell
            secTopX, secTopY = 3 * (i / 3), 3 * (j / 3)
            for x in range(secTopX, secTopX + 3):
                for y in range(secTopY, secTopY + 3):
                    if grid[x][y] == e:
                        return False
            return True
    return False


def solveSudoku(grid, i=0, j=0):
    i, j = findNextCellToFill(grid, i, j)
    if i == -1:
        return True
    for e in range(1, 10):
        if isValid(grid, i, j, e):
            grid[i][j] = e
            if solveSudoku(grid, i, j):
                return True
            # Undo the current cell for backtracking
            grid[i][j] = 0
    return False


def stringify(arrays):
    return "".join("".join([str(c) for c in x]) for x in arrays)


def solve(s):
    arrays = [[int(c) for c in s[i * 9:(i + 1) * 9]] for i in range(9)]
    solveSudoku(arrays)
    result = stringify(arrays)
    return result


def parse_bin(s):
    bins = re.findall("\(.+?\)", s)
    for found in bins:
        s = s.replace(found, str(int(found[1:-1], 2)))
    return s


def parse_base64(s):
    bins = re.findall("\[.+?\]", s)
    for found in bins:
        s = s.replace(found, str(base64.b64decode(found[1:-1])))
    return s


def parse_roman(s):
    s = s.replace('<I>', '1')
    s = s.replace('<II>', '2')
    s = s.replace('<III>', '3')
    s = s.replace('<IV>', '4')
    s = s.replace('<V>', '5')
    s = s.replace('<VI>', '6')
    s = s.replace('<VII>', '7')
    s = s.replace('<VIII>', '8')
    s = s.replace('<IX>', '9')
    return s


def parse(s):
    s = s.replace('.', '0')
    s = parse_roman(s)
    s = parse_bin(s)
    s = parse_base64(s)
    return s


def main():
    url = '35.161.87.33'
    port = 10101
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((url, port))
    while True:
        sleep(1)
        received = s.recv(9999)[:-1]
        print(received)
        received = parse(received)
        result = solve(received)
        print(result)
        s.sendall(result + "\n")


main()

Co dało nam ECTF{jk_w3_41n7_s0rrY}