----------Acid/Base Reactions---------- A 4am crack 2016-02-20 --------------------------------------- Name: Acid/Base Reactions Genre: educational Year: 1983 Authors: J. Frazin & Partners Publisher: Encyclopaedia Britannica Educational Corporation Media: single-sided 5.25-inch floppy OS: Diversi-DOS variant (T02,S02 has the string "C1984 RPS" backwards) Previous cracks: none ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA disk read error on first pass Locksmith Fast Disk Backup can't read anything past track $02 EDD 4 bit copy (no sync, no count) no errors during copying, but copy loads DOS then exits to a prompt with memory wiped Copy ][+ nibble editor T03+ appear normal, not sure why they are unreadable Disk Fixer T00 -> looks like a DOS 3.3 RWTS T00-T02 -> looks like a full DOS T01,S09 -> startup program is "START" T03+ unreadable ["O" -> "Input/Output Control"] set CHECKSUM ENABLED to "NO" T03+ readable, but garbage --v-- -------------- DISK EDIT -------------- TRACK $11/SECTOR $0F/VOLUME $01/BYTE$00 --------------------------------------- $00:>00<11 0E 00 FF 00 FF 00 @QN@.@.@ $08: FF 00 FF ED F0 7D 2C 2B .@.mp=,+ $10: 3E 2D 2B 5F A0 5F A0 5F >-+_ _ _ $18: A0 5F A0 5F A3 5F A3 5F _ _#_#_ $20: A3 5F A0 5C A0 5F A0 5F #_ \ _ _ $28: A0 5F A0 5F EE FF DE FC _ _n.^| $30: 7D 32 39 32 29 4E 5C A0 =292)N\ $38: 5C A0 5F A0 5F A0 5F A3 \ _ _ _# $40: 5F A3 5F A3 5F A0 5C A0 _#_#_ \ $48: 5F A0 5F A0 5F A0 5F F0 _ _ _ _p $50: FF E4 F3 7E 35 51 4D 5C .ds>5QM\ $58: A0 5C A3 5C A3 5C A3 5C \#\#\#\ $60: A3 5F A3 5F A3 5F A3 5F #_#_#_#_ $68: A3 5F A0 5F A0 5F A0 5F #_ _ _ _ $70: A0 5F D8 FF E6 F0 7D 36 _X.fp=6 $78: 51 4E 5C A3 5C A3 5C A3 QN\#\#\# --------------------------------------- BUFFER 0/SLOT 6/DRIVE 1/MASK OFF/NORMAL --------------------------------------- COMMAND : _ --^-- Why didn't COPYA work? weird stuff goin' on after track $02 Why didn't Locksmith FDB work? ditto Why didn't my EDD copy work? Probably a nibble check during boot. DOS does not simply unload itself unless someone tells it to. Why do the sectors look like garbage even after changing the data epilogue? probably some changes to the nibble translate table (possibly tied to the protection check) Next steps: 1. trace the boot to find the protection check and RWTS changes 2. capture the final RWTS and use it to convert the rest of the disk 3. ??? ~ Chapter 1 In Which Automated Tools Get Us Nowhere [S6,D1=original disk] [S6,D2=blank 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] [ to start conversion] ...Advanced Demuffin crashes... Wait, what? ]PR#5 ... ]BLOAD RWTS,A$3800 ]CALL -151 *FE89G FE93G *B800<3800.3FFFM *B800L . . all normal, until... . B925- BC 8C C0 LDY $C08C,X B928- 10 FB BPL $B925 B92A- D9 00 BA CMP $BA00,Y B92D- D0 13 BNE $B942 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- 4C B3 B6 JMP $B6B3 <-- ! B941- EA NOP B942- 38 SEC B943- 60 RTS This is the code to match the data epilogue. But instead of comparing the second nibble (usually $AA), execution continues at $B6B3. This is outside the normal zone of the RWTS ($B800..$BFFF), and I didn't have it in memory when I ran Advanced Demuffin, so as soon as the RWTS tried to jump to it, it crashed. Solution: use the entire BOOT1 file, which contains the RWTS but also the two pages at $B600 and $B700. Normally these are only used during boot, but apparently this RWTS is... special. ]PR#5 ... ]BRUN ADVANCED DEMUFFIN ["5" to switch to slot 5] ["R" to load a new RWTS module] --> At $B6, load "BOOT1" from drive 1 ["6" to switch to slot 6] ["C" to convert disk] [ to start conversion] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM =======PRESS ANY KEY TO CONTINUE======= TRK:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR +.5: 0123456789ABCDEF0123456789ABCDEF012 SC0:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC1:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC2:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC3:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC4:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC5:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC6:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC7:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC8:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SC9:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCA:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCB:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCC:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCD:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCE:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR SCF:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR ======================================= 16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- Well then. That was... not entirely successful. Not entirely unsuccessful, I suppose. I mean, at least it didn't crash. But now it appears that the RWTS is modified mid-stream, or more to the point, mid-boot. I need to dig deeper. ~ Chapter 2 In Which All Secrets Are Laid Bare ]PR#5 ... ]BLOAD BOOT1,A$3600 ]CALL -151 *B600<3600.3EFFM *B700L . . all normal, until... . B747- 4C C1 B3 JMP $B3C1 That normally jumps to $9D84 to cold- start DOS, load the startup program, and so on and so forth. But first, we're doing a little something extra at $B3C1. That is normally part of the temporary buffer that holds the catalog VTOC sector; it shouldn't have anything at all yet. *9600 $0800 (source start address) ($3E) -> $BFFE (source end address) ($42) -> $0801 (target start address) It copies $0800 to $0801, then $0801 to $0802, and so on. Since it works upward in memory, it ends up copying the value of $0800 to every memory address up to $BFFF. Then it issues an "RTS", which pops the address we pushed earlier ($DFFF), adds 1, and jumps to $E000. Which is exactly the behavior I saw on my failed EDD bit copy. The value of $B6B8 is the difference between an original and a copy. But what is it? Then I remembered this... B925- BC 8C C0 LDY $C08C,X B928- 10 FB BPL $B925 B92A- D9 00 BA CMP $BA00,Y B92D- D0 13 BNE $B942 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- 4C B3 B6 JMP $B6B3 <-- ! I glossed over that with a minimum of concern, but I bet the routine at $B6B3 is what is responsible for determining the value of $B6B8. *B6B3L ; check second data epilogue, as usual B6B3- C9 AA CMP #$AA B6B5- F0 02 BEQ $B6B9 B6B7- 60 RTS ... ; execution continues here (from $B6B5) ; and we check the third data epilogue ; nibble B6B9- BD 8C C0 LDA $C08C,X B6BC- 10 FB BPL $B6B9 ; burn some cycles calling a routine ; that does nothing (each JSR costs 6 ; CPU cycles, and each RTS also costs ; 6, so this is burning 24 cycles!) B6BE- 20 B7 B6 JSR $B6B7 B6C1- 20 B7 B6 JSR $B6B7 ; burn another 2 cycles B6C4- EA NOP ; check data latch (only once -- no BPL ; loop here) B6C5- BD 8C C0 LDA $C08C,X B6C8- 30 04 BMI $B6CE ; Because we burned so many CPU cycles, ; we will only end up here if there is ; a timing bit after the third epilogue ; nibble. B6CA- EE B8 B6 INC $B6B8 B6CD- 18 CLC B6CE- 60 RTS And there it is: the difference between an original and a bit copy is a hidden timing bit after the third data epilogue nibble. EDD didn't preserve these timing bits, and the bootloader was counting them as it loaded DOS. (The counter starts at $00 because it's stored on disk. I was confused at first because, by the time I checked it in memory, it had already been incremented by the RWTS!) As soon as DOS is loaded, it checks the counter and knows if it's running on a copy. On an original disk, the counter at $B6B8 is at least $1A, so execution continues at $B40B: ; remove redirect to $B6B3, restore ; normal data epilogue comparison code ; (but remember we've already messed ; with the nibble translation table, so ; tracks $03+ will be decoded slightly ; differently than tracks $00-$02) B40B- A9 C9 LDA #$C9 B40D- 8D 3E B9 STA $B93E B410- A9 AA LDA #$AA B412- 8D 3F B9 STA $B93F B415- A9 F0 LDA #$F0 B417- 8D 40 B9 STA $B940 B41A- A9 5C LDA #$5C B41C- 8D 41 B9 STA $B941 ; restore the normal code at $B6B3 from ; a copy that we've apparently been ; hiding in this page B41F- A0 00 LDY #$00 B421- B9 2F B4 LDA $B42F,Y B424- F0 06 BEQ $B42C B426- 99 B3 B6 STA $B6B3,Y B429- C8 INY B42A- D0 F5 BNE $B421 ; and finally continue the boot B42C- 4C 84 9D JMP $9D84 ~ Chapter 3 In Which We (Finally) Use The Original Disk Against Itself I'm going to trace the boot even further, until after the timing bit counting succeeds and the routines at $B3C1 and $B40B make the modifications that allow me to read the rest of the disk. *C500G ... *9600 At $B6, load "BOOT1 3+" from D1 ["6" to switch to slot 6] ["C" to convert disk] ["Y" to change default values] --v-- ADVANCED DEMUFFIN 1.5 (C) 1983, 2014 ORIGINAL BY THE STACK UPDATES BY 4AM ======================================= INPUT ALL VALUES IN HEX SECTORS PER TRACK? (13/16) 16 START TRACK: $03 <-- change this START SECTOR: $00 END TRACK: $22 END SECTOR: $0F INCREMENT: 1 MAX # OF RETRIES: 0 COPY FROM DRIVE 1 TO DRIVE: 2 ======================================= 16SC $03,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- And here we go... --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 $03,$00-$22,$0F BY1.0 S6,D1->S6,D2 --^-- Gotcha. ]PR#5 ... ]CATALOG,S6,D2 C1983 DSR^C#254 047 FREE *A 017 START *A 012 MENU2 *A 039 I-1 *A 047 I-2 *A 038 I-3 *A 043 I-4 *A 012 MENU3 *A 040 II-1 *A 036 II-2 *A 036 II-3 *A 069 III-1 *B 002 RBOOT *B 009 SET14 *B 034 PIC.GHLLOGO *B 004 TABLE 1 *T 002 COMPOUNDS *T 002 I-1COMPS *T 002 KA'S *T 002 II-2COMPS *B 003 PLOT14.OBJ0 ]RUN START ...works... (The reason I always do this is to see whether there are any runtime checks for subtle differences in the original DOS. If the program runs after booting from a third-party disk, I can eliminate a whole range of possible secondary protections.) Now to make the disk be able to read itself (remember, it still has the original RWTS on it)... [Copy ][+ 8.4] --> COPY --> DOS --> from slot 6, drive 2 --> to slot 6, drive 1 [S6,D1=demuffin'd copy] [S6,D2=newly formatted DOS 3.3 disk] ...read read read... ...write write write... And finally, I need to change the startup program to "START". Copy ][+ has a dedicated function for this, too. [Copy ][+] --> CHANGE BOOT PROGRAM --> on slot 6, drive 1 --> "START" ]PR#6 ...works... There doesn't appear to be any further protection. Quod erat liberandum. --------------------------------------- A 4am crack No. 606 ------------------EOF------------------