--- title: peaCTF 2019 (Round1) - [Forensic] Song of My People (800pts) author: Maltemo tags: CTF, peaCTF, Forensic, PNG, Morse --- peaCTF 2019 (Round1) - [Forensic] Song of My People (800pts) === Written by [Maltemo](https://twitter.com/Maltemo), member of team [SinHack](https://sinhack.blog/). [TOC] ## Statement of the challenge ### Description A specific soundcloud rapper needs help getting into his password protected zipped file directory. The initial password is in the title. You just have to know your memes, and pick the right instrument! We were on the fence on giving you an image to go along with this puzzle, but the loincloth was too scandalous. Alternatively, you could bruteforce. ### File ``` song_of_my_people.zip ├── a lengthy issue.png ├── Ice Cube - Check Yo Self Remix (Clean).mp3 └── README.txt ``` ## Step 1 : Extracting the data from a password ZIP file The first part of the challenge was explained in the statement : extract the content of the zip. Fine, we'll do ! I chose the peaceful method and let my CPU rest this time. So the hint says in the description : :::info The initial **password is in the title**. You just have to **know your memes, and pick the right instrument**! We were on the fence on giving you an **image** to go along with this puzzle, but the **loincloth** was too scandalous. ::: So I searched on internet for "Song of My People" and found write away this [website](https://knowyourmeme.com/memes/the-song-of-my-people) : ![](https://i.imgur.com/zoUeXmD.png) I didn't know this meme, so happy to learn an old one :smile: ! (memes are love, memes are life :heart:). We understand now why they were talking about instruments and we have to find the right one. They were talking about a loincloth, and there it is on the first picture of the website. Perfect, we can come to the conclusion that the password is this instrument, a **violin**. ```shell= unzip -P violin song_of_my_people.zip Archive: song_of_my_people.zip skipping: Ice Cube - Check Yo Self Remix (Clean).mp3 unsupported compression method 99 skipping: README.txt unsupported compression method 99 skipping: a lengthy issue.png unsupported compression method 99 ``` Ouch, so unzip won't do the trick. Trying 7zip : ```shell= 7z x -pviolin song_of_my_people.zip 7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 Scanning the drive for archives: 1 file, 5594494 bytes (5464 KiB) Extracting archive: song_of_my_people.zip -- Path = song_of_my_people.zip Type = zip Physical Size = 5594494 Everything is Ok Files: 3 Size: 5645856 Compressed: 5594494 ``` Yup, we extracted the files successfuly. ## Analysis of the files Let's check the README.md first. After all, it's not called README for nothing :wink: Here is the content : ``` one of the three files is a red herring, but a helpful one at that. does any of this ADD up? This is a LONG problem. ``` Ok, there is not much information. Then, I try to open the png file called `a lengthy issue.png` but I got a message error saying that the PLTE data chunk is too long. We get more information with `pngcheck` tool, but nothing incredible. At this moment, I don't know what it is, so I skip and check the music file. I ran a lot of stego tool to see if there were any data hidden, but nothing at all. The music is a legit one and no weird noise are present in it. I think this is a dead end (in addition of the `README` telling me that one of the file is a red herring). I also check if the `.txt` didn't hide any information in the spaces characters, you never know :smile:, but nothing too. :::warning >*At this moment, Maltemo knew. He had to learn how PNG works.* >[name=Narrator] ::: ## Step 2 : Correcting the PLTE length of the PNG file I spent a LOT of time learning and testing on this image, so here is summary of what you need to know for this challenge. ___ A PNG file is composed of different chunks of data, some must exist and other are optional. The **critical chunks** are (in order): * `IHDR` (**I**mage **H**ea**D**e**R**) : General informations about the image (length, width, color type) * `PLTE` (**P**a**L**e**T**t**E**) : Palettes of colors of the image * `IDAT` (**I**mage **DAT**a) Beginning of image data * `IEND` (**I**mage **END**) End of image data A **chunk of data** is always composed of : |Length of the data chunk | Chunk type | Chunk data | CRC | |-|-|-|-| |4 bytes | 4 bytes | Length bytes | 4 bytes | Now lets focus on the `PLTE` chunk (will see later why). `PLTE` chunk contains from 1 to 256 palette entries, each a three-byte series of the form: Red : 1 byte Green : 1 byte Blue : 1 byte Consequently, the length of the `PLTE` chunk **must** be divisible by 3 (because one palette = 3 bytes). Also, the `PLTE` chunk **must** appear for colour type 3 (that can be read in the `IHDR` chunk). For other types, it's optionnal. In our case, the image uses the colour type 3, so we will be forced to fix our PLTE Length properly. The CRC (Cyclic Redundancy Code or Checksum) aims to check the integrity of the data. For now, I don't have the knowledge to explain to you how it works. [Sicarius explains it well there, but in french.](https://elsicarius.fr/les-images-png-comment-ca-marche-comment-corriger-manuellement-les-erreurs) ___ Those are the main documentations/sources I used to learn all this stuff : * https://www.w3.org/TR/PNG/ * https://en.wikipedia.org/wiki/Portable_Network_Graphics Thanks to this knowledge, i'll try to explain how I did in order to fix the PNG. So first, to display the image as hexa and show the ascii version, we can use command line `xxd`. I'll pipe this command with `head` command to show the beginning of the file. :::info **Quick reminder**, in hexadecimal one byte is represented by two character. Example : (ff)$_{16}$ = (1111 1111)$_{2}$ (ff in hexa = 1111 1111 in binary. Remember the notation above, I will use it later) ::: ```shell= xxd a\ lengthy\ issue.png | head 00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR 00000010: 0000 0500 0000 02d0 0803 0000 018f a41d ................ 00000020: f200 0000 0173 5247 4200 aece 1ce9 0000 .....sRGB....... 00000030: 0004 6741 4d41 0000 b18f 0bfc 6105 4845 ..gAMA......a.HE 00000040: 4c50 504c 5445 ffff fff7 f7f7 4040 4000 LPPLTE......@@@. 00000050: 0000 3232 32f5 f5f5 7272 722d 2d2d c9c9 ..222...rrr---.. 00000060: c9a2 a2a2 b8b8 b87f 7f7f dede de11 1111 ................ 00000070: 5050 50e6 e6e6 3f3f 3f8c 8c8c bdbd bd61 PPP...???......a 00000080: 6161 fbfb fb47 4747 2828 285d 5d5d d0d0 aa...GGG(((]]].. 00000090: d01e 1e1e d4d4 d4a7 a7a7 9d9d 9d4d 4d4d .............MMM ``` I'll not detail the `IDHR` chunk, but we can find the color type value of 3 : * `00000010:` 0000 0500 0000 02d0 08==03== 0000 018f a41d Now, let's check the `PLTE`'s broken length. We take the four bytes before `PLTE` and we got : `48 45 4c 50` which in ASCII is `HELP`. Now we can understand why there was a length problem :dizzy_face: ! Our mission will be to replace those four bytes by the right length. Lets calculate the total length of data from the `PLT` chunk : ![](https://i.imgur.com/F3hwlq4.png) We take everything after`PLTE`, but we let 4 bytes for the CRC, 4 bytes before the next type chunk (here `tRNS`). I found 906 letters of hexadecimal. Converting it to bytes, we divide it by 2. ___ $906/2=(453)_{10}$ bytes If you don't understand this step, go back to the blue text called Quick Reminder. ___ We check if 453 is divisible by 3 => $453/3=151$ Remember from the summary ? A palette is composed of 3 bytes. So the data chunk must be divisible by 3 because it verifies if all the palettes of colour are complete. ___ Ok so now that we have the length, we convert it from base 10 to base 16 (to hexadecimal). $(453)_{10} = (1c5)_{16}$ The chunk length is 4 bytes long, so we will replace in the image `HELP` by the length : `48 45 4c 50` will be replaced by `00 00 01 c5`. To do so, I used `bless` command line to edit the image hexadecimal, but you can use `hexeditor` or many more. **BEFORE** ![](https://i.imgur.com/qcat1FN.png) **AFTER** ![](https://i.imgur.com/jtqN6N5.png) We save the image with this modification. :::success We check the integrity of the PNG with `pngcheck` and we see that it has been correctly fixed ! :confetti_ball: YEEEAAAAAAHH :beers: ! ::: I spent litteraly 3 nights on this problem and learned a lot. I'm so happy that I did finish this step ! ## Step 3 : Get the flag from the given information on the PNG So I thougth that the challenge was finished right here. >He was so wrong :stuck_out_tongue_closed_eyes: >[name=Narrator] The image was this : ![](https://i.imgur.com/qeoq2qp.png) Let's get back to it ! We have a ton of information on this image. I first checked it with [aperisolve](https://aperisolve.fr/) online tool to verify if the are some hidden things, but everything seemed okay. Then I saw that we had to find 2 informations : * **Number of places left** at the most recent concert of [redacted] (author of the [music on soundcloud](https://soundcloud.com/lil-redacted/live-concert-audio)) * **Page number of the concert archive** ### Page Number I went to the [soundcloud page](https://soundcloud.com/lil-redacted/live-concert-audio)) and found this : ![](https://i.imgur.com/YYuZRWZ.png) From the description, we can see the famous page number, but there is a "should" so we don't know if this is a valid information. The music sounded like morse. I decoded it with this awesome online tool [morse code scphillips](https://morsecode.scphillips.com/labs/decoder/) and got this output (it isn't exactly the text because of the method I use to decode, but the website is incredible): > E5UP YALL ITS YA BOI LIL ICE CUBE MELTING OUT HERE IN THE HAWAII HEAT FOR ALL OF YOU. YOU GUESSED IT THIS IS LIVE AUDIO FROM MY WORLD TOUR. I **REPEAT** ==LIL ICE CUBES WORLD TOUR== **MAYBE** A LIBRARY WILL HELP This gives us the archive name thanks to the help we got from the soundcloud description : **LIL ICE CUBES WORLD TOUR** But what is this mysterious hexagonal library ? We will try to answer this question by decoding the hexadecimal text on the PNG. ``` 54 68 65 20 4c 69 62 72 61 72 79 20 6f 66 20 42 61 62 65 6c 3a 0a 28 77 69 74 68 20 6e 65 77 20 61 64 64 69 74 69 74 69 6f 6e 20 6f 66 20 61 6c 6c 20 74 68 65 20 70 6f 73 73 69 62 6c 65 20 64 69 73 73 20 74 72 61 63 6b 73 20 74 6f 20 65 76 65 72 20 62 65 20 6d 61 64 65 20 61 6e 64 20 65 76 65 72 20 63 6f 75 6c 64 20 62 65 20 6d 61 64 65 29 ``` We can decode this hexa to ascii and we get this text : >The Library of Babel: (with new additition of all the possible diss tracks to ever be made and ever could be made) So I search library of babel on the web and find [this website](https://www.libraryofbabel.info/book.cgi) which seems to correspond. I search for LIL ICE CUBES WORLD TOUR and boom : ![](https://i.imgur.com/75fEowu.png) :::success We just confirmed that the page number was **371**. ::: :::info If you are interested in understanding what is the Babel Library, I advise you to check youtube video explaining it, it's quite fascinating. ::: ### Number of places left  For the number of places, I searched every where but got nothing from the 3 files of the beginning. I tried to search online to find number of places left on the most recent concert passed of Ice Cube (a real person, author of the music we got from the zip). I got nothing either. So I guessed and tried 3 for the 3 ice cubes on the profile picture of the music, on the souncloud page. :::success It worked. And I didn't get why. But the number of places left was 3 ::: If you have any explanation for this last part, I would be more than happy to understand how you did find it, if there were a logical way. Feel free to contact me on twitter at [@Maltemo](https://twitter.com/Maltemo). ## TL;DR First step was unzipping a password protected zip. It could be achieved with bruteforce or understanding a little enigma. The next step consisted in correcting a corrupted PNG where the length of the `PLTE` lenght chunk had been replaced by letters. The last step was different puzzles (morse sound to text, hex values to text, Library of Babel) to find informations enabling to get the flag. ## Flag The flag is **peaCTF{3_thousand_spaces_371}** ___ <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>.