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 🙂