-----------Word Attack Plus!----------- A 4am crack 2015-02-11 --------------------------------------- Name: Word Attack Plus! Version: 1.0 Genre: educational Year: 1988 Authors: Jan Davidson, Julie Baumgartner, J.M. Albanese, Kevin R. Burley Publisher: Davidson & Associates, Inc. Media: one double-sided 5.25-inch disk OS: ProDOS 1.4 Other versions: none (preserved here for the first time) Identical cracks: Math Blaster Mystery (4am crack no. 200), several other contemporaneous Davidson titles Only side A is bootable, so I'll start there. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA disk read error on last pass Locksmith Fast Disk Backup read error on T22,S00; copy boots to ProDOS then quits to program selector EDD 4 bit copy (no sync, no count) works Copy ][+ nibble editor can't find any evidence that T22,S00 even exists Disk Fixer can't find any combination of parameters that can read T22,S00 Why didn't COPYA work? intentionally bad sector on T22 Why didn't Locksmith FDB work? Probably a nibble check in the first SYSTEM file that reads the unreadable sector on T22 ~ Chapter 1 In Which We Meditate On The Definition Of Success [S6,D1=original disk] [S7,D1=ProDOS hard drive] ]PR#7 ]CAT,S6,D1 /WORD NAME TYPE BLOCKS MODIFIED FOREIGN.FONT.3 BIN 7 PRODOS SYS 32 MAIN.PAK TXT 10 ENTRY.PAK TXT 7 GAME.STR.OBJ TXT 10 ED.STR.OBJ TXT 7 ED.OVL TXT 22 WAP.SYSTEM SYS 4 IMAGE.OBJ TXT 15 TK.ABS BIN 28 G5.OVL TXT 13 G4.OVL TXT 7 G13.OVL TXT 25 PRINTER.DRIVERS TXT 12 INTER.DRIVERS TXT 5 DUMP.HIRES.R BIN 5 PRINTER.DATA TXT 1 CERT.PAK TXT 9 PRINT.STR.OBJ TXT 1 PRINT.OVL TXT 11 AFORTH BIN 43 10-JUN-88 BLOCKS FREE: 0 BLOCKS USED: 280 ProDOS always loads the first .SYSTEM file at $2000 and jumps to it. ]PREFIX /WORD ]BLOAD WAP.SYSTEM,A$2000,TSYS ]CALL -151 *2000L 2000- 20 D2 25 JSR $25D2 2003- 4C 74 08 JMP $0874 There's nothing loaded at $0874 yet, so the subroutine at $25D2 must load something from disk or copy something from memory. *25D2L ; straightforward memory relocation 25D2- A2 00 LDX #$00 25D4- BD 03 20 LDA $2003,X 25D7- 9D 01 08 STA $0801,X 25DA- BD 03 21 LDA $2103,X 25DD- 9D 01 09 STA $0901,X 25E0- BD 03 22 LDA $2203,X 25E3- 9D 01 0A STA $0A01,X 25E6- BD 03 23 LDA $2303,X 25E9- 9D 01 0B STA $0B01,X 25EC- BD 03 24 LDA $2403,X 25EF- 9D 01 0C STA $0C01,X 25F2- BD 03 25 LDA $2503,X 25F5- E8 INX 25F6- D0 DC BNE $25D4 25F8- 60 RTS That's harmless enough. Let's run it. *25D2G *874L 0874- 20 C8 0A JSR $0AC8 0877- F0 D9 BEQ $0852 Down the rabbit hole we go. *AC8L ; $BF30 is the last used slot and drive ; in "DSSS0000" format ("Beneath Apple ; ProDOS", p. 8-6) 0AC8- AD 30 BF LDA $BF30 0ACB- 4A LSR 0ACC- 4A LSR 0ACD- 4A LSR 0ACE- 4A LSR 0ACF- 29 07 AND #$07 0AD1- 09 C0 ORA #$C0 ; slot number munged into the high byte ; of the drive slot ROM, e.g. $C6 0AD3- 85 61 STA $61 0AD5- A9 00 LDA #$00 0AD7- 85 60 STA $60 ; standard fingerprinting to identify ; the drive ROM 0AD9- A0 01 LDY #$01 0ADB- B1 60 LDA ($60),Y 0ADD- C9 20 CMP #$20 0ADF- D0 22 BNE $0B03 0AE1- A0 03 LDY #$03 0AE3- B1 60 LDA ($60),Y 0AE5- D0 1C BNE $0B03 0AE7- A0 05 LDY #$05 0AE9- B1 60 LDA ($60),Y 0AEB- C9 03 CMP #$03 0AED- D0 14 BNE $0B03 0AEF- A0 FF LDY #$FF 0AF1- B1 60 LDA ($60),Y 0AF3- D0 0E BNE $0B03 ; 5.25-inch floppy drive, so check ; block $110 (includes T22,S00) 0AF5- A9 10 LDA #$10 0AF7- 8D CE 0D STA $0DCE 0AFA- A9 01 LDA #$01 0AFC- 8D CF 0D STA $0DCF 0AFF- D0 0C BNE $0B0D 0B01- F0 0A BEQ $0B0D ; 3.5-inch floppy drive, so check ; block $308 0B03- A9 08 LDA #$08 0B05- 8D CE 0D STA $0DCE 0B08- A9 03 LDA #$03 0B0A- 8D CF 0D STA $0DCF ; set up other MLI parameters 0B0D- AD 30 BF LDA $BF30 0B10- 8D CB 0D STA $0DCB 0B13- A9 03 LDA #$03 0B15- 8D CA 0D STA $0DCA 0B18- A9 CA LDA #$CA 0B1A- 8D CC 0D STA $0DCC 0B1D- A9 0B LDA #$0B 0B1F- 8D CD 0D STA $0DCD ; call MLI to read the specified block ; from disk (the $80 byte following the ; JSR is the READ_BLOCK command, and ; following that is the address of the ; MLI parameter table, $0DCA) 0B22- 20 00 BF JSR $BF00 0B25- [80 CA 0D] ; if there was NOT a disk read error, ; then branch 0B28- 90 09 BCC $0B33 ; if there was any error other than an ; I/O error ($27), then branch 0B2A- C9 27 CMP #$27 0B2C- D0 05 BNE $0B33 ; success path is here 0B2E- A9 FF LDA #$FF 0B30- 85 FF STA $FF 0B32- 60 RTS ; failure path is here 0B33- A9 00 LDA #$00 0B35- 85 FF STA $FF 0B37- 60 RTS This isn't a nibble check, per se. But it is definitely a form of copy protection. (Fun fact: it appears to be written so it can be re-used for 5.25- and 3.5-inch floppies.) It relies on one specific sector being unreadable, and fails if it's actually readable. Since Locksmith FDB just wrote a zeroed (but standard) sector to T22,S00, the MLI read routine unexpectedly succeeds, and the program knows it's been copied. Returning to the caller: 0874- 20 C8 0A JSR $0AC8 0877- F0 D9 BEQ $0852 *852L ; read and write main memory 0852- 8E 04 C0 STX $C004 0855- 8E 02 C0 STX $C002 ; call the quit handler (command $65) 0858- 20 00 BF JSR $BF00 085B- [65 5E 08] ...which explains the behavior I saw on my non-working copy. Let's reproduce the success path. I'm not sure if the side effect of setting zero page $FF is relevant, but let's assume it is. *FF:FF N 879G The program loads without complaint. Out of curiosity, I reproduced this state and tried it with $FF=0. *FF:00 N 879G It still loads without complaint. Popping the stack all the way back to $2003, I can change JMP $0874 to $0879 and bypass the entire thing. T0C,S07,$04 change "74" to "79" Side B is unprotected. Quod erat liberandum. --------------------------------------- A 4am crack No. 218 ------------------EOF------------------