----------Travels with Za-Zoom--------- ---------------The World--------------- A 4am crack 2014-11-14 --------------------------------------- "Travels with Za-Zoom: The World" is a 1984 educational game by Frederick Burggraf, with educational consultant Priscilla Minnich, and distributed by Focus Media. [The copy protection is identical to "The Time Tunnel," also distributed by Focus Media. This write-up is therefore quite similar to that one, with a few corrections.] COPYA fails miserably and immediately. Locksmith Fast Disk Backup fares no better. EDD 4 bit copy gives no read errors, but the copy it creates just hangs very early in the boot process. It doesn't sound like it ever gets off track 0. 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, with one exception: T00,S0A. Given that the original disk boots correctly, I'm going to guess that this sector is either unused (in which case, I have a damaged original disk but caught a lucky break) or part of a copy protection scheme (in which case I don't care). From a brief manual inspection, I'd say the RWTS on track 0 strongly resembles a DOS 3.3 RWTS. There is a VTOC (disk catalog) on track $11, but the original disk sounds like it's doing some extra disk work before loading DOS. It does eventually display the normal DOS prompt and swing out to track $11, though. 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. 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] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 /!\ BOOT0 JUMPS TO ($BBFE) CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 SAVING RWTS Well, that worked flawlessly. My work disk first sets up a minimal boot trace to capture the first sector of track 0 and saves it to the file "BOOT0" (on my work disk, not the original disk). If the first sector looks reasonably normal, it sets up a more involved boot trace to capture the rest of track 0 and save it to the file "BOOT1". And if that looks reasonably normal, it saves the RWTS to a file, unimaginatively named "RWTS", which can be loaded with Advanced Demuffin. Furthermore, my AUTOTRACE program detected a non-standard jump after boot0. Usually boot0 loads boot1 and jumps to it indirectly via ($08FD), but this disk is jumping to ($BBFE) instead. Highly suspicious. Probably a nibble check of some kind. Definitely worth a look. I'll come back to the nibble check. First, I want to take the RWTS I extracted and load it into Advanced Demuffin to convert this disk to a standard format. [S6,D1=original disk] [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: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 that one sector on track 0. (This is the same sector I failed to read in a sector editor.) On the plus side, the disk's own RWTS gave no read errors on any other track or sector. 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. Now I have a copy of each disk in a standard format that can be read by any third-party tool. That is, I can copy these disks with COPYA or Locksmith Fast Disk Backup, without patching the DOS 3.3 RWTS beforehand. I can sector edit the disk without messing with the epilogue bytes, &c. There are two problems with this copy: 1. Depending on how the original RWTS was written, a demuffin'd disk may not be able to read itself. Some developers just patch the RWTS to ignore epilogue bytes, while others patch the RWTS to look for specific non-standard epilogue bytes. Demuffin'd disks in the latter category will grind immediately on boot, since as soon as the RWTS is loaded, all further disk reads will look for the original (non-standard) epilogue bytes and not find them. 2. Even if it can read itself, it won't run. The copies I tried to make -- even the bit copies -- just hung, which means there is some code being executed during boot to check if the disk is original. (Hint: it's not.) Booting my non-working copy, it seems I need to solve #2 before I can tackle #1. The disk exhibits the same behavior as my failed bit copy: the disk hangs very early in the boot process. I don't think it's even getting far enough to call the RWTS. Let's go find that nibble check. ]PR#5 ... ]BLOAD BOOT1,A$2600 ]CALL -151 *FE89G FE93G ; disconnect DOS *B600<2000.29FFM ; move RWTS in place *BBFE.BBFF BBFE- 00 BB *BB00L *BB00L ; Ah, I recognize this routine already. ; It was used by several different ; publishers, and it apparently had ; tweakable options. Turning off an ; option would generate code that makes ; no sense at first glance. BB00- A9 FF LDA #$FF BB02- 85 D6 STA $D6 BB04- BD 8D C0 LDA $C08D,X ; Some disks have a "LDA $C08E,X" here ; to require that the disk be write- ; protected. With the option off, it's ; just an unconditional jump. BB07- A9 FF LDA #$FF BB09- EA NOP BB0A- 30 05 BMI $BB11 BB0C- A2 B1 LDX #$B1 BB0E- 4C F0 BB JMP $BBF0 BB11- AD FD FF LDA $FFFD ; Some disks have a "CMP #$FA" here to ; check if the low-level reset vector ; has been tampered with. Without that, ; it's another unconditional jump. ; (I think this was protection against ; "boot inspectors" like Watson.) BB14- A9 00 LDA #$00 BB16- F0 05 BEQ $BB1D BB18- A2 B2 LDX #$B2 BB1A- 4C F0 BB JMP $BBF0 ; look for a magic nibble sequence on ; track 0 BB1D- BD 8C C0 LDA $C08C,X BB20- A9 00 LDA #$00 BB22- 8D 00 02 STA $0200 BB25- BD 8C C0 LDA $C08C,X BB28- 10 FB BPL $BB25 BB2A- C9 EB CMP #$EB BB2C- D0 F7 BNE $BB25 BB2E- BD 8C C0 LDA $C08C,X BB31- 10 FB BPL $BB2E BB33- C9 D5 CMP #$D5 BB35- D0 EE BNE $BB25 BB37- BD 8C C0 LDA $C08C,X BB3A- 10 FB BPL $BB37 BB3C- C9 AA CMP #$AA BB3E- D0 E5 BNE $BB25 ; wipe most of memory ($0800..$95FF) ; although, ironically, not the part ; I'm using for boot tracing BB40- A9 4C LDA #$4C BB42- A0 00 LDY #$00 BB44- 99 00 95 STA $9500,Y BB47- 88 DEY BB48- D0 FA BNE $BB44 BB4A- CE 46 BB DEC $BB46 BB4D- AD 46 BB LDA $BB46 BB50- C9 07 CMP #$07 BB52- D0 EC BNE $BB40 ; fiddle with the RWTS to ignore ; epilogue bytes BB54- A9 18 LDA #$18 BB56- 8D 42 B9 STA $B942 ; sector $0A BB59- A9 0A LDA #$0A BB5B- 8D ED B7 STA $B7ED BB5E- D0 05 BNE $BB65 ... ; track $00 BB65- A9 00 LDA #$00 BB67- 8D EC B7 STA $B7EC ; seek command (not read) BB6A- 8D F0 B7 STA $B7F0 ; into $4000 BB6D- A9 40 LDA #$40 BB6F- 8D F1 B7 STA $B7F1 BB72- A9 01 LDA #$01 BB74- 8D F4 B7 STA $B7F4 BB77- 8D F8 B7 STA $B7F8 BB7A- 8D EA B7 STA $B7EA BB7D- 8E E9 B7 STX $B7E9 BB80- 8E F7 B7 STX $B7F7 ; more RWTS fiddling, so sector reads ; save raw nibble data in $6C00 range BB83- A0 6C LDY #$6C BB85- 8C 10 B9 STY $B910 BB88- 8C CE B8 STY $B8CE BB8B- 8C D2 B8 STY $B8D2 BB8E- 88 DEY BB8F- 8C 21 B9 STY $B921 ; a sector read, with modified RWTS BB92- 20 E7 BB JSR $BBE7 ; copy the raw nibble data elsewhere BB95- A0 55 LDY #$55 BB97- B9 00 6C LDA $6C00,Y BB9A- 99 00 5C STA $5C00,Y BB9D- 88 DEY BB9E- 10 F7 BPL $BB97 BBA0- AD 02 6B LDA $6B02 BBA3- 85 06 STA $06 ; another sector read BBA5- 20 E7 BB JSR $BBE7 BBA8- AD 02 6B LDA $6B02 BBAB- 85 07 STA $07 ; and another BBAD- 20 E7 BB JSR $BBE7 BBB0- AD 02 6B LDA $6B02 BBB3- 85 08 STA $08 ; compare this read's nibble data to ; the previous read's nibble data BBB5- A0 55 LDY #$55 BBB7- B9 00 6C LDA $6C00,Y BBBA- D9 00 5C CMP $5C00,Y BBBD- D0 2F BNE $BBEE BBBF- 88 DEY BBC0- 10 F5 BPL $BBB7 ; more comparisons of the side effects ; generated by the modified RWTS BBC2- A5 06 LDA $06 BBC4- C5 07 CMP $07 BBC6- D0 04 BNE $BBCC BBC8- C5 08 CMP $08 BBCA- F0 17 BEQ $BBE3 ; success path is here -- ; first, restore the RWTS code BBCC- A9 38 LDA #$38 BBCE- 8D 42 B9 STA $B942 BBD1- A0 BC LDY #$BC BBD3- 8C 10 B9 STY $B910 BBD6- 8C CE B8 STY $B8CE BBD9- 8C D2 B8 STY $B8D2 BBDC- 88 DEY BBDD- 8C 21 B9 STY $B921 ; then continue with boot1 as normal BBE0- 4C 00 B7 JMP $B700 BBE3- 4C 54 BB JMP $BB54 ... BBE7- A9 B7 LDA #$B7 BBE9- A0 E8 LDY #$E8 BBEB- 4C B5 B7 JMP $B7B5 ; failure path is here BBEE- A2 B3 LDX #$B3 BBF0- 20 58 FC JSR $FC58 BBF3- 20 2D FF JSR $FF2D BBF6- 8E 03 04 STX $0403 BBF9- 4C 5B B7 JMP $B75B I'm guessing my non-working copy never got as far as wiping main memory, since the search for the nibble sequence is unconditional and neverending. That explains the behavior I saw -- it spun forever with the drive motor on, and it never got off track 0. The important takeaway here is that there don't appear to be any long-term side effects of this copy protection. If it succeeds, it restores everything that it modified (in the RWTS code), then it just jumps to $B700 to start the boot1 phase. But that's it; nothing else seems to rely on some magic number that it pulls from the raw nibbles or anything. It doesn't decrypt anything. It doesn't even clear the carry flag. A lot of disks need this sort of post- demuffin patching, and I got tired of doing it manually, so I wrote a program to do it for me. It is called, unsurprisingly, Post-Demuffin Patcher. It 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 can also detect and bypass some nibble checks.) 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,S03,$91 change FF to DE T00,S03,$9B change FF to AA T00,S03,$35 change FF to DE T00,S03,$3F change FF to AA T00,S02,$9E change FF to DE T00,S02,$A3 change FF to AA T00,S02,$A8 change FF to EB T00,S00,$4B change FEBB to FD08 T00,S04,$29 change AA to 96 (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.) The first 7 lines are RWTS patches. This solves problem #1 -- the original disk used a modified RWTS that couldn't read a standard disk. The next line is a patch to boot0 to jump to ($08FD) instead of ($BBFE). This solves problem #2 -- the original disk called a nibble check after boot0. Calling ($08FD) bypasses the check. The last line is something that I just added to the latest version of Post- Demuffin Patcher yesterday. That range in T00,S04 is the translation table the RWTS uses to convert bytes in memory to nibbles on disk when it writes to the disk. Some disks never do any writes, so it's an easy modification to miss. But the upshot of using a non-standard translation table on a standard disk is that the disk will grind when it writes that value. In some emulators, action will automatically convert the disk image to another format (since the emulator has detected -- correctly -- that the disk is trying to write something in a non-standard format). That was actually my clue that I was missing something in this crack: I booted my "cracked" copy in Virtual ][, and it converted the image file from .dsk to .v2d during testing. 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 (like the RWTS patches). And in the case of bypassing the nibble check, it actually checks every single byte of code before the jump to ($BBFE) to ensure that the disk is using a standard DOS 3.3 boot0 routine up until that point. There were dozens of patches that it didn't make to this disk, because it decided they weren't needed or it wasn't 100% sure what was going on. ]PR#6 And it works. The disk boots and runs with no complaint. There doesn't appear to be any further protection. Hooray for automation. (Oh, this is getting good.) Quod erat liberandum. --------------------------------------- A 4am crack No. 164 ------------------EOF------------------