2 min read

[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

  1. Charger le contenu du fichier challenge_digits.txt dans une matrice 2D.
  2. Reconnaître que l'un des chiffres représente les modules noirs (pixels) du code QR.
  3. 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).
  4. 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}