The Legend of the Chozo (Forensic Challenge Writeup) -- Space Heroes CTF 2022
FITSEC Team from Florida Tech has done an excellent job preparing this CTF. This challenges have been very interesting, because it allows to demonstrate techniques used in forensic investigations for the reconstruction of files of a specific format.
File recovery is one of the stages in computer forensic investigative process to identify an acquired file to be used as digital evident. The recovery is performed on files that have been deleted from a file system or intentionally destroyed/modified.
This challenge is perfect to analyze in depth the different components that PNG files have and learn how to reassemble these components to reconstruct the evidence and process it (read the flag).
Challenge Description:
We were given a file to download (source here)
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ ls -l
total 64
-rw-r--r-- 1 leonuz leonuz 61816 Feb 6 18:48 CorruptedData.chr
Start by analyzing this file whit the unix/linux command file
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ file CorruptedData.chr
CorruptedData.chr: data
file
won’t recognize it, but inspecting the header we can see strings which are common in PNG files.
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ hd CorruptedData.chr | head
00000000 50 47 89 0a 4e 0d 0a 1a 0d 48 44 00 52 00 00 49 |PG..N....HD.R..I|
00000010 00 00 00 f0 00 00 01 39 08 06 00 00 00 ae c5 ad |.......9........|
00000020 5a 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |Z....sRGB.......|
00000030 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 |..gAMA......a...|
00000040 00 20 63 48 52 4d 00 00 7a 26 00 00 80 84 00 00 |. cHRM..z&......|
00000050 fa 00 00 00 80 e8 00 00 75 30 00 00 ea 60 00 00 |........u0...`..|
00000060 3a 98 00 00 17 70 9c ba 51 3c 00 00 00 09 70 48 |:....p..Q<....pH|
00000070 59 73 00 00 24 e8 00 00 24 e8 01 82 63 05 1c 00 |Ys..$...$...c...|
00000080 00 f0 e1 49 44 41 54 78 5e ec fd 01 b4 66 59 76 |...IDATx^....fYv|
00000090 d7 87 dd b1 1e 52 31 2a 0d 4f f0 92 55 8a 0b 5c |.....R1*.O..U..\|
According to the PNG Specification, the structure of the header is always represented by eight fixed bytes, and the remaining parts consist of three or more chunks of PNG data in a specific order.
PNG header: 89 50 4E 47 0D 0A 1A 0A
+ chunk + chunk + chunk…
so let’s go ahead and fix that. But first we make a copy of the file and change the file extension to .png
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ cp CorruptedData.chr image.png
we use printf and dd to modify the file, but it can be done with any hexadecimal editor such as hexeditor or xxd
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ printf '\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' | dd of=image.png bs=1 seek=0 count=8 conv=notrunc
8+0 records in
8+0 records out
8 bytes copied, 0.000204744 s, 39.1 kB/s
review the header… we see something odd in the chunk section.
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ hd image.png| head
00000000 89 50 4e 47 0d 0a 1a 0a 0d 48 44 00 52 00 00 49 |.PNG.....HD.R..I|
00000010 00 00 00 f0 00 00 01 39 08 06 00 00 00 ae c5 ad |.......9........|
00000020 5a 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |Z....sRGB.......|
00000030 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 |..gAMA......a...|
00000040 00 20 63 48 52 4d 00 00 7a 26 00 00 80 84 00 00 |. cHRM..z&......|
00000050 fa 00 00 00 80 e8 00 00 75 30 00 00 ea 60 00 00 |........u0...`..|
00000060 3a 98 00 00 17 70 9c ba 51 3c 00 00 00 09 70 48 |:....p..Q<....pH|
00000070 59 73 00 00 24 e8 00 00 24 e8 01 82 63 05 1c 00 |Ys..$...$...c...|
00000080 00 f0 e1 49 44 41 54 78 5e ec fd 01 b4 66 59 76 |...IDATx^....fYv|
00000090 d7 87 dd b1 1e 52 31 2a 0d 4f f0 92 55 8a 0b 5c |.....R1*.O..U..\|
check the file…
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ file CorruptedData.chr
CorruptedData.chr: data
file
won’t recognize it yet, so we need continue fix it.
We know that after the header come a series of chunks. PNG contains two types of chunks: one called critical chunks that are the standard chunks, another called ancillary chunks that are optional.
Each chunk starts with 4 bytes for the length of the chunk, 4 bytes for the type, then the chunk content itself (with the length declared earlier) and 4 bytes of a checksum. The first chunk is IHDR and has the length of 0xD, so let’s fix that first.
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ printf '\x00\x00\x00\x0D\x49\x48\x44\x52' | dd of=image.png bs=1 seek=8 count=8 conv=notrunc
8+0 records in
8+0 records out
8 bytes copied, 7.9847e-05 s, 100 kB/s
check the header, everything seems to be fine now…
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ hd CorruptedData.chr | head
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 00 f0 00 00 01 39 08 06 00 00 00 ae c5 ad |.......9........|
00000020 5a 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 |Z....sRGB.......|
00000030 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 |..gAMA......a...|
00000040 00 20 63 48 52 4d 00 00 7a 26 00 00 80 84 00 00 |. cHRM..z&......|
00000050 fa 00 00 00 80 e8 00 00 75 30 00 00 ea 60 00 00 |........u0...`..|
00000060 3a 98 00 00 17 70 9c ba 51 3c 00 00 00 09 70 48 |:....p..Q<....pH|
00000070 59 73 00 00 24 e8 00 00 24 e8 01 82 63 05 1c 00 |Ys..$...$...c...|
00000080 00 f0 e1 49 44 41 54 78 5e ec fd 01 b4 66 59 76 |...IDATx^....fYv|
00000090 d7 87 dd b1 1e 52 31 2a 0d 4f f0 92 55 8a 0b 5c |.....R1*.O..U..\|
check the file again…
┌──(leonuz㉿sniper)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ file image.png
image.png: PNG image data, 240 x 313, 8-bit/color RGBA, non-interlaced
file
already recognizes it!!!
Let’s try another tool called pngcheck
, this tool verifies the integrity of PNG files by checking the internal checksums, and decompressing the image data.
┌──(sniper㉿sniperkal)-[~/SpaceHeroesCTF/Forensics/The_Legend_of_the_Chozo]
└─$ pngcheck -v image.png
File: image.png (61816 bytes)
chunk IHDR at offset 0x0000c, length 13
240 x 313 image, 32-bit RGB+alpha, non-interlaced
chunk sRGB at offset 0x00025, length 1
rendering intent = perceptual
chunk gAMA at offset 0x00032, length 4: 0.45455
chunk cHRM at offset 0x00042, length 32
White x = 0.3127 y = 0.329, Red x = 0.64 y = 0.33
Green x = 0.3 y = 0.6, Blue x = 0.15 y = 0.06
chunk pHYs at offset 0x0006e, length 9: 9448x9448 pixels/meter (240 dpi)
chunk IDAT at offset 0x00083, length 61665
zlib: deflated, 32K window, fast compression
chunk IEND at offset 0x0f170, length 0
No errors detected in image.png (7 chunks, 79.4% compression).
pngcheck
has No errors detected!!!
We fix the file and now its posible to open to get the flag.
Final Notes.
All incident response teams should know the necessary techniques for file reconstruction as well as at least, know the NIST recommendations.
Thanks FITSEC Team for the excellent CTF.
For fun and knowledge, always think out of the box! :)