PGOETZ@LOYVAX.BITNET (04/13/88)
ELECTRONIC ARTS PROTECTION LANGUAGE I was boot-code tracing Amnesia, and I came to $3700. A protection routine starting at $3704 evidently checked for one sector of nothing but $AFs, but I didn't see where it was called. The tracing became very complicated and indirect, but I noticed that I kept circling back to $38C3. Then I realized that $38C3 was the equivalent of Applesoft's GETCHR for EOA's own interpretive language. After much tracing and disassembling, I decoded this language, which I call EOAPL. It is basically a small subset of 6502 machine language, and it is of course much slower, so its only purpose is to confuse crackers. To see this code, boot Amnesia. When it asks you PLAY A SAVED GAME? insert a normal disk into the drive and press reset. All the code is left unaltered. In Amnesia, $3700 jumps to $376A: 376A- JSR $38E1 376D- JSR $38B4 3770- JMP $376A $38B4 is the call to the interpreter. It stores the address 3 bytes beyond the next instruction in the interpreter's program counter (in this case, $3773) and falls through to $38C3, which starts running the program at $3773. $38C3 is the crucial routine to look for: 38C3- B1 52 LDA ($52),Y Get opcode 38C5- C8 INY Advance program counter 38C6- D0 02 BNE $38CA 38C8- E6 53 INC $53 38CA- AA TAX 38CB- BD D4 38 LDA $38D4,X Get low byte of address which executes this instruction 38CE- 8D E0 39 STA $39E0 Store it in the JMP 38D1- 4C DF 39 JMP $39DF Execute; routine will return via a JMP $38C3 39DF- 4C xx 39 JMP $39xx Each instruction consists of a 1-byte opcode followed by a 0, 1, or 2 byte parameter. The opcodes are not encoded. Each 1 byte parameter is EORed with $4C. Every 2 byte parameter is EORed with $D903 (the low byte is EORed with 3 and the high byte with $D9). EOAPL uses $56 as the accumulator and $53,52 as the program counter. $50-5F are used for various things. The commands are: Op. Len Addr Mnemnonic Function 0 3 3900 GOTO addr 1 3 3927 JSRV addr Call a machine language subroutine with $56 as a value parameter: On entry A <- $56, on exit $56 <- A. 2 3 3955 GONE addr Go to addr if $56 > 0 3 2 395F LD56 num 4 3 396D LD56 addr 5 3 398A GSUB addr 6 3 39AD ST56 addr 7 2 39B9 S56- num $56 <- $56 - num 8 1 39A2 RTRN Return from subroutine 9 3 394F JSR addr Call a machine language subroutine A 3 39CE INC addr INC addr : $56 <- (addr) B 1 3926 RTS Exit program & return to machine language caller C 3 3979 S56+ addr $56 <- $56 + (addr) So, for example, a routine to print 4C would look like this: 0300- 20 B4 38 JSR $38B4 0303- 60 RTS 0304- 00 BRK 0305- 00 BRK -------- disassembled EOAPL -------- 0306- 03 00 LD56 #$4C 0308- 01 D9 24 JSRV $FDDA 030B- 0B RTS About $B0 bytes are in EOAPL - too many to disassemble by hand. So I rewrote the monitor disassembler ($F882-FA3F, enter at $F8D0) to disassemble EOAPL. It is written for the Apple Toolkit Assembler. 1. Enter the start address in 1,0. 2. Enter the number of lines to disassemble in 2. 3. 800G (or CALL 2048). Ex: CALL-151 0:0 30 10 800G would disassemble 16 lines of EOAPL starting at $3000. ORG $800 CODE EQU 2 FORMAT EQU $2E LENGTH EQU $2F LDA 0 STA $3A LDA 1 STA $3B LDA 2 STA 6 L1 JSR EOADIS LDA LENGTH SEC ADC $3A STA $3A BCC L2 INC $3B L2 DEC 6 BNE L1 RTS EOADIS JSR INSDS1 PRNTOP LDA ($3A),Y JSR $FDDA LDX #1 PRNTBL JSR $F94A CPY LENGTH INY BCC PRNTOP LDX #3 CPY #4 BCC PRNTBL ;PRINT MNEMONIC LDA CODE ASL A ASL A TAY LDX #4 PMN LDA MTAB,Y JSR $FDED INY DEX BNE PMN JSR $F948 LDY LENGTH LDX #6 PRADR1 CPX #3 BEQ PRADR5 PRADR2 ASL FORMAT BCC PRADR3 LDA $F9B3,X JSR $FDED LDA $F9B9,X BEQ PRADR3 JSR $FDED PRADR3 DEX BNE PRADR1 RTS PRADR4 DEY BMI PRADR2 STX 3 LDX LENGTH CPX #2 BCS ED903 EOR #$4C JMP PR45 ED903 EOR ETAB,Y PR45 JSR $FDDA LDX 3 PRADR5 LDA FORMAT CMP #$E8 LDA ($3A),Y BCC PRADR4 JSR $F956 TAX INX BNE PRNTYX INY PRNTYX TYA JSR $FDDA TXA JMP $FDDA RTS RTS ETAB DFB $3,$D9 LENTAB DFB 2,2,2,1,2,2,2,1,0,2,2,0,2,0 FMTTAB DFB $80,$80,$80,$20,$80,$80,$80,$20,0,$80,$80,0,$80,0 MTAB ASC /GOTOJSRVGONELD56LD56GSUBST56S56-RTRNJSR INC RTS S56+????/ INSDS1 LDX $3A LDY $3B JSR $FD96 JSR $F948 INSDS2 LDA ($3A,X) CMP #$D LEGAL OPCODE? BCC GETFMT YES LDA #$D ???? GETFMT TAY STA CODE LDA LENTAB,Y STA LENGTH LDA FMTTAB,Y STA FORMAT LDY #0 RTS Hex dump of disassembler: 0800- A5 00 85 3A A5 01 85 3B 0808- A5 02 85 06 20 1F 08 A5 0810- 2F 38 65 3A 85 3A 90 02 0818- E6 3B C6 06 D0 EE 60 20 0820- F0 08 B1 3A 20 DA FD A2 0828- 01 20 4A F9 C4 2F C8 90 0830- F1 A2 03 C0 04 90 F2 A5 0838- 02 0A 0A A8 A2 04 B9 B8 0840- 08 20 ED FD C8 CA D0 F6 0848- 20 48 F9 A4 2F A2 06 E0 0850- 03 F0 2E 06 2E 90 0E BD 0858- B3 F9 20 ED FD BD B9 F9 0860- F0 03 20 ED FD CA D0 E7 0868- 60 88 30 E7 86 03 A6 2F 0870- E0 02 B0 05 49 4C 4C 7C 0878- 08 59 9A 08 20 DA FD A6 0880- 03 A5 2E C9 E8 B1 3A 90 0888- E0 20 56 F9 AA E8 D0 01 0890- C8 98 20 DA FD 8A 4C DA 0898- FD 60 03 D9 02 02 02 01 08A0- 02 02 02 01 00 02 02 00 08A8- 02 00 80 80 80 20 80 80 08B0- 80 20 00 80 80 00 80 00 08B8- C7 CF D4 CF CA D3 D2 D6 08C0- C7 CF CE C5 CC C4 B5 B6 08C8- CC C4 B5 B6 C7 D3 D5 C2 08D0- D3 D4 B5 B6 D3 B5 B6 AD 08D8- D2 D4 D2 CE CA D3 D2 A0 08E0- C9 CE C3 A0 D2 D4 D3 A0 08E8- D3 B5 B6 AB BF BF BF BF 08F0- A6 3A A4 3B 20 96 FD 20 08F8- 48 F9 A1 3A C9 0D 90 02 0900- A9 0D A8 85 02 B9 9C 08 0908- 85 2F B9 AA 08 85 2E A0 0910- 00 60 So to disassemble the code in Amnesia at $3773, we type: *0:73 37 13 *800G and we get: 3773- 04 62 EE LD56 $3761 3776- 07 74 S56- #$38 3778- 02 8E E1 GONE $388D Crash if $3761 has been changed 377B- 04 61 EE LD56 $3762 377E- 07 2C S56- #$60 3780- 02 8E E1 GONE $388D Same for $3762 3783- 04 6B EE LD56 $3768 3786- 07 74 S56- #$38 3788- 02 8E E1 GONE $388D Same for $3768 378B- 05 AB EE GSUB $37A8 Call $3704 & check for original 378E- 02 97 EE GONE $3794 Fail, try again 3791- 00 A6 EE GOTO $37A5 OK, exit 3794- 05 AB EE GSUB $37A8 3797- 02 9E EE GONE $379D Fail 379A- 00 A6 EE GOTO $37A5 OK, exit 379D- 07 4E S56- #$02 379F- 02 8E E1 GONE $388D Crash if $56 wasn't 2 after $37A8 37A2- 00 70 EE GOTO $3773 Do it again 37A5- 09 A4 E1 JSR $38A7 Exit to caller Inspection of the disassembly shows us we can bypass the protectiobn by switching the GONE $3794 at $378E with the GOTO $37A5 at $3791. That way it exits OK regardless what happened, and any checksums are satisfied. Scanning the disk, we find 02 97 EE 00 A6 EE on T9 S2 at bytes $E2-E7. So to crack Amnesia, copy all tracks except track 6 & perform this sector edit: T9 S2 B$E2: 02 97 EE -> 00 A6 EE B$E5: 00 A6 EE -> 02 97 EE EOAPL is also used in The Last Gladiator, Archon, Archon II: Adept, and probably many other EOA releases.