---------------Station 5--------------- A 4am crack 2018-04-05 --------------------------------------- Name: Station 5 Genre: strategy Year: 1984 Publisher: Micro-Fun Platform: Apple ][+ or later Media: 5.25-inch disk Sides: 1 OS: DOS 3.3 Previous cracks: Apple Bandit / MPG This disk was automatically cracked by Passport. Here is the transcript: --v-- READING FROM S6,D1 T00,S00 FOUND DOS 3.3 BOOTLOADER USING DISK'S OWN RWTS WRITING TO S5,D2 T02,S02 VOLUME NAME IS DISK VOLUME 254 T00,S03,$91: 9E -> DE T00,S03,$9B: E7 -> AA T00,S03,$35: D5 -> DE T00,S02,$9E: D5 -> DE CRACK COMPLETE. PRESS ANY KEY --^-- [Narrator] But the crack was not complete. The copy that Passport produces is in a standard format, fully readable by third-party tools. But when I boot it, the disk starts loading DOS and starts grinding. The RWTS code for matching prologues and epilogues looks correct, but Passport has missed something somewhere else. The RWTS is almost identical to a standard DOS 3.3 disk, which makes comparison easier. And lo, on T00,S08, I find a suspicious JMP at $BE38: --v-- T00,S08 ($BE00) ----------- DISASSEMBLY MODE ---------- 0038:4C 6A BA JMP $BA6A <-- ! 003B:28 PLP 003C:A2 00 LDX #$00 003E:86 26 STX $26 0040:20 C2 B8 JSR $B8C2 0043:AE F8 05 LDX $05F8 0046:18 CLC 0047:24 38 BIT $38 0049:A0 0D LDY #$0D 004B:91 48 STA ($48),Y 004D:BD 88 C0 LDA $C088,X 0050:60 RTS --^-- $BA6A is in a region that is generally unused. (Later versions of DOS 3.3 used it to patch buggy DOS routines, but not the RWTS itself. Pronto-DOS uses it too but at an entry point of $BA69. Anyway, this is suspicious.) $BAxx is usually on T00,S04, and this disk is no different. --v-- T00,S04 ($BA00) ----------- DISASSEMBLY MODE ---------- ; code to handle the real error cases ; (which would be handled by the code ; at $BE38 if we hadn't jumped here) 006A:08 PHP 006B:90 03 BCC $0070 006D:4C C9 BD JMP $BDC9 ; check track and sector (in zero page, ; put there by the address field parser ; at $B944) 0070:A5 2D LDA $2D 0072:C9 00 CMP #$00 0074:D0 0D BNE $0083 0076:A5 2E LDA $2E 0078:C9 16 CMP #$16 007A:F0 07 BEQ $0083 007C:28 PLP ; oh what fresh hell is this 007D:20 AF BE JSR $BEAF 0080:08 PHP 0081:B0 EA BCS $006D 0083:28 PLP 0084:4C 3C BE JMP $BE3C --^-- And we're back to sector 8. --v-- T00,S08 ($BE00) ----------- DISASSEMBLY MODE ---------- 00AF:A0 00 LDY #$00 00B1:84 26 STY $26 00B3:84 27 STY $27 ; skip over self-sync nibbles ($FF) ; while counting them 00B5:BD 8C C0 LDA $C08C,X 00B8:10 FB BPL $00B5 00BA:C9 FF CMP #$FF 00BC:D0 08 BNE $00C6 00BE:E6 26 INC $26 00C0:D0 F3 BNE $00B5 00C2:E6 27 INC $27 00C4:D0 EF BNE $00B5 ; branch if we find the first nibble of ; the original disk's custom epilogue ; (it was $9E on this disk but I think ; this routine is generic enough to ; handle some variations) 00C6:C9 9E CMP #$9E 00C8:F0 3D BEQ $0107 00CA:C9 CF CMP #$CF 00CC:F0 35 BEQ $0103 ; otherwise check a lookup table using ; the nibble value as the index 00CE:A8 TAY 00CF:B9 9F BE LDA $BE9F,Y ; must be < $80, otherwise fail 00D2:30 37 BMI $010B ; otherwise use that lookup value as an ; index into another table and match ; the next disk nibble against that 00D4:A8 TAY 00D5:BD 8C C0 LDA $C08C,X 00D8:10 FB BPL $00D5 00DA:D9 9F BF CMP $BF9F,Y ; must match, otherwise fail 00DD:D0 2C BNE $010B 00DF:E6 26 INC $26 00E1:D0 02 BNE $00E5 00E3:E6 27 INC $27 ; compare next disk nibble to another ; lookup table 00E5:BD 8C C0 LDA $C08C,X 00E8:10 FB BPL $00E5 00EA:D9 A7 BF CMP $BFA7,Y 00ED:D0 1C BNE $010B 00EF:EA NOP 00F0:EA NOP 00F1:EA NOP ; and again 00F2:BD 8C C0 LDA $C08C,X 00F5:10 FB BPL $00F2 00F7:D9 AF BF CMP $BFAF,Y 00FA:D0 0F BNE $010B 00FC:B9 B7 BF LDA $BFB7,Y 00FF:D0 2A BNE $012B [continued on T00,S09] 0101:F0 19 BEQ $001C 0103:A0 05 LDY #$05 0105:D0 CE BNE $FFD5 0107:A0 06 LDY #$06 0109:D0 CA BNE $FFD5 ; failure path is here -- set carry and ; return to caller (which propagates it ; to the code that called the RWTS to ; read a sector, which explains all the ; grinding) 010B:38 SEC 010C:60 RTS ... ; finally, check the nibble counter (in ; zero page $26/$27) 0161:A9 11 LDA #$11 0163:18 CLC 0164:65 26 ADC $26 0166:85 26 STA $26 0168:90 02 BCC $006C 016A:E6 27 INC $27 ; get track 016C:A0 04 LDY #$04 016E:B1 48 LDA ($48),Y 0170:A8 TAY ; use track number as an index to look ; up the correct nibble count (which ; varies by track) 0171:B9 56 BC LDA $BC56,Y 0174:38 SEC 0175:E5 26 SBC $26 0177:30 92 BMI $000B 0179:C9 05 CMP #$05 017B:B0 8E BCS $000B 017D:B9 7A BC LDA $BC7A,Y 0180:C5 27 CMP $27 0182:D0 87 BNE $000B ; success path clears carry and returns ; to caller (again, this will end up ; being the RWTS "no error" flag that ; is returned to the original sector ; read code) 0184:18 CLC 0185:60 RTS --^-- So... a nibble count, integrated into the RWTS itself, conditionally called from $BA6A which is called from $BE38. No side effects. We can bypass the entire thing by changing the "JMP" at $BE38 back to standard DOS 3.3 code, which is "PHP / BCS $BDC9". T00,S08,$38: 4C6ABA -> 08B08E ]PR#6 ...works, and it is glorious... Grepping through 5000 other disk images (which is a perfectly reasonable number of disk images to have lying around on one's hard drive in 2018), I see that Micro-Fun used an identical protection on several other disks. And you know what that means... I get to update Passport to support this protection. Quod erat liberandum. --------------------------------------- A 4am crack No. 1728 ------------------EOF------------------