Xor (Hacking Tips #12)

By Mr. Spock

Originally published in EUG #71

Xor - a Kevin Edwards loader. Disassembly of XOR2 with comments.

0400 LDA #3    \Disable escape & clear break
0402 STA &0258 \*FX200,3 equivalent
0405 LDA #15   \clear keyboard buffer
0407 LDX #0    \*FX15,0
0409 JSR OSbyte
040C JMP &04E2 \continue execution at &4E2

This next dump is just a copyright message and some asterisks to fill up memory - not used for decryption etc.

0408 ** ** ** ** ** ** ** 50        P
0410 72 6F 74 65 63 74 69 6F rotectio
0418 6E 20 28 63 29 20 4B 65 n (c) Ke
0420 76 69 6E 20 45 64 77 61 vin Edwa
0428 72 64 73 20 31 39 38 37 rds 1987
0430 2A 2A 2A 2A 2A 2A 2A 2A ********
0438 2A 2A 2A 2A 2A 2A 2A 2A ********
0440 2A 2A 2A 2A 2A 2A 2A 2A ********
0448 2A 2A 2A 2A 2A 2A 2A 2A ********
0450 2A 2A 2A 2A 2A 2A 2A 2A ********
0458 2A 2A 2A 2A 2A 2A 2A 2A ********
0460 2A 2A 2A 2A 2A 2A 2A 2A ********
0468 2A 2A 2A 2A 2A 2A 2A 2A ********
0470 2A 2A 2A 2A 2A 2A 2A 2A ********
0478 2A 2A 2A 2A 2A 2A 2A 2A ********
0480 2A 2A 2A 2A 2A 2A 2A 2A ********
0488 2A 2A 2A 2A 2A 2A 2A 2A ********
0490 2A 2A 2A 2A 2A 2A 2A 2A ********
0498 2A 2A 2A 2A 2A 2A 2A 2A ********
04A0 2A 2A 2A 2A 2A 2A 2A 2A ********
04A8 2A 2A 2A 2A 2A 2A 2A 2A ********
04B0 2A 2A 2A 2A 2A 2A 2A 2A ********
04B8 2A 2A 2A 2A 2A 2A 2A 2A ********
04C0 2A 2A 2A 2A 2A 2A 2A 2A ********
04C8 2A 2A 2A 2A 2A 2A 2A 2A ********
04D0 2A 2A 2A 2A 2A 2A 2A 2A ********
04D8 2A 2A 2A 2A 2A 2A 2A 2A ********
04E0 2A 2A ** ** ** ** ** ** **

04E2 SEI       \Disable interrupts
04E3 LDX #255  \Stack pointer=255 ie lose all
04E5 TXS       \previous return addresses
04E6 INX       \X=0
04E7 LDA #3    \disable Escape and clear memory on break
04E9 STA &0258 \*FX200,3 equivalent
04EC LDA #75   \Store some numbers in
04EE STA &70   \which are used for decryption 
04F0 LDA #69   \in &70 -
04F2 STA &71
04F4 LDA #86
04F6 STA &72
04F8 LDA #73
04FA STA &73
04FC LDA #78
04FE STA &74   \ &74

0500 LDA &0500 \beginning of loop that decrypts
0503 EOR &70   \next part of loader
0505 INC &0511
0508 EOR &72
050A INC &71
050C INC &71
050E EOR &71
0510 EOR #237
0512 EOR &0600,X
0515 LDY &74
0517 STY &051B \replaces #236 in next line
051A EOR #236
051C EOR &0601,X
051F EOR &73
0521 STA &0600,X
0524 LDA &73
0526 EOR &74
0528 STA &73
052A SEC
052B ADC #244
052D STA &74
052F EOR &0511 \see 0510 EOR #237
0532 STA &72
0534 LSR A
0535 EOR &74
0537 STA &70
0539 INX
053A BNE &0500
053C LDY #3
053E STY &0258
0541 INC &0501
0544 BNE &0500 \loop till all done
0546 BEQ &058E \go to next part of loader

This is more junk to fill up space:

0548 2A 2A 2A 2A 2A 2A 2A 2A ********
0550 2A 2A 2A 2A 2A 2A 2A 2A ********
0558 2A 2A 2A 2A 2A 2A 2A 2A ********
0560 2A 2A 2A 2A 2A 2A 2A 2A ********
0568 2A 2A 2A 2A 2A 2A 2A 2A ********
0570 2A 2A 2A 2A 2A 2A 2A 2A ********
0578 2A 2A 2A 2A 2A 2A 2A 2A ********
0580 2A 2A 2A 2A 2A 2A 2A 2A ********
0588 2A 2A 2A 2A 2A 2A ** ** ******

058E LDA #0
0590 STA &70
0592 STA &71 
0594 TAY        \Y=0
0595 LDA &71
0597 EOR &0600,Y
059A STA &71
059C LDX #8
059E LDA &71
05A0 ROL A
05A1 BCC &05AF
05A3 LDA &71
05A5 EOR #8
05A7 STA &71
05A9 LDA &70
05AB EOR #16
05AD STA &70
05AF ROL &70
05B1 ROL &71
05B3 DEX
05B4 BNE &059E
05B6 INY
05B7 CPY #20
05B9 BNE &0595
05BB LDA &70
05BD CMP &06FE
05C0 BNE &05D6
05C2 LDA &71
05C4 CMP &06FF
05C7 BEQ &0600 \if bytes match checksum goto &600
05C9 BNE &05D6 \else loop forever

Some more scrap - including a hello message

05C8 37 D0 0B 48 69 20 42 54 7..Hi BT
05D0 57 20 2E 2E 2E 2E ** ** W ....

Code executed if checksums don't match, see &5BD-&5C9

05D6 LDA #200   \disable Escape and clear memory on break
05D8 LDX #3 
05DA JSR OSbyte
05DD INY        \freeze machine by
05E0 JMP &05DD  \looping forever!

Another copyright message:

05E0 ** ** ** ** 20 28 63 29      (c)
05E8 20 4B 65 76 69 6E 20 45  Kevin E
05F0 64 77 61 72 64 73 20 31 dwards 1
05F8 39 38 37 20 20 20 20 20 987     

The next part is revealed when decrypted (see XORZAP at the end of the article). Instead of JMPing to an address to execute the game, note the pushing of the execute address (&28FF) onto the stack and then RTSing at the end of it all.

0600 LDX #&C5  \set stack pointer
0602 TXS 
0603 LDA #&28  \push values onto stack
0605 PHA 
0606 LDA #&FF  \&28FF is the execution address for game
0608 PHA 
0609 LDA #&56  \these are values
060B PHA
060C LDA #&DE  \used in the decryption routine
060E PHA
060F LDX #&35    \check vectors at &234/5 &232/3 etc.
0611 LDA &0200,X \If any have been altered ie poked by
0614 BPL &05DD   \would-be pirate the high byte will be
0616 DEX         \+ve high byte so go to loop forever routine
0617 DEX
0618 BPL &1611
061A LDA #0
061C TAY         \Y=0
061D STA &0600,Y \erase part of program at &600
0620 INY 
0621 CPY #&1D    \to &61C
0623 BNE &161D
0625 CLI         \reenable interrupts
0626 LDA #140    \Select cassette filing system
0628 LDX #12     \*FX140,12 or *TAPE
062A JSR OSbyte  \equivalent
062D LDX #&B8    \star command at
062F LDY #&06    \&6B8
0631 JSR OScli   \*LOAD game file
0634 SEI
0635 LDA #3    \disable Escape and clear memory on Break
0637 STA &0258 \*FX200,3 equivalent  
063A LDY #0
063C LDX #&4A  \decrypt &4A pages of game code
063E PLA       \A=&DE
063F STA &70   \?&70=&DE
0641 STA &71   \?&71=&DE
0643 PLA       \A=&56
0644 STA &72   \?&72=&56
0646 LDA &0E00,Y   \This address inc'd at &66C
0649 EOR &70       \
064B DEC &71       \The routine to decrypt the game code
064D EOR &71
064F EOR &72
0651 STA &0E00,Y   \This address inc'd at &66F
0654 INC &72
0656 LDA &72
0658 SEC 
0659 SBC #95
065B EOR &71
065D STA &72
065F EOR &70
0661 STA &70
0663 EOR #228
0665 STA &71
0667 EOR &72 
0669 INY
066A BNE &0646
066C INC &0648
066F INC &0653
0672 DEX         \loop until page count
0673 BNE &0646   \is zero
0675 CLI         \reenable interrupts
0676 LDX #&77    \erase code
0678 STA &0600,X \
067B DEX         \at &600-&677
067C BNE &0678   \
067E RTS         \return to address on stack - &28FF

More junk to fill up space:

0678 ** ** ** ** ** ** ** 2A        *
0680 2A 2A 2A 2A 2A 2A 2A 2A ********
0688 2A 2A 2A 2A 2A 2A 2A 2A ********
0690 2A 2A 2A 2A 2A 2A 2A 2A ********
0698 2A 2A 2A 2A 2A 2A 2A 2A ********
06A0 2A 2A 2A 2A 2A 2A 2A 2A ********
06A8 2A 2A 2A 2A 2A 2A 2A 2A ********
06B0 2A 2A 2A 2A 2A 2A 2A 2A ********

The OScli string:

06B8 4C 2E 47 41 88 80 BA 47 L.GA...G
06C0 20 45 30 30 0D ** ** **  E00.

And Kevin finally admits defeat:

06C0 ** ** ** ** ** 50 72 6F  E00.Pro
06C8 74 65 63 74 69 6F 6E 20 tection 
06D0 28 63 29 20 4B 65 76 69 (c) Kevi
06D8 6E 20 45 64 77 61 72 64 n Edward
06E0 73 20 31 39 38 37 20 59 s 1987 Y
06E8 6F 75 20 74 6F 6F 6B 20 ou took 
06F0 79 6F 75 72 20 74 69 6D your tim
06F8 65 20 21 20 E5 E5 F6 58 e ! ...X

06FE EQUB &96 \checksum bytes for routine at &5BB-&5C9
06FF EQUB &B2 \in encrypted state

This is a program to 'zap' the loader. XOR2 must be on disc. It will patch, execute and save out a decrypted version of XOR2 under the name XOR2Z. The 'zapped' code from &600 onwards can then be inspected with a disassembler.

   10 REM XOR loader zapper By Mr Spock
   20 oscli=&FFF7
   30 P%=&900
   40 [
   50 .c1:EQUS"L.XOR2 400"+CHR$&D
   60 .c2:EQUS"SAVE XOR2Z 400+301"+CHR$&D
   70 .go
   80 LDX#c1 MOD256:LDY#c1 DIV256:JSRoscli
   90 \RTS before too late
  100 LDA#&60:STA&5BB
  110 \Execute patched code
  120 LDX#0:JSR&4EC
  130 \Save decrypted version
  140 LDX#c2 MOD256:LDY#c2 DIV256:JMPoscli
  150 ]

Mr Spock 26 Mar 2004