By| 2015-12-18 @ 08:37
It’s been a while since our last post, but only because we’ve been quite busy! For many months we were preparing for CSAW CTF, making a new entry in the Pwn Adventure series. This year being the 30th anniversary of that famous plumber, we thought it fitting to create a retro NES game instead of the usual 3D MMORPG that Pwn Adventure is known for. The same core concept applies though – to really win, you need to hack.
We also wanted to combine some modern game elements with the retro platform, so the final idea was a zombie survival game with crafting!
Our favorite aspect of doing a retro-inspired game for a CTF challenge was the prospect of being able to run it on physical hardware as a part of the competition. And since the CSAW final event is an in-person CTF, it was the perfect opportunity. Each team at the finals was given a physical cartridge with custom artwork. We were able to produce physical cartridges in quantity only because of the fine folks at Infinite NES Lives who stock a variety of custom mapper types at very reasonable prices.
If you want to be able to play the game yourself, you can grab all the relevant files from our github account.
Spoilers are below so if you plan to hack first and read second, please go check the game out now!
First of all, congratulations to Andrew Dutcher from team 1064CBread for a fantastic effort on the game during the CTF itself. Sadly, he was only a minutes away from the hardest exploit in the game (and the CTF, by my estimate) when the game ended – and it would have been game-winning points too. Still, he can take pride in knowing he’s the only one who made progress on either of the code execution flaws. His writeups are highly recommended reading as he does a great job walking through the challenges and solutions in the game.
One of the things that is always fascinating about both CTFs and game hacking is all of the unintended bugs. It should be no surprise given the amount of unintended bugs in the real world, but it’s always fun to see them pop up.
In the case of PwnAdventureZ, there were two particularly interesting unintended bugs. The first was caught in testing and turned into an intended challenge, the quarantine_breaker. While Andrew notes in his writeup that he doesn’t know exactly what’s going on with that bug, we have to admit we don’t know either! We found it the same way he did, and merely turned it into a challenge by adding a locked house next to another unlocked house.
The second flaw we found wasn’t discovered by any of the teams during the event so we wanted to write it up in more detail here. It’s
One fun activity is to try to find out exactly how fast you can beat the game. The speed running community has turned this into an art form of late. Of course, we intentionally built one glitch into the game with that in mind. You can see the solution Andrew used in his CreditForCredits and get_flag writeups. Though I will point out that he glossed over one minor detail which is how he knew the proper values to use for both the number of bullets in the item that overflowed the item list as well as the value of the torches. Included in the zip file that each particpant was given was a symbol file. This simple text file is made by the compiler we used to build the game, and it contains all the functions and variable names at different addresses. This makes it easy to find the
show_credits function, for example, or the
blocky_state variable used to speed-run the game.
While we built that speed-run technique into the game intentionally, we found another while testing it live during the competition.
One of the glitches noticed during testing was that dropping a campfire in one of the underground maps would result in the same campfire appearing in the overworld. The campfire/respawn system it turns out had no ability to respawn a player if they placed a campfire and died underground, they’d simply reappear at the same spot above ground. Which immediately led us to wonder how we could abuse it. Fortunately, having the source made life a little easier. We quickly pulled up the sewer and mine maps, and compared them to the overworld. You can see in the animated image how the final boss room (in the grey area in the middle of the forst) is exactly lined up one corner of the mine!
This allows us to jump into the final boss. First, we head to the bottom corner of the mine, drop a campfire, then let ourselves be killed. Next, we re-appear in the boss room and can kill him and win the game. Almost…
We didn’t plan it at all, but it worked out to have one more twist as a result of that single overlap. If you follow the directions above to jump to the boss battle, it will work. But you can only walk into the mine room that overlaps from the North side, or the West side. Neither of those are a valid entrance to the final boss room so you’ll be stuck outside the walls (as you can see here).
Thankfully, another fun quirk saves us – the sniper rifle can shoot through walls. (As an aside, grenades can be lobbed over obstacles in the middle of a room, but not over outer walls, so they won’t work.) This allows us to kill the final boss from outside his room, having only gotten one of the keys we were supposed to need and finish the game extremely quickly!