✅ Day 11 - Padoru

  • REVERSE
  • Date de résolution : 22/12/2024

Reconnaissance

Le chall est de type Reverse et commence avec un executable ! padoru.exe et une liste de librairie et autre fichiers de type .SPV ou .OGG, .PDB et .OBJ (pour la 3D)
En exécutant le fichier padoru.exe, il faut trouver une clé qui permet de changer les couleurs de la représentation 3D !
Allons sans attendre dans le debugger x64dbg pour comprendre tout ça...
On commence l'analyse par une recherche des chaines de caractères potentiellement intéressantes :

.data extract
Plusieurs chaines intéressantes :

  • encTrueChristmasSecret qui semble être le secret à trouver...
  • userGuessedSecretArray qui semble être la clé saisie par l'utilisateur On continue l'analyse et on trouve une boucle qui itère sur 67 caractères et qui construit une string en récupérant des chars dans la partie .text :
    loop encTrueChristmasSecret
    Et on obtient cette string : ** JMzJ7WM7U;VY;^<QV NY'N&IY(X2V[K7X\Z@=@?G$C&LC%IG,D1PV[U2C8[_*-,/r **

Mais qu'en faire...? 🤔🧐

En débuggant, on voit que l'executable lance le fichier : ** fragment.spv **

Perso, je ne connaissais pas avant ce challenge, donc je me suis documenté : SPIR-V
Il s'agit d'un langage simple permettant d'interagir avec des programmes graphiques (ici 3D).
La décomposition en Opcodes est simple et directement en ligne : SPIR-V Visualizer
Ensuite pour passer des opcodes à du code, j'ai demandé de l'aide à ChatGPT...
Voici le code GLSL généré :

 1#version 460
 2
 3layout(set = 0, binding = 4) buffer TrueSecrets {
 4    int encTrueChristmasSecret[67];
 5};
 6
 7layout(set = 0, binding = 1) buffer GuessedSecrets {
 8    int guessedSecret[67];
 9};
10
11layout(set = 0, binding = 2) uniform sampler2D textureColor;
12
13layout(location = 3) in vec2 UV;        // Coordonnées UV pour l'échantillonnage
14layout(location = 4) flat in int finalChristmasKey; // Clé d'entrée
15layout(location = 0) out vec4 color;   // Couleur de sortie
16
17void main() {
18    bool flagDetected = true;
19    int i = 0;
20    int decChristmasLetter = 0;
21
22    while (i < 67) {
23        decChristmasLetter = encTrueChristmasSecret[i] ^ ((i + finalChristmasKey) % 25);
24
25        if (decChristmasLetter != guessedSecret[i]) {
26            flagDetected = false;
27            break;
28        }
29        i++;
30    }
31
32    vec4 sampledColor = texture(textureColor, UV);
33    if (flagDetected) {
34        sampledColor.r = 1.0 - sampledColor.r;
35        sampledColor.g = 1.0 - sampledColor.g;
36        sampledColor.b = 1.0 - sampledColor.b;
37    }
38
39    color = sampledColor;
40}

Exploit

Il suffit donc de prendre la chaine de caractères encTrueChristmasSecret, de XOR char by char avec un compteur incrémental et trouver la valeur init (=finalChristmatKey)
Mon programme Python :

 1finalChristmasKey = 0
 2encTrueChristmasSecret = "JMzJ7WM7U;VY;^<QV NY'N&IY(_X2V[K7X\\Z_@=@?G$C&LC%IG,D1PV[U2C8[_*-,/r"
 3
 4while finalChristmasKey < 26:
 5    print(f"{finalChristmasKey = }")
 6    decrypt = ''
 7    for i in range(67):
 8        #encTrueChristmasSecret[i] ^ ((i + finalChristmasKey) % 25)
 9        enc = ord(encTrueChristmasSecret[i])
10        mod = (i + finalChristmasKey) % 25
11        plain = chr(enc ^ mod)
12        decrypt += plain
13
14    print(f"{  decrypt = }")
15    finalChristmasKey += 1 
FLAG

The flag is : RM{H4SH1R3_S0R1_Y0_K4Z3_N0_Y0U_N1_TSUK1M1H4R4_W0_P4D0RU_P4D0RU!!!!}