socram8888 / tonyhax

PS1 savegame exploit
Do What The F*ck You Want To Public License
436 stars 24 forks source link

Adding more games as entry point #82

Closed Badore90 closed 3 years ago

Badore90 commented 3 years ago

I'd like to make tonyhax booting from one (or more) of these games (PAL version):

socram8888 commented 3 years ago

Hello. I am not personally interested to add any more as entry points, as I think there are enough games already supported. With that said, if anyone is willing to add support himself and make a pull request adding support for them, that would be welcome. Closing since this is not a bug.

Badore90 commented 3 years ago

I'd like being able to do it by myself, but I don't know where to start. I have little free time (and I don't personally know any dev that could teach me) so never could really enter into development stuff. Thank you anyway.

krystalgamer commented 3 years ago

Pick any and try. Tekken 3 might have obfuscation. I've already did Tekken 2 entrypoint: https://github.com/socram8888/tonyhax/pull/20 Sadly due to the exploit being trickier(small workable payload size) it was not able to be upstreamed.

socram8888 commented 3 years ago

If you wanna do it, I can give you some rough guidelines on how to proceed.

All current tonyhax entry points rely on stack overflows caused by C string functions, so I'd recommend reading about what a stack overflow is. Note this is not the only kind of programming error that can be used to launch a payload, but it's one of the easiest to find and exploit.

Then get your hands on a image of the games you want to exploit, for instance by dumping the CDs, and load them onto no$psx. Advance on the gameplay until you're required to enter that text and then save onto the memory card.

Next load the save file (.mcd) into your favorite hexadecimal editor, and look for the text you just entered. If you found it, make a backup of the original save and then edit the save file so the text is waaay longer than expected. Save and then reset the emulator.

Advance until the save file is loaded and the text is used. For example, if the text was the user profile name (as with Crash Bandicoot), go to the load menu. For Tony Hawks, it's the custom career name, so you have to enter the career menu.

If your game freezes, congratulations, your game is likely exploitable. If it does not, it still could be but it might have checksums that complicate things up.

If you find any such game, let me know.

Badore90 commented 3 years ago

If you wanna do it, I can give you some rough guidelines on how to proceed.

All current tonyhax entry points rely on stack overflows caused by C string functions, so I'd recommend reading about what a stack overflow is. Note this is not the only kind of programming error that can be used to launch a payload, but it's one of the easiest to find and exploit.

Thank you very much. It doesn't seems so difficult.

Then get your hands on a image of the games you want to exploit, for instance by dumping the CDs, and load them onto no$psx. Advance on the gameplay until you're required to enter that text and then save onto the memory card.

What text??

bedwa commented 3 years ago

I would suggest looking on how the exploit is implimented here

https://orca.pet/tonyhax/game-exploit.html

It explains how the overflow works, should be adaptable in this case and should be modified for the specific game. Your exploit may vary.

Badore90 commented 3 years ago

I would suggest looking on how the exploit is implimented here

https://orca.pet/tonyhax/game-exploit.html

It explains how the overflow works, should be adaptable in this case and should be modified for the specific game. Your exploit may vary.

I thought you meant about the name you write when saving a game, so i dumped Castlevania SotN (that allows you to write the name on save file).

Btw I'll read the guide, thanks. It is difficult for me since I'm clueless about programming (...used a hex editor only once in my life) and also I'm not english.

Badore90 commented 3 years ago

I would suggest looking on how the exploit is implimented here

https://orca.pet/tonyhax/game-exploit.html

It explains how the overflow works, should be adaptable in this case and should be modified for the specific game. Your exploit may vary.

Most things are like arabic for me '^^

I've done so (using Castlevania):

first time I hex-edited the name adding letters, but only filling the empty boxes afer the name (in practice it resulted in the name enlarged about x3 times, then I stopped where there was other data). Doing so the name results much larger than the maximum characters allowed by the game, however i could normally load the savegame.

Then I edited it again making the name much longer (thus overwriting other data that was some boxes after the name). This way the game gets stuck on the load screen attempting to read the MC.

NOTE: I don't know it it's my PC or game related compatibility problems, but I had random hanging on screen changes in Castlevania using no$psx. So for reaching the first save room I used psxfin v1.13, saved, then copied the save to the mcd that np$psx created at first boot (SLES_00524.mcd).

So the game is exploitable? What should I do now?

socram8888 commented 3 years ago

Alright this is not like Lego bricks and it requires some knowledge before you can really exploit it, but here's some more rough explanation on how to achieve it.

First thing I'd recommend doing is taking a clean backup (right after saving and before editing it externally) of the save file, so we can easily roll back and apply patches to a save file that has the least amount of changes (so we don't risk accidentally breaking anything else).

The next that you can try doing is going to no$psx and on the Settings -> Xcept tab, select "Custom user settings". Then set everything to "Ignore/warning", except for "Invalid opcodes" (ie the processor has jumped to an invalid memory address) and "Memory misalignments" (the processor is trying to read/write to addresses that are not a multiple of 4 as MIPS needs), which should be set to "Show warning".

Next, try to replace the username by a long string of "U"s. The reason is that "U" is 0x55 in hexadecimal, so if the CPU tries to jump to or read from 0x55555555, we'd hit an exception and no$psx will let us know exactly where it happened.

I'd then recommend trimming the string length (by appending nulls for example) until it no longer explodes, so we know the exact minimum length required - using a string longer than required might cause a ton of problems, so the minimum would be the best.

Once we have that sorted out, the next thing is to choose a place in the save file where we can enter the first stage payload, which I'll attach here. Find on the save file a place that has a long run of zeros or 0xFFs, and paste it there. Then reboot the game and run it until it crashes again.

Then on the Debugger window, right click on the bottom left box (the data edition input) and select "Go to". Enter 0x80000000 (the start of the console's RAM). After that, select Utility -> Binary dump to bin file, and when asked about the size input 0x200000 (the size of the console's RAM). Save it wherever you please.

Open that binary dump on your hexadecimal editor of your preference, and then find where the game loaded it. You can easily find it by searching for "TONYHAX". Make note of the start of the payload - not where "TONYHAX" appears, but where the very first byte of the first stage loader is stored. Add 0x80000000 and you'd get where the processor needs to jump to do its magic.

Two very important thing:

The last thing we need is to alter the text so it contains that address, stored in little endian (ie "80123456" should be stored as a sequence of bytes like "56 34 12 80"), at a very precise location. This is more of an art than a science, but you can start by replacing the entire string with a lot of copies of the same 4 byte sequence.

If you get a red screen meaning the first stage payload is running, congratulations! Else, it could be a million different reasons why it did not work - for example, try moving the 4-byte sequence for the payload between 1 and 3 bytes after the start of the username, in case it was just that the address was not properly aligned.

Here's the first stage payload: entry.zip

If you manage to run it or have problems with it, just let me know.

Badore90 commented 3 years ago

Thanks a lot for the disposability, I'll do it as soon as I find some time.

Badore90 commented 3 years ago

Also the name (fabio) is present in 2 points:

Immagine

I modified the one in the upper left. Please tell me if it's wrong.

socram8888 commented 3 years ago

I honestly don't know. In that case I'd probably use trial and error. Try with one and if it doesn't work try with the other.

Badore90 commented 3 years ago

I made a quick try.

Adding "U" until the adjacent box to the highlighted A (41 in hexadecimal), I got no errors from the program (though the game cannot load the savefile already after I overwrited some of the previous data, it doesn't freezes, just says the savegame is no good).

When replacing the A (41) with "U" I get the error from no$psx (and if I disable the warning, the game freezes at the MC check with music running):

hexeditor errore

Badore90 commented 3 years ago

I pasted the payload starting from the line under the name (the long U).

Btw making the dump after the game crashes, there isn't any TONYHAX writed in the dump (though I can find the long UUUU name in it).

If I paste the payload starting from the name (starting from the first U), then the game no longer crash.

I could try pasting the payload just after the last U. Or maybe is better to start all over again trying to make the game to freeze using the other username (the bottom one after the alphabet)?

Badore90 commented 3 years ago

Once we have that sorted out, the next thing is to choose a place in the save file where we can enter the first stage payload, which I'll attach here. Find on the save file a place that has a long run of zeros or 0xFFs, and paste it there. Then reboot the game and run it until it crashes again.

I'm stuck here. I think I need a more precise suggestion about where to copy the payload data if possible.

I tried pasting that from the user name start, after it, before it (much before in a place where it was all zeroes), but after I do the dump I can't find any TONYHAX write into it. I guess it is because I'm pasting it in a wrong place.

Obviously I can't paste it anywhere, since I'm editing the mcd file (full 128kb memory card) not the savefile alone, so I have to make sure I'm always within the savegame block, right?

socram8888 commented 3 years ago

Yes, you need to modify the savefile alone, which will start at 0x2000 and will be 0x2000*blocks in length.

Badore90 commented 3 years ago

Yes, you need to modify the savefile alone, which will start at 0x2000 and will be 0x2000*blocks in length.

Pasting the payload at the very beginning of the MC block (at least I think I'm there, "2024"), thus overwriting a lot of data, username included, I can finally see the TONYHAX payload into the dump. However pasting the payload like that, makes the game to crash with this error:

image

Badore90 commented 3 years ago

Here's where the payload starts searching into the dump. The line address is 7EFE8, so it would be 0x8007EFE8, right? Or should I check the exact boxe address? I don't know how to do it.

Immagine

Badore90 commented 3 years ago

I'm thinking just now that I'm doing a basic error. I shouldn't make the game to freeze at MC screen/check anymore right? I must be able to launch the gamesave for TONYHAX to boot.

socram8888 commented 3 years ago

Mmm... I am not sure which screen you are referring to. The place where it launches varies between games - yours might access the username at that spot and thus crash there.

And regarding the address, yes, you'd need the exact address at which the payload starts. In your picture, 0x7EFE8 is the first byte of that row, but not the one you've got selected.

I have no clue what editor are you using so I can't give you any more specific advise on how to find out the exact address for the selected byte. I use HxD myself which gives the exact address of the selection it on the UI.

EDIT: Please note the save file has a 128*n byte header at the beginning of the save file (0x2000 for the memory card dump), where "n" is the number of frames for the animation. If you corrupt that there are odds the file will not be manageable by the system's save management menu, so don't touch those.

EDIT2: You'd need to store the payload somewhere else than the name (even if just one or few bytes after it). The payload contains zeros so it won't get properly copied to the buffer as explained before.

Badore90 commented 3 years ago

Mmm... I am not sure which screen you are referring to. The place where it launches varies between games - yours might access the username at that spot and thus crash there.

Let me show you. As we said there are 2 points where the username is written:

Immagine

If I stretch the first/upper one, the game crashes here:

https://user-images.githubusercontent.com/44087144/118702398-29338b80-b815-11eb-93c9-22a6ceb7eabd.mp4

If I stretch the second/bottom one, it crashere here:

https://user-images.githubusercontent.com/44087144/118702544-5b44ed80-b815-11eb-9f7a-5c54bd6e6ea5.mp4

And regarding the address, yes, you'd need the exact address at which the payload starts. In your picture, 0x7EFE8 is the first byte of that row, but not the one you've got selected.

I'm using XVI32. The byte's address is showed at the bootom screen but it's "overwritten":

Immagine1

However I found a way (using: address -> remember address -> display differences) for reading it.

Badore90 commented 3 years ago

The last thing we need is to alter the text so it contains that address, stored in little endian (ie "80123456" should be stored as a sequence of bytes like "56 34 12 80"), at a very precise location. This is more of an art than a science, but you can start by replacing the entire string with a lot of copies of the same 4 byte sequence.

Just to be sure I didn't misunderstood. With "alter the text" and "the entire string" you're referring to the username, right??

If you get a red screen meaning the first stage payload is running, congratulations! Else, it could be a million different reasons why it did not work - for example, try moving the 4-byte sequence for the payload between 1 and 3 bytes after the start of the username, in case it was just that the address was not properly aligned.

I tried in a lot of different ways but never got a red screen.

For replacing the username string with the payload address (that's currently 8007F118 so I'm writing 18F10780), writing it up to the "A" (the boxes that makes the game to freeze whan writing U until that), I have to start from the second username letter (the "a" of "fabio"). It fits 10 times. However the game just freezes, no red screen.

Badore90 commented 3 years ago

Also tell me if I'm doing right:

If I just copy the payload, XVI32 adds the bytes to the file (it doesn't overwrites anything), so for copying it, I firstly delete the payload number of bytes from the MC (selecting first and last block, then hit delete block), then I paste the payload.

Edit: Nevermind, I found a way to do it quickly.

Edit2: I should leave the username as "fabio" and paste the payload a few bytes after it or you meant after a few bytes leaving the name as a long "UUUUUU" (up to the A that makes it freeze)??

However in all tries I noticed this:

If I make the game to freeze (at the MC check, like in the first video), the payload won't be readed (no TONYHAX write into the dump). For the game to read the Payload, I must ensure it doesn't crash (this way I can find the TONYHAX write into the dump).

Badore90 commented 3 years ago

I tried pasting the Payload 3 bytes after the second/bottom username (leaving it as fabio).

As we said this way the game freezes at the loading screen, then the game crashed with the "undefined opcode" warning (even if I checked "disabled all warnings"). Making the dump it appears the TONYHAX write, but it seems the payload is partial/corrupted, so I can't find its start address:

Immagine

Badore90 commented 3 years ago

Looking for some indications I checked one of your entry points: crash2-eu-tpl.mcs

I see that the payload pasted into it is completely different from the one you linked me. It is normal?

EDIT: in the BESCES-0096700765150 file it is the same, so I guess it's a matter of file's type.

socram8888 commented 3 years ago

-tpl.mcs files are just skeleton files with no payload. That is later inserted by the entrypoints/Makefile.

Badore90 commented 3 years ago

-tpl.mcs files are just skeleton files with no payload. That is later inserted by the entrypoints/Makefile.

I'm still doing tries when I get some spare time (aside the freezes of the videos I posted, I found a place where the loading don't freeze, it finishes and then black screen). Please tell me if it's all correct. Summarizing:

I just need those 2 things? I mean, the long name is just for verify if the game is exploitable, etc... Or do I need to leave the long name (long enough to make the game to crash?).

A little off-topic (just a question):

I opened a issue on FPSXB page about allowing FPSXB to start from SLOT 2: https://github.com/brad-lin/FreePSXBoot/issues/55 What do you thing about adding it (if possible) on FPSX-tonyhax?

I firstly thought that only FPSXB team could make modifications on their program, but I see you already made an enhancement allowing to keep the FPSXB MC plugged. Making it to start from slot 2 will completely remove the need of swapping MCs.

Also tell me, if you prefer I'll make a separate issue for this.

socram8888 commented 3 years ago

The long name is requiered so the text overflows and you overwrite the return address to the payload.

Regarding the second, the reason why the FPB can be left plugged in is because of a patch I've done on tonyhax, but patching to boot from 2nd slot is something that will require FPB itself to be patched. It's open source so the code can be altered but it's not something straightforward - I'm not even 100% sure if it's feasible at all booting from the second slot, so it would require research.

Badore90 commented 3 years ago

The long name is requiered so the text overflows and you overwrite the return address to the payload.

Ok clear. I'm now trying with the loading screen freeze (I have the name long exactly up to the byte that makes the loading screen to freeze with undefined opcode error).

I don't have any clue on where to place the address so I'm just doing trial & error (I pratically filled the entire savefile with the address in many different ways but it never worked). I checked your Crash Bandicoot 3 savegame. To me the address seems placed on a random place (far away from the user-name). You found the right place putting the address at random or there are some clues that made you put the addrees in there?

socram8888 commented 3 years ago

It's totally random. I just moved it around until I found a place where it wouldn't get destroyed

Badore90 commented 3 years ago

It's totally random. I just moved it around until I found a place where it wouldn't get destroyed

Ah... ok. I firstly tried with Castlevania 'cause is very test friendly (you are on main menu in a couple seconds). But now I'll try with some other games, like Spyro 3 (it uses the naughty dog engine, maybe also the game saving works in a similar way) and Paperino operazione papero (it is pratically a clone of Crash bandicoot 2/3). I'll let you know if I'll make it to work.

One last thing to be sure I'm doing it correctly. In the case of this dump:

Immagine

The highlighted byte (1F, it is blank in text column) is the first byte right? I assumed the entry.bin file you linked me is the actual payload from first to last byte (I paste it from first to last byte, including the last twelve 00).

Thus if this is correct, the first byte (1F) address is 3BF80. So according to your explanation the address I have to paste into the save is by adding 80 and inverting the bytes sequence, so: 80 BF 03 80 Correct?

socram8888 commented 3 years ago

Supose we have address the value at 0x123456, we'll add 0x80000000, so we get 0x80123456, and encoded in little endian would be 56 34 12 80.

To be double sure, you can go to the data viewer on the debugger window and right click, select "go to" and enter that address. You should see the payload pop up

Badore90 commented 3 years ago

Supose we have address the value at 0x123456, we'll add 0x80000000, so we get 0x80123456, and encoded in little endian would be 56 34 12 80.

To be double sure, you can go to the data viewer on the debugger window and right click, select "go to" and enter that address. You should see the payload pop up

So it is exactly as I was doing.

About the debug warnings, You said I have to stop at the first one that makes the game to freeze, right? I don't have to look for a particular one? I'm now trying with Paperino. It normally allows for a 3 characters name.

Enlarging the name up to the first byte that makes it to freeze I get this error (after pressing ok, the error appears again every time I select the game's window):

Immagine

Enlarging the name some more, I get this other error (it appears only one time. selecting the game's windows I hear a sort of click sound from the game once):

Immagine2

But I guess this also can be random/depending on games.

Badore90 commented 3 years ago

However I'm having the same problem as with Castlevania. no matter where I place the payload, leaving the long game, thus doing the dump after the game freezes, the payload isn't present in the dump.

Only if the game doesn't freezes (for example it says "the save is damaged") I can find the payload into the dump.

socram8888 commented 3 years ago

Since it appears this isn't being worked on anymore, I'll be closing this issue.

Badore90 commented 3 years ago

Since it appears this isn't being worked on anymore, I'll be closing this issue.

I haven't given up, just don't have time in summer due to work. I think I'll do some more testing with my games when I'll have some spare time again. I'll let you know if I'll have any good result, for now I agree better to leave it closed.