Kippykip

CEO of cancelled
THE ONE
Found this website, looks incredibly useful and I was always interested in this LibCrypt protection sorta thing hence why I developed SBITools, so I'd thought I'd mirror this goldmine of info here.
Ya never know when something becomes lost media.
https://red-j.github.io/Libcrypt-PS1-Protection-bible/index.htm

Libcrypt PS1 Protection bible
By Red-J
1718505257544.jpeg


Introduction :
In 1998 Sony have introduce a copy protection system on some PS1 games to prevent piracy.
In this article I will explain all informations I have grab on the net on the Playstation protection and give informations with source.
The first game which use this system is the PAL version of Medievil.

The protection verify a 16 bits key based on the cd subchannel's data to verify if the game is original or not.

We have 4 differents protections schema: LC1,LC2,LC3 & LC4

LC1 is used on the first PAL Libcrypt protected game Medievil.
LC2 is the most used.
LC3 is used in : Speed Freaks, Formule 1 '99, Tele + Premier Manager (aka Premier Manager 2000), Ronaldo V- Football, Spyro 2, Spyro 3, Sydney 2000, Men in Black: The Series - Crashdown, Lucky Luke: Western Fever

F1 2000 use LC4

List of protected games : http://redump.org/discs/system/psx/libcrypt/2/

CDROM Protection - LibCrypt

LibCrypt is an additional copy-protection, used by about 100 PSX games. The protection uses a 16bit decryption key, which is stored as bad position data in Subchannel Q. The 16bit key is then used for a simple XOR-decryption on certain 800h-byte sectors.

Protected sectors generation schemas
There are some variants on how the Subchannel Q data is modified:

1. 2 bits from both MSFs are modified, CRC-16 is recalculated and XORed with 0x0080. Games: MediEvil (E). 2. 2 bits from both MSFs are modified, original CRC-16 is XORed with 0x8001. Games: CTR: Crash Team Racing (E) (No EDC), CTR: Crash Team Racing (E) (EDC), Dino Crisis (E), Eagle One: Harrier Attack (E) et al. 3. Either 2 bits or none from both MSFs are modified, CRC-16 is recalculated and XORed with 0x0080. Games: Ape Escape (S) et al.
Anyways, the relevant part is that the modified sectors have wrong CRCs (which means that the PSX cdrom controller will ignore them, and the GetlocP command will keep returning position data from the previous sector).

LibCrypt sectors
The modified sectors could be theoretically located anywhere on the disc, however, all known protected games are having them located on the same sectors:

No. <------- Minute=03/Normal -------> <------- Minute=09/Backup ------->

Bit15 14105 (03:08:05) 14110 (03:08:10) 42045 (09:20:45) 42050 (09:20:50)

Bit14 14231 (03:09:56) 14236 (03:09:61) 42166 (09:22:16) 42171 (09:22:21)

Bit13 14485 (03:13:10) 14490 (03:13:15) 42432 (09:25:57) 42437 (09:25:62)

Bit12 14579 (03:14:29) 14584 (03:14:34) 42580 (09:27:55) 42585 (09:27:60)

Bit11 14649 (03:15:24) 14654 (03:15:29) 42671 (09:28:71) 42676 (09:29:01)

Bit10 14899 (03:18:49) 14904 (03:18:54) 42813 (09:30:63) 42818 (09:30:68)

Bit9 15056 (03:20:56) 15061 (03:20:61) 43012 (09:33:37) 43017 (09:33:42)

Bit8 15130 (03:21:55) 15135 (03:21:60) 43177 (09:35:52) 43182 (09:35:57)

Bit7 15242 (03:23:17) 15247 (03:23:22) 43289 (09:37:14) 43294 (09:37:19)

Bit6 15312 (03:24:12) 15317 (03:24:17) 43354 (09:38:04) 43359 (09:38:09)

Bit5 15378 (03:25:03) 15383 (03:25:08) 43408 (09:38:58) 43413 (09:38:63)

Bit4 15628 (03:28:28) 15633 (03:28:33) 43634 (09:41:59) 43639 (09:41:64)

Bit3 15919 (03:32:19) 15924 (03:32:24) 43963 (09:46:13) 43968 (09:46:18)

Bit2 16031 (03:33:56) 16036 (03:33:61) 44054 (09:47:29) 44059 (09:47:34)

Bit1 16101 (03:34:51) 16106 (03:34:56) 44159 (09:48:59) 44164 (09:48:64)

Bit0 16167 (03:35:42) 16172 (03:35:47) 44312 (09:50:62) 44317 (09:50:67)
Each bit is stored twice on Minute=03 (five sectors apart). For some reason, there is also a "backup copy" on Minute=09 (however, the libcrypt software doesn't actually support using that backup stuff, and, some discs don't have the backup at all (namely, discs with less than 10 minutes on track 1?)).
A modified sector means a "1" bit, an unmodified means a "0" bit. The 16bit keys of the existing games are always having eight "0" bits, and eight "1" bits (meaning that there are 16 modified sectors on Minute=03, and, if present, another 16 ones one Minute=09).

Example (Legacy of Kain)
Legacy of Kain (PAL) is reading the LibCrypt data during the title screen, and does then display GOT KEY!!! on TTY terminal (this, no matter if the correct 16bit key was received).
The actual protection jumps in a bit later (shortly after learning to glide, the game will hang when the first enemies appear if the key isn't okay). Thereafter, the 16bit key is kept used once and when to decrypt 800h-byte sector data via simple XORing.
The 16bit key (and some other related counters/variables) aren't stored in RAM, but rather in COP0 debug registers (which are mis-used as general-purpose storage in this case), for example, the 16bit key is stored in LSBs of the "cop0r3" register.

https://problemkaputt.de/psx-spx.htm

Solution to bypass this protection:
You can make a 1 :1 copy of your original game with clonecd and the good profile file.
You can use LSD/SBI files with emulator if he support it.
You can use SBI tool to recreate subchannel information from LSD/SBI files.
You can patch the game with PPF finded on the web and PPF-O-MATIC.
You can just try to patch the game yourself to have a universal solution which work on all software or hardware

Patching - First step : Find the Magic word value
This method is based on libcrypt sectors of the original PSX CD.
--------------------------------------------
Resident evil 3 nemesis sample SLES 02530:
--------------------------------------------

View of all libcrypt sectors from game:
How to get sectors list: //to add

Sector MSF Contents XOR Comments
Code:
14231 03:09:56 41 01 01 07 07 56 00 23 09 56 df de 8001 c701 LC1 sector, no errors in data & CRC-16
14236 03:09:61 41 01 01 03 07 60 00 03 09 e1 f2 50 8001 bbd8 LC1 sector, no errors in data & CRC-16
14485 03:13:10 41 01 01 03 13 10 00 03 53 10 50 ec 8001 068d LC1 sector, no errors in data & CRC-16
14490 03:13:15 41 01 01 43 11 15 00 01 13 15 23 1e 8001 338d LC1 sector, no errors in data & CRC-16
14579 03:14:29 41 01 01 03 12 09 00 03 14 2d 04 73 8001 c831 LC1 sector, no errors in data & CRC-16
14584 03:14:34 41 01 01 03 1a 34 00 03 04 34 e2 cf 8001 8e30 LC1 sector, no errors in data & CRC-16
14649 03:15:24 41 01 01 03 13 20 00 03 15 04 82 35 8001 2d65 LC1 sector, no errors in data & CRC-16
14654 03:15:29 41 01 01 01 13 29 00 43 15 29 72 e2 8001 fd4f LC1 sector, no errors in data & CRC-16
14899 03:18:49 41 01 01 03 1e 49 00 03 08 49 32 c5 8001 8e30 LC1 sector, no errors in data & CRC-16
14904 03:18:54 41 01 01 01 16 54 00 43 18 54 d4 79 8001 fd4f LC1 sector, no errors in data & CRC-16
15378 03:25:03 41 01 01 03 23 13 00 03 25 0b 93 c9 8001 0553 LC1 sector, no errors in data & CRC-16
15383 03:25:08 41 01 01 0b 23 08 00 13 25 08 ce 5d 8001 50cf LC1 sector, no errors in data & CRC-16
16101 03:34:51 41 01 01 01 32 51 00 43 34 51 d7 a9 8001 fd4f LC1 sector, no errors in data & CRC-16
16106 03:34:56 41 01 01 03 33 56 00 03 b4 56 c0 9a 8001 de39 LC1 sector, no errors in data & CRC-16
16167 03:35:42 41 01 01 03 32 42 00 03 b5 42 69 e2 8001 de39 LC1 sector, no errors in data & CRC-16
16172 03:35:47 41 01 01 03 33 07 00 03 35 45 1a 10 8001 b12b LC1 sector, no errors in data & CRC-16

(Data extracted from http://redump.org/discs/system/psx/libcrypt/2/)

Compare sectors from game with all possible sectors from libcrypt:
How to use the tab:
If one sector of pair is present in sectors list from game the result is 1
If no sector of pair found in sectors list from game the result is 0


Libcrypt Sectors Pairs List14105

14110
14231

14236
14485

14490
14579

14584
14649

14654
14899

14904
15056

15061
15130

15135
15242

15247
15312

15317
15378

15383
15628

15633
15919

15924
16031

16036
16101

16106
16167

16172
Existing result0111110000100011

Binary result: 0111110000100011
Binary result converted to hexadecimal: 7c23
7C23 is the Magic Word value ;)
Open PSXfin 1.13 emulator and load your original game or a 1:1 Clonecd copied file which contains subchannels data
Go to debug menu>monitor>r3000
1718505283445.png

1718505292903.png


Check the BPC register to have the Magic world value, it will be here when the game check the value in the game

1718508999203.png
1718505749469.png


Change the CD and press Start

1718505786641.png


If the Game is protected you will see the value in few seconds
Else the value will be 1F0045

Patching - Second step : Extract the EXE file to patch :
The file to extract is often the SLES_ID file like SLES_025.30
You can verify if we extract the good EXE file:

How to know ?

Open the iso in HxD and change the parameter in DEC mode :
1718506759924.jpeg


Search the libcrypt routine hexadecimal value :

1718506791180.jpeg

1718506797687.jpeg


The offset routine in ISO : 671117360
Psx iso use always 2352 octets/sectors
Offset calcul: 671117360/2352=285339
The exe which contain the libcrypt routine is at 285339 sectors of iso
Open the iso with CDmage in M2 Mode track :

1718506849359.jpeg


Check LBA section to find in which file the 285339 sector is :

1718506873227.jpeg


SLES_025.30 file Begin at sector 2852069 and ended at 285496
It's the good file ;)

Extract the file and close CD-Mage :

1718506930246.jpeg

Patching - Third step : Patch the EXE file :
Open the file in HxD :
1718507108166.jpeg

The protection work in 3 parts:
- A protection to detect Action replay
- A protection to detect a Modchip
- A protection to verify the good value of magic word

You can see the detail of 3 routines in debugger here// to add

We must search the 3 routines to patch :

Replace this Hex value: 80E1023C00388240 //Anti-AR patch
1718507154046.jpeg

With this Hex value: 80E1023C00000000
1718507176356.jpeg



Replace this Hex value: 080020140200E7300600E010ADFF84200400801400000000 //Anti-MODChip patch
1718507196150.jpeg

With this Hex value: 000000000200E73000000000ADFF84200000000000000000



Replace this Hex value: 25308600 // MW patch
1718507337335.jpeg

With this Hex value: 237CC634
detail: 237c(reverted magic word 7c23) + C634

1718507389096.jpeg



Replace the file with CDmage and Enjoy!

Bonus:
Code:
In debugger:

 

Antipar (anti Gameshark) routine LC2:

0x80096534 LUI v0, 0x1F00 offset 86d34 hex value 00 1F 02 3C

0x80096538 MTC0 v0, v1 offset 86d38 00 18 82 40

0x8009653C LUI v0, 0x1FFC offset 86d3C FC 1F 02 3C

0x80096540 MTC0 v0, t3 offset 86d40 00 58 82 40

0x80096544 MTC0 v0, a1 offset 86d40 00 28 82 40

0x80096548 LUI v0, 0x8009 offset 86d44 09 80 02 3C

0x8009654C ADDIU v0, v0, 0x6564 offset 86d4c 64 65 42 24

0x80096550 MTC0 v0, t1 offset 86d50 00 48 82 40

0x80096554 LUI v0, 0xE180 offset 86d54 80 E1 02 3C

0x80096558 MTC0 v0, a3 offset 86d58 00 38 82 40

0x8009655C JR ra offset 86d5c 08 00 E0 03

 

Anti-Mochip + Magic word check

 

0x800967FC ADDIU a0, a0, 0x4AA8 offset 86ff0 hex value:A8 4A 84 24

0x80096800 SW zr, 0x0000(a0) offset 87000 00 00 80 AC

0x80096804 MFC0 a2, v1 offset 87004 00 18 06 40

0x80096808 LB a0, 0x0004(a1) offset 87008 04 00 A4 80

0x8009680C ANDI at, a2, 0xFFFF offset 8700c FF FF C1 30

0x80096810 BNE at, zr, label_0x80096834 offset 87010 08 00 20 14 Anti-MOD Check

0x80096814 ANDI a3, a3, 0x0002 offset 87014 02 00 E7 30

0x80096818 BEQ a3, zr, label_0x80096834 offset 87018 06 00 E0 10 Anti-MOD Check

0x8009681C ADDI a0, a0, 0xFFAD offset 8701c AD FF 84 20

0x80096820 BNE a0, zr, label_0x80096834 offset 87020 04 00 80 14 Anti-MOD Check

0x80096824 NOP offset 87024 00 00 00 00

0x80096828 LB a0, 0x0007(a1) offset 87028 07 00 A4 80

0x8009682C LUI a2, 0x1F00 offset 8702c 00 1F 06 3C

0x80096830 OR a2, a0, a2 offset 87030 25 30 86 00 Calculate MW

0x80096834 MTC0 a2, v1 offset 87034 00 18 86 40 Add MW in BPC register

0x80096838 JR ra offset 87038 08 00 E0 03

 

Hexa Offset calcul sample:

memory adress - base adress= offset

800967FC-8000f800=86ff0
Code:
This is a small gift from B.A.D to all psx coders

Formula 1 2000 - ALL RELEASES

New "Debug Protection" Routine:

LUI t0, 0x0F00
LUI t1, 0x1000
OR t0, t0, t1
MTC0 t0, bpc
LUI t0, 0x0FFC
OR t1, t0, t1
MTC0 t1, bda
MTC0 t1, bpcm
LUI t0, 0x0012
LUI t1, 0x8000
OR t0, t0, t1
ORI t0, t0, 0x03D0
ORI t0, t0, 0x200C
MTC0 t0, bdam
LUI t1, 0x0180
LUI t0, 0xE000
OR t1, t0, t1
MTC0 t1, dcic

It works like an LC prot but you can't see it using a
normal scanner like LCT.

There are 9 of this routines in each modules (45 totals)

The game makes the check at the end of each game session
when the program unload the module and it go back to the menu
(a second before you see the F1-2000 writings on the white background)

It's not a Libcript protection, there are no COP0 register used
but there is only a check on the cd.

Then, the check results is passed to the following module. In this way
the first part of the game after the boot works fine.

Each module is contaned in a file into the BINARIES directory
on the cd. The files are encripted with a 32 bit XOR, the key
is everytime the same ($AF9327A3)
Note: the program into the game_gp.bin file is not word-aligned.

These are the patches to apply to each module:

game_gp.bin offset: $70e8 83 8b 9b af
game_qik.bin offset: $5760 8f 5f b3 03
game_tst.bin offset: $55ac 8f 5f b3 03
game_tt.bin offset: $9940 8f 5f b3 03
game_dem.bin offset: $5014 8f 5f b3 03

Except for the game_gp.bin file, the only change is in B1 -> B3
due to the non word-aligned code.
Don't forget the encription. Just look the line below.

sw v0, $782c(at) --> sw zero, $782c(at)

I hope you all found useful these info
that comes directly from our main coder BAD.

bye

BRT



PSX Libcrypt Tutorial


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.

Introduction

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&#9; ; 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:)

Link

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.​
https://consolecopyworld.com/psx/psx_libcrypt_tutorial.shtml

LibCrypt failed check, causes and effects​

Here's a list of what LibCrypt'ed games will do to the player when it realises the SubChannel data isn't correct. Obviously these aren't all the LibCrypted games (check on Redump.org for that), these are just games I've personally tested and some I've been told about. Look out for these effects when testing games modified with SBITools on an accurate PSX emulator such as BizHawk. (Run from .CCD)

Ape Escape (PAL)
Main menu navigation will be completely disabled, making you unable to start the game.

Crash Team Racing (PAL)
Game will hang once at the end of the loading screen (for the level itself).

Final Fantasy 9 (PAL)
The game freeze on the squaresoft screen at launch.

Legacy of Kain: Soul Reaver (PAL)
The game will hang when you're introduced with the combat tutorial when the camera pans to show the enemies.

Lucky Luke: Western Fever (PAL)
The game stops when you get to the Mexican guy blocking the bridge, he just won't move from there, ever. Even when you complete the quest. The game also has anti-cracking protection where the game will block a path with a fallen tree + maybe more.

MediEvil (PAL)
Will have a disc error icon upon loading The Hilltop Mausoleum. Interesting to note this was actually the FIRST game to use LibCrypt.

MediEvil 2 (PAL)
Will also have the same disc error icon as above, except upon loading Kensington.

PGA European Tour Golf (PAL)
In the third hole of the first tournament or by selecting some holes, the game will get stuck in "demo" mode (and will not you play anything).

Resident Evil 3: Nemesis (PAL)
Will hang at the "Game contains violence and gore" screen. Same issue on Dino Crisis 1

Spyro 3: Year of the Dragon (PAL)
Interesting case for this one, the game will eventually randomly delete eggs, reset progress with unlocked characters, remove sheep in boss battles, change the language and even tell you off for playing a "hacked copy" + more. Interesting to note that the game also detected early LibCrypt knockout PPF patches back when the game was first released as it had checksum checks throughout the game, which caused the same effects above. The US platinum release only has anti mod detection (not libcrypt) and will do the above effects if it realises it's been modified. The original US release appears to not have any protection.

This is Football (PAL)
Hangs on the loading screen going ingame.

V-Rally: Championship Edition 2 (PAL)
The game will endlessly load on the heartbeat loading screen (with no disc activity).

Wip3out (PAL)
The game will freeze when passing the finish line.

https://github.com/Kippykip/SBITools & Red-J

Final Fantasy VIII
Copy Protection
Date
Author
: 14-03-1999
: Mr.T/Champion

Introduction

THE NAME MR. T IS NOT RELATED TO THE MR. T IN ACCESSION. (sorry for the confusion)

This document has been written to cover all the recent myths about the copy protection system in the Japanese version of Final Fantasy 8. Also, it is an inside look at how this crack was made, including some simple-to-understand descriptions of why normal mod chips don't work and a QBASIC example of what the crack does to override it (don't worry, if you can understand IF, GOTO, etc. you're fine).
First of all: THE RUMORS ABOUT FF8 HAVING COPY PROTECTION ARE TRUE.

I. General Information
1. What protection?
2. What can I do about it?

II. The Protection
1. How mod chips work
2. How the new protection works
3. How to break it

I . General Information

1. What Protection?

Simply put, FF8 knows if you have a mod chip. If you try to play either a legit or illegit copy of FF8 on a modded PSX, it's going to give you an error message (translation):

Aborted. The system may have been modified.
1718508308472.jpeg

IT DOES NOT MATTER IF YOU ARE USING A LEGIT VERSION OF FF8. It is detecting the chip itself, which will be described in detail later.


The protection DOES NOT affect owners of "Anti-Piracy" mod chips (and of course legit copies of FF8) and the so-called "Game Enhancers".

NOTICE: Game Enhancers suck, so please don't get one. Also, it's a pirated version of a ROM that was meant for unlicensed PSX development (called caetla), not copying. Please don't support the idiots selling the GEs because they are stealing credit from these authors of a great program. (caetla is free BTW... Go to http://www3.airnet.co.jp/kcomm)

This crack was made with 100% caetla version .33.​

2. What Can I Do About It?

There are 2 general ways to crack it, avoiding it and blocking it. A general list with instructions is below.

  1. BEST ANSWER IF POSSIBLE. Patch the BIN file before burning. There is a file called CPOFF8.EXE out there. This is the crack in patch form. This program patches a BIN (RAW read mode only!) file to not have protection anymore. Works great, if you have a CD writer.
  2. Use a Game Shark / Game Enhancer / Caetla / Xploder / Action Replay.
    There are already codes to crack FF8 quickly and efficiently. They are below (in this order, and yes, the 1st and 3rd codes are the same):

    D009B2B0 FFF3
    8009B2E0 0046
    D009B2B0 FFF3
    8009B2E2 1000

    NOTE: due to a bug in Game Shark v1.99, you CANNOT use v1.99 to crack the game. In fact, it's quite likely no codes in existence will let you.

    The Game Shark method is probably the best as most games will be cracked in Game Shark form. Unlike phantom mods, it is upward compatible as cracks in software can always be done.
  3. Use the "Swap Trick" method. On really old SCPH-100x PSXs, and using Caetla (aka Game Enhancer), you can boot this game without problems. The swap tricks are a bit detailed, so I won't go into them. You can get this information anywhere. Also, for Caetla users, the normal trick to boot copied games is what you use.
    NOTE: THIS TRICK DOES NOT SAVE YOU IF YOU HAVE A MOD CHIP INSTALLED. YOU CAN USE GAME ENHANCERS FOR THEIR CODE ENTERING ABILITY (SEE #4) IF YOU HAVE A MOD CHIP, HOWEVER.
  4. Use a blue PSX. Blue PlayStations don't need mod chips to play copies, and it is the mod chip itself the system is checking for. What good is this though, since nobody but developers have blue PSXs? Well, it's listed because it IS a working method. (I asked a developer to try it on a blue PSX and it worked fine.)
  5. Use a "Phantom" mod chip. These mod chips are designed to thwart the mod chip detection scheme these programs use. This is a good option if you intend to mod an unmodded PSX. #4 is better if you already have a mod chip, as it ensures forward cracking compatibility without needing to burn.
    WARNING: THE ORIGINAL "PHANTOM" MOD CHIP DOES NOT WORK. IT NEEDS TO SPECIFICALLY SAY FF8-COMPATIBLE IN ITS ADVERTISING.
  6. Install a switch on your mod chip. If you have a switch between pin 1 and the PSX board that is accessible from the outside, you can manually turn off your mod chip after the game has booted. Putting the switch on is beyond this document's scope, but instructions for using it with FF8 are below:

    a. With the PSX off, turn the mod chip to "ON".
    b. Stick in CD (if not already done) and turn on PSX.
    c. The instant you see "Licensed by Sony Computer Entertainment Inc.", turn your mod chip switch to "OFF". This has to be done while the PSX is in the black PSX screen.
  7. Use an "anti-piracy" mod chip. These work, although my question is why you'd want to do this. However, it is a working solution.

II . The Protection

1. How Mod Chips Work

In order to understand most of the rest of this document, you need to understand a few basic things of the copy protection system of the PSX. This is all closely related to why FF8's protection system exists at all.

Somewhere, on black PSX CDs, is an ASCII (IE, letters) string. This is how the copy protection works. Not even I know where it is, but I do know what form it's in. These 4 (known) strings are: SCEI (Japan), SCEA (America), SCEE (Europe/other PAL places), and SCEW (Yaroze). Look familiar? They should. On the black PSX screen, there is this (for American games on American gray PSXs):

Licensed by
Sony Computer Entertainment America
SCEA tm

Since the location of this data is unknown, when you copy CDs, you don't copy the SCEx data on the CD. This is why you need a mod chip.

Each PSX has a particular SCEx "code" it waits for. American PSXs look for SCEA, for example. When you stick in a CD, the PSX waits for its particular code, and if it doesn't find it it considers it an invalid CD. All invalid codes are ignored. QWETKSDFUSCEAIRGTKVL is a valid code for American PSXs because the other letters are ignored and it sees SCEA. If a 3rd party developer figured out the copy protection, they could have a licensed code of NOTLICENSEDBYSCEASCEIORSCEE and get through the copy protection.

From CD-ROM PSX wants Comments Correct? Result
-----------------------------------------------------------------------------
SCEA..SCEA..SCEA.. SCEA American CD Pass..Pass..Pass.. -> Valid CD
SCEA..SCEA..SCEA.. SCEE American CD Fail..Fail..Fail.. -> Invalid CD
SCEI..SCEA..SCEE.. SCEA Mod chipped Fail..Pass..Fail.. -> Valid CD
.................. any Copy w/o mod .................. -> Invalid CD

THE COPY PROTECTION IS THE SAME AS THE IMPORT PROTECTION. Each PSX (excepting blue and black PSXs) has only 1 copy protection code that it recognizes. This is how import protection is done. See the above table,rows 1`and 2. The first is an American PSX, the second is a European PSX.

The 3rd one on that table above is the one of interest. If you have all 3 codes on the CD (which Sony never does but it in theory possible) it will work with all PSXs. This is the technology of the mod chip. The inventor of the mod chip (who is, contrary to conventional wisdom, NOT Old Crow) found a way to fake the SCEx data from the CD-ROM. A method of putting anything you want instead of the SCEx was discovered. At first, mod chips were "burned" according to what PSX the mod chip was being installed to. Mod chips destined for American PSXs sent SCEASCEASCEASCEASCEA... to trick them.

However, people began to notice how much of a pain it was to make 3 different types of mod chips. Someone (probably Old Crow) figured out that if you send SCEISCEASCEE instead of only 1 code, you will have a mod chip that works on any PSX. This, and the discovery of the "gate"/"pin 5" wire,
led to the name "Universal Mod".

So that mod chips don't need more than 4 wires (the absolute minimum for non-American PSXs), a decision was made that it doesn't matter WHEN the PSX checks copy protection. The mod chip just sends data continuously from when you turn the PSX on until you turn it off. This shortcut turns out to be why the mod chip is detectable at all. Unmodded PSXs only send the SCEA a few times before turning off.

I hope this explanation was enough to explain why mod chips work the way they do, as the next section says how the FF8/Poporogue copy protection takes advantage of the design of mod chips to work.

2. How the New Protection Works

If you look above, you'll see that the normal (IE, unmodded) operation of the PSX only has the SCEx code data during bootup, while modded operation sends the data continuously, even when it's not wanted. Because of this, it is possible to detect mod chips by seeing if data is being transmitted during times when normal operation wouldn't. In fact, this is exactly what is done by FF8.

With the release of Poporogue (the first "mod-detecting" game) in Japan, many people wondered what was going on that was detectable. With the help of some HK crackers, the programming team that made Caetla figured out what Poporogue was doing to check protection. It turned out that another undocumented CD-ROM command (0x19), was able to count the number of SCEx codes that had been received.

FF8's detection scheme is actually not too difficult to understand. First, it places the CD-ROM in a "distracted" state. It plays a data track as audio (and blanks the sound of course) apparently so that no SCEx data gets sent. It then sets the "counter" to zero. If it receives SCEx codes, that means a mod chip is present. If none are received, it means one isn't.

. = nothing
"Mode" SCEx codes Counter Result
-----------------------------------------------------------------------------
Normal .................. 0 -> No mod chip
Chipped SCEI..SCEA..SCEE.. 3 -> Mod chip

FF8 reads the counter data, and uses that to determine if a chip is
present.

3. How to Break It

A. Don't use a mod chip, or use swap trick/mod switch

If you don't use a mod chip, no SCEx data is sent during FF8's check, so obviously it isn't detected. However, not using a mod chip is not very useful since you'll need a legit FF8 and a Japanese PSX.

However, the "swap trick" and switchable mod chip work great. These methods work because there is no SCEx data sent - there is either no mod chip or the mod chip is disabled when the FF8 check is occurring. See section I.2 for more information.


B. Use an "anti-piracy" mod chip.

An "anti-piracy" chip works like this: the chip waits for SCE before sending the A (or whatever letter is needed for that PSX). If even SCE is received, it has to be a legit CD. This is how it plays imports and not copies.

Conditions SCEx data PSX sees Result
-----------------------------------------------------------------------------
Legit From PSX SCE...SCE...SCE... SCEA..SCEA..SCEA.. -> Valid CD
From Chip ...A.....A.....A..
Copy From PSX .................. .................. -> Invalid CD
From Chip ..................

Since no data is sent during the check, the anti-piracy chip doesn't add add any and is undetected by FF8's method. However, this could change easily, since there is a simple way to check for anti-piracy chips, one that could prevent imports from running AT ALL, regardless of what type of mod chip you have. Not even stealth chips would fix it - it is inherent to the PSX's design. For this reason, I won't be giving details out because if I did then developers would use it.


C. Here's something a bit more obvious: crack the game.

This is by far the simplest solution if you can do it. As stated in I.2, there are several direct crack methods available.

The crack itself works by basically skipping over the code. The code, in a pseudocode QBASIC (chosen as the most people know it) form, looks like this:

' Original FF8 code
FUNCTION CopyProtect%

' Execute the CD-ROM commands used to get SCEx counter data.
NumberOfCounts% = StartCopyProtection

' If any were received, then fail protection
IF NOT NumberOfCounts% = 0 THEN
CopyProtect% = 1
EXIT FUNCTION
END IF

CopyProtect% = 0
END FUNCTION


What my crack does is jump over all of the protection stuff, instead starting at the part at the end (CopyProtect% = 0). In QBASIC pseudocode form again:

' Cracked FF8 code
FUNCTION CopyProtect%

' Execute the CD-ROM commands used to get SCEx counter data.
' DELETED: NumberOfCounts% = StartCopyProtection
GOTO Skip ' ADDED

' If any were received, then fail protection
IF NOT NumberOfCounts% = 0 THEN
CopyProtect% = 1
EXIT FUNCTION
END IF

Skip: ' ADDED
CopyProtect% = 0
END FUNCTION


Basically, it just skips over the code. In reality, however, it is written in R3000 (the PSX's CPU) assembly language, not BASIC. This QBASIC description works though because it depicts accurately the crack itself. The 10000046 in the Game Shark codes, for example, is a "beq zero,zero,???" R3000 command that means basically "GOTO".

(NOTE for programmers: StartCopyProtection is actually in-line (not shown here for simplicity))

The jump itself is 1 instruction, or 2 Game Shark codes. In order to keep the game stable, since FF8 shares RAM among different parts of the game (overlays), you need "D" codes. D codes only activate the code under it if its memory location is a certain value. This is so that you don't mess around with the wrong data.

Game Shark codes a whole lot different from a true crack. In order to make a real crack, you must first make an EXE file (the SLPM file is an EXE). It's not as simple as yanking out ye olde Hex Workshop and making a few changes that match those in the Game Shark codes. First of all, the copy protection code is not in the EXE, but rather, compressed somewhere on the monster file known as FF8DISC1.IMG. Second, RAM is reused.

My solution was as follows: Attach a "waiting" piece of code to the part of the EXE that decompresses the protection code. As soon as the decompression code decompressses copy protection code, my program kicks in and hacks it. However, this solution adds a new problem: how to add in this code. There is simply no space in the EXE to add code, as the 00'd areas in the EXE get overwritten and the code needs to stay. I ended up choosing the reserved RAM area at 8000F800 as the place for my code, which caused yet another problem: how to get code into 8000F800. The PSX EXE format does not allow for using 8000F800 simply by loading an EXE. In order to fix this, my final solution was made:

  1. Take over the start of FF8. This allows me to have my code execute before FF8 even starts.
  2. In the code that starts before FF8, copy the "attachment" to the decompression code I described before into 8000F800.
  3. Patch the decompression code to call 8000F800 every byte that is decompressed (slow, but only adds 1 second to load time).
  4. Start FF8.
  5. When the copy protection code is decompressed, first make sure that it is the right code that is being modified. (This occurs in 8000F800).
  6. If so, write 0x10000046 to 0x8009B2E0 (as shown in the GS code).
  7. Resume normal FF8 operation.

I hope this clears up the many misconceptions about FF8.

Mr. T
Author

Keeping the Pirates at Bay - By Gavin Dodd from Business/Marketing​

So you've worked 10- to 12-hour days for the past two years, trying to make your latest game the best ever. You even added copy protection to try to stop the pirates, but within a few days of release there are already crack patches flying around the Internet. Now anyone can help themselves to your hard work, without so much as a "please" or "thank you."

This is what happened to Insomniac's 1999 Playstation release, Spyro 2: Ripto's Rage . Even though it had good copy protection, it was cracked in a little over a week. So when we moved on to Spyro: Year of the Dragon (YOTD), we decided that something more had to be done to try to reduce piracy. The effort was largely successful.

View attachment 1718508835191.webp
Though a cracked version of YOTD has become available, it took over two months for the working patch to appear, after numerous false starts on the part of the pirates (the patch for the European version took another month on top of that). The release of patches that didn't work caused a great deal of confusion among casual pirates and plenty of wasted time and disks among the commercial ones.

Two months may not seem like a long time, but between 30 and 50 percent of most games' total sales occur in that time. Approximately 50 percent of the total sales of Spyro 2 , up to December 2000, were in the first two months. Even games released in the middle of the year rather than the holiday season, such as Eidetic's Syphon Filter, make 30 percent of their total sales in the first two months. If YOTD follows the same trend, as it almost certainly will, those two to three months when pirated versions were unavailable must have reduced the overall level and impact of piracy. On top of this, since YOTD was released in Europe one month after the U.S., those two months protected early European sales from pirated copies of the U.S. version.

Though a cracked version of YOTD has become available, it took over two months for the working patch to appear, after numerous false starts on the part of the pirates.

So why did it take so long to crack YOTD when a patch was available for Spyro 2 so quickly? The difference was that Spyro 2 only had copy protection, while YOTD added crack protection. The crack protection complemented the copy protection by checking for alterations to the game, rather than just making sure the game was run from an original disk. This extra layer of protection slowed down the crackers significantly, because removing the copy protection had to be done without triggering the crack protection. Basically, YOTD is booby-trapped - one wrong bit and it will blow up in your face. This article will explain the techniques that we used in YOTD , what we learned from using them, and some ideas about how to take our techniques even farther. However, I will not go into explicit detail, as most of the coding involved is relatively simple. Crack protection is more about out-thinking the crackers than out-coding them. A great advantage of any method of protection is novelty. Even a new implementation will give an advantage over simply reusing code, regardless of whether it was successful in previously delaying a crack.
Defining the Problem

From the very beginning we recognized that nothing is uncrackable. Many different software and hardware techniques have been used in an attempt to stop piracy; as far as I know every one of them has been bypassed or cracked. Our goal was to try to slow the pirates down for as long as possible.

First we looked at the copy protection: was there any way to reduce its vulnerability to cracking? We could call the copy protection multiple times throughout the game, making it harder to bypass. Unfortunately, the copy protection requires exclusive access to the CD for about 10 seconds, which is an eternity when you are waiting for a level to load. So that was out of the question.

Then we looked at how a typical crack is made. Most cracks for Playstation games replace the boot executable with an "intro" that proclaims the prowess of the crackers and allows cheats to be activated. This intro is concatenated with a copy of the patched executable and compressed so that the total file size is no larger than the original file. The new file bears little resemblance to the original boot program. This difference gives us the opportunity to reload the boot executable sometime after startup, causing severe corruption if it has been altered in this way. As with the previous option, this solution suffers from the problem of adding to the load time. It is also vulnerable to the pirates finding some other space on the disk to hide their crack, leaving the original boot file untouched. While this solution might have slowed the pirates down for a few more days, it didn't seem like it was the answer we were looking for.

We decided that we needed a thorough way of detecting at run time that the game had been cracked. When we could reliably determine whether the game had been modified, we could stop the game anytime we found a discrepancy. We also needed a method that didn't require access to the disk. It should just check the code in memory, unlike the standard copy protection or our option of reloading the boot program. This would allow us to place the check anywhere in the game, making it much harder to remove.

So now we had a definite goal, an approach that should significantly improve the protection for YOTD .

Checksumming

Finding out if a block of data has changed in any way is actually pretty easy. Techniques have been used for error detection for years and are well documented. Just search for "checksum" on the Internet. For YOTD , we decided to use a CRC checksum: it's robust, simple, and fast.

The checksum was calculated bitwise rather than using tables, as tables would be an easy point for a cracker to attack. We took care to hide and protect the checksum values as well. If these could be found and altered easily, a cracker would simply replace the checksum with a new value that matched the cracked data, which is far easier than removing the code. For the same reason we didn't use functions to calculate checksums, we inlined the code as much as possible. If the code was in a function, it would only have to be removed once. The inline code would have to be removed as often as it was used.

We used a few slightly different implementations to stop simple pattern searches from being used to find the checksum code. To what degree this survived compiler optimization we don't know. To make our lives easier we made macros. These could be sprinkled around the code and mixed in with other tasks, which would make it much more difficult to spot where the checksum was being calculated.

Unfortunately, because checksums are designed to detect errors and not modification, they cannot offer full protection against modification. The checksum value for any block of data can be made to add up to any value by modifying the same number of bits that are used for the checksum. In other words, if the checksum is 16 bits, altering 16 bits in the data can make the checksum match any value.

To deal with this, multiple checksums were applied to the same data. Each checksum used a different start offset into the data, and stepped through the data by different amounts. This meant that overlapping and interleaved sections of data were checksummed at different points, making it almost impossible to alter anything and still have all the checksums add up. I could have used different checksum algorithms for the same effect, but in this case I didn't have time to implement more than one method.

We used the fact that altering a small number of bits can give you any checksum value to our advantage. By inserting the correct value into the middle of the data, the checksum could be made to equal any predetermined value. This meant the checksum value could be hard-coded and therefore become part of the data being checksummed. This is bewildering to even think about, let alone try to crack.

Since the game used multiple code overlays (or DLLs), they cross-checked each other as much as possible. This further reduced the chance that any section could be altered without being spotted. If any overlay noticed a discrepancy, it altered data in the core such that no subsequent checksum would be valid. This meant that if an alteration was detected in one overlay, then other overlays loaded later would know about it. This made it difficult for the cracker to spot what actually triggered the protection, as I'll explain later.

Obfuscation

Now that the meat of YOTD 's crack protection had been implemented, it was time to move on to the second stage slowing down the crackers as much as possible. We had already tried to make the protection as difficult as possible to understand, mixing in the checksum code with regular game code, and using different implementations so that it would be hard to understand. We thought that if the crackers couldn't understand what we had done, it would be a lot harder for them to crack the game. We wanted to make it hard enough to reduce the pool of people capable of cracking it. If there are only a couple of pirates with enough skill to crack a game's protection, it might take them a week or two to get around to it. Unfortunately, with YOTD being such a high-profile game, this was probably wishful thinking.

Thus we wanted to make the job of cracking YOTD time-consuming and tedious. If we could just keep the crackers busy at finding the protection, that's time taken away from them working out how to remove it. Again, we were trying to reduce the pool of people available who could crack the game. Not every cracker would have enough time available to make the crack; it probably isn't anyone's day job. On this note, it's worth pointing out that for most crackers this is a hobby. If they get bored, they may well give up. We tried to make the crackers have to wade through plenty of chaff before finding the protection. There were a couple of techniques we tried to achieve this.

First of all, if the crackers know what they are looking for, they often don't even have to boot up the game to find the protection. They can simply search the disk and sometimes even edit the protection right there and then. Simply doing an XOR of as much of YOTD's code as possible before burning it to the CD means that this technique will not work. It also makes it difficult to match up data in memory with its source on the disk. We worked under the assumption that code can't be modified if it can't be found.

Second, we made it as difficult as possible to debug. If you've ever had to debug code that behaves differently when you trace through it, you know how much of a pain debugging can be. We used trace traps to make the code behave differently if breakpoints had been placed. The checksum helped with this, as any software breakpoints used would alter the checksum. Rebooting the debugger and the game takes time, and the more often we could force the cracker to do this, the more of their time we were wasting.

Perversely, though, the harder a crack is to make, the more fun it is for the cracker to make it. It's a challenge, and therefore fun. Paradox, the cracking group who produced the working patch for YOTD , even thanked the "Sony coders" who added such interesting protection to the game. The more difficult the crack, the more effort they will put into making it.

It's the same with the length of time it takes to produce. The longer that the game has been out without a crack, the more prestige there is in being the first to produce one. Again, this means more effort will be put into producing it.

Taking Action

Of course, all of this effort is worth nothing if the game doesn't do anything once a crack is detected, but this needs to be handled carefully. If the game just halts as soon as any modification is detected, the cracker would soon find and remove all the protection. However, if we wait too long to react, too much of the game would be playable even if an incomplete crack was used. To balance this, we used as many layers of protection as possible, which occurred at different points during the game. In YOTD we had four layers, including the copy protection.

The copy protection stopped the game very early. When this was removed, the game appeared to work for some time. We assumed that the crackers generally don't play the games they crack very much, they just play until the point where the protection they know about kicks in. Then they release a crack, believing it to be complete.

To play on this, we designed the game to break in ways that weren't immediately obvious. Most of the protection is "off-camera," affecting levels other than the one currently being played. In YOTD the object of the game is to collect eggs and gems, which are then used to open later parts of the game. The protection removed eggs and gems, so that the player could not make progress. We tried to make the game unplayable for any length of time, while at the same time making it difficult to determine exactly where things had gone wrong. If errors accumulated slowly until the game broke, the cracker would not notice such behavior so easily.

Other, more obvious protection was done less frequently. Callbacks were corrupted, which made the game crash in odd ways. The European version changed languages randomly. Some of these actions break the game and others are just an annoyance to the player, but if the game is difficult or frustrating to play because of the failed crack, this can be more effective than breaking completely.


By making the game behave in as many odd ways as possible, we hoped to cause a lot of confusion. The pirates wouldn't know if the crack didn't work, whether they had just failed to apply the crack correctly, or if the disk had failed to burn correctly. The people who didn't play a lot of the game wouldn't notice that anything was wrong and claim that the crack worked. This happens more than you would think. A lot of people pirate more out of habit than anything else, booting up the game to have a look before moving on quickly. All of this would help to delay a complete crack from being made, because no one would be sure that it was required.

The Costs
Implementing all of this protection takes time and resources away from actually developing the game. For YOTD those costs were as follows:

Programmer time. One programmer was required for three to four weeks. The programmer spent this time adding the copy protection, integrating the anticrack protection into the game, and writing tools to mask the data and generate checksums. For about six months prior to actually writing any code, some time was spent thinking of methods for protecting the game and what to do when a crack was detected. This was slightly less than two percent of the total programmer time budgeted for the game.

Game data preparation. The game data needed additional preparation before a disk could be burned. The game's WAD file had to be run through tools to generate checksums and mask data. This added about an hour to the burn cycle, making it about three hours long. The extra steps involved also made this process more prone to error, though this diminished over time as we became used to it and automated what we could.

Debugging. Any version of the game with protection included was very difficult to debug, as any software breakpoints would trigger the protection. Beyond a certain point, hardware breakpoints were turned off by the copy protection. This effectively meant that any debugging had to be done by the programmer who implemented the protection (me) on production versions of the game.

Testing. The protection was designed to produce effects almost indistinguishable from bugs, so testing was also affected. If any false positives occurred in the protection, they could be reported incorrectly. For this reason a very thorough debugging plan was produced just for the protection. Every location that could trigger protection was listed, along with how long it would take to trigger, what the exact effect would be, and where you had to look to see the effect. Testers had to visit the locations, wait the required amount of time, and then look to see if the protection had been triggered. Having any of the protection give a false positive was obviously our biggest worry. Therefore all the protection was set up on a compile-time switch so that it could be turned off at any time if we weren't absolutely sure that the protection was reliable (and believe me, there were a few moments when it didn't seem to be).

After the Crack
In the end, rather than trying to remove all the checksum code, the crackers simply found a way to bypass it. I'm not exactly sure how, but I know YOTD was vulnerable because the copy protection was only run once, at boot time. I assume the crack bypassed the copy protection and then restored the data to its original state. Any checksums performed after this point would not find any alterations (and any checksums before this were removed by the crackers).

While the protection on YOTD was reasonably effective, there were definitely things that we could have done better. If we had been able to check the data on the disk and run multiple copy protection checks, then it would have been a lot more difficult for the crackers. As I mentioned at the beginning of this article, there were practical reasons why these approaches could not be applied to YOTD . Maybe if the protection had been integrated into the game earlier, these difficulties could have been overcome.

Also, too much of the game could be played with a partial crack. This was a balancing act, though. If the protection had kicked in faster, perhaps the crackers would have realized sooner that they hadn't been successful with the first crack. But in the end, we were perhaps a little too cautious. We could have reduced the amount of the game that could be played with an incomplete crack.

What We Learned
Were all our efforts worth it? Yes. While the effects of crack protection against piracy are extremely difficult to measure, we certainly caused a great deal of confusion. Until the crack came out, YOTD was the most talked about game on the copying forums. People wasted disks, blamed the cracking teams, and claimed that the cracks that didn't work were O.K., just because they hadn't seen anything go wrong. People were saying nasty things about Insomniac and Sony because they couldn't "back up" the game. Some people even thought it was funny when the fairy character, who normally offers players helpful advice, instead told them they were playing a modified game. There is also an effect on future piracy to consider: at the very least we made a few people think twice about buying a cheap copy of a game.

We've gained valuable knowledge about what works and what doesn't. Layering protection that doesn't kick in immediately is definitely a very effective protection. If nobody thinks a crack is required, they won't be working on one. Even when they do work on the crack, it takes them longer. The crackers apparently spent quite some time play-testing YOTD before they released the final crack, just to make sure they didn't get burned twice.

Unfortunately, the crack protection is weaker once the copy protection has been run. The cracker only needs to remove the code that runs the copy protection. Once it has been run, the original code can be restored, and the checksum will be correct. If this is only in one place, it is easier to attack. To combat this, the copy protection needs to be run as often as practical from independent copies of the code.

If there is space, put multiple copies of the game data on the disk. The cracker will have to find out which one is used or alter them all. Either way, you've slowed them down. An extension to this would be to actually use multiple copies of the data, either loading a random selection or loading using a pattern based on when the data is being loaded. If some of the copies are masked differently and some are never used, the cracker will have to find and alter them all to ensure that the crack is complete.

Even better than masking the data is compressing it, which offers many advantages over simple masking. The relationship between compressed and uncompressed data is much less obvious, the file sizes are different, and any cracked data has to be compressed or else it won't fit back on the disk. This means the cracker has to find out what compression was used, and if you customize the algorithm for your data, they may have to write a compression program just to be able to make the crack.

Looking back at the choices we made, we could have implemented multiple copy-protection checks throughout the course of the game. Unfortunately, this isn't always possible or practical, depending on the method of protection used (especially if minimizing load times is a primary concern). An alternative is to check the source data on the disk. Of course you can't check the entire disk, but all the executables can be checked, along with the table of contents and boot information. This is something YOTD failed to do and is probably how it was cracked.

Reality Check
We may not be able to stop the pirates, but we can have enough of an impact to make pirating a much less attractive option. Given the choice of buying a game or waiting two to three months for a pirated version, a lot of pirates are going to start buying games. Or at least they'll buy their favorite ones.

There is also an advantage in numbers; the more games that add effective protection, the greater the benefit is for all games. Crackers have limited resources, and the longer that they're tied up on each game, even if it's only for a few weeks, the fewer cracks they can produce.

Games that implement just a standard copy protection scheme can be cracked in less than a day. Sometimes a tool is even available which does it in seconds. Any game that takes longer than this because of added protection will be put in line until the cracker has time to deal with it. The longer that line is, the longer it will take for any given game to be cracked. The trick is to keep your game from reaching the front of that line for as long as possible.

https://www.gamasutra.com/view/feature/131439/keeping_the_pirates_at_bay.php
 
Top