3 min read

[CTF GEMA] Random

CTF GEMA Groupe 2025

Niveau de Difficulté : Medium

Catégorie du Challenge : Reverse

Description :

Comment je peux résoudre le problème avec le hasard !

Steps to Solve

Tout d'abord, nous obtenons deux fichiers : le premier est un fichier txt dont le flag est chiffré.

Et le second a le programme qui fait l'encodage pour le flag.

Si nous exécutons le fichier, il demande une entrée, donc nous pouvons utiliser n'importe quoi.

Local Image

Nous voyons ici qu'il s'agit d'une entrée erronée

Aller à l'analyse :

Local Image

La première étape la fonction main :

Local Image

Nous pouvons voir que la fonction principale est composée de deux éléments importants :

Generatekey

Xorencrypt

Local Image

Pour xorencrypt, il obtient deux paramètres : le premier est local_58, c'est l'entrée de l'utilisateur, et le second est la clé : local98, c'est la clé pour le processus de chiffrement. Le chiffrement consiste simplement à faire un xor entre la clé et l'entrée et le mod 255 pour produire le texte encodé ; ainsi, pour résoudre le défi, nous devons faire un xor entre l'encod que nous obtenons et la clé. 

Local Image

Ici, la clé est générée avec une longueur de 19 seulement et le problème est que la clé est aléatoire, donc qui peut la deviner ? On peut voir que la valeur aléatoire est fixe, donc on peut la deviner par la seed.

Nous pouvons voir que srand récupère la seed, donc la graine est 99999 à partir de la page principale.

Local Image

Ici vous pouvez voir local_1c qui a la même adresse que la valeur dans srand donc c'est la seed nous pouvons voir aussi si l'entrée est lvar2 doit être égale à 0x13 cela signifie que la longueur de l'entrée doit être 19 et c'est la longueur du flag et c'est aussi la longueur du texte enc que nous avons nous faisons du code en c++ seulement pour le résoudre n'utilisez pas python parce que le random entre python et c++ est différent.

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <sstream>

using namespace std;

vector<unsigned char> generateKey(size_t length, int seed = 12345) {
    srand(seed);
    vector<unsigned char> key(length);
    for (size_t i = 0; i < length; ++i) {
        key[i] = rand() % 256;
    }
    return key;
}

string xorDecrypt(const vector<unsigned char>& encryptedData, const vector<unsigned char>& key) {
    string decryptedText(encryptedData.size(), '\0');
    for (size_t i = 0; i < encryptedData.size(); ++i) {
        decryptedText[i] = encryptedData[i] ^ key[i % key.size()];
    }
    return decryptedText;
}

int main() {
    string input;
    int seed = 99999;

    cout << "Enter exactly 19 encrypted numbers separated by spaces: ";
    getline(cin, input);

    vector<unsigned char> encryptedData;
    stringstream ss(input);
    int value;
    while (ss >> value) {
        encryptedData.push_back(static_cast<unsigned char>(value));
    }

    if (encryptedData.size() != 19) {
        cerr << "Error: You must enter exactly 19 encrypted numbers." << endl;
        return 1;
    }

    vector<unsigned char> key = generateKey(19, seed);
    string decryptedText = xorDecrypt(encryptedData, key);

    cout << "Decrypted Text: " << decryptedText << endl;

    return 0;
}

Nous pouvons voir ici le code qui récupère le texte encodé et le décode avec la même clé en utilisant la même seed pour l'aléatoire et nous obtiendrons le flag.

Flag

FLAG{w0w_y0u_d0_17}