Chip Buster (Hacking Tips #5)

By Mr. Spock

Originally published in EUG #71

Chip Buster - Noisy code, decryption and using OSBGET to get bytes from a file.

Code executes at &C02. An example of 'noise', undocumented but harmless opcodes interspersed with legal instructions (shown indented for clarity).

The legal instructions make up a simple - although long-windedly written -decyption loop, the Basic equivalent of which is:

FOR y=0 TO &FF:y?&B00=y?&B00 EOR y:NEXT

0C02 EQUB &83 
0C03 EQUB &FD 
0C04  LDA #&00  \
0C06 EQUB &7A 
0C07  STA &72
0C09 EQUB &D3 
0C0A EQUB &D9 
0C0B  LDA #&0B  \A%=&B00
0C0D EQUB &04 
0C0E EQUB &39 
0C0F  STA &73
0C11 EQUB &0C 
0C12 EQUB &00 
0C13 EQUB &1E 
0C14  LDY #&00  \Y%=0
0C16 EQUB &14 
0C17 EQUB &99 
0C18  TYA         \Y%?A%=Y%?A%
0C19  EOR (&72),Y \EOR Y%
0C1B EQUB &7E 
0C1C EQUB &20 
0C1D EQUB &20 
0C1E  STA (&72),Y
0C20 EQUB &83 
0C21 EQUB &20 
0C22  INY         \Y%=(Y%+1) AND&FF
0C23  BNE &0C2A   \IF Y%<>0 goto &C2A
0C25 EQUB &1A 
0C26  INC &73     \else A%=A%+&100
0C28 EQUB &34 
0C29 EQUB &20 
0C2A  LDA #&0B   
0C2C EQUB &54 
0C2D EQUB &B9 
0C2E  CMP &73
0C30  BNE &0C18
0C32 EQUB &54 
0C33 EQUB &B9 
0C34  CPY #&FF \if Y%<>&FF
0C36 BNE &0C18 \goto &C18  
0C38 EQUB &0C 
0C39 EQUB &00 
0C3A EQUB &4C 
0C3B  JMP &0B4C \continue execution at &B4C

\Filename at &C3E appears on screen as ?????
0C38 ** ** ** ** ** ** C2 D5       ..
0C40 D3 D4 C5 D2 0D 00 00 00 .....   

0B00 SEI        \set up interrupt routine
0B01 LDA &0204  \copy default interrupt
0B04 STA &76    \to &76/77
0B06 LDA &0205  \
0B09 STA &77    \
0B0B LDA #&17   \and put new routine
0B0D STA &0204  \in &204/5
0B10 LDA #&0B
0B12 STA &0205
0B15 CLI  \clear interrupt
0B16 RTS 

\interrupt routine to unlock tape file
0B17 PHP  \preserve status register
0B18 PHA  \and A
0B19 LDA &03CA \get tape file flag
0B1C AND #&FE  \ensure bit 1 is clear (file unlocked)
0B1E STA &03CA
0B21 PLA   \retrieve A
0B22 PLP   \and status reg
0B23 JMP (&0076)  \jump to default interrupt

0B26 BIT &80   \loops forever if contents of &80
0B28 BPL &0B26 \are +ve

0B2A LDA #&4C   \set up break intercept
0B2C STA &0287  \store JMP opcode at &287
0B2F LDA #&2A   \
0B31 STA &0288  \Jump to &B2A
0B34 LDA #&0B   \on pressing break
0B36 STA &0289  \
0B39 LDA #&FF
0B3B STA &80
0B3D LDA &70  \Cassette motor flag
0B3F AND #1   \Get bit 1
0B41 TAX 
0B42 LDA #137   \swtich cassette motor on/off
0B44 JSR OSbyte \*FX137,x equivalent
0B47 INC &70    \toggle motor flag
0B49 JMP &0B2A  \loop forever!

\come here from &C3B
0B4C SEI       \disable interrupts
0B50 BPL &0B2A \if +ve has been altered so crash
0B52 LDA #&F7  \Set Break intercept
0B54 LDX #&4C  \to point to &2626
0B56 LDY #&00  \*FX247,76
0B58 JSR OSbyte
0B5B LDA #&F8  \*FX248,38
0B5D LDX #&26
0B5F LDY #&00
0B61 JSR OSbyte
0B64 LDA #&F9
0B66 LDX #&26  \*FX249,38
0B68 LDY #&00
0B6A JSR OSbyte
0B6D LDX #&01    \check hi bytes of vectors
0B6F LDA &0200,X \if any have been altered
0B72 BPL &0B2A   \ie hi bytes +ve then go to crash routine
0B74 INX 
0B75 INX 
0B76 CPX #&31    \until checked all vectors
0B78 BNE &0B6F
0B7A LDA #200 \Disable Escape and clear memory on Break
0B7C LDX #3   \*FX200,3 equivalent
0B7E LDY #0
0B80 JSR OSbyte
0B83 JSR &0B00 \Set up interrupt routine
0B86 LDA #&00  \contents of &80 zero so routine
0B88 STA &80   \at &B26 will toggle cassette motor
0B8A LDA #&00  \
0B8C STA &72   \&72/3
0B8E LDA #&19  \=&1900
0B90 STA &73
0B92 LDA #139  \Set file options *OPT equivalent
0B94 LDX #1    \*FX139,1,2 same as *OPT1,2
0B96 LDY #2    \Give long tape messages
0B98 JSR OSbyte
0B9B LDA #&8B  \*FX139,2,1
0B9D LDX #&02  \same as *OPT2,1
0B9F LDY #&01  \Prompt rewind tape etc
0BA1 JSR OSbyte
0BA4 LDA #&40   \Open file whose name is
0BA6 LDX #&3E   \at &C3E, consists of control codes
0BA8 LDY #&0C   \so apears on screen as ?????
0BAA JSR OSfind 
0BAD STA &71    \Store file ID in &71
0BAF LDX #&FF   
0BB1 INX         \X=0 first time
0BB2 LDA &03A7,X \Load char of filename being BGETed
0BB5 BNE &0BB1   \loop till found zero
0BB7 CPX #&0A    \and offset=10
0BB9 BNE &0BBD   \ie 10 character filename
0BBB LDX #5      \store
0BBD LDA #32     \space
0BBF STA &03A7,X \in 5th char
0BC2 INX         \X=6
0BC3 LDA #&00    \store
0BC5 STA &03A7,X \zero in 6th char
0BC8 DEC &03DD   \next block
0BCB DEC &03DD   \minus 2
0BCE LDY #&00  
0BD0 STY &75  \page offset for data
0BD2 LDY &71    \retrieve file ID
0BD4 JSR OSbget \get byte from file
0BD7 BCS &0BE6  \C=1 if end of file
0BD9 EOR #&4B   \EOR with 75
0BDB LDY &75  \retrieve page offset
0BDD STA (&72),Y \store in memory
0BDF INY       \loop till
0BE0 BNE &0BD0 \one page done
0BE2 INC &73   \page=page+1
0BE4 BNE &0BAF \always <>0

\come here when loaded file
0BE6 LDA &03CA \block flag byte
0BE9 AND #2    \bit 1 set
0BEB BNE &0BF0 \if loaded ok
0BED JMP &0B2A \if not jump to crash routine
0BF0 SEI       \disable interrupts
0BF1 LDA &76   \while we
0BF3 STA &0204 \restore default
0BF6 LDA &77   \machine IRQ1 address
0BF8 STA &0205
0BFB CLI       \enable interrupts
0BFC JMP &4200 \and start the game

Mr Spock 28 Mar 2004