--- title: picoCTF 2019 - [Forensic] c0rrupted (250 points) author: Maltemo tags: CTF, picoCTF, Forensic, PNG --- picoCTF 2019 - [Forensic] c0rrupted (250 points) === Written by [Maltemo](https://twitter.com/Maltemo), member of team [SinHack](https://sinhack.blog/) in collaboration with [SaladeTomateOnion](https://twitter.com/saladtomat0nion) team. [TOC] ___ ## Statement of the challenge ### Description We found this file. Recover the flag. ### File ``` mystery ``` ## Hint Try fixing the file header ## Analyzing the file When you have a challenge with a corrupted `file`, you can start with file command : ```sh file mystery mystery: data ``` But most of the time, as the file is corrupted, you will obtain this answer : data. The next step will be to open the file with an hexadecimal editor (here I use `bless`). When you are on the file, search for known elements that give hints about the file type. In this file, I found and IEND and multiple IDAT chunks name in the hexa values, so at this moment I already knew it was a corrupted PNG picture. ## Fixing the corruption problems :::info **Usual tips to uncorrupt a PNG** * Use an hexadecimal editor like `bless`,`hexeditor`,`nano` with a specific option or many more. * For debugging and detect CRC problem, you can use : `pngcheck -v [filename]` * For more in depth knowledge about how works chunks in PNG, I strongly recommend you two read my other write-ups that explains a lot of things : * https://hackmd.io/@FlsYpINbRKixPQQVbh98kw/Sk_lVRCBr * https://hackmd.io/k4zl24xaSHqntmIR6SsdZA#Step-2--Correcting-the-PLTE-length-of-the-PNG-file ::: ### Correcting the PNG header Lets start with the PNG header. I noticed that it was not correct ! A PNG image always starts with those 4 bytes: |Hexa Values|Ascii Translation| |-|-| |`89 50 4E 47`|`. P N G`| And at the start of our file, we did have this : |Hexa Values|Ascii Translation| |-|-| |`89 65 4E 34`|`. E N 4`| So I corrected it with `bless` hexa editor. ### Correcting the IHDR chunk The next chunk in a PNG after the header is the IHDR chunk, which defines the composition of the image. Also, the creator of the challenge give you a hint with the two last letters. In the file, we found this instead : |Hexa Values|Ascii Translation| |-|-| |`43 22 44 52`|`C " D R`| So I correct it with `bless`. |Hexa Values|Ascii Translation| |-|-| |`49 48 44 52`|`I H D R`| ### Correcting the IDAT chunk The next chunks after the IHDR were alright until it ends with an unknown header name : |Hexa Values|Ascii Translation| |-|-| |`AB 44 45 54`|`. D E T`| There is a hint with the `D` and `T` letters, which help us to deduce that it is a `IDAT` chunk. So let's change the name of the chunck |Hexa Values|Ascii Translation| |-|-| |`49 44 41 54`|`I D A T`| Also, I saw the length anounced for this chunk was enormous : `AA AA FF A5`. So I checked the lenght of the chunk by selecting the data chunk in bless. You can find the length value of what you select in the right bottom corner: ![](https://i.imgur.com/Yufot5T.png) :::danger Be careful to **select only the data chunk and not the checksum (CRC)** with it ! It will give you 4 bytes more than the right result. ::: We can read `0xffa5 bytes`. :smile: Nice, we just get the same values at the end of the wrong length. We just have to set the first two bytes to zero which give us : `00 00 FF A5` After saving all those modifications, let's check the integrity of our newly modified image with `pngcheck` : ```sh pngcheck -v mystery_solved_v1.png File: mystery_solved_v1.png (202940 bytes) File is CORRUPTED. It seems to have suffered EOL conversion. ERRORS DETECTED in mystery_solved_v1.png ``` ![](https://proxy.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.tenor.com%2Fimages%2F4641449478493d8645990c3794ea7429%2Ftenor.gif&f=1&nofb=1) ### Correcting again the PNG header to make it readable After a little time of thinking, I finally found what was wrong. The PNG header had End Of Line specific that wasn't recognized on Linux. The older PNG header was : `89 50 4E 47 0D 0A B0 AA` So I decided to change the PNG header **again** to correct this problem : `89 50 4E 47 0D 0A 1A 0A` From the wikipedia [PNG format page](https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header), everything is explained. I copy pasted it here : |**Values (hex)** | **Purpose**| |-|-| |`89` | Has the high bit set to detect transmission systems that do not support 8-bit data and to reduce the chance that a text file is mistakenly interpreted as a PNG, or vice versa.| |`50 4E 47`| In ASCII, the letters PNG, allowing a person to identify the format easily if it is viewed in a text editor.| |`0D 0A`| A DOS-style line ending (CRLF) to detect DOS-Unix line ending conversion of the data.| |`1A`| **A byte that stops display of the file under DOS when the command type has been used—the end-of-file character.**| |`0A`| **A Unix-style line ending (LF) to detect Unix-DOS line ending conversion.** | After this change, I run again pngcheck : ```sh pngcheck -v mystery_solved_v1.png File: mystery_solved_v1.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) ERRORS DETECTED in mystery_solved_v1.png ``` This error indicates that the checksum of pHYs chunk isn't right, so let's change it :smiley: ! pHYs CRC Chunk before rectifying : `49 52 24 F0` pHYs Chunk after rectifying : `38 D8 2C 82` Let's save again, run the pngcheck : ```sh pngcheck -v mystery_solved_v1.png File: mystery_solved_v1.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 chunk IDAT at offset 0x00057, length 65445 zlib: deflated, 32K window, fast compression chunk IDAT at offset 0x10008, length 65524 chunk IDAT at offset 0x20008, length 65524 chunk IDAT at offset 0x30008, length 6304 chunk IEND at offset 0x318b4, length 0 No errors detected in mystery_solved_v1.png (9 chunks, 96.3% compression). ``` And we got the final image : ![](https://i.imgur.com/baF6Iul.png) ## TL;DR The file was a PNG corrupted, chunk name were changed, the length and the checksum of the PLTE chunk was changed. To make it readable on linux, had to change the PNG header. ## Flag The flag is **picoCTF{c0rrupt10n_1847995}** ___ <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License</a>.