CTF Write-Up

entièrement en français et réalisé par ThaySan.

View on GitHub

[Cryptanalyse] Une littérature animalière - 1000pts

chiffre.wav

title: Une littérature animalière

category: Cryptanalyse

difficulty: Facile

point: 1000

author: NainCapable#2614

description: Au café littéraire, vous bavardez avec Voltaire.

Il se trouve que ce petit sacripan s’est infiltré dans la maison de Rousseau pour trouver des informations compromettantes sur son nouveau livre “Le Gorfou ou de l’éducation”.

La seule chose qu’il a récupéré est un étrange fichier, qu’il a mis dans son manteau avant de prendre la poudre d’escampette.

Il espère pouvoir obtenir votre aide pour lire ce fichier décidément bien étrange…

Bonne chance


Solution

En faisant la commande file on voit que chiffre.wav est en fait un fichier ZIP :

┌──(kali㉿kali)-[~]
└─$ file chiffre.wav 
chiffre.wav: Zip archive data, at least v2.0 to extract, compression method=deflate

A l’intérieur se trouve le fichier chiffre.png qui est en fait un fichier texte qui ne contient que des 0 et des 1.

Au total il y a 29 740 656 chiffres dans ce fichier. Ce nombre étant divisible par 8, on peut les interpréter en octets pour former un fichier :

data = open('chiffre.png').read()
data = [int(data[i:i+8], 2) for i in range(0, len(data), 8)]

Cependant même avec cela, le fichier ne semble correspondre à rien.

Sachant que d’après l’extension c’est un PNG et que nous sommes en Cryptanalyse, on peut se dire que le fichier est chiffré. On va donc tester le chiffrement le plus basique : le XOR.

On prend le header des PNG : 89 50 4E 47 0D 0A 1A 0A et on le XOR avec le début du fichier :

data = open('chiffre.png').read()
data = [int(data[i:i+8], 2) for i in range(0, len(data), 8)]

header = bytes.fromhex("89 50 4E 47 0D 0A 1A 0A")
print([header[i] ^ data[i] for i in range(len(header))])
# [100, 111, 196, 144, 40, 198, 200, 223]

En regardant en base 10, rien d’apparant. Mais si on passe le tout en binaire :

data = open('chiffre.png').read()
data = [int(data[i:i+8], 2) for i in range(0, len(data), 8)]

header = bytes.fromhex("89 50 4E 47 0D 0A 1A 0A")
print(''.join([f"{header[i] ^ data[i]:0>8b}" for i in range(len(header))]))
# 0110010001101111110001001001000000101000110001101100100011011111

Là on voit que tous les 47 bits, on a un répétition :

01100100011011111100010010010000001010001100011 01100100011011111

On va donc XOR ces bits en les répétant autant de fois que nécessaire avec les bits de chiffre.png :

data = open('chiffre.png').read()
data = [int(data[i:i+8], 2) for i in range(0, len(data), 8)]

header = bytes.fromhex("89 50 4E 47 0D 0A 1A 0A")

key = "01100100011011111100010010010000001010001100011"
key = key * (len(data) * 8 // len(key) + 1)
key = [int(key[i:i+8], 2) for i in range(0, len(key), 8)]

with open('decrypted.png', 'wb') as f:
	f.write(bytearray([key[i] ^ data[i] for i in range(len(data))]))


Image déchiffrée


FLAG : 404CTF{1g0rfu4v3rt1Env4ut2}