• Content count

  • Joined

  • Last visited

Community Reputation

11 Good

About Tux

  • Rank
  • Birthday 09/06/97
  1. Holy sh*t ... I've not been there for a month. Kudos for releasing this @StarsMmd
  2. Why is compression size an issue? Be careful as you'll need to move all branches since they are absolute.
  3. It's only debugging info iirc. Pokémon has a debugging menu disabled on retail. I've made a code to make it appear a while ago, but it was PAL only and doesn't work on latest Dolphin releases. Basically it just displays timers, currently running functions on each task with the lines, and the free stack space for each task.
  4. Sorry for not reponding ^^' I didn't made any research on for some time; however I've identified some other classes (Shadow Pokémon handling, party handling) but the problem is that I'm missing the significance of many of their methods... feel free to PR though. It's debugging information, and it's most likely a remnant of a higher-level language being assembled.
  5. Someone else got a corrupted PMD EoS save file, for some unknown reason. I mean, TWLSaveTool reads the 128KB eeprom's contents like it does for any other kind of eeprom. Anyways, that's good news .
  6. It is, but I haven't tested it.
  7. I've been doing some research about PBR since yesterday, and found some really interesting stuff. The save file, which is location is "nand:/title/00010000/52504250/data/GeniusPbr/PbrSaveData" is made of two contiguous "save slots" ("current" and "backup"), each one being 0x1c0000 bytes of size. It turns out that they are encrypted the same way save slots are. The encryption/decryption/checksum calculation routines can be here. Without further ado, here is what I know about the various structures. Save slots (0x1c0000 bytes): /* struct SaveSlot (size = 0x1c0000) */ 0x00: u16 encryptionKeys[4] ****************ENCRYPTED DATA**************** (refer to decryptSaveSlotAndCheckChecksums for more details) ** Start of game config data ** /* Checksum from 0x00 to 0x100. Refer to decryptSaveSlotAndCheckChecksums for more details. */ 0x08: u32 configChecksum[16] ... unknown data ... 0x1c: u8 isBackup (computed at runtime from saveCount) ... unknown data ... 0x4c: u32 saveCount ... unknown data ... ** End of game config data ** 0x100 to 0x37f: unknown 0x380: SaveSubSlots subSlots[4] (each one is 0x6ff00 of size and is associated to a particular NDS save file (probably by the TID/SID)) 0x1bff80 (= end - 0x80): u32 checksum[16] (of the whole structure (i.e. 0 to 0x1c0000)) (refer to decryptSaveSlotAndCheckChecksums for more details) 0x1bffc0 -- end: probably padding Pokémon: 140 bytes. I don't know anything else about these. Trainer cards: 0x738 bytes. When sent to/received from Wiimotes, 8 bytes of encryption keys and 64 bytes of checksum (same algorithms as before) are prepended. You can actually trigger a buffer overflow vulnerability (by playing with the trainer's name), but that's not really something exploitable.
  8. You need to download BOTH archives (the one that is ~300KB and the ~15MB one) and extract them in the same folder.
  9. I assumed you wanted to play backup games, sorry . But, still, $60 for a single game you may not play much is a lot ... Have you got a friend having an exploited 3DS and a cartridge of OOT ? If so, you can install the corresponding exploit (although it's a bit tricky ...)
  10. Done, I've added "--display-code-offsets".
  11. 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.
  12. Looks like there is a buffer overflow vulnerability in the implementation of the script version of printf: ROM:801BE670 # int __fastcall scriptPrintf(void *format, void *args) ROM:801BE670 scriptPrintf: # CODE XREF: scriptStdFunctions2Handler+270p ROM:801BE670 ROM:801BE670 .set var_12C, -0x12C ROM:801BE670 .set sprintf_buffer, -0x128 ROM:801BE670 .set var_28, -0x28 ROM:801BE670 .set var_1C, -0x1C ROM:801BE670 .set lr, 4 ROM:801BE670 ROM:801BE670 stwu r1, -0x130(r1) ROM:801BE674 mflr r0 ROM:801BE678 stw r0, 0x130+lr(r1) ROM:801BE67C stmw r25, 0x130+var_1C(r1) ROM:801BE680 mr r26, r3 ROM:801BE684 mr r29, r4 # ... NOTE: this function refers to "script error line[%d] : printf argument %d error \n" ROM:801BE840 loc_801BE840: # CODE XREF: scriptPrintf+1C4j ROM:801BE840 add r3, r29, r27 # var ROM:801BE844 lha r0, 0(r3) ROM:801BE848 cmpwi r0, 3 ROM:801BE84C bne loc_801BE884 ROM:801BE850 lwz r4, 0x954(r26) # dst ROM:801BE854 bne loc_801BE860 ROM:801BE858 lwz r6, 4(r3) ROM:801BE85C b loc_801BE868 ROM:801BE860 # --------------------------------------------------------------------------- ROM:801BE860 ROM:801BE860 loc_801BE860: # CODE XREF: scriptPrintf+1E4j ROM:801BE860 bl scriptConvertToString ROM:801BE864 mr r6, r3 ROM:801BE868 ROM:801BE868 loc_801BE868: # CODE XREF: scriptPrintf+1ECj ROM:801BE868 addi r3, r1, 0x130+sprintf_buffer # str ROM:801BE86C addi r4, r2, -0x56E8 # aSS # format ROM:801BE870 mr r5, r3 ROM:801BE874 crclr 4*cr1+eq ROM:801BE878 bl sprintf # "%s%s" # BOOOOOOOOOOOOOOOOOOOOOOOOOOOOOM ROM:801BE87C mr r25, r3 ROM:801BE880 b loc_801BEA20 # ... # the buffer is cleared IFF '\\n' is encountered ROM:801BEA2C # --------------------------------------------------------------------------- ROM:801BEA2C ROM:801BEA2C loc_801BEA2C: # CODE XREF: scriptPrintf+80j ROM:801BEA2C cmpwi r0, 0x5C # '\' ROM:801BEA30 bne loc_801BEAB8 ROM:801BEA34 addi r30, r30, 1 ROM:801BEA38 lbz r0, 0(r30) ROM:801BEA3C extsb r0, r0 ROM:801BEA40 cmpwi r0, 'n' # '\n' ROM:801BEA44 bne loc_801BEA94 ROM:801BEA48 addi r3, r1, 0x130+sprintf_buffer # str ROM:801BEA4C addi r4, r2, -0x56D8 # aS_0 # format ROM:801BEA50 mr r5, r3 ROM:801BEA54 crclr 4*cr1+eq ROM:801BEA58 bl sprintf ROM:801BEA5C addi r3, r1, 0x130+sprintf_buffer # msg ROM:801BEA60 crclr 4*cr1+eq ROM:801BEA64 bl sendToLog # '%s\n' ROM:801BEA68 li r5, 0 ROM:801BEA6C li r0, 0x100 ROM:801BEA70 addi r3, r1, 0x130+sprintf_buffer ROM:801BEA74 li r4, 0 ROM:801BEA78 mtctr r0 ROM:801BEA7C ROM:801BEA7C loc_801BEA7C: # CODE XREF: scriptPrintf+418j ROM:801BEA7C stb r4, 0(r3) # clear temporary buffer ROM:801BEA80 addi r5, r5, 1 ROM:801BEA84 addi r3, r3, 1 ROM:801BEA88 bdnz loc_801BEA7C ROM:801BEA8C li r25, 0 ROM:801BEA90 b loc_801BEAC4 # ... ROM:801BEAB8 ROM:801BEAB8 loc_801BEAB8: # CODE XREF: scriptPrintf+3C0j ROM:801BEAB8 addi r3, r1, 0x130+sprintf_buffer ROM:801BEABC stbx r0, r3, r25 ROM:801BEAC0 addi r25, r25, 1 ROM:801BEAC4 ROM:801BEAC4 loc_801BEAC4: # CODE XREF: scriptPrintf+3B8j ROM:801BEAC4 # scriptPrintf+420j ... ROM:801BEAC4 addi r30, r30, 1 ROM:801BEAC8 ROM:801BEAC8 loc_801BEAC8: # CODE XREF: scriptPrintf+74j ROM:801BEAC8 lbz r3, 0(r30) ROM:801BEACC extsb r0, r3 ROM:801BEAD0 cmpwi r0, 0 ROM:801BEAD4 bne loc_801BE6E8 ROM:801BEAD8 addi r3, r1, 0x130+sprintf_buffer # msg ROM:801BEADC lbzx r0, r3, r25 ROM:801BEAE0 extsb r0, r0 ROM:801BEAE4 cmpwi r0, 0xA # '\n' ROM:801BEAE8 beq loc_801BEB04 ROM:801BEAEC cmpwi r25, 0 ROM:801BEAF0 beq loc_801BEB04 ROM:801BEAF4 li r0, 0xA ROM:801BEAF8 stbx r0, r3, r25 # msg ROM:801BEAFC crclr 4*cr1+eq ROM:801BEB00 bl sendToLog ROM:801BEB04 ROM:801BEB04 loc_801BEB04: # CODE XREF: scriptPrintf+478j ROM:801BEB04 # scriptPrintf+480j ROM:801BEB04 li r3, 0 # empty string ROM:801BEB08 ROM:801BEB08 loc_801BEB08: # CODE XREF: scriptPrintf+11Cj ROM:801BEB08 # scriptPrintf+1BCj ... ROM:801BEB08 lmw r25, 0x130+var_1C(r1) ROM:801BEB0C lwz r0, 0x130+lr(r1) ROM:801BEB10 mtlr r0 ROM:801BEB14 addi r1, r1, 0x130 ROM:801BEB18 blr ROM:801BEB18 # End of function scriptPrintf
  13. 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.
  14. Ask me if you need anything.