------------Video Title Shop----------- A 4am crack 2014-12-15 --------------------------------------- "Video Title Shop" is a 1987 graphics program programmed by John Butrovich and Richard Mirsky and distributed by DataSoft. COPYA copies the original disk with no complaint, but the copy does not work. It boots, loads several tracks, then prints "PLEASE USE ORIGINAL DISK" and hangs. Turning to my trusty Disk Fixer sector editor, I don't see any evidence of a disk catalog on track $11 or anywhere else. I don't see any evidence of a normal operating system (DOS, ProDOS, or Pascal). The bootloader on track 0 appears to be entirely custom. Oh, and encrypted. Let's see if AUTOTRACE can make heads or tails of it. [S6,D1=original disk] [S5,D1=my work disk] ]PR#5 CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 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 (like this one, apparently), it just captures track 0, sector 0 (saved in a file called "BOOT0") and stops. Gonna have to do this the hard way. ]CALL -151 *800<2800.28FFM 0801- 4C 7E 08 JMP $087E *87EL 087E- A2 79 LDX #$79 0880- BD 04 08 LDA $0804,X 0883- 48 PHA 0884- 4A LSR 0885- 68 PLA 0886- 6A ROR 0887- 9D 04 08 STA $0804,X 088A- CA DEX 088B- D0 F3 BNE $0880 088D- 4C 14 08 JMP $0814 A decryption loop for the first half of the sector (more or less). It looks like it's self-contained (not dependent on any initial state), so I should just be able to run it and see the decrypted code. *88D:60 ; put "RTS" after decryption *801G ; go Well, the good news is that it worked. The bad news is... well, see for yourself. *814L ; ends up with $40 in $0801, which is ; the little-used "RTI" instruction 0814- A9 0C LDA #$0C 0816- 4D 01 08 EOR $0801 0819- 8D 01 08 STA $0801 ; save boot slot (x16) in zero page $DF 081C- A6 2B LDX $2B 081E- 8A TXA 081F- 85 DF STA $DF ; munge boot slot (weird) 0821- 0A ASL 0822- 0A ASL 0823- 2A ROL 0824- 2A ROL 0825- 2A ROL 0826- 49 C0 EOR #$C0 0828- 8D 08 08 STA $0808 ; set up zero page to reuse disk ; controller ROM routine to read more ; sectors 082B- A0 03 LDY #$03 082D- B9 05 08 LDA $0805,Y 0830- 99 27 00 STA $0027,Y 0833- B9 09 08 LDA $0809,Y 0836- 99 3E 00 STA $003E,Y 0839- 88 DEY 083A- 10 F1 BPL $082D ; at this point, $28 has the value from ; $0806, which was $06 083C- A4 28 LDY $28 ; $080D is a table of physical sectors ; to read 083E- B9 0D 08 LDA $080D,Y 0841- A0 00 LDY #$00 ; At this point, $40 has the value from ; $080B/$080C, which is $003D. Multiple ; levels of indirection going on here. 0843- 91 40 STA ($40),Y ; $0805 starts at $45 and is used as ; the target address (high byte) 0845- AD 05 08 LDA $0805 0848- 85 27 STA $27 ; ...and decremented 084A- CE 05 08 DEC $0805 ; a sector count (starts at $06) 084D- CE 06 08 DEC $0806 ; break out of sector read loop 0850- 30 0F BMI $0861 ; set up a return address on the stack 0852- A9 08 LDA #$08 0854- 48 PHA 0855- A9 5E LDA #$5E 0857- 48 PHA ; ...and one more byte (WTF) 0858- A9 00 LDA #$00 085A- 48 PHA ; At this point, $29/$2A have the value ; from $0807/$0808, except that $0808 ; was modified earlier based on the ; munged boot slot. It ends up being ; $C65C if the boot slot was 6. 085B- 6C 29 00 JMP ($0029) So this will jump to $C65C (or similar, depending on the boot slot), which will read a sector based on the zero page addresses set up earlier, then jump to $0801. But $0801 got munged into an RTI instruction. What does RTI do? It pulls one byte off the stack and sets the processor flags (like PLP). Then it pulls an address off the stack and jumps to it. Note: unlike RTS, the address on the stack is the actual address, not the actual address -1. In other words, it clears all flags and jumps to $085E. 085E- 6C 3E 00 JMP ($003E) More indirection. What's at $3E? At this point, it holds the value from $0809/$080A, which is the address $082B. Without a doubt, this is the strangest way I have ever seen to read a few sectors from track 0. The sector read loop ends when $0806 goes negative, and the BMI at $0850 branches to $0861. So let's continue there. ; put address $4000 in $02/$03 0861- A9 40 LDA #$40 0863- 85 03 STA $03 0865- A0 00 LDY #$00 0867- 84 02 STY $02 ; another loop, to decrypt the 6 pages ; of boot1 code we just read 0869- A2 06 LDX #$06 086B- B1 02 LDA ($02),Y 086D- 48 PHA 086E- 4A LSR 086F- 68 PLA 0870- 6A ROR 0871- 91 02 STA ($02),Y 0873- C8 INY 0874- D0 F5 BNE $086B 0876- E6 03 INC $03 0878- CA DEX 0879- D0 F0 BNE $086B ; jump to boot1 087B- 4C CB 43 JMP $43CB Before I get to tracing the next stage of the boot, I want to save my progress with the decrypted boot0. I'll make one more patch so that the initial JMP goes straight to $0814 instead of the decryption loop at $087E. *802:14 ; patch to skip decryption *BSAVE BOOT0 DECRYPTED,A$800,L$100 Now then. I need to interrupt the boot at $087B and capture the decrypted boot1 code. But of course boot0 is still encrypted on disk, so I'll need to do it in two callbacks. *9600