Code Injection into Existing PS-X EXE files
Posted: September 4th, 2018, 8:54 am
I'm working on a project to patch an existing PS-X EXE file so that I can inject code into the game binary.
The game in particular is the arcade version of Dance Dance Revolution EXTREME. This game runs on a hardware platform called the System 573, which is based on the original PS-X hardware.
My goal is to interpose a handful of functions in the game with my own functions, cross-compiled for the r3000 and appended to the end of the EXE file.
My strategy is as follows:
1. Reverse engineer the game using a disassembler to find the code that needs to be patched. I chose to use IDA Pro for this.
2. Setup a toolchain in Linux to cross-compile C code for the r3000 and produce a relocatable ELF executable.
3. Since I'm working on an embedded system without a dynamic loader, I need to write a static loader that takes my ELF object and relocates it on-disk to prepare for injection into the game binary.
4. Test and debug using the MAME debugger. Using the MAME debugger I can inject code by loading the ELF binary into RAM. There is no memory protection on the PSX OS so I can overwrite an existing JMP/JAL instruction with one that jumps to my payload in RAM instead.
5. Modify the original PS-X EXE file to inject my code and patch the necessary functions using a binary patcher.
I've already done steps 1 and 2 (major thanks to the PSXDEV community for the helpful resources). I now have a relocatable ELF executable that I want to try injecting into RAM using MAME. Currently I am working on the loader so that it can take the destination virtual address in RAM as input, and use this to generate a Global Offset Table and compute the offsets from the various relocation entries in the ELF binary. The GOT will then be added as another section to the ELF file, and the offsets will be overwritten in-place.
My questions is: is this the right approach? Is there precedent for injecting code into an existing PSX game? While working on the loader, I realized that an alternative approach would be to separate out global variables (data) and helper functions into distinct objects and load these independently. The problem with this is that I would need to hardcode the destination addresses for these variables in my code, which would be fragile if I ever moved these around or wanted to add new functionality later.
I'd appreciate someone's help on this topic. Thanks!
The game in particular is the arcade version of Dance Dance Revolution EXTREME. This game runs on a hardware platform called the System 573, which is based on the original PS-X hardware.
My goal is to interpose a handful of functions in the game with my own functions, cross-compiled for the r3000 and appended to the end of the EXE file.
My strategy is as follows:
1. Reverse engineer the game using a disassembler to find the code that needs to be patched. I chose to use IDA Pro for this.
2. Setup a toolchain in Linux to cross-compile C code for the r3000 and produce a relocatable ELF executable.
3. Since I'm working on an embedded system without a dynamic loader, I need to write a static loader that takes my ELF object and relocates it on-disk to prepare for injection into the game binary.
4. Test and debug using the MAME debugger. Using the MAME debugger I can inject code by loading the ELF binary into RAM. There is no memory protection on the PSX OS so I can overwrite an existing JMP/JAL instruction with one that jumps to my payload in RAM instead.
5. Modify the original PS-X EXE file to inject my code and patch the necessary functions using a binary patcher.
I've already done steps 1 and 2 (major thanks to the PSXDEV community for the helpful resources). I now have a relocatable ELF executable that I want to try injecting into RAM using MAME. Currently I am working on the loader so that it can take the destination virtual address in RAM as input, and use this to generate a Global Offset Table and compute the offsets from the various relocation entries in the ELF binary. The GOT will then be added as another section to the ELF file, and the offsets will be overwritten in-place.
My questions is: is this the right approach? Is there precedent for injecting code into an existing PSX game? While working on the loader, I realized that an alternative approach would be to separate out global variables (data) and helper functions into distinct objects and load these independently. The problem with this is that I would need to hardcode the destination addresses for these variables in my code, which would be fragile if I ever moved these around or wanted to add new functionality later.
I'd appreciate someone's help on this topic. Thanks!