Niveau | Outils | Auteur |
---|---|---|
Newbie | Un editeur hexadecimal quelconque | elooo |
Zamer est un tyran, et même durant les périodes de fête, il a décidé de nous faire bucher !!
Evidemment il faut jouer le jeu et faire ce challenge dans un état d'ebriété certain. Je vous propose donc d'aller chercher votre
bouteille d'alcool préféré et de vous laisser aller à en boire quelques verres (pas trop non plus, 'faut que vous puissiez
voir et lire les octets dans l'éditeur hexa quand même ensuite).
Première chose à faire : lire le Readme fourni dans l'archive.
Oui je sais c'est chi*nt, mais y'a quelques infos à en tirer :)
On y voit :
Vous devez trouver le moyen de lire l'image, pour trouver le mot de passe à me donner pour confirmer le challenge. C'est tres facile, y'a que 2 choses à faire, mais comme je pense que vous êtes tous déjà bourrés, j'ai choisi de ne pas faire compliqué. Bonne chance !
Pour ceux qui lisent un mot sur deux, il va falloir préciser les choses utiles dans ce court intitulé :
Zamer est un tyran, certes, mais peut-être pas au point d'avoir sorti de derrière les fagots un format d'image exotique,
peu ou plus du tout utilisé (j'en connais un autre qui ne se serait pas géné, hein mimas ;))
On va donc faire une brève étude des formats de fichiers image les plus courants, histoire de comprendre un peu mieux leurs spécifications,
et plus précisément leurs entêtes.
Le format GIF de CompuServe semble être le plus complexe et, potentiellement, le plus interessant. Même si sa structure
en général n'interesse que les programmeurs ;)
GIF est un acronyme de "Graphics Interchange Format" (format d'échange d'images).
Voilà à quoi correspond l'entête d'un fichier GIF :
typedef struct _gifheader { unsigned char gif_signature[3]; /* GIF */ unsigned char gif_version[3]; /* 87a ou 89a */ unsigned char gif_width_lo; /* Largeur Low-Byte */ unsigned char gif_width_hi; /* High-Byte */ unsigned char gif_height_lo; /* Hauteur Low-Byte */ unsigned char gif_height_hi; /* High-Byte */ } GIFHEADER;
Ou pour ceux qui préfèrent les schémas :
+-----------------------+ | +-------------------+ | | | GIF Signature | | | +-------------------+ | | +-------------------+ | | | Screen Descriptor | | | +-------------------+ | | +-------------------+ | | | Global Color Map | | | +-------------------+ | . . . . . . | +-------------------+ | ---+ | | Image Descriptor | | | | +-------------------+ | | | +-------------------+ | | | | Local Color Map | | |- Répété de 1 à n fois | +-------------------+ | | | +-------------------+ | | | | Raster Data | | | | +-------------------+ | ---+ . . . . . . |- GIF Terminator -| +-----------------------+
La signature permet seulement d'identifier de quel fichier il s'agit. Ici si on voit GIF87a ou GIF89a
(ce qui donne en hexa "474946383761" ou "474946383961") en signature, on
s'attendra ensuite à voir du data correspondant aux spécifications du format GIF.
Je vais pas détailler tout le reste, là on veut juste avoir suffisamment d'info pour pouvoir identifier l'extension qu'il
faudra attribuer au fichier fourni par Zamer.
Par contre on peut parler aussi du GIF Terminator.
Un fichier GIF se terminera toujours par 0x3B (en ascii ça correspond à une virgule). C'est une convention, et c'est aussi
ce qui marque les fins de blocs dans le fichier, mais il n'est pas utile ici, encore une fois, de rentrer dans les
détails.
Le format PNG (Portable Network Graphics) a été mis au point en 1995 afin de fournir une alternative libre au
format GIF, format propriétaire dont les droits sont détenus par la société Unisys (propriétaire de l'algorithme de
compression LZW utilisé dans le format GIF). D'ailleurs PNG est également un acronyme pour PNG's Not Gif ;)
De plus la compression proposée par le format PNG est une compression sans perte (lossless compression) 5 à 25% meilleure que la
compression GIF, bref faites votre choix !!
Tout comme le GIF vu précédemment, le fichier PNG contient une signature, qui correspond en notation hexadécimale à
89504E470D0A1A0A et qui correspond aux 8 premiers octets du fichier.
S'en suivent une série d'éléments appelés chunks, chunks aux-mêmes composés de 4 parties : la taille du chunk, le type de chunk
codé sur 4 octets, les données du chunk, et le CRC du chunk permettant de vérifier son intégrité.
Les chunks peuvent être agencés dans n'importe quel ordre, par contre il faut obligatoirement que le 1er chunk soit IHDR (Image Header, chunk d'entête) et que le dernier soit IEND (Image Trailer, chunk de fin).
Les principaux chunks (critical chuncks) sont :
Je ne parlerai pas des autres segments ici :)
Pour ceux qui souhaiteraient la structure du PNG Header :
typedef struct _pngheader { unsigned char png_res1[1]; /* 0x89 */ unsigned char png_signature[3]; /* PNG */ unsigned char png_res2[12]; /* Reservé */ unsigned char png_res3[2]; /* Reservé */ unsigned char png_width_hi; /* Largeur Low-Byte */ unsigned char png_width_lo; /* High-Byte */ unsigned char png_res4[2]; /* Reservé */ unsigned char png_height_hi; /* Hauteur Low-Byte */ unsigned char png_height_lo; /* High-Byte */ } PNGHEADER;
Le format JPEG JFIF est communément référé au format JPEG.
Voici la structure du JFIF Header :
typedef struct _JFIFHeader { BYTE SOI[2]; /* 00h Start of Image Marker */ BYTE APP0[2]; /* 02h Application Use Marker */ BYTE Length[2]; /* 04h Length of APP0 Field */ BYTE Identifier[5]; /* 06h "JFIF" (zero terminated) Id String */ BYTE Version[2]; /* 0Bh JFIF Format Revision */ BYTE Units; /* 0Dh Units used for Resolution */ BYTE Xdensity[2]; /* 0Eh Horizontal Resolution */ BYTE Ydensity[2]; /* 10h Vertical Resolution */ BYTE XThumbnail; /* 12h Horizontal Pixel Count */ BYTE YThumbnail; /* 13h Vertical Pixel Count */ } JFIFHEAD;
En fait l'entête débute avec FFD8FFE0 (FFD8 étant les 2 octets du SOI, etFFE0 les 2 octets de APP0), puis on a la longueur du segment JFIF sur 2 octets, la string "JFIF" terminé par un 0 (ça correspond à la signature du fichier JPEG JFIF. Notation hexadécimale : 4A46494600) sur 5 octets, La version sur 2 octets, puis les champs relatifs à la résolution de l'image.
Les données d'un fichier JPEG sont stockées sous forme de blocs et chaque bloc est identifié par un marqueur.
Le format TIFF (Tagged image file format) a été créé par Aldus (appartient à Adobe) et Microsoft.
Il a été conçu pour l'acquisition et la création d'images en vue de l'impression et peut être compressé ou non compressé.
La structure de l'entête d'un fichier TIFF :
typedef struct _TiffHeader { WORD Identifier; /* Byte-order Identifier */ WORD Version; /* TIFF version number (always 2Ah) */ DWORD IFDOffset; /* Offset of the first Image File Directory*/ } TIFHEAD;
L'Identifier contient toujours soit 4949 (II) soit 4D4D (MM) et signifie simplement que les données sont agencées en
little-endian (format Intel) ou en big-endian (format motorola).
La signature d'un fichier TIFF se trouve toujours auniveau du 4eme byte du fichier, ce qui correspond à la version, et sera toujours
42 (soit 0x2A). En fait il s'agit de la version et non de la signature à la base, mais le format TIFF n'ayant pas été revu,
on y retrouvera toujours cette même valeur, qu'on peut par conséquent considéré comme une "signature".
En fonction de l'Identifier précisé on aura donc pour les 4 premiers bytes, soit 49492A00, soit 4D4D002A.
Le principe du format TIFF consiste à définir des balises (tags, d'où le "Tagged Image File Format") décrivant les caractéristiques de l'image, aussi bien les dimensions de l'image que le nombre de couleurs, le type de compression, etc.
Un fichier BMP se compose de plusieurs parties :
Comme pour les précédents, voici la structure de l'entête d'un fichier BMP :
typedef struct _BmpInfo /* Offset Description */ { WORD Type; /* 00h File Type Identifier (4D42h) */ DWORD FileSize; /* 02h Size of File */ WORD Reserved1; /* 06h Reserved (should be 0) */ WORD Reserved2; /* 08h Reserved (should be 0) */ DWORD Offset; /* 0Ah Offset to bitmap data */ } BMPINFO;
Dans les 2 premiers octets du fichiers, on y trouve la signature, qui peut être :
Ensuite on a la taille du fichier sur 4 octets, un champs réservé de 4 octets, puis l'offset dans le fichier vers les données data du bitmap.
Commencons par ouvrir le fichier cible (roelofs) dans l'éditeur hexadécimal :
Deux choses me sautent aux yeux, après avoir lu les différentes infos citées ci-dessus sur les formats de fichiers
image : le IEND et le IDAT.
Il semblerait que ce soit des chunks d'un fichier PNG !
Par contre la signature (les 8 premiers octets du fichier) ne correspond pas du tout à la signature d'un fichier PNG...
Si on descend tout à la fin du fichier dans l'éditeur hexa, on y voit également :
On remarquera assez rapidement la présence d'un chunk IHDR.
Bref nul doûte qu'on se trouve en face d'un fichier PNG, il va donc falloir le remettre en forme afin qu'il s'affiche correctement. Ainsi on sera en mesure de récupérer le fameux pass que Zamer nous demande.
On a lu au-dessus que dans un fichier PNG les chunks pouvaient se trouver dans n'importe quel ordre, par contre il y
avait quand même deux invariants à conserver : le chunk IEND comme dernier chunk et le chunk IHDR comme premier chunk.
On va donc commencer par remettre ça en ordre :
Puis on passe à la signature, qu'on va également rétablir :
On met une extension .png à notre nouveau fichier qu'on a sauvegardé, et on double-clique dessus :
Waouh du grand art, Zamer est un graphiste né :>
Bon ben je crois qu'on a fini le boulot là :) Vous pouvez vider votre cave maintenant, vous l'avez mérité !! (Je peux venir ? :p)
Qui veut :)
Cordialement,
elooo.