Introduction
I've been on a bit of a floppy disc protection odyssey recently. This will probably be the last floppy disc related post for some time, so how better to end things than describe a stroke of genius I came across during my research of BBC Micro disc protection?
In my previous posts, we've already covered (directly or tangentially) some interesting floppy disc protection schemes:
- Weak bits. [link: Weak bits floppy disc protection: an alternate origins story on 8-bit]. "Weak bits" protection is where a patch of disc surface is left empty of magnetic flux transitions. Absent a signal, the floppy disc drive itself will turn up the gain on its amplifier and see noise, which manifests as non-deterministic digital reads from the disc.
- Fuzzy bits. [link: Technical Documentation - Dungeon Master and Chaos Strikes Back - Detailed analysis of Atari ST Floppy Disks]. "Fuzzy bits" protection is where magnetic flux transitions are recorded at intervals that are out-of-spec with regards to timing expectations (e.g. MFM). By using intervals right in the middle of a pair of expected values (e.g. 5us instead of the expected 4us or 6us), it's possible to cause the disc controller to return non-deterministic digital reads.
- Long / short tracks. [link: Turning a £400 BBC Micro (1981) into a $40,000 disc writer (1987)] [see the "Capabilities Unlocked" section]. Long track protection is where flux transitions are written a little bit faster than they should be. This could be the whole track or just part of a track. In either case, the track will appear to contain more bytes than a track normally should. This works because the floppy disc controller usually has a broad tolerance of bitrate, to cater for disc drives naturally spinning at different speeds.
Western who, now?
Jolly Jack Tar by Sherston Software |
Phantom Combat by Doctor Soft |
Disc Duplicator 3, if it thinks it's a copy |
Discbeast's view of Jolly Jack Tar |
A recap of disc protection fundamentals
Before diving in to how the Western Security protection works, let's recap the fundamentals of disc protection. The specifics are nuanced but the general principle is pleasantly simple:
- The disc is easy to read but hard to write.
- Simon Hosler's weak bits scheme, as linked above. (And here: [link].) [1]
- Many discs, such as The Sentinel by Firebird, hid data between sectors. [2]
Analyzing the Western Security Ltd. protected loader
This version of The Wizard's Revenge by Sherston Software features Western Security Ltd. disc protection. |
Here's a gratuitous screenshot of the game.
And here's what discbeast makes of the disc:
There's nothing too unusual here. The red block at the end denotes a track with 1 sector that has a CRC error. It's not part of the disc protection; it's the duplicator marker. The green color represents a standard sector layout with nothing particularly exotic present. The "D" indicates the presence of deleted sectors. This is disc protection, but not exotic or hard to copy. However, loading the disc in my beebjit emulator, using the Western Digital WD1770 floppy disc controller and -log disc:commands, yields something highly unusual:
info:disc:1770: command $E4 tr 1 sr 3 dr 1 cr $29 ptrk 1 hpos 1884
[ITRP] 3CF7: JSR $3D16[ITRP] 3CFA: LDA $75[ITRP] 3CFC: SEC[ITRP] 3CFD: SBC $3F4E[ITRP] 3D00: TAX[ITRP] 3D01: LDA $86[ITRP] 3D03: STA $3F71,X[ITRP] 3D06: INC $75[ITRP] 3D08: LDA $3F4F[ITRP] 3D0B: CMP $75[ITRP] 3D0D: BCS $3CF7
As can be seen, my disc reads almost exactly to expectations except track 2, which was 3125 bytes instead of the expected 3124. That's within the +-1 range so all 8 tracks pass the check (7 or more are required).
To spell it out, the protected loader expects the track length (in FM encoded bytes) for tracks 1-8 inclusive to be 3122, 3124, 3123, 3122, 3123, 3124, 3123, 3122. That's an incredible level of precision and accuracy of writing for 1985 technology. Each byte covers about 64us on a spinning disc, but disc drives of the era would often specify running RPM variation of "less than +-1.5%". At 300rpm, +-1.5% is +-3ms per rotation! In my experience, drives are much much better than that but still! How did 1985 technology cope??
One further note, on the WD1770 vs. Intel 8271 disc controllers. We've focused our analysis on the protection as seen by the WD1770. This disc also loads fine with an Intel 8271 controller. It uses a completely different code path to indirectly calculate track length in this case. It works because the padding bytes up to the end of the track are all 0x00 instead of the usual 0xFF. An "over-read" past the final sector on the track is used, and track length is detected by the change from reading 0x00 to 0xFF.
The genius twist
And then we realize the genius of this scheme. What if they didn't write the tracks with extreme precision, because the technology wasn't there? What if they just wrote the track any-old-how and then examined the result? I think this what they did:
- Format the disc. (That's it. Just format the disc normally and you've created a fiendishly protected disc.)
- Read the lengths of tracks 1-8 of the disc you just wrote.
- On a per-disc basis, generate, obfuscate and write the required table of expected track lengths into the loader on track 9.
- The disc is easy to read but hard to write.
- The disc is easy to read but hard to recreate.
"Western Security – this wasn’t my system but I think it worked like this... It works because each disk drive runs at slightly different speeds. So when a drive creates a track on the disk – after it has added all of the headers and sectors etc, it has a bit of space to fill up, so adds a few extra ‘fill in’ bits that do nothing. The number of fill in bits will depend on the exact speed of the original formatting drive. So will be different if it was copied. I remember this system became a pain because disk drives were changing (?) all the time. [...] the system was called 'Fingerprinting'"
There remains the mystery of how a commercial duplicator could handle making these discs. One thing I've come across is references to a "Freeform" script [link], used in conjunction with Trace duplicators. I haven't been able to find a manual for this scripting language. There are some strange fragments in the memory of the loader after de-obfuscation; could it be related?
3F80: 54 70 00 41 44 44 20 20 20 20 20 72 00 4D 4F 56 Tp.ADD r.MOV
3F90: 45 54 4F 20 20 74 00 55 4E 49 54 20 20 20 20 75 ETO t.UNIT u
3FA0: 00 54 52 41 43 4B 20 20 20 76 00 53 45 43 54 4F .TRACK v.SECTO
3FB0: 52 20 20 77 00 54 4F 50 54 52 41 43 4B 78 00 55 R w.TOPTRACKx.U
Recreating Western Security style protected discs
I happen to have a couple of very different disc drives, so I thought I'd try them out. I formatted a disc in each drive, then had a look at the track lengths (in bytes) read back by a WD1772 disc controller in a real BBC Micro model B.
Track lengths from Chinon F-051MD:
[...]
Track 1 sectors 10 length 3137 fixups 1 CRC32 67F0950E
Track 2 sectors 10 length 3138 fixups 1 CRC32 67F0950E
Track 3 sectors 10 length 3138 fixups 1 CRC32 67F0950E
Track 4 sectors 10 length 3139 fixups 1 CRC32 67F0950E
Track 5 sectors 10 length 3138 fixups 1 CRC32 67F0950E
Track 6 sectors 10 length 3140 fixups 1 CRC32 67F0950E
Track 7 sectors 10 length 3140 fixups 1 CRC32 67F0950E
Track 8 sectors 10 length 3139 fixups 1 CRC32 67F0950E
Track 9 sectors 10 length 3140 fixups 1 CRC32 67F0950E
Track 10 sectors 10 length 3140 fixups 1 CRC32 67F0950E
[...]
Track lengths from Mitsubishi MF504C:
[...]
Track 1 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 2 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 3 sectors 10 length 3118 fixups 0 CRC32 67F0950E
Track 4 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 5 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 6 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 7 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 8 sectors 10 length 3119 fixups 1 CRC32 67F0950E
Track 9 sectors 10 length 3118 fixups 1 CRC32 67F0950E
Track 10 sectors 10 length 3119 fixups 1 CRC32 67F0950E
[...]
These two drives definitely have unique fingerprints! The older drive has a bit more variance / wobble in individual track lengths. In fact, it seems to fit more bytes per track on the later sectors -- most of the latter tracks are length 3142. The older drive also generally fits 20 or so more bytes per track. This means it is spinning a little slower. By contrast, the newer drive runs like clockwork with minimal track-to-track variance. This might make it a little less suitable for generating varied per-disc fingerprints, but copying the disc on home computing hardware would still be tricky -- the machine used would need to have a similarly precise drive, and the drive would also need to be running at the exact same speed as the drive that made the original disc.
One last look at track lengths, this time from a Phantom Combat game disc, by Doctor Soft. This disc uses Western Security Ltd. protection:
[...]
Track 1 sectors 10 length 3152 fixups 0 CRC32 67F0950E
Track 2 sectors 10 length 3152 fixups 1 CRC32 67F0950E
Track 3 sectors 10 length 3152 fixups 0 CRC32 67F0950E
Track 4 sectors 10 length 3152 fixups 1 CRC32 67F0950E
Track 5 sectors 10 length 3151 fixups 0 CRC32 67F0950E
Track 6 sectors 10 length 3152 fixups 0 CRC32 67F0950E
Track 7 sectors 10 length 3150 fixups 0 CRC32 67F0950E
Track 8 sectors 10 length 3151 fixups 0 CRC32 67F0950E
[...]