The binary lets us create different clips (video, audio, subtitles, metadata), edit them and play (video and audio only).
Playing a clip is basically just printing it to the screen xored with a constant byte, so this might become useful for leaking data.
While reversing the binary, you’ll quickly stumble over a “heap initialization” method, which looks a bit scary at first.
When this bummer is through, the heap will be quite cluttered. This will render any heap leaks useless, since even if we knew an address on the heap, there’s no way to conclude any other chunk addresses from this, since there will be many random gaps between the chunks.
On the other side, it indicates, that we won’t need to care about finding heap leaks at all, so this also has a bright side :).
Since it’s a C++ binary, there are a lot of structs and virtual functions to reverse, so reversing the complete binary was a little bit time consuming. And in the end, it turned out, that the VideoClip class is all we need, to pwn this binary.
The clip base class and the video clip class should look like this:
When going through the code, most of the virtual functions for the different clips look quite similar, but there’s one small discrepancy in the Edit method for the video clip.
Edit method of AudioClip (skipped the exit calls for better readability):
So, everything is looking fine. The function allocates some memory, frees the possible already existing data pointer, and then reads in the data for this clip.
Now, let’s take a look at the Edit method for video clips:
The edit function of VideoClip also allocates memory for its content and uses the same method as AudioClip but the order of the 3 steps (Allocate, free existing, assign new chunk) is mixed up.
Thus, it allocates a new chunk for the video data, assigns it to clip->Data and AFTER that, it frees clip->Data, which is now containing a dangling pointer to the freed memory chunk. Use-After-Free, all we need to get to our flag :)
So first, we’ll have to create a video clip and edit it afterwards. The creation of the clips is a bit awkward, since it doesn’t read the values as numbers, which get converted with atoi, but reads them directly into the class members instead. So we have to specify them as packed values.
In Edit, the binary will allocate a chunk for holding our data, freeing it directly afterwards (thus putting it into the fastbin list) and then read our input into this chunk (effectively overwriting the FD pointer of the freed fastbin chunk).
When we now allocate another fastbin with the same size, it will put our fake FD pointer into the fastbin list, so we can control where malloc allocates the next chunk (of this size). We only need something, that looks like a fastbin.
We’ll be using the misalignment trick (often used for overwriting malloc_hook), to get a chunk overlapping the clip array.
By using 0x6043e5 as fake FD pointer, we can trick malloc into recognizing this as a valid fastbin chunk and serving it as the data pointer for our next video clip.
We’ll now just create a dummy video clip. This will allocate the freed chunk from our previous video, putting our fake FD pointer into the fastbin list. The next video will then overwrite the area of clip array.
Since we don’t know any heap addresses, we can use this overwrite to migrate all data to the bss section, creating fake chunks there and point the clip array to our fake chunks. Thus, we don’t need to worry about the heap and its randomization anymore.
Index 0 of the clip array now points to our fake video chunk. The Length for our clip is set to 6 and the Data ptr points to rand got entry.
With this set up, we can leak the content of rand got by playing this clip.
The Play method prints out the content of Data while xoring every byte with 0xcc, so we decode the leaked data by just xoring it again.
So, we have the libc address and since we can just do an UAF agin, we still have an arbitrary write. With libc known, malloc_hook is a good target using one_gadgetto get a shell.
Again, we’ll be placing a misaligned FD pointer in another video clip.
All there’s left to do, is creating another video, which will call malloc. This will trigger malloc_hook, effectively calling our one_gadget…