Paper Mario and the Thousand Year Old Door (TTYD) is a popular gamecube video staring Mario. This video discusses how to warp to the end credits by using very specific inputs.
Events in TTYD are stored in a large queue (FIFO), with at most 256 events on a frame via a custom scripting language. Although this seems like a lot of space for a single frame and there is a validation on the size of the queue, there are ways to get around this. By pausing and hammering, the queue can be completely filled up. Eventually, this can lead to a buffer overflow on the event table which bleeds over into our important memory.
This was discovered by a crash via an invalid memory read in the event table. The idea of the attack is to point event data to a place that is controllable so that we control the custom scripting language. Using this, a credit warp can be performed.
There is a section of memory called the Effect heap. These are effects that happen in the game, such as dust particles flying up. When data is allocated, it tries to find the next free chunk in the list. Additionally, data that is written is NOT erased.
Because the location of this data is somewhat controlled and we control the data on it, this was an ideal place to write! The heap grooming is predictable and we can easily keep data around if it is at the end of the heap.
After a month of reverse engineering and documentation, they found out that Mario's X-position will be set to a specific location if a specific combination of actions occurs. The X-coordinate is a controllable value! So, using this as a pointer (I assume there is no ASLR) was a good option. This pointer can be a reference to the code to jump to.
Although, there is an issue with this... Mario's X-coordinate is stored as a floating point value. The memory address they originally wanted to reference was impossible to reach because of this.
However, there are two types of memory on the gamecube: cached and uncached memory. It was possible to reference the uncached memory location in order to specify the location, as this was a valid x-position. We have this set, but where to jump to exactly?
The devs set controller inputs to be at a specific part of memory. The values being stored range from 0x0 to 0xFF depending on how hard the button is being pressed! This gives us 6 bytes that can be fully controlled from controller inputs and 2 other ones that have limited values. These are copied 4 times for the 4 different controller slots.
With a proper reference to the fake event, upon opening a door with a full queue the magic occurs. The improper index, set with the buffer overflow, now references the fake event struct in the effects heap. This struct has a pointer to our code to get the end credits, which was written with Mario's X-coordinate. Finally, this pointer is dereferenced to jump to our code, written via the controller inputs on the extra controllers. Now, we're at the end credits.
This was an incredibly technical and detailed video. The amount of subtle tricks and sanity checks bypassed to make this work was truly incredible. The author of this article is quite a good speaker too!