HOW TO HACK

By Jon North

Sinclair ZX Spectrum
ISSUE 58
As has been promised to you for months, this issue I will be showing you how to crack the Firebird Bleepload. So stand by your disassemblers - this is going to be tricky.
The First Stage
As with any protection system, you will need a copy of a game with the Bleepload on it (cracking it may be a bit difficult otherwise). As an example, I will be cracking Beach Buggy, but all the other Bleepload games are almost identical, so any one will do.
The Basic Bit
First off, *Load the basic loader:
Buggy LINE 10 LEN 179
When *Loaded, *List it:

10 REM
20 CLEAR 25500
30 BORDER 0: PAPER 0: INK 0: CLS
40 PRINT AT 1,9; PAPER 1; INK 7;" BEACH BUGGY "
50 LOAD "Buggy1"CODE 52480
60 RANDOMIZE USR 52480
The Loader (The Juicy Bit)
Load the next block (the loading system) into 52480 and disassemble it. 52480 is CD00 hex. Following the code down from CD00, we see a JP (HL) at CD58. Normally you would put a breakpoint over the JP, but JP (HL) is a 1-byte instruction, and a breakpoint takes 3 bytes. What you do in this situation is put a breakpoint over the previous instruction, as long as you have 3 spare bytes. The first instruction you can do this on is the LD (FF15),A at CD54. Put a breakpoint here and JP to CD00. When control returns to the disassembler, inspect the Z80 registers to find the value of HL (ie, where the JP will JP to). It is FF0A; disassemble this and we see it holds the instruction JP CD1B, which will go back and load another block. Put a breakpoint at CD1B and continue (so you can now put a second breakpoint at CD54).
The next time control returns, HL=FF06 which is again another JP CD1B. This will keep going on forever, or until HL holds an instruction other than JP CD1B. Rather than repeating the procedure of running and executing breakpoints, we will write a simple routine which will do it for us.

LD (FF15),A
INC HL
LD A,(HL)
DEC HL
CP 1B
RET Z
Taking one instruction at a time:
LD (FF15),A is simply a copy of the 3 bytes we are overwriting (at CD54) by passing control to our routine.
INC HL makes HL equal to the address of the first of the two bytes of the JP address (HL originally holds the value of an address containing C3, which is Z80 code for JP)
LD A,(HL) makes A equal to the contents of HL (remember the brackets), i.e. the first byte of the JP address.
DEC HL returns HL to its original value.
CP 1B stands for ComPare 1B, i.e. does A equal 1B?
RET Z stands for RETurn if Zero, i.e. return back to the loader if A=1B. This routine can be placed anywhere in memory, but I will put it at CCA0, because it is close to the loader and so is unlikely to get loaded over. It is possible that it could, in which case we would have to start again, but putting the routine somewhere else.
The final stage is to put a CALL CCA0 at CD54 (in place of the breakpoint) and return control to the loader. Control is returned to the disassembler after 2E has loaded. HL is FF08, which reads JP 5D00. Disassemble this:

5D00 PUSH IX
5D02 CALL CD6E
5D05 CALL CE2A
5D08 CP (HL)
5D09 JR Z,5D12
5D0B LD B,0
5D0D CALL CE7E
5D10 JR 5D02
5D12 DI
5D13 POP HL
5D14 LD L,0
5D16 LD DE,(FEE7)
5D1A LD A,(DE)
5D1B XOR (HL)
5D1C INC H
5D1D XOR (HL)
5D1E DEC H
5D1F LD (DE),A
5D20 INC L
5D21 INC E
5D22 JR NZ,5D1A

5D00-5D10 looks like it will load another block (CD6E, CE2A and CE7E are all in the loading system).
The routine 5D1A-5D23 is a decrypter, which you can see by the use of brackets in LD A,(DE) and, more importantly, LD (DE),A. However, we do not know where it decrypts, as DE has a value of the contents of FEE7 and FEE8 (which may be loaded in that last block), so put a breakpoint at 5D1A and JP CD57 (this is where we broke control from the loading system, and so is where control needs to be returned to.
Rule number one: always cover your tracks!)
When control comes back to you, DE=C900. The decrypter finishes when E=0, so this decrypter changes the code from C900-C9FF, and DE will equal CA00 after it. Continuing the disassembly:

5D24 LD DE,(FEE7)
5D28 LD HL,5D40
5D2B LD A,(DE)
5D2C XOR (HL)
5D2D LD (HL),A
5D2E INC E
5D2F INC L
5D30 JR NZ,5D2B
5D32 LD HL,0
5D35 LD (5CB0),A
5D38 LD A,2
5D3A LD (5C6B),A

This is all that can be disassembled at this stage, because the routine 5D24-5D31 decrypts 5D40-5DFF. Put a breakpoint at 5D3A and continue.

5D3D LD DE,(FEE7)
5D41 LD HL,(FEE9)
5D44 LD A,(DE)
5D45 XOR (HL)
5D46 LD (HL),A
5D47 INC HL
5D48 LD B,B
5D49 JR NZ,5D44
5D4B LD A,(FEEC)
5D4E CP H
5D4F JR NZ,5D44
Before we carry on the disassembly, put a breakpoint at 5D44 and continue, because HL=(FEE9) which could be a couple of bytes after the decrypter. When control returns, however, HL=CF00 which is nowhere near the area in memory we are concentrating on. Therefore, although we didn't need to put a breakpoint there, at least we definitely know we are safe.

5D51 LD HL,CF00
5D54 LD DE,4000
5D57 LD BC,1B00
5D5A LDIR
5D5C LD HL,EA00
5D5F LD DE,6300
5D62 LD BC,1000
5D65 LDIR
5D67 LD A,3D
5D69 LD BC,7
5D6C LD DE,6
5D6F CALL FA00
5D72 LD SP,63BF
5D75 EI
5D76 CALL 28E
5D79 JR Z,5D98
5D7B LD A,D
5D7C SUB E
5D7D CP 21
5D7F JR NZ,5D98
5D51-5D66 moves a couple of chunks of code around (including the screen)
5D67-5D71 must obviously load the rest of the game (it is the only CALL to somewhere other than the ROM)
5D72-5D80 sets up the stack and interrupts (unimportant as far as we are concerned) and JP to 5D98 (in the unlikely event that the JR at 5D79 is ignored, the one at 5D7F will definitely be executed). Disassembling 5D98 (where it JPs to)
5D98 JP B1FB
That's it! We've cracked Bleepload! You can move the POKEs you've got to 5D98 from your hacking routine, and end them with a JP B1FB to start the game. Or, if you're actually hacking the game, you can put the NEW routine I gave you last month at 5D98, so the game will load and then NEW, so enabling you to hack it.
Wasn't that exciting? Your very first "commercial" crack. Today, Bleepload... tomorrow, Barclays - who knows? If you don't, or aren't sure whether you do or not, drop a line to Jon North, H2H, YS, 30 Monmouth Street, Bath, Avon BA1 2AP. Enclose an SAE and you'll certainly get a reply; don't and you certainly won't. Catch you next month.
Sinclair ZX Spectrum

  Previous Page Back Next Page