--------The Ripple That Changed-------- ------------American History----------- A 4am crack 2016-11-13 -------------------. updated 2017-08-29 |___________________ Name: The Ripple That Changed American History Genre: educational Year: 1987 Authors: Shaun Cutts Publisher: Tom Snyder Productions Media: single-sided 5.25-inch floppy OS: custom Previous cracks: none ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA fails on second pass Locksmith Fast Disk Backup copies everything except track $0E; copy boots but hangs just before the title screen EDD 4 bit copy (no sync, no count) no errors, but copy boots then clears the screen and says "PLEASE REBOOT" just before the title screen Copy ][+ nibble editor track $0E is all $FF (sync bytes) with just a handful of non-sync bytes Disk Fixer T00,S00 -> custom bootloader no sign of DOS 3.3 or a standard RWTS no sign of any OS at all Why didn't any of my copies work? Probably a runtime protection check that looks at the funky track $0E. Next steps: 1. Trace the boot 2. ??? ~ Chapter 1 In Which We Brag About Our Humble Beginnings I have two floppy drives, one in slot 6 and the other in slot 5. My "work disk" (in slot 5) runs Diversi-DOS 64K, which is compatible with Apple DOS 3.3 but relocates most of DOS to the language card on boot. This frees up most of main memory (only using a single page at $BF00..$BFFF), which is useful for loading large files or examining code that lives in areas typically reserved for DOS. [S6,D1=original disk] [S5,D1=my work disk] The floppy drive firmware code at $C600 is responsible for aligning the drive head and reading sector 0 of track 0 into main memory at $0800. Because the drive can be connected to any slot, the firmware code can't assume it's loaded at $C600. If the floppy drive card were removed from slot 6 and reinstalled in slot 5, the firmware code would load at $C500 instead. To accommodate this, the firmware does some fancy stack manipulation to detect where it is in memory (which is a neat trick, since the 6502 program counter is not generally accessible). However, due to space constraints, the detection code only cares about the lower 4 bits of the high byte of its own address. Stay with me, this is all about to come together and go boom. $C600 (or $C500, or anywhere in $Cx00) is read-only memory. I can't change it, which means I can't stop it from transferring control to the boot sector of the disk once it's in memory. BUT! The disk firmware code works unmodified at any address. Any address that ends with $x600 will boot slot 6, including $B600, $A600, $9600, &c. ; copy drive firmware to $9600 *9600 *2000<6000.BFFFM *C500G ... ]BSAVE BOOT2 6000-BAFF,A$2000,L$5B00 ]BLOAD BOOT2 6000-BAFF,A$6000 ]CALL -151 *67DBL 67DB- A9 01 LDA #$01 67DD- 85 04 STA $04 67DF- A9 50 LDA #$50 67E1- 85 06 STA $06 67E3- A9 04 LDA #$04 67E5- 85 05 STA $05 67E7- A9 06 LDA #$06 67E9- 85 02 STA $02 67EB- A9 02 LDA #$02 67ED- 85 03 STA $03 ; this is yet another multi-sector read ; routine ; zp$02 = start track ($06) ; zp$03 = start sector ($02) ; zp$05 = sector count ($04) ; zp$06 = start address ($5000) 67EF- 20 93 92 JSR $9293 Se we're loading 4 sectors into $5000. 67F2- A9 01 LDA #$01 67F4- 85 04 STA $04 67F6- A9 20 LDA #$20 67F8- 85 06 STA $06 67FA- A9 20 LDA #$20 67FC- 85 05 STA $05 67FE- A9 06 LDA #$06 6800- 85 02 STA $02 6802- A9 06 LDA #$06 6804- 85 03 STA $03 6806- 20 93 92 JSR $9293 We're loading $20 sectors into $2000. 6809- 20 27 A4 JSR $A427 *A427L A427- D8 CLD A428- 8D 00 C0 STA $C000 A42B- A9 C0 LDA #$C0 A42D- 8D F6 B8 STA $B8F6 A430- A9 01 LDA #$01 A432- 85 04 STA $04 A434- A9 BE LDA #$BE A436- 85 06 STA $06 A438- A9 02 LDA #$02 A43A- 85 05 STA $05 A43C- A9 0F LDA #$0F A43E- 85 02 STA $02 A440- A9 00 LDA #$00 A442- 85 03 STA $03 A444- 20 93 92 JSR $9293 We're loading 2 sectors into $BE00. A447- 20 AF BE JSR $BEAF And that's in just-loaded code, but I can set up another boot trace to capture it. However, I'll need to move my trace program somewhere else, since $9600 gets clobbered during boot and I need to have callbacks running after that part is loaded from disk. Luckily, I can put my boot tracer anywhere in memory, as long as it's at $x600. Looking at all the disk reads, it appears that $1600 is untouched during boot. *1600 Success! ~ Chapter 4 Self-Modifying Code Is Best Code! *BEAFL BEAF- 4E B2 BE LSR $BEB2 BEB2- DD B5 BE CMP $BEB5,X BEB5- 44 ??? BEB6- 00 BRK BEB7- 6E BA BE ROR $BEBA Ooh, self-modifying code. This looks like garbage, but it's not (quite). The first instruction at $BEAF changes the next instruction at $BEB2. The disassembly listing beyond that is misleading, because the code will be different by the time it's run. I'll step through this one line at a time. Let's save it first. *2E00