Tux Posted October 27, 2015 Posted October 27, 2015 td;dr: So, it is basically possible to run arbitrary code on Pokémon Colosseum and , provided you can load modified save files. (even if it's actually useless ...) How it works: On Pokémon Colosseum and , text, and especially Pokémon names, is stored as UTF-16 null-terminated strings (well, not UTF-16 exactly, but almost). When sending a Pokémon in battle, the games copies its name on a stack-allocated buffer, without proper bound-checking. # Pokémon , PAL ROM:8023B034 # =============== S U B R O U T I N E ======================================= ROM:8023B034 ROM:8023B034 ROM:8023B034 sub_8023B034: # CODE XREF: sub_80238CF0+58p ROM:8023B034 # sub_8023AFE4+14p ... ROM:8023B034 ROM:8023B034 .set var_7C, -0x7C ROM:8023B034 .set var_78, -0x78 ROM:8023B034 .set var_4C, -0x4C ROM:8023B034 .set pkmNameBuffer, -0x48 ROM:8023B034 .set var_1F, -0x1F ROM:8023B034 .set var_1B, -0x1B ROM:8023B034 .set var_C, -0xC ROM:8023B034 .set arg_4, 4 ROM:8023B034 ROM:8023B034 stwu r1, -0x80(r1) ROM:8023B038 mflr r0 ROM:8023B03C stw r0, 0x80+arg_4(r1) ROM:8023B040 stmw r29, 0x80+var_C(r1) ROM:8023B044 mr r29, r5 ROM:8023B048 mr r31, r3 ROM:8023B04C mr r30, r7 ROM:8023B050 mr r5, r6 ROM:8023B054 bl sub_8023B16C ROM:8023B058 mr r0, r3 ROM:8023B05C mr r3, r31 # pkm ROM:8023B060 mr r31, r0 ROM:8023B064 addi r4, r1, 0x80+pkmNameBuffer # dstName ROM:8023B068 bl copyPkmInfoForBattle # this will copy the Pokémon name into r4, WITHOUT CHECKING BOUNDARIES #etc..................................................................................... #....................................................................................... ROM:8023B0FC ROM:8023B0FC loc_8023B0FC: # CODE XREF: sub_8023B034+70j ROM:8023B0FC lmw r29, 0x80+var_C(r1) ROM:8023B100 lwz r0, 0x80+arg_4(r1) ROM:8023B104 mtlr r0 ROM:8023B108 addi r1, r1, 0x80 ROM:8023B10C blr ROM:8023B10C # End of function sub_8023B034 That means, if you fill your Pokémon's name (located at offset 0x4e () or 0x2e (Colo) in the Pokémon data structure) with 76 () or 124 (Colosseum) bytes of anything but not 00 00 or FF FF, followed by an address, the game will jump to that address. Now, what makes it actually exploitable is that the address of in-battle Pokémon is always the same for a given version. (804DC708 for PAL etc...). After jumping to the Pokémon data address (knowing its address), we can then jump to the PC data in a region-independent way: # lwz r3, -0x4720(r13) # This is the saved data structure addi r3, r3, 0xAD0 # PC data address mtctr r3 bctrl # Colosseum lwz r3, -0x5A58(r13) # This is the saved data structure addi r3, r3, 0xB88 # PC data address mtctr r3 bctrl This eventually enable us to execute at most 0xbc50 () or 0x7198 (Colosseum) bytes of code.
Tux Posted October 29, 2015 Author Posted October 29, 2015 I made a tool exploiting this vulnerability : http://www.mediafire.com/download/10xm5gjb8yo299s/pkmgchax.zip (all NTSC-U/PAL versions supported, tested on PAL; I'm lacking the address of in-battle Pokémon for Japanese versions). You need to copy your save file under the name "save.gci", and the code you want to be executed upon entering a Pokémon battle (NOTE: its location in RAM may is only known at runtime) under the name "payload.bin", in the same folder as the executable.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now