Lieu :

- Insomni'Hack 2010
- Genève, CH

Fichier de départ :

- Nom : 1.pdf
- Type : PDF document, version 1.6
- MD5 : 66791d1068b963f04845cf6474b92f4e
- Taille : 8,6 Mo !

Outils :

- Didier Stevens' Tools
- Origami
- QPDF

Objectifs :

- s'amuser ;-)
- obtenir pour chaque niveau un token à remettre aux organisateurs

Indices :

- Level 1 : la taille, ca compte
- Level 2 : il faut savoir recoller les morceaux
- Level 3 : ???

Plus bas, les solutions ...............












































Level 1

Le fichier ne s'ouvre pas avec evince / xpdf / ... Une analyse manuelle ou via pdfid.py montre des données (au format Base64) à la fin du fichier : $> python pdfid.py -e 1.pdf [...] After last %%EOF 2518 [...] => Offset : 0x894175 == 8995189 Récuperation des données Base64 : $> dd bs=1 skip=8995189 if=1.pdf of=data.b64 OU $> tail -n 42 1.pdf > data.b64 $> base64 -d data.b64 > data.bin $> file data.bin => PDF document, version 1.4 $> mv data.bin data.pdf => Le PDF obtenu (data.pdf) contient en texte non compressé le mot de passe du level 1 (spk!sal10) Suppression du footer Base64 : $> dd bs=1 count=8995189 if=1.pdf of=orig.pdf => Obtention d'une doc Adobe (format PDF 1.7)

Level 2

Le fichier data.pdf contient un autre fichier (3.pdf) : [...] /embeddedFiles [...] /F (3.pdf ) [...] Le contenu de ce fichier est encodé : [...] /Filter /FlateDecode [...] Obtention du password (volkl+sf%) contenu dans le fichier :

Level 3

Le fichier 3b.pdf contient deux streams encodées : /Filter /LZWDecode (objet 7) /Filter /PlatDecode (objet 10) Décompression de l'objet 7 (LZWDecode) : $> pdf-parser.py -f -o 7 3b.pdf => "hervearaison$maiscenestpaslemotdepasse..." Décompression de l'objet 10 (PlatDecode) : $> pdf-parser.py -f -o 10 3b.pdf => "Unsupported filter: ['/PlatDecode']" Décompression de l'objet 10 (FlateDecode) : $> pdf-parser.py -f -o 10 3b.pdf => "FlateDecode decompress failed" Décompression de l'objet 10 (LZWDecode) : $> pdf-parser.py -f -o 10 3b.pdf => "LZWDecode decompress failed" Vu que les deux streams commencent par "80 10 8a 80" et que la 1ère est bien décodée en LZW, on insiste. Ouverture avec walker.rb, avec encodage de l'objet 10 positionné à "LZWDecode" : => lecture de la deuxième stream OK : password = "%opi598*kljp"