--------------Word Attack!------------- A 4am crack 2015-11-01 --------------------------------------- Name: Word Attack! Version: title screen says (c) 1983, 1985 disk label says (c) 1985, v06.01.87 newest file in catalog is 17-DEC-87 Genre: educational Year: 1987 Authors: Richard Eckert and Janice Davidson, Ph.D. Publisher: Davidson & Associates, Inc. Media: 3.5-inch floppy (800K) OS: ProDOS 1.4 Previous cracks: none ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways Copy ][+ 9.1 ("COPY" > "DISK") read error on block $0308; copy loads ProDOS, displays a prompt, prints "PLEASE PRESS SPACE BAR", and crashes 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 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 Success Is Failure, Failure Is Success, Black Is White, Night Is Day, Teaching Is Dead [S7,D1=my ProDOS hard drive] [S5,D1=non-working copy] ]PR#7 ... ]CAT,S5,D1 /WORD NAME TYPE BLOCKS MODIFIED *DATA DIR 3 17-DEC-87 *PICTURES DIR 1 25-OCT-87 *PRODOS SYS 32 17-APR-87 *BASIC.SYSTEM SYS 21 15-NOV-83 *STARTUP BAS 39 6-OCT-87 *WORD.C BAS 28 25-OCT-87 *DEMO BAS 14 25-OCT-87 *EDITOR BAS 20 17-NOV-87 DESKTOP $00 3 16-SEP-56 BLOCKS FREE: 1063 BLOCKS USED: 537 I saw a BASIC prompt during boot (even on my unsuccessful copy), so let's start with STARTUP.BAS. ]PREFIX /WORD ]LOAD STARTUP ]LIST 10 CALL 9361 Ah! A fake BASIC program that really calls the embedded assembly language program within it. 9361 = $2491. Let's see what's there. ]CALL -151 *2491L 2491- 4C 94 24 JMP $2494 *2494L 2494- 20 00 24 JSR $2400 *2400L ; save registers, flags, and several ; zero page locations 2400- 08 PHP 2401- 48 PHA 2402- 98 TYA 2403- 48 PHA 2404- 8A TXA 2405- 48 PHA 2406- A5 F8 LDA $F8 2408- 48 PHA 2409- A5 F9 LDA $F9 240B- 48 PHA 240C- A5 FA LDA $FA 240E- 48 PHA ; get unit number (slot+drive, but in a ; weird format that ProDOS likes) 240F- AD 30 BF LDA $BF30 2412- 4A LSR 2413- 4A LSR 2414- 4A LSR 2415- 4A LSR 2416- 29 07 AND #$07 2418- 09 C0 ORA #$C0 ; so this is the boot slot, munged into ; $Cx form (so $C6 for slot 6) 241A- 85 F9 STA $F9 241C- A9 00 LDA #$00 241E- 85 F8 STA $F8 ; 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") 2420- A0 01 LDY #$01 2422- B1 F8 LDA ($F8),Y 2424- C9 20 CMP #$20 2426- D0 22 BNE $244A 2428- A0 03 LDY #$03 242A- B1 F8 LDA ($F8),Y 242C- D0 1C BNE $244A 242E- A0 05 LDY #$05 2430- B1 F8 LDA ($F8),Y 2432- C9 03 CMP #$03 2434- D0 14 BNE $244A 2436- A0 FF LDY #$FF 2438- B1 F8 LDA ($F8),Y 243A- D0 0E BNE $244A ; if 5.25-inch, use block $110 (which ; is somewhere on track $22) 243C- A9 10 LDA #$10 243E- 8D 04 22 STA $2204 2441- A9 01 LDA #$01 2443- 8D 05 22 STA $2205 2446- D0 0C BNE $2454 2448- F0 0A BEQ $2454 ; if 3.5-inch, use block $308 (this is ; the block I couldn't read when I ; tried to copy the disk) 244A- A9 08 LDA #$08 244C- 8D 04 22 STA $2204 244F- A9 03 LDA #$03 2451- 8D 05 22 STA $2205 ; fill out the rest of an MLI parameter ; table 2454- AD 30 BF LDA $BF30 2457- 8D 01 22 STA $2201 245A- A9 03 LDA #$03 245C- 8D 00 22 STA $2200 245F- A9 00 LDA #$00 2461- 8D 02 22 STA $2202 2464- A9 20 LDA #$20 2466- 8D 03 22 STA $2203 ; now call the ProDOS MLI to perform a ; raw block read on the specified block 2469- 20 00 BF JSR $BF00 246C- [80 00 22] ; if there was NOT a disk read error, ; then branch 246F- 90 0C BCC $247D 2471- 85 FA STA $FA ; if there was any error other than an ; I/O error ($27), then branch 2473- C9 27 CMP #$27 2475- D0 06 BNE $247D ; success path falls through to here -- ; set a flag in zero page 2477- A9 FF LDA #$FF 2479- 85 FF STA $FF 247B- D0 04 BNE $2481 ; failure path is here (via $246F or ; $2475) -- set the magic zero page ; flag to $00 instead of $FF 247D- A9 00 LDA #$00 247F- 85 FF STA $FF ; restore everything on the way out ; (except the magic flag at zp$FF) 2481- 68 PLA 2482- 85 FA STA $FA 2484- 68 PLA 2485- 85 F9 STA $F9 2487- 68 PLA 2488- 85 F8 STA $F8 248A- 68 PLA 248B- AA TAX 248C- 68 PLA 248D- A8 TAY 248E- 68 PLA 248F- 28 PLP 2490- 60 RTS Continuing from $2497... ; munge reset vector 2497- A0 FF LDY #$FF 2499- 8C F4 03 STY $03F4 ; set RUN flag 249C- A0 80 LDY #$80 249E- 8C D6 00 STY $00D6 ; check magic zero page flag that was ; set by the bad block check at $2400 24A1- A0 FF LDY #$FF 24A3- C4 FF CPY $FF 24A5- F0 03 BEQ $24AA ; very bad 24A7- 6C F2 03 JMP ($03F2) ; very good 24AA- A0 40 LDY #$40 24AC- 8C 68 00 STY $0068 24AF- 4C 66 D5 JMP $D566 This 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 block or sector being unreadable, and fails if it's actually readable. 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. To bypass the protection, I can change the failure path at $247D so it sets the magic zero page flag to $FF instead of $00. Block Warden ["C"hange device -> S5,D1] ["F"ollow file] ["STARTUP"] Block $01C4, offset $7D change 00 to FF ]PR#5 ...works... Quod erat liberandum. --------------------------------------- A 4am crack No. 480 ------------------EOF------------------