COPY ME - I WANT TO TRAVEL (HOW TO PROTECT YOUR SOFTWARE)
by Claus Brod
There's nothing more senseless than copy protection (surprising
intro for an article about self-made protection methods, isn't
it?) - for there will never be the perfect one. Nevertheless, it
is a fascinating subject, anyway. And one of the most
challenging, too. This article shows you how to install a
particularly nasty copy protection on your didks...
To understand how to install a copy protection method you should
be able to tell a disk from fish & chips (frivolous as I am, I
suppose that you can manage this). Furthermore, you'll need some
background information. Et voila:
A standard disk has got 80 concentrical circles on it, called
tracks. Every track carries its data in specific blocks, called
sectors. Between two sectors (and even inside sectors!) is a gap
that the controller needs as a little spare time to relax from
the hard work of reading data.
Controller? What's that? Well, simplified version first: A device
that gets data from the processor, codes it, and writes it onto
disk. It also reads bit streams from the disk and decodes it. To
transfer data to and from the controller, the built-in DMA chip
in the ST carries data from main memory to the FDC (floppy disk
controller) and also from the controller to memory. The processor
itself doesn't have to do this dirty work; while DMA (direct
memory access) is working, the processor can do anything else
(have tea or dinner with Gershwin or go shopping...).
The controller sends electrical impulses to the disk drive's
read/write head (very similar to the one in the ghetto blaster
cassette recorder that the son of your neighbour uses to test
your resistance against noise pressure). These impulses are coded
using the so-called MFM method (modified frequency modulation)
which packs clock bits into the data stream. This ensures that
reading and writing is safe even with drives that have problems
with holding the correct speed.
MORE THAN PURE DATA
On a disk you'll find more than data that you have transferred
thereto by a XBIOS or BIOS call. Additionally, some control
information is hidden between the data. A typical track looks
like this (well, OK, it's concentric in reality; please use your
imagination):
================================================================
Intro (trackheader or "Post Index Mark")
(*) gap bytes (Pre Address Mark)
3 synchronization bytes
address mark & sector info
checksum
gap bytes (Post Address Mark)
3 synchronization bytes
data mark & data
checksum
gap bytes (Post Data Mark)
back to (*), until all sectors
are written, then:
gap bytes to track end
===============================
What the heck are synchronization bytes? In short: Bit sequences,
that tell the controller as it reads them "Go on, old fella, a
new byte's starting right now". For the controller just reads a
string of bits from disk without knowing exactly where a byte
begins. The controller has a dedicated department inside that
only fiddles with sorting those bit combinations out of the bit
stream that are meant as sync bytes (as you call them shortly).
A BUG IN THE CONTROLLER
In normal cases, this sync unit (officially called Address Mark
Detector) only reacts upon the bytes $A1 and $C2 which have to be
stored in a special format (MFM with missing clock bits; just to
mention it for the professionals who read my articles in "ST-
Computer"). Unfortunately, there is an eddy in the controller (if
you want to know exactly about eddies, I recommend you "Life, The
Universe And Everything" by Douglas Adams). A bit string of
%000101001 can fool the sync byte detection department
completely!
Whenever this bit string occurs, the controller thinks there is a
sync byte and starts to synchronize (what else should it do). All
the following bytes are shifted in a certain way and their bits
shattered all over the place.
This error only occurs when reading a complete track with all
informations on it (with the controller's read-track command).
When reading sectors (with read-sector), the controller switches
off the sync unit, so that it can read without the sync bug
confusing it.
To make it clear (for the ones who only believe what they see):
Suppose you want to write the following onto disk:
FE 29 00 01 (all bytes in hex)
Reading these bytes with a read-track command you get:
FE 14 7F FE
Strange, eh?
The error occurs with the following bytes:
$29 and previous even byte
$52/$53 and previous byte dividable by 4
$A4 to $A7 and previous byte dividable by 8
$14 and following byte's first bit (MSB) set to 1
Some other byte combinations can cause the error, too (shifts of
the byte sequences above, for example).
As long as these data are packed into a sector (which you can
easily read correctly using the read-sector command),
everything's fine. As soon as you put $FE29 (for example) in an
area unreachable by read-sector (or read-address, which reads a
sector info sequence), however, you're in a mess.
Naturally, copy programmers know about this quirk. Consequently,
they use read-sector commands. They also know that gap bytes
(which are normally $4E or $00) aren't read correctly in most
cases but somehow shifted (from one to seven bits, even by "half
bits").
So you cannot rely on what you're reading with read-track. Most
programmers therefore suppose that gaps consist of $4E's and
$00's and nothing else, basta.
DEVELOPING THE PROTECTION
Now you could insert a string like "(C) 1987 by Claus Brod" into
those gap bytes. As normal copy programs don't check the contents
of the gap areas, they would fail in copying this string - so you
can detect a copy from within your program.
Stop press! How can you check your copyright string if the
controller reads something different every time you use the read-
track command? In one in ten cases, approximately, you will read
the correct string (perhaps never!); in all other cases you will
get something that your copy protection doesn't recognize -
crashdown & bomb attack (very user friendly, isn't it?)...
Now those mysterious sync bytes come into action. These bytes
make the controller read the following stuff correctly (in most
cases). Normally, a track starts with approx 60 gap bytes of
$4E's. Instead, we write:
4E 4E 4E A1 A1 A1 copyright string 4E 4E ...
This synchronizes the controller in a read-track command so that
it can at least read the copyright string correctly. Of course,
the copyright string must not contain any bytes or byte
sequences that may fool the sync department.
In your copy protection routine you read a complete track and
look for your copyright text. If it's there, it's the original
disk (or someone's got a very very good copy program). If not,
something went into wrong channels.
I tried to copy this protection method with several copy programs
- all of them were a complete loss except one (I won't tell you
which one, no, no, no). So I had to refine the protection. Now I
use the "forbidden" sync byte $29 with a previous even byte to
synchronize the controller. Synchronization is shifted by half a
byte after $29, so we have to add an ordinary $A1 sync byte to
make the sun shine again. These two bytes are read as $14 $0B
which no copy program recognizes as correct sync sequence. The
following byte sequence (your copyright string) is now
interpreted correctly with every Read-Track command. And there
you are: the perfect protection (at least until someone comes up
with a hyper-ultra-jolly-good copy program).
MEN AT WORK
Let's work: How do you program such a protection? To give you
full information about programming the controller and DMA chip
and whatever relates to this problem I would have to write an
article that spans three or four issues of ST NEWS, leaving just
enough space for the editorial and nothing else. In order to cut
this neverending story short, you're presented a prefab routine
from my software lab which you can use to implement the
protection method.
In the PROGRAMS folder, you'll find a GfA Basic program called
PROTECT.BAS, which creates a machine routine in a string (for the
real big chucks, there is an assembler listing on this disk).
This machine code reads and writes an ordinary 9-sector track 41
- nearly ordinary: the sync byte combination followed by a
copyright message is copied into the gap before the first sector.
Why do I write track 41? 41 in hex gives $29; this byte occurs in
every sector intro of track 41 and therefore confuses the read-
track command.
Therefore, this track is never read correctly; all the copy
programs I know switch to sector mode on this track - reducing
the probability that someone can copy our protection (which is
only possible by reading the whole track, analyzing it, and
writing it back with some corrections).
HOW TO USE "THE PROTECTOR"
Just format a disk (single or double sided, doesn't matter) with
the DESKTOP format utility and then start the routine in
PROTECT.BAS. Choose option 2 to write a protected track 41. You
are asked a password string that you want to write onto disk.
Afterwards, you copy data and programs to this disk; among them
the program to be protected. Option 1 of "The Track 41 Protector"
reads a complete track 41 from disk and searches for a password
that you can freely choose. The password can have up to 50
characters. If you need more, adjust Gap1$ in Procedure Mktrk.
How do you include the routines in your own programs? GfABASIC
programmers are better off this time; it should be no problem,
however, to adapt the routines for FASTBASIC or whatever.
To call the machine code routines, you have to poke values into
the routine's parameter field. If the program starts at location
START, you have to store a mode longword into location START+2
and the address of a track buffer into START+6 (see BASIC
listing). A mode of '0' activates the Read-Track routine, '1'
makes the program write a track from the buffer referred to by
the address pointer in START+6.
Assembler programmers are supplied with the source code (for
AS68) on this disk. The routine must be called with 'bsr' or
'jsr' as it terminates with a simple 'rts'. It is fully
relocatable (for it had to be transferred into a BASIC program)
and PC-relative.
You have to set up the track to be written before calling the
machine code. In Procedure Mktrk you'll find all the information
you're looking for. To satisfy the curious (curiosity kills the
cat, fellas!): Here is another version of the table above
including the codes that the controller needs to create a track.
===============================
Intro: 60 bytes of $4E
(*) gap bytes: 12 bytes of $00
sync bytes: 3 bytes of $F5
address mark: $FE
sector info: track number, side number, sector number, size
(0=128 bytes, 1=256 bytes, 2=512 bytes,
3=1024 bytes)
checksum: $F7
gap bytes: 22 bytes of $4E
12 bytes of $00
sync bytes: 3 bytes of $F5
data mark: $FB
data: 512 bytes (lower than $F4!!!)
checksum: $F7
gap bytes: 40 bytes of $4E
back to (*), until all sectors
are written, then:
gap bytes to track end (normally 1400 bytes of $4E, which is more
than enough to fill the track)
===============================
You may wonder why sync bytes are written as $F5 but read as $A1.
The reason is that the controller needs an own control "language"
when writing a track. Bytes exceeding a value of $F4 are special
control bytes that are written in other formats than ordinary
bytes. $F5, for example, is a sync byte of $A1 with certain clock
bits missing. $F7 writes a checksum onto disk (consisting of two
bytes). $FB and $FE announce data and sector info, respectively.
By the way, this control language is the reason why you must not
format your disks (using the XBIOS call) with certain "virgin"
values (the virgin word's bytes must not exceed $F4).
Some additional comments concerning the BASIC program and its
usage: '0' in the main menu terminates the program (what else did
you expect?). '3' shows the contents of the track buffer in both
hex and ASCII; to stop output, press any key; then press 'X' to
leave the routine or any other key to continue. The track buffer
(in this program buf$) must be at least 7K.
If you want to use 10-sector disks you only have to change the
"FOR T=1 TO 9" loop in Procedure Mktrk into "FOR T=1 TO 10".
If you want to know more about disk drives you are given three
possibilities: read my "Floppyspielereien" articles in the German
computer magazine "ST Computer" or buy my book about floppy
programming (out in late fall) or write to ST NEWS. If there are
some readers out there who are interested to read more about disk
drives in ST NEWS: Write to ST NEWS and reveal your innermost
wishes... depending on demand I will continue to write about
floppy programming in ST NEWS from time to time.
Claus Brod
Am Felsenkeller 2
D-8772 Marktheidenfeld
West Germany
Disclaimer
The text of the articles is identical to the originals like they appeared
in old ST NEWS issues. Please take into consideration that the author(s)
was (were) a lot younger and less responsible back then. So bad jokes,
bad English, youthful arrogance, insults, bravura, over-crediting and
tastelessness should be taken with at least a grain of salt. Any contact
and/or payment information, as well as deadlines/release dates of any
kind should be regarded as outdated. Due to the fact that these pages are
not actually contained in an Atari executable here, references to scroll
texts, featured demo screens and hidden articles may also be irrelevant.