--------------Microzine 20------------- A 4am crack 2014-09-16 --------------------------------------- "Microzine" was an educational disk- based magazine published by Scholastic between 1983 and 1992. Issue no. 20 is a double-sided disk that features "Voyage to See What's On The Bottom" and "Heroes and Villains." Side B is unprotected. However, side A is uncopyable by any automated method. COPYA fails miserably and immediately. EDD 4 bit copy gives no read errors, but the copy it creates only gets as far as loading DOS and displaying the BASIC prompt before crashing into the monitor at address $90C6. Turning to my trusty Disk Fixer sector editor, I press "O" to get to the Input/Output Control and set "CHECKSUM ENABLED" to "NO". This will ignore the checksum bytes and epilogue sequences. i.e. 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 $11 does appear to contain a disk catalog, which strongly suggests this program is file-based. 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 a sector editor would give read errors, even when ignoring checksums] - 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. Just by looking at the first few sectors, it appears that this disk uses a DOS 3.3-derived RWTS, which means that my AUTOTRACE program should be able to extract the RWTS from the original disk. [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 Well, that worked flawlessly. My work disk first runs AUTOTRACE0, which 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 runs AUTOTRACE1, which sets up a more involved boot trace to capture the rest of track 0 and save it to the file "BOOT1". If *that* looks reasonably normal, it saves the RWTS to a file, unimaginatively named "RWTS", which can be loaded with Advanced Demuffin to copy each track of the original disk to a duplicate with standard address/data prologue/epilogue sequences. Now I can use Advanced Demuffin to convert the disk to a standard format. [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. 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 -- just rebooted endlessly, which means there is some code being executed during boot to check if the disk is original. (Hint: it's not.) Just by booting my copy, I can rule out problem #1. The disk seems to read itself just fine. It makes it exactly as far as my failed bit copy -- far enough to figure out that it's not an original disk and crash gracelessly. But wait... [S6,D1=demuffin'd copy] [S5,D1=my work disk] ]PR#5 ... ]CATALOG,S6,D1 C1983 DSR^C#254 011 FREE B 003 WAVEDATA B 006 DBASEF.SET B 014 GMH B 003 NET.IMAGE B 004 WEED.IMAGE B 002 TABLET.IMAGE B 003 WHIRLPOOL.IMAGE B 003 SERPENT.IMAGE B 003 CLAM.IMAGE B 009 PANEL.IMAGE *B 002 BUOY.IMAGE *B 003 BOAT.IMAGE B 003 LIGHT.IMAGE B 004 TREE.IMAGE B 009 TAGA B 007 TAGC B 006 TAGD B 007 TAGE B 005 TAGG B 020 TAPMAIN.C B 033 ONE.DOWN.ALL B 003 TAPMAIN.1 B 015 TAPMAIN.2 B 005 TAPMAIN.4 B 002 TAPMAIN.5 B 002 TAPMAIN.6 B 002 TAPMAIN.7 B 002 TAPMAIN.8 B 002 TAPMAIN.9 B 002 TAPMAIN.A B 002 TAPMAIN.B B 010 TAPMAIN.D B 005 TAPMAIN.E B 002 TAPMAIN.F B 002 BOXEDGES B 007 TAPF B 004 TAPO B 007 TAPI B 009 TAPB B 005 TAPQ B 006 TAPC B 007 TAPH B 009 TAPMAIN.13 B 006 OBSTICLES.0 B 009 TAGL B 008 TAPD B 014 TAGM B 002 TAPP B 009 TAGF B 006 DICTIONARY.0 B 006 TAPL B 005 TAPG B 006 TAPK B 007 TAPJ B 005 TAGN B 006 TAGO B 007 TAGQ B 008 TAGR B 004 TAPM B 002 TAPN B 005 TAPR B 003 TAPS B 009 TAPA B 006 TAPE B 006 NEW.SET A 003 HELLO B 003 UNPACKDATA.1 B 007 TOC.2 B 002 TOC.3 B 049 TOC.4 B 012 PACK.MICRO7 B 005 TOC.5 B 004 TOC.6 B 002 XMGPRT1 ]RUN HELLO It works! All further disk access is done through DOS functions, and it doesn't seem to mind being booted from a third-party DOS. However, examining the demuffin'd copy with Copy ][+ shows something odd: HELLO is not the HELLO program. ("CHANGE BOOT PROGRAM" will show the current boot program, even if you don't want to change it.) I mean, HELLO is not the program that runs on boot. The boot program is XMGPRT1, a binary program that starts at $9000. ("CATALOG DISK" -> "W/ FILE LENGTHS" will show the start address of each file.) Since running the HELLO program brought up the main menu without any crashes, I'm guessing that XMGPRT1 is where the copy protection lies. ]PR#5 ... ]BLOAD XMGPRT1,S6,D1 ]CALL -151 *9000L ; get address of RWTS parameter table 9000- 20 E3 03 JSR $03E3 9003- 85 FB STA $FB 9005- 84 FA STY $FA ; hmm 9007- A9 C5 LDA #$C5 9009- 48 PHA ; set up RWTS parameters 900A- A9 00 LDA #$00 900C- 85 FC STA $FC 900E- A2 03 LDX #$03 9010- BC 49 90 LDY $9049,X 9013- 91 FA STA ($FA),Y 9015- CA DEX 9016- 10 F8 BPL $9010 9018- 8A TXA ; hmm 9019- 48 PHA At this point, we've pushed two bytes on the stack -- $C5 and $FF. In other words, an RTS right now would pop those values off the stack, add 1, and "return" to... $C600. Which reboots. There is absolutely no reason for legitimate code to do this. 901A- 20 3C 90 JSR $903C *903CL ; call RWTS 903C- 20 E3 03 JSR $03E3 903F- 20 D9 03 JSR $03D9 9042- A9 00 LDA #$00 9044- 85 48 STA $48 ; on error, jump to The Badlands 9046- B0 78 BCS $90C0 9048- 60 RTS Continuing from $901D... *901DL ; get the slot number (x16) from the ; RWTS parameter table and put it in X 901D- A0 01 LDY #$01 901F- B1 FA LDA ($FA),Y 9021- AA TAX ; here we go 9022- 20 73 90 JSR $9073 *9073L ; turn on the drive motor 9073- BD 89 C0 LDA $C089,X ; set up some counters 9076- A9 56 LDA #$56 9078- 85 FD STA $FD 907A- A9 08 LDA #$08 907C- C6 FC DEC $FC 907E- D0 04 BNE $9084 9080- C6 FD DEC $FD ; if this counter hits zero, jump to ; The Badlands 9082- F0 3C BEQ $90C0 ; commencing nibble check 9084- BC 8C C0 LDY $C08C,X 9087- 10 FB BPL $9084 9089- C0 FB CPY #$FB 908B- D0 ED BNE $907A 908D- F0 00 BEQ $908F 908F- EA NOP 9090- EA NOP 9091- BC 8C C0 LDY $C08C,X 9094- C0 08 CPY #$08 9096- 2A ROL 9097- B0 0B BCS $90A4 9099- BC 8C C0 LDY $C08C,X 909C- 10 FB BPL $9099 909E- C0 FF CPY #$FF 90A0- D0 D8 BNE $907A 90A2- F0 EB BEQ $908F 90A4- BC 8C C0 LDY $C08C,X 90A7- 10 FB BPL $90A4 90A9- 84 FC STY $FC 90AB- C9 0A CMP #$0A 90AD- D0 CB BNE $907A 90AF- BD 8C C0 LDA $C08C,X 90B2- 10 FB BPL $90AF 90B4- 38 SEC 90B5- 2A ROL 90B6- 25 FC AND $FC 90B8- 49 FF EOR #$FF ; wrong answer? Badlands 90BA- D0 04 BNE $90C0 ; turn off drive motor 90BC- DD 88 C0 CMP $C088,X ; return gracefully (no flags on the ; way out) 90BF- 60 RTS ; The Badlands 90C0- A8 TAY 90C1- DD 88 C0 CMP $C088,X That's it. That's the end of the file. I'm assuming there was supposed to be more code here, but there isn't. No wonder it crashes. Continuing from $9025... ; pop the bogus return value ($C5FF) ; off the stack 9025- 68 PLA 9026- 68 PLA ; Route a series of bytes through the ; DOS output vector at ($36). This is ; how binary files "execute" DOS 3.3 ; commands, like PRINT CHR$(4)"..." in ; Applesoft BASIC. 9027- A0 00 LDY #$00 9029- 84 FE STY $FE 902B- B9 4D 90 LDA $904D,Y 902E- 09 80 ORA #$80 9030- 20 39 90 JSR $9039 9033- A4 FE LDY $FE 9035- C8 INY 9036- 4C 29 90 JMP $9029 9039- 6C 36 00 JMP ($0036) Here's the buffer that gets printed: 904D- 04 52 55 9050- 4E 20 48 45 4C 4C 4F 20 9058- 20 20 20 20 20 20 20 20 9060- 20 20 20 20 20 20 20 20 9068- 20 20 20 20 20 20 20 20 9070- 20 0D 00 *FC58G N 400<904D.9072M DRUN HELLO M@ It doesn't translate well to text, but the "D", "M", and "@" are in inverse because they're control characters. So this executes the DOS command RUN HELLO There are two ways I could go here. The XMGPRT1 program does nothing useful. I could bypass it entirely by changing the boot program from XMGPRT1 back to HELLO. However, I'm a little concerned that other programs on the disk might be executing XMGPRT1 to get back to the main menu -- so my copy would work on boot but crash after exiting from one of the programs on the disk. The safer choice is to modify XMGPRT1 directly to skip over the nibble check. Putting a "JMP $9027" at $9000 would skip to the part where it runs HELLO. Turning to my trusty Disk Fixer sector editor, I press "D" for directory mode and select "XMGPRT1" from the file list, and I find the code on T08,S0A. T08,S0A,$04 change "20 E3 03" to "4C 27 90" Quod erat liberandum. --------------------------------------- A 4am crack No. 136 ------------------EOF------------------