Hacking consoles: a learning journey (part 4)
(Previous post in this series: Hacking consoles: a learning journey, part 3)
Hello and welcome to my Learning Journey! Last week, we ended up being able to crash Patapon 2 the way we wanted, using a forged player name in our save file. This might have not seemed like much at the time, but this was in fact the first step towards actually achieving something.
Now, before even starting today’s post, I’d like to fix a mistake in the last one: as an anonymous user pointed out in the comments, I messed up my bits and bytes when talking about the name in the savefile. You see, hexadecimal notation is useful because, in binary, a byte is made of 8 bits, and we can shorten that by a factor of 4 in hexadecimal. That’s to say, FF in hex is 1111 1111 in binary, and A1 will be 1010 0001. So this means that two hexadecimal digits make a byte, and four make two bytes. Hence, if each letter in the save takes up 4 hexadecimal digits instead of 2, they use 2 bytes instead of 1, not 4 instead of 2 like I said.
Well, I have something very exciting to present to you today. I managed to get one step further on our hacking path, as I managed to turn our Patapon 2 crash into something bigger. For now, I only made it so that the game exits, but that means that I virtually have control over what is executed in the game, which means that I can load whatever binary program I want now.
I am planning on dividing this in two parts, though. Today, we will be actually calling that exit function without explaining much of the assembly code behind it, and next time, I will dedicate the whole post to diving deeper into the code itself. Thanks to that, people that are here to be entertained will be able to have the simpler version here, and people willing to actually learn the subject will have a little course next time.
Today, we will need a few more tools than we did last time. First of all, you will need a way to do some very simple hexadecimal calculations (Windows’ calculator does that, for instance). You’ll also need the minimal PSP SDK, which we installed a while ago, as well as a code editor (I’ll be using Atom) and our trusty Hexadecimal Editor (HxD for me).
The last thing you’ll need is PRXDecrypter in order to decrypt Patapon 2’s EBOOT. You’ll need to put the content of this file in the /PSP/GAME folder of your memory stick in order for it to be an app on your console.
I will also be following Wololo’s post on writing a binary loader for the PSP, so head there in order to follow along too.
And, lastly, the file(s) I’ll be talking about here will be available on my newly created GitHub repository.
Well, well, well… To be completely honest with you, I don’t really know how to arrange this post. We’ll be covering a lot of things here, a lot of which will be relatively technical (especially to someone new to hacking or low-level programming), so this will be a dense post.
As I mentioned above, I am planning on only explaining the processes in this post, and to explain the actual assembly in a next one, in order to keep things interesting for anyone that isn’t interested in the technical stuff. I will still be explaining things a little though, so bear with me.
To start it all off, let’s just understand why what we achieved last time was interesting. You see, when a program is made (Patapon 2, for instance), it all becomes a complex series of instructions executed by the console’s processor. Add this and that, turn this pixel yellow, and so on… And in order to know what to do, and when to do it, there are some variables in that processor. The variable named $ra, for example, tells the program where to go next in its set of instructions (somewhere in the memory).
You can think of it as a very complex role-playing book. “If you decided to attack this person, go to page 18”, for example. Well, this 18 would have been stored in the $ra variable if it was a program running on a computer. That means that, if we can take control of this variable, we can make the program go anywhere we want, and even someplace where we wrote our very own piece of code.
What’s very interesting is that, when we wrote our thing in place of our player’s name in the Patapon 2 savefile, we actually took control of this $ra variable. The direct consequence of that is that we can now write some code in the savefile itself, redirect the processor to that code using the $ra variable we now control, and then make the game run our code. Cool, isn’t it?
You see, what’s great is that when a game interacts with its game save, the game save is (at least partially) loaded as-is in the memory. And, if you remember our thing with $ra, the memory is exactly where the processor finds what to do next. Knowing that, if we can put something for the processor to do in our game save, find the exact memory address (think page 18 from earlier) where this stuff ends up, and then point the game to it using $ra, the processor will be reading our stuff unknowingly.
Eh… In short: we can write useful stuff, and then we can point the program to it in order to run the cool stuff. Did I make things clearer?
Now, understanding the whole thing is one part of it, actually being able to pull it off is another. For now, the only thing we know for sure is that we have control over $ra, The next step, after that, is to find where the savefile is loaded in the game’s memory, and from that, to find where to put our code in the savefile in order to find it in the memory afterwards.
To move in that direction, the first thing we can do is to get a reading of the game’s memory. When we have that, we’ll be able to find our savefile’s contents inside of it.
For that, we just have to fire up PSPLink, crash our game like we did last time, and once we’re there, we can write this command:
savemem 0x08800000 200000000 memdump.bin
This will create a memdump.bin file in the same folder as PSPLink, so go find it and open it up in your favourite hexadecimal editor. Since you’re there, you should also load the Patapon 2 savefile we worked on in the last post. If you take some part of the savefile and search for it in the memdump file, you should be able to find it pretty easily.
Are you beginning to see the plan here? If we can find parts of the savefile in the actual game’s memory, that means that whatever we in the save here will actually be found in the memory too, and that it has an address as well.
Speaking of address, you are going to want to take note of the offset your pattern begins at, because we need to know what to put in $ra in order to point the processor there. In my case, the pattern I’ve found starts at offset 0x00519720 in the memdump. Since our savemem command we did earlier told PSPLink to gather anything after address 0x08800000 in the memory, that means that we need to do a small addition in order to find the real place our pattern will be located in memory. In our case, 0x08800000 + 0x00519720 = 0x08D19720.
Now, I encourage you to take a break and look back on what we did today, since that’s already a good amount of information. We learned that taking control of $ra in a game crash was the key to arbitrary code execution, which we are coming to, and that a big chunk of the game’s savefile was found in the game’s memory. We also found this chunk’s actual address in the memory.
Putting all this information together gives us this: we can overwrite this chunk in the savefile with whatever we want, and since we know the address of it, we can use the control that we have over $ra to point the PSP to this pattern we just overwrote, and it’ll execute whatever is in there. Does things make a little more sense?
If they do, great! We can now get to things that will make even less sense!
First of all, you’ll need to grab an ISO of your game. If you already have it, that’s one thing you don’t have to do, but if you’re playing on an UMD, you just have to switch your custom firmware’s USB option from “Memory Stick” to “UMD”. That way, you’ll have access to the ISO file that’s present on it.
When you have that on your computer somewhere, you’ll just need to open this file with your favorite archive manager (I personally use 7-ZIP) and navigate to the SYSDIR folder inside the PSP_GAME folder. Once you’re there, grab the EBOOT.BIN file and save it somewhere nice on your computer.
Your EBOOT.BIN file will most likely be encrypted, so you’ll need to create a folder named “enc” on your PSP’s memory stick, and then put the EBOOT in there. You can now fire up PRXDecrypter, tell it to decrypt the file, and then get it back in the “dec” folder of your PSP. If PRXDecrypter tells you that your file is already decrypted, then good news, you can already work on it as-is.
If you installed the Minimal PSP SDK on your computer like you should have a long time ago, you can now use a nice little thing called prxtool, which we will use to tell us what the function imports of the game are.
I’ll be honest with you, this one took me a long time to understand, and even now I’m not entirely comfortable with it. This is why no explanation will be given here, only the rough process, so if you want to learn exactly how and why we do what we are about to do, everything will be explained in the next post.
In order to manipulate the game with whatever we’re going to overwrite the pattern in the savefile with, we need to know how to call the various functions that the game uses in the first place, since we won’t have access to anything more than that. For this purpose, we can use this command:
prxtool -f EBOOT.BIN
This command will give us the list of function imports sorted by library, but they won’t be of any use until we can translate them to actual function names. That’s where the psplibdoc_660.xml file located in my GitHub repository will be useful:
prxtool -f -n psplibdoc_660.xml EBOOT.BIN
The output of this function will be the same as the one before, but with the actual names of the functions instead of something we can’t use.
Unfortunately, I can’t explain the next part without diving into assembly code, and since that’s planned for the next post in the series…
Basically, the next step is to make the thing that we put in the savefile. In other words, we craft the instructions we want the game to execute, and then put them in the savefile in place of the pattern we chose earlier. The very last step is to set $ra to the address we got earlier, and voilà! What I did was call the function that exits the game in order to see if that worked, and it did.
Today was quite a heavy day, wasn’t it? We found how to control where the console was going to read the next instructions, and through a whole process of digging into the game’s data, I was able to call the function that quits the game. That might not sound that different from what we did last time, but it really is: now, instead of just crashing the game, we actually have control over how the game behaves, and that’s going to enable a lot of things to happen.
If you want to understand the technicalities of whatever happened today, tune in to part 4.5 to hear me do my best to explain something I don’t fully understand myself. Until then, farewell!
Today was a very, very heavy post for me. I know I’m not the best teacher, and the wall of text above certainly isn’t clear enough, so please come and ask questions, have conversations, and overall help me improve the series on my Twitter account, @theoct0. I’m improving in hacking, but I also need to better myself in teaching, explaining and a lot of stuff, so any help and tips would be much appreciated.