Intro
Dernier exercice donné lors du challenge, dernier exercice résolu pour moi. De prime abord, il peut faire peur, mais finalement il n’était pas si compliqué que cela.
Premier contact
Comme à l’accoutumé nous allons commencer par regarder la source, et c’est codé sur une ligne, c’est imbuvable. Soit nous passons par un code beautifier, soit nous passons par les DevTools de notre navigateur.
C’est la seconde solution que j’ai choisie, j’ai trouvé cela plus simple, et cela nous donne accès à un code beautifier, cela pourrait peut être se révéler utile pour la suite.
Dans la colonne de gauche, nous avons la liste des fichiers utilisés par notre page, et pour la première fois, je vois l’extension “.wasm”.
Cela serait-il de l’assembleur pour les pages web ? Une petite recherche sur le net nous rapporte ceci :
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
C’est presque cela, c’est bien une nouvelle syntaxe de programmation, une fois dans le code de la page, un tout nouveau langage apparaît, qui semble être un dérivé de l’assembleur.
À la fin du code, un bloc attire mon attention :
Nous retrouvons au début les caractères E@P@ , qui pourraient être FCSC, de plus la répétition des “@” colle avec les “C”. On regarde rapidement, et on voit que le “E” dans la table ASCII est à un caractère d’écart, que les quatre caractères suivants sont à trois d’écart au-dessus et que le dernier caractère est à un caractère d’écart, le pattern est donc nul. Mais la fréquence est trop grosse pour être due au hasard.
Méthode 1 : analyse du code en deadlisting
Nous savons que nous avons une chaîne qui dévie de façon logique, nous allons chercher dans le code une fonction qui pourrait faire l’affaire.
Dans le bloc juste au-dessus, nous trouvons une fonction très intéressante :
Désolé, cela n’a rien à voir avec le Sherif de l’espace, pour les plus jeunes qui ne comprennent pas la référence, je vous laisse googleliser X-or
Nous allons coder rapidement une petite appli en C# pour en avoir le cœur net, j’ai volontairement transformé la chaîne de caractères en sa représentation hexadécimale pour raccourcir le code :
static void Main(string[] args)
{
byte[] Resultat = new byte[70];
string FinalFlag;
byte[] tableau =
{
0x45,0x40,0x50,0x40,0x78,0x34,0x66,0x31,0x67,0x37,0x66,0x36,0x61,0x62,0x3a,0x34,0x32,0x60,0x31,0x67,0x3a,0x66,0x3a,0x37,
0x37,0x36,0x33,0x31,0x33,0x33,0x3b,0x65,0x30,0x65,0x3b,0x30,0x33,0x60,0x36,0x36,0x36,0x31,0x60,0x62,0x65,0x65,0x30,0x3a,
0x33,0x33,0x66,0x67,0x37,0x33,0x32,0x3b,0x62,0x36,0x66,0x65,0x61,0x34,0x34,0x62,0x65,0x33,0x34,0x67,0x30,0x7e
};
int i;
for (i = 0; i < tableau.Length ;i++)
{
tableau[i] ^= 3;
Resultat[i] = tableau[i];
}
FinalFlag = Encoding.UTF8.GetString(Resultat, 0, Resultat.Length);
Console.WriteLine("La clef est : {0}", FinalFlag);
Console.WriteLine("Press Enter to quit");
while (Console.ReadKey().Key != ConsoleKey.Enter) ;
}
Vous pouvez tester ce code sur ce site, qui vous permettra de le compiler même sans avoir d’IDE sur votre ordinateur.
FCSC{7e2d4e5ba971c2d9e944502008f3f830c5552caff3900ed4018a5efb77af07d3}
Méthode 2 : approche au shotgun, CyberChef
Nous savons qu’il y a une logique derrière la chaîne de base, nous l’ajoutons dans cyberchef, je suis déçu car il ne nous trouve pas de suite ce que c’est, dans la recherche de la colonne opération, nous allons chercher brute et il va nous proposer ceci :
Nous avons repéré qu’il y avait une logique dans l’encodage de la chaine, nous allons tester le XOR Bruteforcer :
Mais pourquoi une chaîne XORée une seconde fois retourne la chaîne en clair ?
En effet mon petit chaton, pourquoi ?
C’est une propriété du XOR :
Pour essayer de dégrossir la chose, imaginons A et B comme nos entrées dans la table du XOR et C son résultat, nous allons avoir la correspondance suivante :
A xor B = C
Nous savons que le XOR ne fonctionne que si A ou B est activé :
Nous pouvons donc définir que le déchiffrement du xor est le suivant :
C xor B = A
Exemple :
A = 0
B = 1
A xor B = C
0 xor 1 = C
C = 1
Et nous pouvons donc prouver que l’inverse est bien ce que nous avions déduit :
C xor B = A
1 xor 1 = A
A = 0
Dans notre cas nous sommes dans cette configuration :
A = flag en clair
B = module de xor
C = flag XORé
Pour retourner sur le flag en clair, nous devons bien faire l’opération inverse et XORer notre flag au module.
Bonus
Nous pouvons aussi trouver la clef du XOR, en nous basant sur les observations précédente, notre clef de chiffrement B est donc égale à:
B = A xor C
clef = “message en clair” xor “message codé”