Pragyan CTF 2018: Pictorial mess
Détails du challenge
| Event | Challenge | Category | Points | Solves |
|---|---|---|---|---|
| Pragyan CTF 2018 | Pictorial mess | Stéganographie | 300 | 66 |
Téléchargement : files.zip - md5: 7b9178aa713d584c7811725a1289dda9
Description
Johnny avait une image qu’il allait utiliser dans un but très important. Quelqu’un a piraté son système et altéré l’image. Aidez-le à la récupérer.
TL;DR
Dans ce challenge, nous avions 7 images à analyser. Toutes contenaient des messages cachés dans leur LSB (découverts avec Stegsolve de Caesum). Le message extrait était « Make me Tall ». Grâce à ce message, nous avons augmenté la hauteur des images de 25px. Ce challenge a été réalisé avec TweakPng mais aurait pu l’être en éditant l’hexa du fichier. L’augmentation de la taille nous a révélé 7 nouvelles lignes de carrés blancs et noirs (0 et 1). Nous avons extrait les 7 lignes et pris chaque premier carré puis chaque deuxième carré… Le flag était encodé dans les colonnes extraites, en ascii (7 bits).
Méthodologie
Observation des fichiers
La première chose que nous avons faite a été d’ouvrir les fichiers contenus dans files.zip. L’archive contenait 7 images nommées de 0.png à 6.png :
… Rien d’apparent ici. Nous avons décidé de faire quelques recherches de stéganographie dessus.
LSB
Le LSB est la technique de stéganographie la plus courante utilisée en CTF. J’ai décidé de vérifier si les images précédentes contenaient un message caché en utilisant cette technique. Pour cela, j’ai utilisé l’outil nommé « Stegsolve » de Caesum. L’outil est écrit en Java (fichier jar) et nous permet de « naviguer » dans les différentes couches de bits.
Voici la première image analysée avec Stegsolve :
Parfait ! Nous avons extrait une partie d’un message. Voici les différentes parties du message :
Le message extrait est : MakeMeTall. Ce n’était pas le flag.
Augmentation de la taille
Avec une image png, nous pouvons redimensionner la taille de l’image en éditant directement le fichier binaire. Ce type de redimensionnement affectera seulement la taille de l’image et non les données contenues dans l’image. Compte tenu de l’indice obtenu dans le LSB, j’ai décidé de « rendre les images plus grandes » : des données pourraient être cachées dans les images mais non affichées à cause de la taille actuelle de l’image.
La première fois que j’ai fait la manipulation, j’ai regardé la structure des chunks png.
http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
Le chunk IHDR doit apparaître EN PREMIER. Il contient :
Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte
J’ai décidé de modifier la hauteur de la première image en l’augmentant de 25px.
$xxd 0.png | head -n 5
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 0190 0000 017c 0806 0000 00e1 39ed .......|......9.
00000020: 3500 0000 0467 414d 4100 00b1 8f0b fc61 5....gAMA......a
00000030: 0500 0004 1969 4343 506b 4347 436f 6c6f .....iCCPkCGColo
00000040: 7253 7061 6365 4765 6e65 7269 6352 4742 rSpaceGenericRGB
Ici, la hauteur de l’image est 017c (380), je l’ai modifiée en 0195 (405) :
$xxd new0.png | head -n 5
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 0190 0000 0195 0806 0000 00e1 39ed .......|......9.
00000020: 3500 0000 0467 414d 4100 00b1 8f0b fc61 5....gAMA......a
00000030: 0500 0004 1969 4343 506b 4347 436f 6c6f .....iCCPkCGColo
00000040: 7253 7061 6365 4765 6e65 7269 6352 4742 rSpaceGenericRGB
Nous avons obtenu l’image suivante :
Nous pourrions utiliser cette technique pour agrandir chaque image, mais j’ai préféré utiliser l’outil TweakPng qui peut le faire pour nous :
Voici les images extraites :
Nous pouvons voir 7 lignes avec des carrés blancs et noirs. Je les ai convertis en 0 et 1 :
Image 0: 11111101111110101111
Image 1: 11111011111111111111
Image 2: 10101011000101110011
Image 3: 00001001110010000101
Image 4: 00110000111100001011
Image 5: 01011110110001101000
Image 6: 01001011100001111001
Nous savons que nous cherchions un flag commençant par pctf :
p: 01110000
c: 01100011
t: 01110100
f: 01111011
Après quelques observations, nous avons remarqué que le flag était écrit verticalement, 1 caractère par colonne, en utilisant seulement 7 bits.
img0 = "11111101111110101111"
img1 = "11111011111111111111"
img2 = "10101011000101110011"
img3 = "00001001110010000101"
img4 = "00110000111100001011"
img5 = "01011110110001101000"
img6 = "01001011100001111001"
flag = ""
for i in range(len(img0)):
c = img0[i]+img1[i]+img2[i]+img3[i]+img4[i]+img5[i]+img6[i]
flag += chr(int("0b"+c,2))
print(flag)
FLAG !
FLAG
pctf{B3yondth3s1ght}
Zeecka