c0rrupt
Problem
We found this file. Recover the flag. You can also find the file in /problems/c0rrupt_0_1fcad1344c25a122a00721e4af86de13.
Solution
Checking the
file mystery
indicates nothing. However, viewing thehead
of the mystery file shows it looks like a PNG image:$ xxd -g 1 mystery | head 00000000: 89 65 4e 34 0d 0a b0 aa 00 00 00 0d 43 22 44 52 .eN4........C"DR 00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab ...j...G.....|.. 00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 x....sRGB....... 00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 ..gAMA......a... 00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49 ..pHYs...%...%.I 00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f R$......DETx^..? 00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0 .d.q.-. ..A.... 00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e [email protected]@{.#... .> 00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc ...p.t...Ak..... 00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88 >}*"3o.[U.==. ..
The PNG Specification tells that the PNG signature (first eight bytes of a PNG datastream) must be
137 80 78 71 13 10 26 10
(decimal) or89 50 4E 47 0D 0A 1A 0A
(hex).So lets replace the signature using a hex editor:
$ xxd -g 1 mystery.png | head 00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 43 22 44 52 .PNG........C"DR 00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab ...j...G.....|.. 00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 x....sRGB....... 00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 ..gAMA......a... 00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49 ..pHYs...%...%.I 00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f R$......DETx^..? 00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0 .d.q.-. ..A.... 00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e [email protected]@{.#... .> 00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc ...p.t...Ak..... 00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88 >}*"3o.[U.==. ..
After the header come a series of chunks. 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. See the "5.3 Chunk layout" section of this page for more information.
The first chunk is called
IHDR
and has the length of0xD
, so we know that the next 8 bytes are00 00 00 0D 49 48 44 52
(hex):$ xxd -g 1 mystery.png | head 00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 .PNG........IHDR 00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab ...j...G.....|.. 00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 x....sRGB....... 00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 ..gAMA......a... 00000040: 00 09 70 48 59 73 aa 00 16 25 00 00 16 25 01 49 ..pHYs...%...%.I 00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f R$......DETx^..? 00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0 .d.q.-. ..A.... 00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e [email protected]@{.#... .> 00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc ...p.t...Ak..... 00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88 >}*"3o.[U.==. ..
Now the file is identified as a PNG file:
$ file fixed.png fixed.png: PNG image data, 1642 x 1095, 8-bit/color RGB, non-interlaced
pngcheck
lists two more errors to solve:pngcheck -vf mystery.png File: mystery.png (202940 bytes) chunk IHDR at offset 0x0000c, length 13 1642 x 1095 image, 24-bit RGB, non-interlaced chunk sRGB at offset 0x00025, length 1 rendering intent = perceptual chunk gAMA at offset 0x00032, length 4: 0.45455 chunk pHYs at offset 0x00042, length 9: 2852132389x5669 pixels/meter CRC error in chunk pHYs (computed 38d82c82, expected 495224f0) : invalid chunk length (too large)
We need to fix the CRC (checksum) error in chunk
pHYs
and find a chunk with an invalid length.The CRC error means that either the checksum (CRC value) is corrupted, or the data is. To solve this error in chunk
pHYs
we can simply replace the CRC (expected) value with the computed value. The purpose of the CRC section is to check for corruption of the data. It essentially is a checksum of that chunk. While replacing the CRC will work, the more "correct" method is to correct the content ofpHYs
in order to get the same CRC, thus fixing the corruption that occurred. The below table shows the layout of thepHYs
chunk:Name
Length
Current Value
Pixels per unit, X axis
4 bytes (PNG unsigned integer)
aa 00 16 25
Pixels per unit, Y axis
4 bytes (PNG unsigned integer)
00 00 16 25
Unit specifier
1 byte
01
Since the pixels per unit differ in just one byte, and the
0xaa
for the X axis makes the value very large, it makes sense to place a zero instead. This fixes the checksum.$ xxd -g 1 mystery.png | head 00000000: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 .PNG........IHDR 00000010: 00 00 06 6a 00 00 04 47 08 02 00 00 00 7c 8b ab ...j...G.....|.. 00000020: 78 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 x....sRGB....... 00000030: 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 ..gAMA......a... 00000040: 00 09 70 48 59 73 00 00 16 25 00 00 16 25 01 49 ..pHYs...%...%.I 00000050: 52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f R$......DETx^..? 00000060: 8e 64 cd 71 bd 2d 8b 20 20 80 90 41 83 02 08 d0 .d.q.-. ..A.... 00000070: f9 ed 40 a0 f3 6e 40 7b 90 23 8f 1e d7 20 8b 3e [email protected]@{.#... .> 00000080: b7 c1 0d 70 03 74 b5 03 ae 41 6b f8 be a8 fb dc ...p.t...Ak..... 00000090: 3e 7d 2a 22 33 6f de 5b 55 dd 3d 3d f9 20 91 88 >}*"3o.[U.==. ..
$ pngcheck -v -f mystery.png File: fixed.png (202940 bytes) chunk IHDR at offset 0x0000c, length 13 1642 x 1095 image, 24-bit RGB, non-interlaced chunk sRGB at offset 0x00025, length 1 rendering intent = perceptual chunk gAMA at offset 0x00032, length 4: 0.45455 chunk pHYs at offset 0x00042, length 9: 5669x5669 pixels/meter (144 dpi) : invalid chunk length (too large) ERRORS DETECTED in fixed.png
The
invalid chunk length (too large)
error does not specify a chunk, so we must begin at the start and check each chunk, with the knowledge of the format of chunks and each field’s length: 4 bytes (length) - 4 bytes (chunk type) - lengthbytes (data) - 4 bytes (CRC).The chunk after
pHYs
has a size of0xaaaaffa5
, which is very large, and a type of\xabDET
which doesn't exist. The closest chunk type is IDAT. Let's fix that by replaying the chunk name with49 44 41 54
(hex).To solve the large chunk length we need to calculate the chunk length and update its value.
IDAT
chunks must be consecutive so lets find the next one. We find the next IDAT at offset0x10008
. The first IDAT was at offset0x57
. The difference is FFB1. We must subtract 4 bytes for the length field of the second IDAT, subtract 4 bytes for the CRC of the first IDAT, and subtract 4 bytes again for the chunktype of the first IDAT. Subtracting 12 in total, we get FFA5. Replace the length field with00 00 FF A5
(hex). The original value was0xAAAAFFA5
so we just needed to overwrite theAAAA
with0000
.Running
pngcheck mystery.png
showsmystery.png (1642x1095, 24-bit RGB, non-interlaced, 96.3%).
which means there are no errors and we can open the image:
Flag
picoCTF{c0rrupt10n_1847995}
Last updated
Was this helpful?