HOW TO HACK

By Jon North

Sinclair ZX Spectrum
ISSUE 66
This month sees the first of a few "one-off" protection systems, which are those you'll only find on one particular game. The particular game needed for this month's HTH is MoonStrike by Mirrorsoft, which was protected by MovieLoad - perhaps the hardest protection system yet covered in this column.
The First Basic Bit
Follow the usual procedure of *Loading and *Listing.
MOONSTRIKE LINE 0 LEN 395 0 REM 1 PAPER 0: INK 0: POKE 23624,70: CLEAR 27013: PRINT #0;" PLEASE DO NOT BE ALARM ED BY "''"ANYTHING STRANGE THAT MAY OR MAY"''" NOT HAPPEN. THIS IS A PRODUCT "'  '" OF A DERANGED IMAGINATION."'" ";#2;AT 8,0;: RANDOMIZE USR 23760: LOAD ""
That USR 23760 loads the headerless block that follows and does the bit of funky animation (pretty, isn't it?). The only thing you need to worry about in all the code loaded so far is the LOAD "" at the end, which loads the second bit of basic.
Loading The Second Bit
First of all, try doing a standard *Load. It'll load the header, then return back to basic with an error. The reason for this is that the filename is taken up by strange control characters, which stop anything being printed after them (like the LINE and LEN messages). To overcome this, take a look in the *Load code for a 215 (there's only one), and replace it with a 0. This stops the routine printing the filename, so it only prints the start line and length of the basic block. Now try it again.
LINE 0 LEN 2410
You can now *List in the usual way.
0 ,X POKE 23614.081,PEEK 23627.319: POKE 23613.433,PEEK 23627.679: POKE 23624 .2,PEEK 23605.71: POKE 23692.669,PEEK 23624.011: PRINT "NASTYLOAD": RANDOMIZE US R 2.8881517E+34^ IF YOU ENJOY DIFFICULT TASKS, ATTEMPTING TO HACK THIS PROGRAM WILL ELECTROCUTE YOUR PLEASURE CENTRES-1.3412728E+30R"AT ASCREEN$ CLEAR -1.0578 132E-19<; OR CHR$ lATN FOR SCR.....
Don't be put out by that weird code at the start, it doesn't actually do anything. This basic starts the machine code in a similar way to Speedlock 1 - it sets a specific value for ERRSP (with the POKE 23613 and 23614's) then creates an error with that dodgy USR call. But what has ERRSP been set to? Try PRINT PEEK 23627. Now try it again. Spot the difference? That's because Basic has been told, by a dodgy header, that the program is longer than it actually is, with the result being that trying to find out values to do with the basic program are impossible. Hmmmmm. The way to overcome this is to type directly, RANDOMIZE USR 3E4: RANDOMIZE USR DIS where "dis" is replaced by the address of your disassembler. When you enter the disassembler, you are no longer affecting Basic, so you can find the values of 23627 and 23628 (5C4B and 5C4C hex). Bear in mind that you want the value of PEEK 23628+256*PEEK 23627 (ie the MSB becomes the LSB and vice versa) because of the POKEs in the Basic program.

PEEK 23627 is 5D and PEEK 23628 is E5, so ERRSP is set to 5DE5. PEEK 5DE5 is 73 and PEEK 5DE6 is 5D, so the return address is 5D73. Now, in a similar way to cracking the basic in Speedlock 1, you need to put a breakpoint in at 5D73, then GOTO 0 so that the registers have their correct values. Unfortunately, you can't. Not directly, anyway, because as soon as you type something in in Basic, all the values of the all-important system variables (particularly VARS at 23627 and 23628) go crazy. What you need to do is load the basic as a headerless file to 8CCB (ie LD IX with #8CCB and DE with 2410), then return to your disassembler and put a breakpoint at 8D73. Now resave this new block of basic as a headerless file (use the same routine as a headerless load but the call is to #04C2, not #0556). Now load the header from the original basic, then, when it's loaded ("Program:" on the screen), stop the tape and load in your new basic. It will load and control will pass to the disassembler.
Making A Start
Now that the basic's been cracked, we can start on the machine code. The all-important register values you should have at this point are:

A'=7E
BC'=0008
DE'=5D49
HL'=663B
A=D1
BC=0D4E
DE=4EF4
HL=663B
IX=6635
IY=5C3A SP=5DE9

A lot of the ideas in this protection system were nicked from Speedlock 1 (as you may have noticed by now). 5D73, where the machine code starts, is the middle of a message. There is a lot of useless crap in this loader, but it is all executed, and you need to know the register values at the end of it because they're decrypted with.

5D73 DEFM "ICULT.TASKS,.ATTEMPTING.TO.HACK.THIS.PROGRAM.WILL.ELECTROCUTE.YOUR.PL EASURE.CENTRES"
5DC6 LD L,80
5DC8 ADC A,A
5DC9 LD SP,#1F40
5DCC LD E,L
5DCD LD IXL,#41
5DD0 DI
5DD1 LD R,A
5DD3 DEFB #FD
5DD4 LD B,#8D
5DD6 LD E,#40
5DD8 LD IYL,#22
5DDB LD HL,#F81D
5DDE LD IXH,#16
5DE1 JR NZ,#5DE7
5DE7 DJNZ #5DE7
5DE9 LD BC,#07C4
5DEC LD D,#F9
5DEE DEC IXH
5DF0 LD A,B
5DF1 EXX
5DF2 LD B,A
5DF3 LD H,#5E
5DF5 LD E,A
5DF6 LD C,#E5
5DF8 ADD A,A
5DF9 LD L,A
5DFA LD D,#F8
5DFC LD D,D

So far, all the code has been crap. But it's been crap which has altered the registers. The decrypter which follows uses the new values for HL, DE and BC, which are 5E0E, F807 and 07E5 respectively. Your value for R (which you have to keep track of) should be 82.

5DFD LD A,(HL)
5DFE XOR H
5DFF SUB B
5E00 RLCA
5E01 XOR D
5E02 ADC A,C
5E03 LD IYL,#22
5E06 LD (HL),A
5E07 LDI
5E09 LD IYH,#23
5E0C CALL PE,#5DFD

Note that this decrypter changes it's last byte, and note also that, at the end of it, the stack is in the ROM. The easy way out is to move it somewhere and, after the necessary code to keep track of R, do something along the lines of LD (#6000),SP: LD SP,7000: . When control returns, examine (6000) and (6001) to find the value of SP (which should be 0F78).

5E0F EXX
5E10 CALL NZ,#F815
For this decrypter, HL should be F81D and BC should be 07C4. These are the only two values obviously necessary at this stage, but afterwards, SP should be FFF0 and R should be DF.

F815 LD A,#1F
F817 RRD
F819 CPI
F81B CALL PE,#F817
F81E DEC E
F81F JR NZ,#F829
F829 EXX
F82A LD HL,#5900
F82D LD DE,#5901
F830 LD BC,#9F26
F833 LD (HL),L
F834 LDIR

Rip this LDIR out by POKEing F82E with 0 (so that HL=DE). Afterwards, simply add one to the value in DE.

F836 EX DE,HL
F837 LD D,(HL)
F838 DEC D
F839 INC HL
F83A LD E,(HL)
F83B RRC HL
F83D EX DE,HL
F83E LD C,#19
F840 LDIR
F842 EXX
F843 DEFM "#25-.IF.YOU.DON'T.STOP.HACKING.INTO.MY.SACRED.PROTECTION.SYSTEM,.I.WI LL.GET.A.LARGE.AXE.AND.GIVE.YOU.A.HACKING.YOU.WILL.NEVER.FORGET.!.."
F8CB DEC B
F8CC RLC B
F8CE DEC B
F8CF LD A,E
F8D0 LD E,B
F8D1 AND #36
F8D3 LD B,A
F8D4 LD A,H
F8D5 SUB B
F8D6 LD D,A
F8D7 LD A,L
F8D8 SUB B
F8D9 LD H,D
F8DA DEC A
F8DB LD C,A
F8DC LD L,B
F8DD DEC L

Now there follows the third decrypter. The values needed are

HL=F905
DE=F93F
BC=06DC
R=85
F8DE RLC (HL)
F8E0 RLC (HL)
F8E2 RLC (HL)
F8E4 RLC (HL)
F8E6 RLC (HL)
F8E8 LD A,C
F8E9 ADD A,(HL)
F8EA XOR L
F8EB LD (HL),A
F8EC LD A,R
F8EE ADD A,(HL)
F8EF RLCA
F8F0 XOR B
F8F1 LD (HL),A
F8F2 RRD
F8F4 LD A,(HL)
F8F5 RRA
F8F6 JR C,#F8F5
F8F8 AND #07
F8FA INC A
F8FB DEC A
F8FC INC A
F8FD DEC A
F8FE JR NZ,#F8FB
F900 LD A,B
F901 CPI
F903 OR C
F904 JR NZ,#F8E4
F906 LD A,(DE)
F907 EX (SP),HL
F908 LD H,A
F909 RRCA
F90A INC DE
F90B LD L,A
F90C LD A,(DE)
F90D EXX
F90E ADD A,(HL)
F90F EXX
F910 SUB L
F911 LD L,A
F912 EX (SP),HL
F913 INC SP
F914 INC SP
F915 INC DE
F916 EX (SP),HL
F917 EX DE,HL
F918 XOR (HL)
F919 RLCA
F91A INC HL
F91B SUB (HL)
F91C LD D,A
F91D INC HL
F91E RLCA
F91F XOR (HL)
F920 LD E,A
F921 INC HL
F922 EX DE,HL
F923 EX (SP),HL
F924 EX DE,HL
F925 ADD A,(HL)
F926 LD B,A
F927 INC HL
F928 RRCA
F929 SUB (HL)
F92A RRCA
F92B LD L,A
F92C LD H,B
F92D RLCA
F92E DJNZ #F92D
F930 EX DE,HL
F931 EXX
F932 DEC (HL)
F933 INC HL
F934 RLC (HL)
F936 INC HL
F937 RRC (HL)
F939 INC HL
F93A DEC (HL)
F93B EXX
F93C JP #FF50
FF50 INC B
FF51 RL H
FF53 ADD HL,DE
FF54 LD A,(DE)
FF55 XOR (HL)
FF56 ADD A,B
FF57 DEFM "#24-.GO.AWAY.BEFORE.I.GET.REALLY.NASTY.!"
FF7D LD D,#21
FF7F DEC B
FF80 RRCA
FF81 LD C,A
FF82 LD A,D
FF83 ADC A,H
FF84 RR B
FF86 LD E,B
FF87 LD H,A
FF88 SBC L
FF89 RRA
FF8A LD L,A
FF8B AND #8F
FF8D LD B,A
FF8E SBC H
FF8F NEG
FF91 LD C,A
FF92 CCF
FF93 RRA
FF94 ADC A,D
FF95 LD D,C
FF96 INC D
FF97 LD C,A
For this next decrypter,
HL=F946
DE=F47F
BC=69B
R=8F

The address at (SP) is FA51 and that at (SP-2) is FF98. To crack it, simply change the address at (SP), ie (FFF2) and (FFF3) to something convenient. This is the RET PO address, which is RETed to on completion of the decrypter. Otherwise, FF98 (from SP-2) is RETed to and another byte is decrypted. This is similar in principle to the recent Speedlock decrypter, which had a RET PO to jump out.

FF98 LD A,(HL)
FF99 EX DE,HL
FF9A LD (HL),A
FF9B RLC (HL)
FF9D DEC (HL)
FF9E RLC (HL)
FFA0 RLC (HL)
FFA2 LD A,R
FFA4 SUB (HL)
FFA5 LD (HL),A
FFA6 RRD
FFA8 AND B
FFA9 RRA
FFAA JR C,#FFA9
FFAC AND #0E
FFAE DEC A
FFAF DEC A
FFB0 JR NZ,#FFAE
FFB2 CPI
FFB4 INC DE
FFB5 EX DE,HL
FFB6 RET PO
FFB7 DEC SP
FFB8 DEC SP
FFB9 RET PE
FA51 EXX
FA52 LD DE,#0000
FA55 LD HL,#FA84
FA58 LD BC,#0589
FA5B LDDR
FABD LDD
FABF RET PO
FAC0 LD H,#18
FAC2 LD DE,#FFF2
FAC5 LD B,#00
FAC7 LDDR
FAC9 POP HL
FACA POP DE
FACB LD BC,#001E
FACE LDIR
FAD0 LDD
FAD2 EXX
FAD3 RET PE
F9D9 LD A,(BC)
F9DA LD B,A
F9DB RLCA
F9DC SBC HL,BC
F9DE NEG
F9E0 INC A
F9E1 RRA
F9E2 ADD A,B
F9E3 DEFM "#23-.GO.AHEAD,.MAKE.MY.DAY"
F9FD JR NZ,#FA00
FA00 RRCA
FA01 DEC A
FA02 LD C,A
FA03 LD A,B
FA04 RRA
FA05 ADC A,H
FA06 INC A
FA07 INC A
FA08 LD L,A
FA09 AND #83
FA0B INC SP
FA0C ADC A,L
FA0D LD E,A
FA0E LD A,D
FA0F SBC #08
FA11 LD D,A
FA12 INC A
FA13 LD H,A
FA14 CPL
FA15 RRA
FA16 LD B,A
FA17 INC SP

This decrypter uses values HL=F47F, DE=F382, BC=055A, R=8C. The RET PO should be to FA34 (which you should change to retain control) and the RET PE should be to FA18 (to loop back and do the next byte).

FA18 LD A,R
FA1A RRC (HL)
FA1C INC (HL)
FA1D RRC (HL)
FA1F INC A
FA20 SUB (HL)
FA21 LD (HL),A
FA22 AND A
FA23 RLA
FA24 JR C,#FA23
FA26 OR #E0
FA28 INC A
FA29 JR NZ,#FA28
FA2B LDI
FA2D RET PO
FA2E DEC SP
FA2F DEC SP
FA30 RET PE
FA34 DEC E
FA35 JR NC,#FA39
FA39 LD A,D
FA3A JR NZ,#FA3E
FA3E RRA
FA3F JR #FA43
FA43 LD D,E
FA44 JR NC,#FA48
FA48 LD E,A
FA49 JR NZ,#FA4C
FA4C DEC E
FA4D DEC H
FA4E RET NZ
F382 SBC HL,DE
F384 LD A,#01
F386 RLCA
F387 RRA
F388 DEFM "#22-.I'M.NOT.GETTING.YOU.DOWN,.AM.I?.I.WOULD.HATE.TO.THINK.I.WAS.GETT ING.YOU.DOWN..."
F3DC RL H
F3DE RL H
F3E0 RL H
F3E2 RR B
F3E4 DEC B
F3E5 DEC B
F3E6 LD A,H
F3E7 ADC A,B
F3E8 LD H,A
F3E9 DEC H
F3EA CPL
F3EB INC A
F3EC LD L,A
F3ED LD D,H
F3EE LD E,#08
F3F0 LD A,#D1
F3F2 LD C,A
F3F3 XOR #BF
F3F5 AND #95
F3F7 LD B,A
F3F8 PUSH DE

You're now dangerously close to cracking MovieLoad!

HL=F40B
DE=F408
BC=04D1
R=D3
The RET PO is to F408.
F3F9 LD A,R
F3FB RLC (HL)
F3FD ADD A,(HL)
F3FE LD (HL),A
F3FF AND A
F400 RRA
F401 JR C,#F400
F403 LDI
F405 RET PO
F406 JR #F3F9
F408 EXX
F409 IN A,(#1F)
F40B LD L,A
F40C DEC SP
F40D DEC SP
F40E POP DE
F40F IN A,(#FB)
F411 LD H,A
F412 DEC E
F413 JR NZ,#F40F
F415 INC E
F416 IN A,(#EF)
F418 INC D
F419 JR NZ,#F40F
F41B LD E,A
F41C IN A,(#F7)
F41E LD D,A
F41F LD A,I
F421 LD C,A
F422 EXX
F423 LD HL,#F8AD
F426 PUSH HL
F427 LD HL,#C8CA
F42A LD DE,#C8CB
F42D LD BC,#2B67
F430 LDIR
F432 RET
F8AD CALL #F694
F8B0 PUSH IX
F8B2 POP HL
F8B3 LD A,(HL)
F8B4 INC HL
F8B5 XOR (HL)
F8B6 INC HL
F8B7 LD E,A
F8B8 RLCA
F8B9 RLCA
F8BA XOR (HL)
F8BB LD D,A
F8BC DEC SP
F8BD DEC SP
F8BE POP HL
F8BF SBC HL,DE
F8C1 JP NZ,#F5D3
F8C4 PUSH HL
F8C5 POP IX
F8C7 CALL #F694
F8CA LD DE,#30DA
F8CD ADD IX,DE
F8CF LD E,(HL)
F8D0 INC HL
F8D1 LD D,(HL)
F8D2 LD A,#01
F8D4 OUT (#FE),A
F8D6 JP #F8A1
As could perhaps be expected, the JP at F8D6 is to the game. Change it to 65000ish to bung your pokes in.
       
  ORG 33000  
LOAD LD IX,#5CCB  
  LD DE,2410  
  LD A,#FF  
  SCF    
  CALL #556  
  JR NC,LOAD  
  DI    
  LD SP,33000  
  LD HL,#5E0C  
  LD (HL),#C9  
  INC HL  
  INC HL  
  LD DE,#F807  
  LD BC,#7E5  
DCR1 CALL #5DFD  
  JP PE,DCR1  
  LD HL,#F81B  
  LD (HL),#C9  
  INC HL  
  INC HL  
  LD BC,#7C4  
  LD A,#1F  
DCR2 CALL #F817  
  JP PE,DCR2  
  LD HL,#F8DE  
  LD DE,#A000  
  LD BC,39  
  LDIR    
  EX DE,HL  
  LD (HL),222  
  INC HL  
  LD (HL),#C9  
  LD HL,#F905  
  LD BC,#6DC  
  LD A,#84  
  LD R,A  
DCR3 CALL #A000  
  LD SP,STACK  
DCR4 POP HL  
  POP DE  
  POP BC  
  LD A,#8E  
  LD R,A  
  RET    
DCR5 POP HL  
  POP DE  
  POP BC  
  LD A,#8B  
  LD R,A  
  RET    
DCR6 POP HL  
  POP DE  
  POP BC  
  LD A,#D2  
  LD R,A  
  CALL #F3F9  
  LD HL,POKES  
  LD DE,65000  
  LD BC,END-POKES  
  LD (#F8D7),DE  
  LDIR    
  LD SP,0  
  JP #F408  
STACK DEFW #F946,#F47F,#69B,#FF98,DCR5  
  DEFW #F47F,#F382,#55A,#FA18,DCR6  
  DEFW #F40B,#F408,#4D1  
POKES LD A,#C9  
  LD (#98ED),A  
  JP #F8A1  
END EQU $  
Sinclair ZX Spectrum

  Previous Page Back Next Page