Day 6 in the Advent of Cyber 2023. Throughout the merger, it has been clear that coding practices from the South Pole elves hasn't been up to the same standard that The Best Festival Company require.
WARNING: Spoilers and challenge-answers are provided in the following writeup.
Official walk-through video is as well available at Youtube - arebelsec.
Day 6 - Memories of Christmas Past
When writing games, programs and applications, code is used to define their functionality, logic and more. For these applications to work - they usually use RAM memory to store their instructions, store variables and alike. Handling this memory access is critical, as it can lead to bugs, errors and pathways for adversaries to perform actions not intended - either by overriding values, gaining sensitive information or allowing for arbitrary code execution.
These vulnerabilities are often categorized as Memory Buffer Errors with the CWE-125 - Out-of-bounds Read and CWE-787 - Out-of-bounds Write being directly related to reading and writing arbitrary values to parts of the memory-stack they shouldn't.
In the challenge we're provided with a game where we're told that they've seen some strange behaviours when you have played to get 13 coins and then use these to change your name to something more than 12 characters.
To answer the first question of the value stored in the
coins memory-space, we need to convert the hex values
4F 4F 50 53 to decimal numbers. On most systems, especially when programming in C++, they are as well stored in "little-endian" byte order - basically meaning that they are in reversed order. We can use an online tool to perform the conversion, and quickly we can see the answer.
We now need to find the final flag, so let's take a deeper look into the game that was provided. Tabbing
[TAB] in the game and we get access to a debug-panel having information about the Memory allocations and their content. As seen in the image below, it clear that the memory is divided in a way where the players name is first, followed by the coins allocation. This might be used to make a buffer overflow on the player name and by that modify the coins value.
So, by navigating the the computer in the game and clicking space a few times, we can get those 13 coins needed to buy 13 characters for the player name at the elf. Buying a name of
aaaabbbbccccd we can see in the memory-debug panel, that we surely overflowed the memory allocation for the player name and now have 100 coins even though we should have used all our coins at the moment.
To win the game and retrieve the final flag, we need to buy a star for the tree. A star from the shop costs 10.000 coins, so firstly we're going to use some of our gained 100 coins to overflow again with something much higher - this time the name of
aaaabbbbccccdefg. This grants us the staggering amout of 1.734.763.876 coins. But at the store trying the buy the star, we're just informed that we're not supposed to have that kind of money and furthermore that the game is rigged to be unwinnable.
Maybe we can use the same out-of-bounds write to write the correct values to the
inv_items memory allocation. Using a player name string of
aaaabbbbccccdefgwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwdddd, we overflows into all the later memory allocations and ingests four d's into the inventory memory and gaining four stars in our inventory as seen in the left panel.
And by that, we should be able to go to the tree and gain our flag: