BalCCon 60 seconds WriteUp

Basic explanation of the challenge :

In this challenge, the goal is to get rid of all the « 1 » in the matrix that we get from their netcat server.
To do so we can input coordinates such as « d2 » for instance, to invert the value of the number located at those coordinates aswell as its close neighbours (up, right, down and left).
Example of a matrix :

    a  b  c  d  e  f  g  h
 1  0  0  0  0  1  0  0  1
 2  1  0  1  0  0  0  1  0
 3  1  1  0  1  1  0  1  0
 4  0  1  1  0  0  0  1  1
 5  0  0  1  1  0  1  0  0
 6  0  0  0  0  0  1  1  1
 7  1  1  0  0  0  0  0  1
 8  0  1  1  0  0  1  0  1

How to solve this challenge ?

As I’m not a rocket scientist and I didn’t want to think too much, I was like : « Why not try to target every ‘1’ in the matrix and once we’re done, repeat until there are no more ‘1’ ? »
So in clear here are the steps that my algorithm will follow :

1 : Find every coordinates for the « 1 » for the matrix first received, then send them
2 : Once every coordinates are sent, take a snapshot of the new matrix and then repeat the step 1 with the matrix newly received 🙂

The code !

1] Format the matrix :

The matrix that we receive is a long string that we can’t work with, here is my function that returns a usable matrix for python :

def input_to_matrice(received_matrix):

    received_matrix = str(received_matrix, "utf-8")
    temp_matrice = received_matrix.split("\n")[1:len(received_matrix.split("\n"))-2]
    matrice = []

    for i in range(len(temp_matrice)):
        matrice.append([])
        k = temp_matrice[i].split("  ")
        for l in k:
            matrice[i].append(int(l))

    for i in matrice:
        i.pop(0)

    return matrice

2] Get the coordinates

Now that we can work with the matrix, let’s get a list of all the coordinates of the « 1 » :

def get_moves_for_ones(matrice):
    moves = []

    for i in range(len(matrice)):
        # matrice[i] will represent the row n°i
        for j in range(len(matrice[i])):
            # matrice[i][j] will represent the column n°j in the row n°i

            if matrice[i][j] == 1:
                # If we find a one, add the coordinates to our list of moves to do
                move = ""

                # The row :
                move += 'abcdefgh'[i]
                
                # The column :
                move += str(j+1)
                
                moves.append(move)
                move = ""

    return moves

3] Put that together :

We can now put those 2 functions together with a nice while True and boom, just let it run to get the flag !
Though this script has the advantage to be simple and doesn’t require any math, one of its main drawbacks is that it’s not « move efficient » because there isn’t much logic behind it.

Code :

#!/usr/bin/env python3
# Small disclaimer : this program was first written using french words, and also I'm not a python expert, sorry ¯\_(ツ)_/¯
import socket

#Initialization : connect to their server
host = "pwn.institute"
port = 22527
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

def input_to_matrice(received_matrix):
    """
    This functions returns a nicely formatted matrix that we can work with in python
    Also this was first written in french, that's why there could be some weir words
    """
    received_matrix = str(received_matrix, "utf-8")
    temp_matrice = received_matrix.split("\n")[1:len(received_matrix.split("\n"))-2]
    matrice = []

    for i in range(len(temp_matrice)):
        matrice.append([])
        k = temp_matrice[i].split("  ")
        for l in k:
            matrice[i].append(int(l))

    for i in matrice:
        i.pop(0)

    return matrice

def get_moves_for_ones(matrice):
    moves = []

    for i in range(len(matrice)):
        # matrice[i] will represent the row n°i
        for j in range(len(matrice[i])):
            # matrice[i][j] will represent the column n°j in the row n°i

            if matrice[i][j] == 1:
                # If we find a one, add the coordinates to our list of moves to do
                move = ""

                # The row :
                move += 'abcdefgh'[i]
                
                # The column :
                move += str(j+1)
                
                moves.append(move)
                move = ""

    return moves

try:
    
    matrice = s.recv(2048)
    s.recv(2024)
    print("The received matrix : ")
    nice_matrice = input_to_matrice(matrice) #Nice because now it's pretty :)
    print(nice_matrice) #Debug

    while True:
        #The goal here is to follow a simple algorithm :
        # 1 : Find every coordinates for the "1", then send them
        # 2 : Once every coordinates are sent, repeat :)
        # There isn't much thinking behind it but it works ¯\_(ツ)_/¯
        moves = get_moves_for_ones(nice_matrice)
        print("Moves : ")
        print(moves) #Debug

        if moves == []:
            #Something wrong heppened or we reached the end
            break

        for i in moves:
            s.send(i.encode())
            print("Sent : " + str(i))
            received_matrice = s.recv(2024)
            print("Received first :\n" + str(received_matrice)) # Those two prints are for debug but also to print out the flag when it arrives
            print("Received second :\n" + str(s.recv(2024)))
        
        #When we sent our wave of coordinates, repeat
        nice_matrice = input_to_matrice(received_matrice)

finally:
    s.close()

In the end we get that delightful message : « You made it in 63 moves and 39.403 seconds! Here is your reward: BCTF{cl0ck_is_tick1ng_but_we_are_fasterrr} » and here is our flag 🙂

Share Button