-------------Spell It Plus!------------ A 4am crack 2015-11-03 --------------------------------------- Name: Spell It Plus! Genre: educational Year: 1989 Authors: Product Leader: Fave Schwartz Product Advisor: Cathy Johnson Lead Programmer: Kevin Burley Graphic Artist: Carol Carpenter Publisher: Davidson & Associates, Inc. Media: 3.5-inch floppy (800K) OS: ProDOS 1.4 Other versions: Asimov archive has an uncredited crack Similar cracks: #481 Math Blaster Mystery 1.3 (3.5") #457 Math Blaster Mystery 1.3 (5.25") #200 Math Blaster Mystery 1.0 (5.25") #166 Word Attack Plus French (5.25") #165 Alge-Blaster Plus (5.25") ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways Copy ][+ 9.1 ("COPY" > "DISK") read error on block $0308; copy loads ProDOS then quits to program selector CFFA 3000 import read error on block 776 (= $0308); booting the disk image in an emulator exhibits the same behavior as the backup I made with Copy ][+ disk copy (boots ProDOS then quits via a "Quit" MLI call) It's a very ProDOS-y way of saying "f--- you." The original disk boots without complaint, so either this bad block is part of the protection check, or it's unrelated and I got incredibly lucky. Next steps: 1. Trace the startup program 2. Find and disable the protection check 3. Declare victory(*) (*) Take a nap ~ Chapter 1 FORTH? In *My* Apple II? It's More Likely Than You Think [S7,D1=my ProDOS hard drive] [S5,D1=non-working copy] ]PR#7 ... ]CAT,S5,D1 /SPELL NAME TYPE BLOCKS MODIFIED PRODOS SYS 32 25-OCT-89 GMENU.DAT TXT 3 25-OCT-89 SPELL.SYSTEM SYS 4 20-DEC-88 TK.ABS BIN 28 25-OCT-89 GS.OBJ TXT 13 25-OCT-89 G4.OVL TXT 13 26-OCT-89 PRTREC.OVL TXT 3 25-OCT-89 QUOTES.DAT TXT 12 25-OCT-89 FOREIGN.FONT.4 BIN 7 25-OCT-89 G2.OVL TXT 13 25-OCT-89 SETUP.OVL TXT 4 25-OCT-89 CERT.PAK TXT 8 25-OCT-89 SETUP.DAT TXT 1 2-DEC-91 TOOLS.OBJ BIN 3 25-OCT-89 TEXTCERT.OVL TXT 3 25-OCT-89 G1.OVL TXT 13 25-OCT-89 DATA DIR 4 25-OCT-89 G5.OVL TXT 13 25-OCT-89 G3.OVL TXT 13 25-OCT-89 ED.OVL TXT 15 25-OCT-89 DUMP.HIRES.R BIN 5 25-OCT-89 INTER.DRIVERS TXT 5 25-OCT-89 PRINTER.DRIVERS TXT 12 25-OCT-89 HELP.DAT TXT 4 25-OCT-89 G5.GRF TXT 17 25-OCT-89 G5.OBJ BIN 3 25-OCT-89 EMENU.DAT TXT 3 25-OCT-89 G3.GR TXT 18 25-OCT-89 MAIN.PAK TXT 8 26-OCT-89 SIPFIELD.OBJ BIN 4 25-OCT-89 SMALL.GR TXT 19 25-OCT-89 SILVER.PAK TXT 4 25-OCT-89 GOLD.PAK TXT 4 25-OCT-89 BRONZE.PAK TXT 4 25-OCT-89 TWOPLAYER.GR TXT 9 25-OCT-89 G4.GR TXT 5 25-OCT-89 ENTRY.PAK TXT 7 25-OCT-89 PUZZLE.OBJ BIN 1 25-OCT-89 FROG.DAT TXT 1 25-OCT-89 AFORTH BIN 58 26-OCT-89 MFORTH BIN 65 26-OCT-89 CONVERT SYS 4 25-OCT-89 UTIL DIR 1 25-OCT-89 *UTILITIES SYS 21 25-OCT-89 STARTUP BAS 1 25-OCT-89 DESKTOP $00 3 16-SEP-56 BLOCKS FREE: 612 BLOCKS USED: 988 ProDOS always loads the first .SYSTEM file at $2000 and jumps to it. ]PREFIX /SPELL ]BLOAD SPELL.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 *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 04 00 00 00 00] ...which explains the behavior I saw on my non-working copy. *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 ; now look at some signature bytes in ; the peripheral ROM for the boot slot ; to determine what kind of floppy ; disk we booted from (5.25" or 3.5") 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 ; if 5.25-inch, use block $110 (which ; is somewhere on track $22) 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 ; if 3.5-inch, use block $308 (this is ; the block I couldn't read when I ; tried to copy the disk) 0B03- A9 08 LDA #$08 0B05- 8D CE 0D STA $0DCE 0B08- A9 03 LDA #$03 0B0A- 8D CF 0D STA $0DCF ; fill out the rest of an MLI parameter ; table 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 falls through to here -- ; set a flag in zero page 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 is definitely a form of copy protection. It relies on a specific sector being unreadable, and fails if it's actually readable. Fun fact(*): it is written so it can be re-used for 5.25-inch and 3.5-inch floppies. Since my copy didn't reproduce the badness of block $308, the MLI read routine unexpectedly succeeds, and the program knows it's been copied. (*) not guaranteed, actual fun may vary To bypass the protection, I can change the failure path at $0B33 so it sets the magic zero page flag to $FF instead of $00 (just like the success path). Block Warden ["C"hange device -> S5,D1] ["E"dit mode] [earch] ["$20 00 BF 80"] That will find the READ_BLOCK MLI call, which is very close to the failure path that I want to change. Block $002C,offset $136 change 00 to FF Continuing the search, Block Warden finds another match later. (I believe this is in the spelling list editor.) The code is substantially similar to what I saw in SPELL.SYSTEM. Block $02E7,offset $133 change 00 to FF ]PR#5 ...works... Quod erat liberandum. --------------------------------------- A 4am crack No. 484 ------------------EOF------------------