-------Science Volume 2: Geology------- A 4am crack 2014-12-16 --------------------------------------- "Science Volume 2: Geology" is a 1986 educational program developed by Decision Development Co. and distributed by The Ellen Nelson Learning Library. The program is distributed on one double-sided disk and uses both sides. Only side A is bootable. COPYA fails miserably and immediately with a disk read error on both sides. EDD 4 bit copy gives no read errors, but the copy it produces just reboots endlessly. In my experience, programs do not spontaneously reboot unless someone tells them to. Turning to my trusty Disk Fixer sector editor, I go to "Input/Output Control" (press "O") and set CHECKSUM ENABLED = NO. This option ignores checksum bytes and epilogue sequences -- as long as the address and data prologue are standard ("D5 AA 96" and "D5 AA AD", respectively), this will allow me to read each sector. And lo and behold, it works! I can read the data from every sector on every track. Track $00 appears to have a relatively standard RWTS, but I don't see any disk catalog on track $11. Hmm. Based on my limited experience cracking other disks, I would guess that this disk has - Standard prologue bytes before the address and data fields [otherwise Copy ][+ sector editor would give read errors, even with the "DOS 3.3 PATCHED" option] - Non-standard epilogue bytes after the address and data fields [otherwise COPYA would work] - Some secondary protection [otherwise the bit copy created with EDD 4 would work] Given the (relatively) weak structural protection, I used to turn to the DOS 3.3 master disk, patch the RWTS to ignore checksums and epilogue bytes (changing $B942 from "SEC" to "CLC"), and run COPYA. Then, one fine day, and completely by accident, I came across an original disk with a bad sector. I suppose this shouldn't surprise me. These floppies are decades old by now; it's amazing any of them work at all. The point is, I shouldn't be using tools that ignore potentially serious read errors. There are other tools, like Super Demuffin, that can convert a disk like this (with non-standard epilogue bytes) into a standard format. It requires figuring out what the actual epilogue bytes are, but it has the advantage of surfacing a read error if the original disk actually has a read error. So... no more COPYA+B942:18 patch. From now on, it's Super Demuffin or Advanced Demuffin to convert disks to a standard format. Given that this disk is self- booting, I should be able to use my AUTOTRACE program to extract the RWTS from the original disk, then load that into Advanced Demuffin to convert it to a standard format. Time for boot tracing with AUTOTRACE. [S6,D1=original disk (side A)] [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 /!\ NIBBLE CHECK AT $BB00 For those of you just tuning in, my work disk uses a custom program that I affectionately call "AUTOTRACE" to automate the process of boot tracing as far as possible. For some disks, this just captures track 0, sector 0 (saved in a file called "BOOT0") and stops. For other disks that load in the same way that an unprotected DOS 3.3 disk loads, it captures the next stage of the boot process as well (in a file called "BOOT1"). BOOT1 contains sectors 0-9 on track 0, which are loaded into memory at $B600..$BFFF. This generally contains the RWTS routines which the program uses to read the rest of the disk. If the RWTS is fairly normal as well (and my AUTOTRACE program just spot- checks a few memory locations to guess at its "normalcy"), there's a good chance I'll be able to use a tool called Advanced Demuffin (written in 1983 by The Stack) to convert the disk from whatever weird format it uses to store its sector data into a standard disk readable by unprotected DOS 3.3 disks or any other third-party tools. In this case, AUTOTRACE extracts the RWTS routines (generally loaded from track 0, sectors 2-9 into $B800..$BFFF) and saves *that* into a third file called "RWTS". If anything looks fishy or non- standard, AUTOTRACE just stops, and I have to check the files it saved so far to determine why. But in this case, it ran all the way through, automatically capturing BOOT0, BOOT1, and RWTS files. Now I can use Advanced Demuffin to convert the disk to a standard format. (It uses the disk's own RWTS to read the original, then a standard DOS 3.3- compatible RWTS to write out the data, sector by sector.) Along the way, AUTOTRACE gave me a warning about a possible nibble check, which is very exciting(*). I just added this warning recently, and here I am already reaping the benefits. It just scans the $BB00 page for the opcodes "BD 89 C0" (LDA $C089,X), which is a common instruction in nibble checks. (*)not guaranteed, excitement may vary I'll come back to the nibble check in a moment. First, I want to use Advanced Demuffin to convert the disk to a standard format. It uses the disk's own RWTS to read the original (stored in the RWTS file), then a standard DOS 3.3 RWTS to write out the data, sector by sector. [S6,D1=original disk (side A)] [S6,D2=blank disk] [S5,D1=my work disk] ]PR#5 ... ]BRUN ADVANCED DEMUFFIN 1.5 [press "5" to switch to slot 5] [press "R" to load a new RWTS module] --> At $B8, load "RWTS" from drive 1 [press "6" to switch to slot 6] [press "C" to convert disk] This disk is 16 sectors, and the default options (copy the entire disk, all tracks, all sectors) don't need to be changed unless something goes horribly wrong. --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 --^-- The disk's own RWTS gave no read errors on any track. (I repeated the procedure with side B; it also gave no errors.) This is the power and the genius of Advanced Demuffin. Every disk must be able to read itself. So, let it read itself, then capture the data and write it out in a standard format. There are two problems with this copy: 1. Depending on how the original disk was written, this copy may or may not be able to read itself. I may need to patch the disk's RWTS to deal with the fact that the disk is now in a standard format. 2. Even if it can read itself, it won't run. The copies I tried to make -- even the bit copies -- would reboot early, which means there must be a routine being executed during boot to check if the disk is original. (Hint: it's not.) Just booting the demuffin'd copy confirms problem #2: it still reboots endlessly, just like the bit copies I tried to make. That means there's a nibble check somewhere, and based on how quickly the copy reboots, it's very early in the boot process. Let's go find that nibble check. ]PR#5 ... *BLOAD BOOT1,A$2600 *FE89G FE93G ; disconnect DOS *B600<2600.2FFFM ; put custom RWTS in ; place *B700L B700- 20 1A BC JSR $BC1A *BC1AL ; this is the instruction I was ; expecting at $B700 (but it called ; this subroutine instead) BC1A- 8E E9 B7 STX $B7E9 ; OK BC1D- A9 00 LDA #$00 BC1F- 8D 78 04 STA $0478 BC22- 48 PHA BC23- A6 2B LDX $2B BC25- A9 00 LDA #$00 ; OK BC27- 20 A0 B9 JSR $B9A0 ; hello BC2A- 20 03 BB JSR $BB03 BC2D- 68 PLA BC2E- 08 PHP BC2F- A6 2B LDX $2B BC31- 20 A0 B9 JSR $B9A0 BC34- 28 PLP BC35- 60 RTS $B9A0 moves the drive head to the track specified in the accumulator. Anything in the $BB00 range is suspect. In any relatively normal RWTS, that entire page of memory gets overwritten with every disk read during denibblization, which is a real word that I totally just made up. *BB03L ; save some zero page state 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 ; hello BB0D- 20 00 BC JSR $BC00 *BC00L ; set 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 BC15- A6 2B LDX $2B ; hello BC17- 4C 30 BB JMP $BB30 *BB30L ; turn on the disk motor manually: ; always a sign of impending evil bits BB30- A6 2B LDX $2B BB32- BD 89 C0 LDA $C089,X BB35- BD 8E C0 LDA $C08E,X ; this is an address, $BBAE, used later 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 ; the death counter BB44- A9 80 LDA #$80 BB46- 85 08 STA $08 ; if the death counter hits zero... BB48- C6 08 DEC $08 BB4A- F0 5C BEQ $BBA8 ;fail ; read the next available address field BB4C- 20 44 B9 JSR $B944 BB4F- B0 57 BCS $BBA8 ;fail ; look for sector $0D BB51- A5 2D LDA $2D BB53- C9 0D CMP #$0D BB55- D0 F1 BNE $BB48 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 the disk will ; get out of sync and read the wrong ; nibble values. 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 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 ; success path falls through to here -- ; clear carry and exit BBA6- 18 CLC BBA7- 60 RTS ; any failure ends up here -- decrement ; the death counter and retry BBA8- C6 09 DEC $09 BBAA- D0 98 BNE $BB44 ; out of chances, set carry and exit BBAC- 38 SEC BBAD- 60 RTS OK, so it's a nibble check that clears the carry if it works and sets the carry if it fails. (This is the same convention that DOS 3.3 RWTS uses.) Unwinding the calling stack, we left off here: BB0D- 20 00 BC JSR $BC00 ; save flags BB10- 08 PHP ; restore zero page state 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 ; restore flags BB1B- 28 PLP ; if nibble check passed, continue BB1C- 90 0F BCC $BB2D ; if nibble check failed, push the ; $Cx00 address onto the stack and ; "return" to it (i.e. reboot) BB1E- A5 2B LDA $2B BB20- 4A LSR BB21- 4A LSR BB22- 4A LSR BB23- 4A LSR BB24- 09 C0 ORA #$C0 BB26- A8 TAY BB27- 88 DEY BB28- 98 TYA BB29- 48 PHA BB2A- A9 FF LDA #$FF BB2C- 48 PHA BB2D- A6 2B LDX $2B BB2F- 60 RTS Which is exactly the behavior I saw. It appears I can simply bypass this entire routine without any adverse consequences. Unwinding the stack even further, this all started at $B700, which called $BC1A, which stored the X register in $B7E9 (useful) then did a nibble check (not useful). If I replace the JSR at $B700 with the instruction that is usually there (STX $B7E9), that should bypass the entire thing. A lot of disks need this sort of patching, and I got tired of doing it manually, so I wrote a program to do it for me. It is called Post-Demuffin Patcher ("PDP" for short). PDP prompts you to select a slot and drive, then reads the demuffin'd disk, checks for a modified DOS 3.3-shaped RWTS, and applies the necessary patches so the disk can read itself. It also detects and bypasses some known nibble checks, like the one on this disk. I've included a copy of Post-Demuffin Patcher on my work disk; the full source code is currently available at . [S6,D1=demuffin'd copy] [S5,D1=my work disk] ]PR#5 ... ]BRUN PDP T00,S01,$00 change 201ABC to 8EE9B7 (This is the actual output of the program. Post-Demuffin Patcher prints out the changes it is going to make before it writes them to the disk.) I should point out that Post-Demuffin Patcher is really quite conservative in making patches. It checks a lot of the surrounding code before deciding to patch a specific location. In the case of bypassing this nibble check, it checks every single byte of code up to and including the JSR $BC1A, to ensure that the disk is using a known DOS 3.3- shaped bootloader up until that point. And there were dozens of patches that it didn't make to this disk (like RWTS patches), because it decided they weren't needed. ]PR#6 Everything works. The disk boots and runs without complaint. The RWTS must be liberal enough that it can still read the disk even after it's been converted to a standard format. (Press 6 at the main menu to get to an option that prompts for side B. It also reads with no problem.) There doesn't appear to be any further protection. Quod erat liberandum. --------------------------------------- A 4am crack No. 179 ------------------EOF------------------