Problema

We found this file. Recover the flag. You can also find the file in /problems/c0rrupt_0_1fcad1344c25a122a00721e4af86de13.

Soluzione

Per prima cosa devo aprire il file con un hex editor, per esempio HxD per Windows. Ora guardo l’header e il footer e capisco che, a meno di qualche carattere errato, è un file png. Modifico l’header con

89 50 4E 47 0D 0A 1A 0A

e ottengo quindi un file png corretto ma che comunque non si apre.

Funzionamento file PNG

Studiando la struttura dei file png scopro che questi sono divisi nei seguenti chunk:

NomeSignificato
IHDRContiene le informazioni sul file, come With, Height…
sRGBSe presente, utilizza lo spazio dei colori RGB
gAMA
pHYs
IDATContiene tutti i dati dell’immagine
IENDChunk terminatore, è sempre uguale a 00 00 00 00 49 45 4E 44 AE 42 60 82

Ogni chunk è definito come segue:

  • 4 byte che ne indicano la lunghezza
  • 4 byte che ne indicano il tipo
  • n byte (con n definito dai primi 4 byte) con il valore
  • 4 byte di controllo CRC

Il file in questione è stato corrotto in vari chunk e in alcuni CRC, per risolvere il problema utilizzare il tool pngcheck che fornisce un po’ di debugging comodo.

Fix corruzione file

Una volta fixato l’header del file lanciando pngcheck ottengo:

chunk pHYs at offset 0x00042, length 9: 2852132389x5669 pixels/meter
CRC error in chunk pHYs (computed 38d82c82, expected 495224f0)

Anche se mi dice che è un errore di CRC, il problema è invece che il chunk pHYs fornisce un valore (2852132389x5669 pixels/meter) assurdo, per risolvere prendere un hex di un altro PNG valido e sostituirlo al content del chunk pHYs. Ora rilanciando il pngcheck ottengo errore di CRC, come è giusto che sia:

chunk pHYs at offset 0x00042, length 9: 3779x3779 pixels/meter (96 dpi)
CRC error in chunk pHYs (computed c76fa864, expected 495224f0)

Sostituisco quindi 495224f0 con c76fa864. Ora vi è la parte più complicata: pngcheck fornisce un errore di

invalid chunk length (too large)

che mi dice poco. Andando a vedere i chunk mi aspetto di avere ora il chunk IDAT contenente tutti i dati, preceduto da 4 byte che ne indicano la lunghezza. Quello che ho sono 4 byte casuali (dove vi è una lunghezza del chunk esagerata) con 4 byte con IDAT corrotto. Sistemando questi in modo che vi sia scritto IDAT mi serve sapere la lunghezza di tale chunk. Con HxD seleziono tutti i byte fino in fondo al file (tranne gli ultimi 11 byte, 4 di CRC, 4 di lenght di IEND e 4 per IEND e il footer finale) e ottengo come lunghezza il valore 31851. Ora l’ultimo passo e inserire tale valore nei primi 4 byte del chunk IDAT per poter quindi fixare completamente il file:

00 03 18 51

CheatSheet