|PSX Cracks - Tutorial - Lesson 1 of ??? by B.A.D - Best Amiga Dominator(s)
With this document I hope to be able to satisfy the curiosity of all those people that have written to me asking for information on the new protections for PSX and on the methods used to get around them; it clearly doesn't constitute a complete guide to the cracking, but I hope it can be useful however to those people with a basic knowledge of the subject and who wish to tackle this type of job.
From here on in a good knowledge of the R3000 assembly language will be required, CPU of the Playstation: Anyone who already has experience of the Amiga should not encounter any serious difficulties, it will be sufficient to know the operation of a RISC cpu ;
If you are experienced with X86 assembler instead, you may have a few more difficulties
A series of essential tools are required: assemblers, disassemblers, debuggers, etc... as well as some info relating to the PSX hardware. All the documentation and the tools That I used are available at the sites pointed out at the end of this document.
How Libcrypt works
As with any other type of protection, LibCrypt is composed of two separate routines:
the first one performs a control check on the disk to discover if it is a copy, the second, based on the result of the first one, decrypts a block of data and crashes the PSX in the case of an incorrect result. Although based on the same code, the two routines have been altered a few times, to the point that in the last evolution (LC3) they have very little in common with the initial basic code.
This code is all written in pure assembler, and uses the registers of the PSX directly.
hardware of the PSX: there is not any call to the standard system and every precaution has been taken to prevent the program from being traced and therefore understood.
The routine that performs the check on the disk uses the hardware registers of the CD-ROM(1F80180X) directly and it memorizes the temporary data in the scratchpad memory
(1F800000-1F8003FF). It then calculates a 16bit number with a recursive algorithm.
(Magic Word!) this magic word is then used as a parameter for the subroutines, the value is stored in some register of COP0 (coprocessor of system), leaving it in the low part of the BPC register until the program finishes.
Obviously the BPC will have a different value if the CD is not an original!
This peculiar use of the hardware makes PSX emulators fail at this routine since at the moment none of them support low level access of the CD-ROM, but, more importantly, the use of the registers of COP0 prevents the Action Replay from tracing the program step by step , and it also prevents some of the normal operations of the A.R. because it uses the scratchpad memory to preserve the actual state of the PSX and therefore it alters the data contained in this area of memory.
Those of you that have a Pro Action Replay, with ram, are immune to the problem of scratchpad memory sharing as it always foresees a routine that stops the PSX as soon as the P.A.R. is activated; this last routine is the only one to have remained unchanged up until now.
To complicate things further from (revision)LC2 onwards an autocheck was introduced on this routine that reveals whether or not it has been altered.
The second routine, that that checks the presence of the MagicWord in the BPC, is implemented in different ways in the various games that use it: some perform the check immediately (FF8 for example), others wait until a certain level (Spyro2), others perform the check cyclically during some CD loading (SoulReaver). Or at specific moments (Mulan).
How to bypass LibCrypt
The simplest solution would seem to be to look for the second routine and to force it to operate as if the BPC contained the MagicWord.
This routine is almost always easily found within the main program, and it is easy to localize because the PSX has locked up.
Unfortunately there may be a number of routines within a game at various points throughout, in SoulReaver I have counted 3 of them and I cannot be sure that there are not any others as I haven't reached the last level! The best thing to do is to alter the first routine in such a way so that program thinks The CD is an original. Unfortunately a 'normal' copy doesn't contain some of the data present in the original CD. I have not found any system to force this routine to produce the MagicWord without the presence of this 'missing' data.
The best system developed up to now consists simply of picking up the games MagicWord while a CD is in operation. This also has the advantage of minimizing the alteration to the programs original form, i.e. just enough is changed to insert the one correct value in the BPC at the end of the first routine.
There are clearly there some disadvantages: You must have an original CD that works, and since generally the MagicWords of the games are different from one country to the next, it is not possible to develop 'universal' cracks. Each new game has a different approach to the protection, Therefore every time you want to develop a crack it is necessary to trace through the program (with a debugger) to search for the points where the routine first reads and then forces the MagicWord. This process is further complicated by the fact that now (revision(LC3)) every subroutine is encrypted (xor) and invisible in the main program;
once an appropriate point to read the MagicWord has been discovered, it is necessary to force it to be written in one some location of memory rather than in the BPC register because it obviously can not be read directly from the BPC using the A.R.
A practical example
I have taken as my example the routine that stops the PSX in presence of an A.R. because its removal is necessary first of all, and also because it is the only routine that has remained unchanged up until now (even if it has been encrypted).
This is the routine we are presented with in the executable of Mulan:
1) 8003a054 lui v0,0x1f00 ; lui == load upper immediate
2) 8003a058 mtc0 v0,BPC	 ; BPC == BreakPoint on execute address
3) 8003a05c lui v0,0x1ffc
4) 8003a< mtc0 v0,BPCM ; BPCM == BreakPoint on execute address Mask
5) 8003a064 mtc0 v0,BDA ; BDA == BreakPoint on dates access address
6) 8003a068 lui v0,0x8004
7) 8003a06c addiu v0,v0,0xa084 ; addiu == add immediate unsigned word
8) 8003a070 mtc0 v0,BDAM ; BDAM == BreakPoint on dates access address Mask
9) 8003a074 lui v0,0xe180
10) 8003a078 mtc0 v0,DCIC ; DCIC == BreakPoint on control register
11) 8003a07c jr ra ; jr == jump to register(ra == return address(register 31))
12) 8003a080 nop
(1)(2) - load $1f000000 into the BPC, the initial value for the MagicWord is zero (the low part of the BPC)
(3)(4)(5) - load $1ffc0000 into BPCM and BDA
(6)(7)(8) - load the address $80035f7c in BDAM
(9)(10) - load $e1800000 into DCIC and finally
(11)(12) - cause the rentry from the subroutine.
The values loaded in BPC and BPCM enable you to verify an exception if it executes any instruction present in the first 256k of memory, to leave from the address $1f000000, where the EEPROM of the A.R is positioned. The values inserted in BDA and BDAM vary, since they will be subsequently used as if they were normal registers, in fact the value loaded in DCIC
only actives the BreakPoint on execute and it doesn't activate the BreakPoint on it "dates access."
To avoid the A.R. crashing the PSX, we will need to prevent a breakpoint from being activated in this area of memory: considering that you cannot alter the values inserted in BPC and BPCM because they will be used later , the solution is simple, it consists of removing (and replacing with nop) the instruction (10), in this way no register is altered, but the BreakPoint is not activated.
(You could also have put $e080 in place of $e180, but a nop is easier:) This small patch of the code is necessary to allow the use of the A.R., it is better if you don't insert this code in the final patch, because the less original code you change the better, him you/he/she can never know, once arrived even to the if when you reach the final level of the game, the program verifies the value contained in the register DCIC:)
This section contains the links to three sites that contain all the relevant material needed too develop applications for the PSX, each of these contains a section link from where other similar sites can be reached.
Naturally you shouldn't forget the PsEmuPro emulator, even with all it's limitations, is still a useful tool: thanks to the integrated debugger and simulator of the Action Replay you can view the code and trace through it's operation step by step. This will give you a better understanding of the operation of the R3000 than you could get from simply reading the documentation.
Translated from the original Italian/Spanish By Goose, Additional help from Mr Denvir.