First of all, this should not be considered an ultimate guide, specially for more advanced devs.
This guide is more for those starting to look for exploits and can’t make out if a crash is an exploit or not. (shameless self-promotion note by wololo: also check my own guide here)
What makes a crash exploitable is the amount of control we have over it, in other words, how many registers we have influenced, either directly or indirectly.
Normal registers start with 0×08, 0×09, or has 0×00000000, 0xDEADBEEF. Other registers with unusual addresses (i.e. 0×61616161, 0xF125321B and any other weird looking address) are influenced, which means you can control it directly (by means of the savedata) or indirectly (by means of the savedata plus reversing, which makes these registers a bit harder).
First, look at the register called $ra, is it controlled? if yes then congrats, if no then don’t give up yet.
Make a disasm of the EPC, this has been explained a lot so I’m not going into details, with this disasm you want to be
looking for two different commands:
- jalr (jump and link to register)
- sw (store word)
The jalr command is essentially the same as $ra, just with another register, for example, if you have this:
Then the system will jump to whatever $v0 points to, so you want to look at $v0 to see if you control it, if yes then congrats, if not then don’t give up yet. Try looking at the disasm to see if before the jalr command there is another
command that changes $v0 using a register that you control, with this you can indirectly make $v0 into whatever you want. If you can then it just takes a bit of effort to make your useless crash into an exploit, if not then keep reading.
After the jalr command, we have the sw command. Exploiting a game using an sw command is harder than anything else, but don’t worry, there are lots of people in /talk willing to help (me being one of them). These types of commands have the
sw $v0, 8($v1)
The 8 is just an example, it can be any number, and the registers $v0 and $v1 are also examples, it can be any register.
Just like the jalr command, you have to check if you can control $v0 and $v1, if yes then you can turn this into an exploit, if not then like above, look at the code to see if the registers are influenced by other registers that you can control.
To sum up:
If you skipped all the above reading, then I’ll make a small summary of what I’ve said.
Basically, when exploiting you have to follow these steps:
- Is $ra controlled? if yes then you have an exploit, if not then continue
- Is there a jalr command? if yes then look if you can control the register in the command, if no then continue
- Is there a sw command? if yes then look if you can control the registers in the command, if not then find another crash