-----------Practical Algebra----------- A 4am crack 2015-01-21 -------------------. updated 2015-12-21 |___________________ Name: Practical Algebra Genre: educational Year: 1988 Publisher: Queue, Inc. OS: DOS 3.3 Media: 5 single-sided 5.25" floppies Other versions: none (preserved here for the first time) Identical cracks: Practical Grammar (4am crack 195) I have five disks: 1. Symbols and Sets 2. Real Number System 3. Equations I 4. Equations II 5. Algebra Word Problems I'll start with disk 1. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA immediate disk read error Locksmith Fast Disk Backup unable to read any track EDD 4 bit copy (no sync, no count) no errors, but copy grinds on boot Copy ][+ nibble editor T00 --> standard prologues T01+ --> modified address prologue ("AB BF D5") also modified address epilogue (not sure what exactly, not consistent?) --v-- COPY ][ PLUS BIT COPY PROGRAM 8.4 (C) 1982-9 CENTRAL POINT SOFTWARE, INC. --------------------------------------- TRACK: 04 START: 2DE2 LENGTH: 0F6D 2DC0: EC 9A 9A D3 97 CE E9 EE VIEW 2DC8: CE 96 96 EF DE AA EB F5 ^^^^^^^^ data epilogue 2DD0: FA BC FE DE EF FD BD BF 2DD8: FF E5 B5 FF AA CF EF DF 2DE0: BB FB D5 DB AF EB FE AA <-2DE2 2DE8: FF AB BF D5 FF FE AA AE ^^^^^^^^ address prologue 2DF0: AF AF FA FF F6 9C FF 9F 2DF8: E7 F9 FE FF FF D5 AA AD ^^^^^^^^ data prologue 2E00: 96 96 96 96 96 96 96 96 --------------------------------------- A TO ANALYZE DATA ESC TO QUIT ? FOR HELP SCREEN / CHANGE PARMS Q FOR NEXT TRACK SPACE TO RE-READ --^-- Disk Fixer ["O" -> "Input/Output Control"] set Address Prologue to "AB BF D5" turn off epilogue checking T00 looks like a DOS 3.3 RWTS T11 looks like a DOS 3.3 disk catalog T01,S09 -> startup program is "HELLO" Why didn't COPYA work? modified prologue and epilogue Why didn't Locksmith FDB work? modified prologue and epilogue Why didn't my EDD copy work? I don't know. Maybe a nibble check during boot? Next steps: 1. capture RWTS with AUTOTRACE 2. convert disk to standard format with Advanced Demuffin 3. patch RWTS to read demuffin'd disk 4. find nibble check and bypass it ~ Chapter 1 In Which We Attempt To Use The Original Disk As A Weapon Against Itself [S6,D1=original disk] [S6,D2=blank disk] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ]BLOAD BOOT0,A$800 ]CALL -151 *801L . . all normal until... . 084A- 4C F0 08 JMP $08F0 *8F0L 08F0- A9 AA LDA #$AA 08F2- 85 31 STA $31 <-- ? 08F4- A9 00 LDA #$00 08F6- 8D F1 B6 STA $B6F1 08F9- 4C 00 BB JMP $BB00 <-- ! I've seen this before. The RWTS uses zero page $31 to check some byte of the prologue or epilogue. In this case, probably the data epilogue, since the address prologue and epilogue are non- standard. *C500G ; reboot my work disk ... ]RUN 130 ; continue AUTOTRACE CAPTURING BOOT1 SAVING BOOT1 SAVING RWTS (Note to self: update AUTOTRACE so it can trace past a jump to $08F0.) Boot0 jumped to $BB00 (from $08F9), which is probably a nibble check. ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; move RWTS into place *BB00L BB00- A9 59 LDA #$59 BB02- 8D F2 03 STA $03F2 BB05- A9 B7 LDA #$B7 BB07- EA NOP BB08- 8D F3 03 STA $03F3 BB0B- 49 A5 EOR #$A5 BB0D- 8D F4 03 STA $03F4 BB10- 4C 00 B7 JMP $B700 Hmm, not a nibble check. Just setting the reset vector. Now look at this code to match the data epilogue: *B92FL B92F- BD 8C C0 LDA $C08C,X B932- 10 FB BPL $B92F B934- C9 DE CMP #$DE B936- D0 0A BNE $B942 B938- EA NOP B939- BD 8C C0 LDA $C08C,X B93C- 10 FB BPL $B939 B93E- C5 31 CMP $31 <-- ! B940- F0 5C BEQ $B99E B942- 38 SEC B943- 60 RTS There's zero page $31, initialized at $08F0 during boot. Solution: an IOB module that Advanced Demuffin calls before calling the original disk's RWTS. (Read the docs on my work disk.) *C500G ... ]CALL -151 ]BLOAD ADVANCED DEMUFFIN 1.5 ; standard Advanced Demuffin setup ; (unchanged) 1400- 4A LSR 1401- 8D 22 0F STA $0F22 1404- 8C 23 0F STY $0F23 1407- 8E 27 0F STX $0F27 140A- A9 01 LDA #$01 140C- 8D 20 0F STA $0F20 140F- 8D 2A 0F STA $0F2A ; initialize zero page 1412- A9 AA LDA #$AA 1414- 85 31 STA $31 ; call RWTS 1416- A9 0F LDA #$0F 1418- A0 1E LDY #$1E 141A- 4C 00 BD JMP $BD00 *BSAVE IOB $31,A$1400,L$FB *BRUN ADVANCED DEMUFFIN 1.5 ["5" to switch to slot 5] ["R" to load a new RWTS module] --> At $B8, load "RWTS" from drive 1 [press "I" to load a new IOB module] --> load "IOB $31" from drive 1 ["6" to switch to slot 6] ["C" to convert disk] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:................................... +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:................................... SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- ]PR#5 ]CATALOG,S6,D2 C1983 DSR^C#254 085 FREE *A 003 HELLO T 002 DN *A 059 TUT *A 025 ACSES B 002 XF1 T 003 SM B 016 L10 B 003 L101 B 002 L104 B 013 L15 B 003 L151 B 016 L20 T 002 TF1 T 002 IF1 T 003 SF1 B 003 L201 B 002 L204 B 013 L25 B 003 L251 B 002 UPFP B 002 L254 B 015 L30 B 003 L301 B 018 L35 B 003 L351 B 002 L354 B 013 L40 B 003 L401 B 002 L404 B 019 L45 B 003 L451 B 003 L454 B 017 L50 B 003 L501 B 002 L504 B 015 L55 B 003 L551 B 003 L554 *B 002 GS *A 002 BTUT B 024 FP+ B 005 CS I 006 APPLESOFT B 050 FPBASIC ]RUN HELLO ...works... ]PR#6 ...works... Wait, what? ~ Chapter 2 In Which We Angrily Investigate Why We Suddenly Have A Working Copy [S6,D1=mysteriously working copy] [S5,D1=my work disk] ]BLOAD RWTS,A$2800 ]CALL -151 *FE89G FE93G *B800<2800.2FFFM *B944L ; routine to find address prologue B944- A0 FC LDY #$FC B946- 84 26 STY $26 B948- C8 INY B949- D0 04 BNE $B94F B94B- E6 26 INC $26 B94D- F0 F3 BEQ $B942 ; find prologue nibble #1 B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- C9 D5 CMP #$D5 <-- ? B956- D0 F0 BNE $B948 B958- EA NOP I could have sworn the original disk's address prologue was "AB BF D5". ; and again? B959- BD 8C C0 LDA $C08C,X ; Wait, no BPL loop here! It only reads ; the data latch once. B95C- C9 D5 CMP #$D5 ; if data latch is (still) $D5, jump ; right to address field logic B95E- F0 12 BEQ $B972 ; otherwise continue and... look for ; the (standard) prologue nibble #2 B960- BD 8C C0 LDA $C08C,X B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 ; and the standard prologue nibble #3 B969- BD 8C C0 LDA $C08C,X B96C- 10 FB BPL $B969 B96E- C9 96 CMP #$96 B970- D0 D6 BNE $B948 ; decode address field (standard) B972- A0 03 LDY #$03 B974- A9 00 LDA #$00 B976- 85 27 STA $27 B978- BD 8C C0 LDA $C08C,X B97B- 10 FB BPL $B978 B97D- 2A ROL B97E- 85 26 STA $26 B980- BD 8C C0 LDA $C08C,X B983- 10 FB BPL $B980 B985- 25 26 AND $26 B987- 99 2C 00 STA $002C,Y B98A- 45 27 EOR $27 B98C- 88 DEY B98D- 10 E7 BPL $B976 B98F- A8 TAY B990- D0 02 BNE $B994 ; immediately exit -- no epilogue ; checking at all B992- 18 CLC B993- 60 RTS B994- 38 SEC B995- 60 RTS B996- 00 BRK | These are B997- 00 BRK | really on B998- 00 BRK | the disk, B999- 00 BRK | just taking B99A- 00 BRK | up space, B99B- 00 BRK | much like B99C- 00 BRK | this B99D- 00 BRK | comment. B99E- 18 CLC B99F- 60 RTS This RWTS will accept two different address prologues. If it finds a $D5 followed by a timing bit, that's it; that's the entire address prologue. Without the timing bit, it looks for the rest of a standard prologue. Turning back to the Copy ][+ nibble editor, I see the crucial detail that I missed the first time. The "D5" that I thought was the third nibble in the address prologue is actually the first, and it is displayed in inverse, meaning it has timing bits after it. (Sorry that doesn't show up in text.) The disk does happen to have a 3-nibble address prologue on every sector, but it only uses the one of them (plus a timing bit). I'm guessing that this accidental consistency is a side effect of the original mastering process. Why didn't the EDD copy work? EDD preserved the original address prologue but not the timing bits. The prologue checker finds the $D5 (at $B954) but no timing bit after it (at $B95C), so the disk can't read itself. There was never any separate nibble check; the structure of the disk itself is designed to foil nibble copiers. Why did the demuffin'd copy work? Advanced Demuffin wrote out the data from each sector onto a standard disk that uses "D5 AA 96" prologue and "DE AA EB" epilogue. The RWTS finds the first $D5, doesn't find a timing bit, but it finds the remaining standard prologue (AA 96) and decides that it found a valid address field. Thus, no RWTS patches are necessary. All 5 disks use the same protection. Quod erat liberandum. ~ Chapter 3 In Which We Patch The RWTS Anyway, And Explain Why Emulators aren't perfect. Real hardware is complicated, and the Disk II is especially difficult to emulate (being, as it is, an analog device). Many edge cases are left as "an exercise for the reader." Many copy protection schemes rely on edge cases to work. You may see where this is going. My crack of this disk works perfectly on real hardware. It also works in most Apple II emulators that run on modern hardware. But it does not work in every emulator, so I set out to discover why. Here is the RWTS code from the original disk, which I have left untouched thus far: ; find address prologue #1 B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- C9 D5 CMP #$D5 B956- D0 F0 BNE $B948 ; kill 2 CPU cycles B958- EA NOP ; read data latch one more time B959- BD 8C C0 LDA $C08C,X ; if the data latch still has $D5 in it ; then we are reading an original disk ; which uses a single nibble + timing ; bit as the address prologue, so jump ; forward to start parsing the address ; field B95C- C9 D5 CMP #$D5 B95E- F0 12 BEQ $B972 ; otherwise we are reading a standard ; disk (like a data disk -- or, in my ; case, a cracked copy), so continue ; checking the prologue for the regular ; second and third nibbles B960- BD 8C C0 LDA $C08C,X B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 B969- BD 8C C0 LDA $C08C,X B96C- 10 FB BPL $B969 B96E- C9 96 CMP #$96 B970- D0 D6 BNE $B948 At $B95C, we're checking the data latch to see if it is still holding the $D5 value. On real Disk II hardware, this will only be true if there was an extra timing bit after the $D5. The timing bit causes the data latch to retain its value for 4 more CPU cycles. This is the crux of the entire copy protection. Here's the problem: some emulators will (incorrectly) retain the $D5 value in the data latch for longer than a real drive would. This makes the RWTS think that it's reading an original disk. Specifically, $B95E (incorrectly) branches to $B972 and tries to start parsing the address field. Of course, on my crack, the address field hasn't started yet -- there are still two more nibbles in the address prologue. The address field checksum fails because we're off by two nibbles, disks grind, programs crash, everything is terrible. The solution is tricky, because we're in the middle of RWTS code so timing is tight (even in misbehaving emulators). But if we change the code at $B958 to branch to $B960, we'll have enough time to catch the second and third nibbles of the standard address prologue. This should work on real hardware, faithful emulators, and misbehaving emulators (since we'll never execute the compare at $B95C that went awry). The patched RWTS code: B94F- BD 8C C0 LDA $C08C,X B952- 10 FB BPL $B94F B954- C9 D5 CMP #$D5 B956- D0 F0 BNE $B948 B958- F0 06 BEQ $B960 ------+ B95A- [8C C0] \ | B95C- [C9 D5] } never executed | B95E- [F0 12] / | B960- BD 8C C0 LDA $C08C,X <---+ B963- 10 FB BPL $B960 B965- C9 AA CMP #$AA B967- D0 DF BNE $B948 T00,S03,$58 change "EA BD" to "F0 06" ~ Changelog 2015-12-21 - apply and explain patch for legacy emulators --------------------------------------- A 4am crack No. 199 ------------------EOF------------------