------------Algebra Volume 1----------- A 4am crack 2015-04-27 --------------------------------------- Name: Algebra Volume 1 Version: 1.7 (1984-09-14) Genre: educational Year: 1984 Publisher: Edu-Ware, Inc. Media: single-sided 5.25-inch floppy OS: DOS 3.3 Other versions: none (preserved here for the first time) Identical cracks: The World's Greatest Baseball Game (4am crack no. 91) ~ 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 hangs on boot Copy ][+ nibble editor all tracks use standard prologues (address: D5 AA 96, data: D5 AA AD) but modified epilogues (address: FF FF FF, data: FF FF FF) Disk Fixer ["O" -> "Input/Output Control"] set Address Epilogue to "FF FF FF" set Data Epilogue to "FF FF FF" Success! All tracks readable! T00 -> looks like a DOS 3.3 RWTS T11 -> DOS 3.3 disk catalog T01,S09 -> startup program is "BOOT" Why didn't COPYA work? modified epilogue bytes (every track) Why didn't Locksmith FDB work? modified epilogue bytes (every track) Why didn't my EDD copy work? probably a nibble check during boot Next steps: 1. AUTOTRACE to capture RWTS 2. Advanced Demuffin to convert disk to standard format 3. Post-Demuffin Patcher to patch RWTS (if necessary) 3. 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] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 SAVING RWTS ]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 ["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:R.................................. +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:................................... SC1:................................... SC2:................................... SC3:................................... SC4:................................... SC5:................................... SC6:................................... SC7:................................... SC8:................................... SC9:................................... SCA:R.................................. SCB:................................... SCC:................................... SCD:................................... SCE:................................... SCF:................................... ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- Hmm. Even the disk's own RWTS can't read T00,S0A. I'm hoping that's part of the copy protection and not a bad disk. ]PR#5 ]CATALOG,S6,D2 C1983 DSR^C#254 025 FREE *B 031 EWS3 *A 012 ALGEBRA 1 *I 002 APPLESOFT T 002 AM1.PROGRESS T 002 AM1.ERR *A 058 AM1.1 *A 028 AM1.1.1 *A 057 AM1.2 *A 023 AM1.2.1 *A 057 AM1.3 *A 026 AM1.3.1 *A 052 AM1.4 *A 058 AM1.5 *A 040 AM1.6 *A 015 AM1.ERROR *A 008 BOOT ]RUN BOOT ...works... [S6,D1=demuffin'd copy] ]PR#6 ...reboots endlessly... Let's go find that nibble check. ~ Chapter 2 In Which We Find That Nibble Check ]PR#6 ... ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; move RWTS into place *B700L ; hey now, what's all this then? B700- 20 00 BB JSR $BB00 Highly suspect. I definitely want to see what evil lurks at $BB00. That area of memory is normally reserved for the denibblizing process when reading data from a sector. It's scratch space, essentially. It's overwritten every time the disk reads itself (after boot1 is loaded). *BB00L ; this is the instruction I expected to ; see at $B700 BB00- 8E E9 B7 STX $B7E9 ; save zero page BB03- A2 00 LDX #$00 BB05- B5 00 LDA $00,X BB07- 9D 00 50 STA $5000,X BB0A- CA DEX BB0B- 10 F8 BPL $BB05 ; hmm BB0D- 20 00 BC JSR $BC00 ; restore zero page BB10- 08 PHP BB11- A2 00 LDX #$00 BB13- B9 00 50 LDA $5000,Y BB16- 95 00 STA $00,X BB18- CA DEX BB19- 10 F8 BPL $BB13 BB1B- 28 PLP ; hmm, branching based on the carry bit BB1C- 90 0F BCC $BB2D ; The Badlands (the point of no return) ; this takes the slot (x16) and munges ; it into a $Cx value, like $C6 for ; slot 6 BB1E- A5 2B LDA $2B BB20- 4A LSR BB21- 4A LSR BB22- 4A LSR BB23- 4A LSR BB24- 09 C0 ORA #$C0 ; ...then decrements it BB26- A8 TAY BB27- 88 DEY BB28- 98 TYA ; ...pushes it to the stack BB29- 48 PHA ; ...now pushes $FF to the stack BB2A- A9 FF LDA #$FF BB2C- 48 PHA BB2D- A6 2B LDX $2B ; ...and "returns" to that address (+1) ; which will reboot. You know, just in ; case you were searching for the magic ; string "4C 00 C6" to find where the ; program rebooted, you won't find it. BB2F- 60 RTS Let's see what wonderfulness awaits us at $BC00. *BC00L ; set the reset vector to reboot BC00- A5 2B LDA $2B BC02- 4A LSR BC03- 4A LSR BC04- 4A LSR BC05- 4A LSR BC06- 09 C0 ORA #$C0 BC08- 8D F3 03 STA $03F3 BC0B- 49 A5 EOR #$A5 BC0D- 8D F4 03 STA $03F4 BC10- A9 00 LDA #$00 BC12- 8D F2 03 STA $03F2 ; and jump back to $BB30 BC15- A6 2B LDX $2B BC17- 4C 30 BB JMP $BB30 *BB30L ; Oh look, we're turning on the drive ; motor manually. Will this ever not ; be suspicious? Every nibble check ; does it, and it's always suspicious. BB30- A6 2B LDX $2B BB32- BD 89 C0 LDA $C089,X BB35- BD 8E C0 LDA $C08E,X BB38- A9 AE LDA #$AE BB3A- 85 1E STA $1E BB3C- A9 BB LDA #$BB BB3E- 85 1F STA $1F BB40- A9 0A LDA #$0A BB42- 85 09 STA $09 ; loop to search for specific sector BB44- A9 80 LDA #$80 BB46- 85 08 STA $08 BB48- C6 08 DEC $08 BB4A- F0 5C BEQ $BBA8 ;fail ; find next address field BB4C- 20 44 B9 JSR $B944 BB4F- B0 57 BCS $BBA8 ;fail ; sector $0A? BB51- A5 2D LDA $2D BB53- C9 0A CMP #$0A ; nope, try again BB55- D0 F1 BNE $BB48 ; find next $D5 nibble BB57- A0 00 LDY #$00 BB59- BD 8C C0 LDA $C08C,X BB5C- 10 FB BPL $BB59 BB5E- 88 DEY BB5F- F0 47 BEQ $BBA8 ;fail BB61- C9 D5 CMP #$D5 BB63- D0 F4 BNE $BB59 ; Search for a specific sequence of ; nibbles in the "dead zone" between ; the address field and data field. ; This area is normally not important, ; so COPYA didn't copy it precisely ; because normal disks don't care. ; (Actually, it's even more evil than ; that, because the original disk is ; written with timing bits in specific ; non-standard places between the ; nibbles in the dead zone. This code ; not only requires the right nibbles ; in the right order, it reads them ; just slightly slower than normal. So ; the timing bits need to be in the ; right places too, or else this code ; will read the wrong nibble values ; while it's out of sync. This will ; trip up even the best bit copiers. ; And you can forget about making a ; disk image for emulators -- those ; don't store timing bits at all.) BB65- A0 00 LDY #$00 BB67- BD 8C C0 LDA $C08C,X BB6A- 10 FB BPL $BB67 BB6C- 88 DEY BB6D- F0 39 BEQ $BBA8 ;fail BB6F- C9 E7 CMP #$E7 BB71- D0 F4 BNE $BB67 BB73- BD 8C C0 LDA $C08C,X BB76- 10 FB BPL $BB73 BB78- C9 E7 CMP #$E7 BB7A- D0 2C BNE $BBA8 ;fail BB7C- BD 8C C0 LDA $C08C,X BB7F- 10 FB BPL $BB7C BB81- C9 E7 CMP #$E7 BB83- D0 23 BNE $BBA8 ;fail BB85- BD 8D C0 LDA $C08D,X ; kill some time to get out of sync ; with the "proper" start of nibbles) BB88- A0 10 LDY #$10 BB8A- 24 FF BIT $FF ; now start looking for nibbles that ; don't really exist (except they do, ; because we're out of sync and reading ; timing bits as data) BB8C- BD 8C C0 LDA $C08C,X BB8F- 10 FB BPL $BB8C BB91- 88 DEY BB92- F0 14 BEQ $BBA8 ;fail BB94- C9 EE CMP #$EE BB96- D0 F4 BNE $BB8C ; check for nibble sequence stored ; in reverse order at $BBAE, via ($1E) BB98- A0 07 LDY #$07 BB9A- BD 8C C0 LDA $C08C,X BB9D- 10 FB BPL $BB9A BB9F- D1 1E CMP ($1E),Y BBA1- D0 05 BNE $BBA8 ;fail BBA3- 88 DEY BBA4- 10 F4 BPL $BB9A ; if we made it this far, the nibble ; check passed -- clear carry and exit BBA6- 18 CLC BBA7- 60 RTS ; failure path is here -- after enough ; tries, set carry and exit BBA8- C6 09 DEC $09 BBAA- D0 98 BNE $BB44 BBAC- 38 SEC BBAD- 60 RTS Which gets us all the way back to the branch-if-carry-is-clear at $BB1C. So basically, this entire routine is unnecessary. If the nibble check succeeds, it clears the carry ($BBA6) and returns to code that checks if the carry is clear ($BB1C) and if so just returns to the caller ($B700). If the nibble check fails, it sets the carry ($BBAC) and returns to code that is somewhat obfuscated but ends up rebooting (which matches the behavior I saw in my failed bit copy). The first instruction (at $BB00) is really the code that belongs at $B700, which called this entire mess. So let's just restore that instruction and this code will never execute. ~ Chapter 3 In Which We Remove All Traces Of Copy Protection Using An Automated Tool That I Wrote For Just Such An Occasion [S6,D1=demuffin'd copy] [S5,D1=my work disk] ]PR#5 ... ]BRUN PDP T00,S01,$00 change 2000BB to 8EE9B7 The RWTS is flexible enough to read a standard format disk, so no patches are required. Quod erat liberandum. --------------------------------------- A 4am crack No. 298 ------------------EOF------------------