[CTF GEMA] The_Enigma_of_the_Digits
CTF GEMA Groupe 2025
Niveau de Difficulté : Medium
Catégorie du Challenge : Forensic
Description :
Dans un recoin isolé du monde numérique, nos meilleurs experts en cybersécurité ont intercepté un fichier texte suspect.
Steps to Solve
- Charger le contenu du fichier challenge_digits.txt dans une matrice 2D.
- Reconnaître que l'un des chiffres représente les modules noirs (pixels) du code QR.
- Convertir la grille en une matrice binaire où l'un des chiffres est remplacé par 1 (noir) et tous les autres chiffres sont remplacés par 0 (blanc).
- Utilisez la matrice binaire pour créer un fichier image représentant le code QR.
import numpy as np
from PIL import Image
# Step 1: Load the contents of the Challenge.txt file into a 2D matrix
def load_file_to_matrix(file_path):
"""
Loads the content of a text file into a 2D matrix.
:param file_path: Path to the input file.
:return: 2D matrix (list of lists) with integer values.
"""
try:
with open(file_path, 'r') as file:
content = file.readlines()
except FileNotFoundError:
print(f"Error: The file {file_path} was not found.")
return None
matrix = []
for line in content:
# Strip any whitespace and convert each character to an integer
row = list(map(int, line.strip()))
matrix.append(row)
return matrix
# Step 2: Identify the digit that represents the black modules (pixels)
def find_black_digit(matrix):
"""
Identifies the most common digit in the matrix, assuming it represents black pixels.
:param matrix: 2D matrix of digits.
:return: The digit assumed to represent black modules.
"""
flattened_matrix = [digit for row in matrix for digit in row]
unique_digits, counts = np.unique(flattened_matrix, return_counts=True)
most_common_digit = unique_digits[np.argmax(counts)]
print(f"Assumed black digit is: {most_common_digit}")
return most_common_digit
# Step 3: Convert the grid into a binary matrix
def convert_to_binary_matrix(matrix, black_digit):
"""
Converts a matrix of digits into a binary matrix (1 for black, 0 for white).
:param matrix: 2D matrix of digits.
:param black_digit: The digit representing black pixels.
:return: 2D binary matrix.
"""
binary_matrix = np.array(
[[1 if cell == black_digit else 0 for cell in row] for row in matrix],
dtype=np.uint8
)
return binary_matrix
# Step 4: Scale up the binary matrix to increase the barcode size
def scale_up_matrix(binary_matrix, scale_factor):
"""
Scales up a binary matrix by repeating each element according to the scale factor.
:param binary_matrix: 2D binary matrix representing the QR code.
:param scale_factor: The factor by which to scale up the matrix.
:return: Scaled-up binary matrix.
"""
return np.kron(binary_matrix, np.ones((scale_factor, scale_factor), dtype=np.uint8))
# Step 5: Use the binary matrix to create an image file
def create_qr_code_image(binary_matrix, output_file_path):
"""
Creates an image from a binary matrix and saves it as a file.
:param binary_matrix: 2D binary matrix representing the QR code.
:param output_file_path: Path where the output image will be saved.
"""
try:
image = Image.fromarray(binary_matrix * 255) # Multiply by 255 to make the image black & white
image = image.convert('L') # Convert to grayscale
image.save(output_file_path)
print(f"QR code image saved to {output_file_path}")
except Exception as e:
print(f"Error creating the image: {e}")
# Main function to orchestrate the steps
def main():
# File paths
input_file_path = 'Challenge.txt' #########
output_file_path = 'qr_code.png' #########
scale_factor = 10 # Set the scale factor for the barcode size
# Step 1: Load the matrix from the file
matrix = load_file_to_matrix(input_file_path)
if matrix is None:
return
# Step 2: Identify the black digit
black_digit = find_black_digit(matrix)
# Step 3: Convert to binary matrix
binary_matrix = convert_to_binary_matrix(matrix, black_digit)
# Step 4: Scale up the binary matrix
scaled_matrix = scale_up_matrix(binary_matrix, scale_factor)
# Step 5: Create and save the QR code image
create_qr_code_image(scaled_matrix, output_file_path)
# Execute the main function
if __name__ == "__main__":
main()
Flag
FLAG{Wh0_Th0ught_1T_w1ll_Be_QR}