NDH2k12-wargame Write-up What the file ?
By w3pwnz on Monday, July 2 2012, 21:08 :: ndh2k12 :: Permalink
Name What the file ?
Score 1000
Content While doing some forensics, an analyst found a weird file. Please help him.
We have this file unknown.bin
$ file unknown.bin.png unknown.bin.png: PNG image data, CORRUPTED
$ pngcheck -vt7f unknown.bin File: unknown.bin (1179008 bytes) File is CORRUPTED. It seems to have suffered EOL conversion. It was probably transmitted in text mode.
Ok, it's a corrupted PNG that we have to patch.
We realized that the lengths and the chunks' names are affected by several alterations.
We begun by correcting those names and lengths for each chunk.
A quick reminder from the RFC 2083 about the chunk layout :
Length A 4-byte unsigned integer giving the number of bytes in the chunk's data field. The length counts only the data field, not itself, the chunk type code, or the CRC. Zero is a valid length. Although encoders and decoders should treat the length as unsigned, its value must not exceed (2^31)-1 bytes. Chunk Type A 4-byte chunk type code. For convenience in description and in examining PNG files, type codes are restricted to consist of uppercase and lowercase ASCII letters (A-Z and a-z, or 65-90 and 97-122 decimal). However, encoders and decoders must treat the codes as fixed binary values, not character strings. For example, it would not be correct to represent the type code IDAT by the EBCDIC equivalents of those letters. Additional naming conventions for chunk types are discussed in the next section. Chunk Data The data bytes appropriate to the chunk type, if any. This field can be of zero length. CRC A 4-byte CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk, including the chunk type code and chunk data fields, but not including the length field. The CRC is always present, even for chunks containing no data. See CRC algorithm (Section 3.4).
No apparent problem for IHDR, sBIT, pHYs, tEXt(Software) and IEND chunks.
For IDAT chunks, we can understand that they're 8192 bytes long.
We scripted the thing to patch the file from offset 0x6A each 8204 bytes (8192 + 4 + 4 + 4) to 00 00 20 00 49 44 41 54 (Length + "IDAT").
$ pngcheck -vt7f unknown.bin.png [...] chunk IDAT at offset 0x11c717, length 8192 chunk IDAT at offset 0x11e723, length 8192: EOF while reading data
We almost got a proper and genuine png file from pngcheck's point of view, except the latest IDAT chunk. This is normal, as this chunk is the latest one and isn't 8192 bytes long.
We fixed this by correcting with that value : size until the end of file - IEND chunk (12 bytes) - checksum (4 bytes) = 5705 bytes (0x1649).
$ pngcheck -vt7f unknown.bin.png [...] chunk IDAT at offset 0x11c717, length 8192 chunk IDAT at offset 0x11e723, length 5705 CRC error in chunk IDAT (actual 66b9b445, should be 68cf7786) chunk IEND at offset 0x11fd78, length 0
Weird, the checksum is not correct, unlike all the IDAT checksums so far...We'll see later.
As the image can be open with several editors, some others won't because of the latest chunk's checksum. Nevertheless, we can see our old Chuck Norris and only half of the flag.
650b0a5aa1ec4cea................
So at this time we have the first part of the flag...
The wrong checksum of the last IDAT is probably a good clue to get the second part of the flag.
At the end of the file, we can see above IEND chunk a ...zTX3..., maybe a zTXt chunk ? Let's give it a try...
The length will be 27 bytess, 0x1B.
We also changed the length of the last IDAT chunk, 5705 - 27 - 12 = 5666 that's to say 0x1622.
Excellent, this time no more problem with checksums.
$ pngcheck -vt7f unknown.bin.png
[...]
chunk IDAT at offset 0x11e723, length 5666
chunk zTXt at offset 0x11fd51, length 27: keyword has control characters, keyword: x\DA\D3\D3C\05\96\A9\06\C9\16\A6I\86\86i\89I\A6\A6\C9f
(compressed zTXt text)
zTXt chunk contains one or more control characters
chunk IEND at offset 0x11fd78, length 0
Then let's decompress the string with zlib.
#!/usr/bin/python import zlib print zlib.decompress("78 DA D3 D3 43 05 96 A9 06 C9 16 A6 49 86 86 69 89 49 A6 A6 C9 66 00 6D 17 07 6F".replace(" ","").decode("hex"))
................9e0c85b11fab55c6
w3ll done
