Introduction into Copy Protection Contents 0. Preface 1. Copy protection based on key disk 1.1 MFM floppy disk data recording 1.1.1 Data bits separation 1.1.2 Synchronization field and ID byte 1.1.3 Overall track format 1.2 Intel 8272A floppy disk controller 1.2.1 8272A registers 1.2.2 8272A commands summary 1.2.3 8272A commands description 1.2.4 AT floppy disk controller 1.2.5 "Normal" PC floppy formats 1.3 Time independent protection tricks 1.3.1 Extra or missing sectors 1.3.2 Weak data bits 1.3.3 Data in gap 1.3.4 Sectors with no data address mark 1.3.5 Sectors with no sector ID address mark 1.3.6 Sectors with bad sector ID address mark 1.3.7 Data field passing over index address mark 1.3.8 Multirate tracks 1.3.9 Data access over gap 1.3.10 Crazy ideas 1.4 Timer based protection tricks 1.4.1 Sector ordering (interleave) checks 1.4.2 Data transfer rate measurements 1.5 Protection based on special hardware 1.5.1 Modified MFM formats 1.5.2 Misplaced data tracks 1.5.3 Non-standard transfer rates 1.6 Protection schemes examples 1.6.1 IBM Filing Assistant 1.6.2 SuperLok 1.6.3 Cops CopyLock II 1.6.4 PC Shield 2. Hard Disk based protection 2.1 Chip-level protection 2.2 BIOS-level protection 2.2.1 Interleave changes 2.2.2 Changed sector numbers 2.2.3 Unused disk areas 2.3 DOS-level protection 2.3.1 Dependence on cluster number 2.3.2 Unused (reserved) disk areas 2.3.3 Unused (allocation unit rounded) disk areas 3. Motherboard and system BIOS based protection 3.1 Data based tricks 3.2 Time based tricks Glossary Appendix A. Simple 8272A program Appendix B. Simple HDC exerciser program Appendix C. How to find out cluster number Appendix D. Accessing file tail Appendix E. How to distinguish motherboards Preface The following discussion of copy protection issues is almost completely based on my own experiences with copy protected PC software and personal communications with my colleagues. Therefore any statement made herein can't be considered as the holy truth (or any truth at all). This document is NOT the manual on development of copy protection schemes, but a brief introduction into "breaking" them. Anyone using this document or examples supplied with it for the development of copy protection software or hardware will violate license agreement. No legal aspects of copy protection will be covered here. Nevertheless, you can use this data from this manuscript only according to law. If there is no law on computer software (as in Soviet Union), you should always regard moral considerations. I can't be held responsible for any improper use of this document and code supplied with it. You will see that protection examples are somewhat scarce in number and are not always up to date. (E.g., parallel port locks, currently the most popular protection device, are not covered at all). Taking into account geographic location of Novosibirsk, this can hardly be my fault. Any work of this sort is always based on support of other enthusiasts, because no individual can afford to purchase all (or any, because they are sold for the hard currency) of new copy protected programs. So I wish to express my warmest gratitude for all people who supplied me with protected PC software. Finally, I beg your pardon for my far from good english. I will welcome any suggestions on this document organization and style. Serge Pachkovsky Novosibirsk 06 June 1991 1. Copy protection based on key disk This type (or rather types) of copy protection are of the same age as PC itself. The years of development and sophisticated floppy disk hardware give rise to numerous protection methods. Although with recently appear of parallel port locks, key disk technique seems to be old-fashioned, it still has at least two obvious qualities. First, key disk can be simultaneously used as distribution disk and second, this type of protection is very cheap (but nevertheless hard to tamper with). So, key disks still can be used for wide distributed personal use software. On my account, in the SU key disk protection will dominate for a while. In order to understand floppy disk controller (FDC) protection tricks, one should be aware of basic FDC data and operation. Let us now consider them. (Note: Sections 1.1 and 1.2 are mostly based on Intel documents "An intelligent Data Base System Using the 8272", "8272 Singe/Double Density Floppy Disk Controller Data Sheet", "8272A Single/Double Density Floppy Disk Controller".) 1.1 MFM floppy disk data recording Modified Frequency Modulation (MFM) floppy disk format was introduced in the IBM System 34 and is often referred to as "double density recording". Term "single density recording" corresponds to straightforward IBM 3740 Frequency Modulation (FM) format, which used 4 æs to record one bit of data. Original MFM recorded one bit in 2 æs cell, but for the IBM PC mini-floppies was used 4 æs cell. Therefore, unformatted size of one track become 6.1 Kb. So called "high density" PC disks merely implement 2 æs data bit cell of original MFM specification. 1.1.1 Data bits separation Data recording in FM format was simple: beginning of each bit cell was specified by so called clock bit, and actual data was recorded at center of each cell (data bit) (See fig 1.1.1a). Such technique allows simple data bits separation, but wastes frequency range twice as needed to save actual data. Nevertheless, complete removal of clock bits will make recorded data containing large series of zero bits undecipherable because of random variations in floppy rotation speed and controller oscillator. ³ Ú¿ Ú¿ ³ Ú¿ ³ ³ ³³ ³³ ³ ³³ ³ ³ ³³ ³³ ³ ³³ ³ ÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄ '1' '0' Fig 1.1.1a FM data recording. To deal with such deficiency, most clock bits were removed in MFM by the following rule: Clock bit should be written at the edge of bit cell if no data bit was written in the previous cell and no data bit will be written in the current bit cell. (See fig 1.1.1b). Such encoding makes data bit separation a more difficult task, but nearly removes clock bits overhead. ³ |Ú¿ ³ |Ú¿ ³ | ³ Ú¿ | ³ ³ |³³ ³ |³³ ³ | ³ ³³ | ³ ³ |³³ ³ |³³ ³ | ³ ³³ | ³ ÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄ '1' '1' '0' '0' Fig 1.1.1b MFM data recording. One can easily see, that meaning of both FM and MFM encoding depends upon initial position of bit cell. For example, if we will place bit cell as shown by dashed lines on fig 1.1.1b, sequence '1100' will become '0010'. To provide unambiguous data bits decoding each data field on track is supplied with synchronization field. 1.1.2 Synchronization field and ID byte MFM synchronization fields consist of 96 zero bits (i.e., cells with clock bit and no data bits) followed by 3 bytes of A1h (10100001b). Zero bits permits to align correctly data cell, and A1s to identify beginning of actual data bytes. Although 12 zero bytes are written by FDC during format (this value can't be changed by software), only 1 byte (8 bits) is needed actually to synchronize bit cell. Other 11 are for "just in case". FM sync fields are simple - they consist of 48 zero bits only. (Again, FDC needs 8 bits and other are for safety). Different data (both user and auxiliary data) fields can be distinguished by the single byte immediately following sync field. These bytes can't be mixed with user data even if the later contains the exact byte sequence sync/ID, because these bytes (and only these bytes) do not use standard clock bit conventions. Unfortunately, I have information on corresponding clock bits for FM encoding only. ID bytes seem to apply to MFM as well. (Note what data fields are recorded MSB-first). ID byte Clock Field description FC D7 Index address mark FE C7 Sector ID address mark FB C7 Sector data F8 C7 Deleted data FE C7 IBM bad track ID Although in Intel documentation sync field is always referred to as part of preceding gap, we will consider it to be part of following data field. 1.1.3 Overall track format The reference point for all floppy operations is physical index mark, which is generated by diskette index hole. Entire floppy track format starting with physical index mark can be described as follows: - Physical index mark - Preindex gap (GAP 5) - Index address mark (IAM) - Post index gap (GAP 1) For n from 1 to N-1, where N is number of sectors on track: - Sector n ID - Post ID gap (GAP 2) - Sector n data - Post data gap (GAP 3) For the last data sector on track: - Sector n ID - Post ID gap (GAP 2) - Sector n data - Final gap (GAP 4) Index address mark (which is not used for any purpose by 8272A) has somewhat different sync field: instead of A1h it uses C2h (11000010b), which are followed by FCh (11111100b) ID byte. Sector ID field contains FEh followed by one byte values C,H,R,N, where C stands for cylinder number, H for head number, R for sector number and N for sector size code. These bytes (including FEh) are validated by 16-bit CRC, which follows. Size of user data in the following data field can be calculated as 128 * 2^N, i.e., N=0 specifies data size of 128 bytes, N=1 - 256 bytes, N=2 - 512 bytes, and so on. C=H=R=N=FFh specifies IBM bad track. Data field contains FBh followed by 128 * 2^N bytes of user data and two bytes of CRC. Both in sector ID and in data field CRC is calculated using polynomial x^16 + x^12 + x^5 + 1 with initial value of FFh (as always, MSB first). 1.2 Intel 8272A floppy disk controller Rumors say, what original PC FDC was implemented on Intel 8272 chip. Of course, it could be any pin compatible - 8272A, NEC æPD765, and so on. I had never seen such a PC, so I just can't tell. Nevertheless, in order to maintain register level compatibility (good feature!) with first PCs, all more recent controllers are nearly the same for programmer. Commands are performed by 8272A in three subsequent phases: command phase, execution phase and result phase. During command phase CPU instructs 8272A what to do. During execution phase, FDC performs requested action. All user data transfers (if any) will be done during execution phase. Execution phase is followed by result phase, when FDC returns status data. While FDC data requests during command and result phases could be infinitely delayed (data will be stored in internal 8272A registers), all FDC requests during execution time should be satisfied immediately, or FDC will generate data overrun error and terminate operation. More strictly speaking, data request could not be delayed for more then time of transfer of 8 data bits. Therefore, on 360Kb disk drive, which operates at 250K (1K here = 1000) bits per second (KBPS), FDC will transmit byte of data each 32 æs or 31250 bytes per second. Although 8272A itself can operate in either DMA or poling mode, only relatively fast CPU is capable of transmitting data at such rate. Running FDC in poling mode on double density disks requires at least 6 MHz 80286, while AT high density floppy will eat up entire 10 MHz 80286. 1.2.1 8272A registers 8272A chip interacts with CPU trough two registers: Main Status Register (MSR) and Data Register (DR). MSR is read only. Either DR could be read or written is determined by RQM bit of MSR. Meaning of bits in MSR could be seen on fig 1.2.1a. ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ RQM ³ DIO ³ NDM ³ CB ³ D3B ³ D2B ³ D1B ³ D0B ³ ÀÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÙ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄ Drive 0 busy. ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄ Drive 1 busy ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Drive 2 busy ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Drive 3 busy ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ FDC busy ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ non-DMA mode ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Data Input/Output ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Request for Master Fig 1.2.1a Main Status Register of 8272A. Bit DxB will be set to 1 then corresponding drive performs seek or recalibrate command. CB bit will be set then FDC performing read or write operation. NDM is set when FDC is in execution phase and DMA operations disabled (So it indicates what more data should be fed to or read from DR). DIO will be one then CPU should read data from DR and zero if CPU should feed data to DR. RQM = 1 indicates that DR is ready to transfer next byte. Direction of transfer depends upon DIO value. Internally, 8272A stores current cylinder number for each of disk drives connected to it. Because floppy drive can't distinguish one cylinder from another (except cylinder 0), this is needed to perform seek operations, which are translated by FDC to drive step pulses. These registers are cleared by FDC reset (but floppy disk drive will not return to track 0 on reset). Other important internal registers contain step rate time, head unload time and head load time (see Specify command). 1.2.2 8272A commands summary 8272A commands can be divided into three groups: user data transfer, floppy control and diagnostic aids. User data transfer includes read data, read deleted data, write data, write deleted data and three scan commands: scan for equal, scan for lower or equal and scan for higher or equal. Floppy control includes recalibrate, seek, sense drive status, sense interrupt status and format a track commands. Read sector ID and read track commands could be considered as diagnostic. All commands with unrecognized first byte will be treated as invalid command. 8272A commands can be easily identified by low nibble of first command byte - see table 1.2.2 (although some of such commands will be invalid). Table 1.2.2. 8272A opcodes. x1 Scan equal x2 Read a track x3 Specify x4 Sense drive status x5 Write data x6 Read data x7 Recalibrate x8 Sense interrupt status x9 Write deleted data or Scan lower or equal xA Read ID xC Read deleted data xD Format a track or Scan higher or equal xF Seek Generic sequence to execute 8272A command consists of the following steps: 0. If DMA will be used in operation, program channel 2 of 8237A for the single byte transfer mode. (Note: Terminal Count (TC) signal from DMA will cause immediate completion of FDC operations). 1. For each byte in command, wait until RQM bit = 1, when check DIO: value of 0 indicates what FDC ready to accept command, 1 says what either your command was not recognized by FDC (and next read from DR will return 80h) or that you had already fed all data in FDC (and your command is invalid, too). If your command does not have execution and result phase (Specify), you stop here. 2. If you are running FDC in poling mode and command transfers data during execution phase (read, write, format), you wait here while NDM bit is zero. When while NDM is not zero, for each byte read or written you wait for the RQM bit to be set and then writes next byte to (or reads from) DR. If you are using DMA-mode transfer (or no transfer at all), you simply goes to step 3. 3. End of execution phase is indicated by IRQ 6 (int 0eh). You can either enable 8272A interrupts and detect this in your interrupt routine or you can constantly poll 8259A interrupt request register (IRR). If command does not have execution phase (Sense drive status), you go to step 4. 4. In the result phase you read command status from FDC by poling RQM byte (be sure that DIO = 1 here). 8272A can return up to 3 status bytes (which are shown below) along with other data, which will change from command to command. ÚÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ IC ³ SE ³ EC ³ NR ³ H ³ DS1 ³ DS0 ³ ST0 ÀÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ EN ³ 0 ³ DE ³ OR ³ 0 ³ ND ³ MW ³ MA ³ ST1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ 0 ³ CM ³ DD ³ WC ³ SH ³ SN ³ BC ³ MD ³ ST2 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ FT ³ WP ³ RDY ³ T0 ³ TS ³ H ³ DS1 ³ DS0 ³ ST3 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ Fig 1.2.2 Status bytes 0-3 of 8272A ST0. IC - Interrupt code: 00 - Normal termination of command. 01 - Abnormal termination of command (Operation still can be Ok, other condition codes should be tested). 10 - Invalid command. 11 - Abnormal termination (disk ready signal changed during execution). SE - Seek operation ended. EC - Equipment check error (fault signal received from drive or cylinder 0 was not reached after 77 pulses during Recalibrate). NR - Not ready (Drive becomes not ready during read or write or side 1 was requested for single-sided disk). H - Head address. DS0, DS1 - Drive address. ST1. EN - End of track error (FDC attempt to access a sector beyond the final sector of track). This flag will be set to 1 (and therefore IC will be equal to 01) if FDC had read sector specified in EOT command parameter and TC signal is low, so every read operation in poling mode will end with EN error. DE - Data error. Either sector AM of sector data CRC is invalid. OR - Overrun error. 8272A had not received CPU or DMA services within the specified time interval (32 æs on 360Kb drive), so data was lost. ND - Sector not found. Specified sector was not found during 2 disk revolutions (i.e., two index pulses were detected since the start of operation). For multi-sector transfers, 2-revolutions time-out applies for each sector separately. NW - Write protect error. Write protect signal was detected during write or format operation. MA - Missing address mark. Either sector AM or data AM was not found. ST2. CM - Control mark. Deleted data AM detected during read data command or data AM during read deleted data command and SK bit was not set. DD - Data error. Sector data CRC invalid. DE will be set, too. WC - Cylinder address error. Cylinder address on track does not match specified cylinder address. SH - Scan hit. Scan command conditions were satisfied. SN - Scan not satisfied. BC - Bad track error. As WC, but cylinder address from track is FFh. MD - Missing data AM error. MA will be set, too. ST3. FT - Fault. Disk drive indicated fault. WP - Write protect. RDY - Drive ready signal. On PC and AT floppy subsystems this will always be set, regardless whether drive is ready (or installed at all). T0 - Track 0 signal. TS - Two-sided. On PC and AT floppy subsystems this will be 0 always. 1.2.3 8272A commands description Here I'll list all 8272A commands in the order in which they appear in table "8272A command set" of Intel 8272A manual. Of course, this description is not sufficient to implement floppy disk driver. See Intel manual for complete information or Appendix A for the simple example. Read Data ÄÄÄÄÄÄÄÄÄ Command: MT MFM SK 0 0 1 1 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/DTL Execution: Data fields on track been read. Result: ST0/ST1/ST2/C/H/R/N MT (MultiTrack) instructs to continue read operation on track 1 of the same cylinder. SK causes FDC to skip deleted data fields. HDS indicates head number used in operation. DS1,DS0 constitute a drive number. C/N/R/N sector ID of starting sector EOT number of sectors on track GPL inter-sector gap length DTL should be FFh for MFM. Read Sector ID ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: 0 MFM 0 0 1 0 1 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ Execution: First correct sector ID been read. (First signifies "first encountered starting from current head position" and not "first after physical address mark") Result: ST0/ST1/ST2/C/H/R/N Read Deleted Data ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: MT MFM SK 0 1 1 0 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/DTL Execution: Deleted data fields on track been read. Result: ST0/ST1/ST2/C/H/R/N SK instructs FDC to skip data fields. Read a Track ÄÄÄÄÄÄÄÄÄÄÄÄ Command: 0 MFM SK 0 0 0 1 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/DTL Execution: Data fields on track been read. Result: ST0/ST1/ST2/C/H/R/N This command will read data fields regardless of C/H/R/N values stored in sector IDs. Data field that lacks valid IDs can be read by this command. Although Intel documentation specifies that Read Track command stops then no data fields at all found on track or sector count reaches EOT value, this command will terminate then no data address mark was found after sector ID address mark with bad CRC. Read a track command will accept ANY N value, so it can read inter-sector gap (or all track, if N is large enough) along with sector data. Sectors will be read in order of appearance under r/w head, i.e., if track was formatted with 8 512-byte sectors (interleave 1:1), and you start read track command with R = 1, N = 3, EOT = 4, sectors 1, 3, 5 and 7 will be read. Write Data ÄÄÄÄÄÄÄÄÄÄ Command: MT MFM 0 0 0 1 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/DTL Execution: Data fields on track been written. Result: ST0/ST1/ST2/C/H/R/N Write Deleted Data ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: MT MFM 0 0 1 0 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/DTL Execution: Deleted data fields on track been written. Result: ST0/ST1/ST2/C/H/R/N Format a Track ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: MT MFM 0 0 1 1 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ N/SC/GPL/D Execution: Command formats track with SC sectors of size N. Sectors are filled with byte D. C/H/R/N values for each written sector ID should be supplied by user (as in write data command). Result: ST0/ST1/ST2/C/H/R/N Note: GPL = 0 will be understood as 100h. Scan Equal ÄÄÄÄÄÄÄÄÄÄ Command: MT MFM SK 1 0 0 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/STP Execution: Data fields on track been read and compared byte by byte with data supplied by CPU or DMA. If scan condition not satisfied, scan continues with sector R+STP. Result: ST0/ST1/ST2/C/H/R/N Scan Lower or Equal ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: MT MFM SK 1 1 0 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/STP Execution: Data fields on track been read and compared byte by byte with data supplied by CPU or DMA. If scan condition not satisfied, scan continues with sector R+STP. Result: ST0/ST1/ST2/C/H/R/N Scan High or Equal ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: MT MFM SK 1 1 1 0 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C/H/R/N/EOT/GPL/STP Execution: Data fields on track been read and compared byte by byte with data supplied by CPU or DMA. If scan condition not satisfied, scan continues with sector R+STP. Result: ST0/ST1/ST2/C/H/R/N Recalibrate ÄÄÄÄÄÄÄÄÄÄÄ Command: 0 0 0 0 0 1 1 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 0 DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ Execution: Recalibrates specified drive. All 4 drives can be recalibrated simultaneously. 8272A can perform read or write operation on any other drive. So sense interrupt status command should be used to distinguish interrupt caused by completion of recalibrate from operation completion interrupt. FDC will not permit any command on recalibrated drive before sense interrupt status issued for seek completed interrupt. Sense Interrupt Status ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: 0 0 0 0 1 0 0 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ Result: ST0/C (Note: then IC = 10 (invalid), C will not be returned) 8272A will generate interrupt request if any of the following events occurs: a) Result phase begins for Read/Write/Format/Scan b) Ready signal from one of drives changed. c) Seek/Recalibrate completed. d) Non-DMA data transfer required. Interrupt service routine can easily distinguish this cases: if NDM = 1 then it's data transfer request else if CB = 1 then it's result phase beginning else if SE = 0 then it's ready signal change else it's seek or recalibrate end. Specify ÄÄÄÄÄÄÄ Command: 0 0 0 0 0 0 1 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ SRT HUT ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ HLT ND ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÙ SRT Step rate interval. Sets the minimal delay between two drive step pulses. (1-16 ms, SRT = 0Fh corresponds to 1 ms). Older PC drives supported 3 or 4 ms step rate, some never ones can cope with 2 or even 1 ms step rate. HUT Head unload time. Delay between completion of read/write operation and lifting head. (16-240 ms, HUT = 0 is 16 ms). This is usually set to 240 ms. HLT Head load time. Delay between head load command and start of read/write operation. (2-254 ms, HLT=1 is 2 ms). This is usually set to 2 ms. ND 0: DMA mode. 1: non-DMA mode. All timers inside 8272A are actually synchronized to WR CLK signal, so all values shown here are correct for WR CLK 500 KHz or data transfer rate 500 KBPS. Lowering frequency of WR CLK will lengthen all internally counted delays. Sense Drive Status ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command: 0 0 0 0 0 1 0 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ Result: ST3 Seek ÄÄÄÄ Command: 0 0 0 0 1 1 1 1 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 0 0 0 HDS DS1 DS0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ C See Recalibrate. 1.2.4 AT floppy disk controller Original PC and XT floppy disk controllers were capable of running four floppies. AT FDC, although register compatible, can run only 2, so one can install 2 FDCs into AT. Most clone BIOSes does not support secondary FDC, and I never had IBM AT to check wether IBM BIOS does. First FDC occupies address range 3F0-3F7, secondary FDC is at 370-377. All information here on primary FDC also can be applied to secondary by moving references to this address range. 8272A (or it's large scale integrated substitution) is mapped to ports 3F4 (MSR) and 3F5 (DR). As you have already seen, 8272A itself can't control disk drive motor status, so register 3F2 (digital output register) provides such services. (see fig 1.2.4a). ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ D ³ C ³ B ³ A ³ IE ³ EC ³ DS1 ³ DS0 ³ ÀÄÄÂÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÙ ÀÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÙ ³ ³ ÀÄÄÂÄÄÙ ³ ³ ³ ÀÄÄÄÄÄÄÄ Drive select ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Controller enable ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Interrupts enable ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Motor enable Fig 1.2.4a Digital output register (3F2h). Bits DS1 and DS0 of digital output register overrides DS bits specified in 8272A command, so one can change disk drive on the fly during command execution. Although this is dangerous technique, many copy protection tricks are based on this feature. Setting EC bit to zero resets controller, so any operation (e.g., format track or write data) can be stopped on any time. (Although special care should be applied to perform abrupt termination without oscillations). IE bit was intended for use in multiply-controller systems. Because all FDCs use the same IRQ 6 and DMA channel 2, inactive controller can (or cannot - no one can say) drive this line low, thus forbidding other controllers from obtaining system services. Drive motor enable bits is another source of protection tricks (See 1.4.2). Second additional register is at 3F7 (diskette control register). (This register does not exist on old XTs, but can often be found on recent clones). To my best knowledge, only two lower bits are meaningful for write and single upper bit for read. 3F7 write - select transfer rate: 00 - 500 KBS (MFM) 01 - 300 KBS (MFM) 10 - 250 KBS (MFM) 11 - 125 KBS (FM) Thirst three values (00 thru 10) was mentioned in IBM manuals. Although last value is undocumented, it works Ok on any AT FDC I'd ever encountered. (This is significant transfer rate - it permits to read/write SD disks in 360 Kb drive). Values 00 thru 10 are intended for use with MFM floppies, so they have pulse length 1/4th of cycle length. 125 KBS clock have pulse width 1/8th of cycle length. Because AT FDC have no 175 KBS FM clock, single density disks can't be written in high density (360 RPM) drive. Due to high error resistance of FM data format, single density disks still can be red in 360 RPM drive. FM floppies can be both red and written in 360Kb (300 RPM) drive. 3F7 read - drive change status: bit 7 set ( test al, 80h ) means that diskette was changed. Media changed indicator will be reset after first seek to cylinder other then zero. Obvious use for the 3F7 register in the copy protection world concerns adjusting of bit cell position. Because FDC switches to new transfer speed almost instantaneously, switching transfer speed at calculated moment will shift bit cell by small fraction of it's length. This technique permits to read any section of track, provided that at least one valid data field exists and position of section of interest is approximately known. 1.2.5 "Normal" PC floppy formats First standard PC floppies were designated for use with single- and double-sided 40 tracks mini-floppies. Following Intel specification, they had 8 512-bytes sectors per track, thus using 4096 bytes (65%) of 6250 bytes of unformatted track capacity. Sectors on track were ordered sequentially (interleave 1:1), as in all other standard formats. More recent 9 and 10 sector/track floppies use 74% and 82% of total space respectively. Theoretical limit for formatted DD track capacity is something about 89.2% (5575 bytes or 10.89 sectors/track). Such increase in floppy capacity was made possible by high stability of revolution time in modern floppies. Although deviation of 2.5% from nominal revolution time is permitted by IBM, I'd never seen floppy drive with revolution time outside 0.2% region. Such stability permits to decrease intersector gap length. For example, if possible deviation in rotation speed is ñ2.5%, one should reserve inter-sector gap sufficient to hold any resulting sector length. Suppose that floppy been formatted on drive with slowest possible rotation speed, and will be updated of drive with fastest rotation speed. In such a case, one should reserve at least (512+62) * (2*2.5%) bytes for intersector gap (62 is minimal sector header size for MFM format). This will result in minimal gap of 29 bytes, so even 10 sectors/track format is Ok for such deviations. In order to maintain compatibility (at least partial) with 40 tracks formats on 80 tracks HD drive, they are simulated by skipping all odd tracks. Therefore 360K disks written in 360K drive always can re read in HD drive, but 360K floppy written in HD drive can be incompatible with 360K drives. Because key floppies are almost invariably implemented on 360K drives, we will leave all high density formats alone. 1.3 Time independent protection tricks Here we will consider floppy protection marks, which can be verified without use of devices others then FDC itself. This tricks should work on any system equipped with compatible FDC. Note: Anytime when I will mention bit-copier, it will concern the latest version i'd seen. Anyway, they are not the latest versions exists. I have copies (illegal copies for the causes mentioned in preface) of Copy II - PC release 7.10, CopyWrite September 1988 edition and TeleDisk v 2.11. Note: Statement "could not be reproduced" applied hereafter to one or other protection mark indicates not physical limits of PC hardware, but limits of my knowledge of it. I will be grateful to anyone who will expand these limits. 1.3.1 Extra or missing sectors Because first MS-DOS floppies had a lot of unused space on track, it was an obvious idea to store additional sector(s) on track along with standard MS-DOS sectors. Even far better packed 10 sectors/track format will accommodate single 256-bytes sector. Other place to locate such additional sectors is track 41, which is not used by DOS, but can be accessed in most drives. On 80 track drives, extra sectors could be hidden on odd tracks. Now, this mark alone can't be considered as good copy protection, because extra sectors can be easily found by read sector ID command. Any bit-copier on market (CopyWrite, CopyIIPC, TeleDisk, etc.) will do it. (Although sectors on odd tracks will not be found by some programs). For the nice variations of this scheme, see sections 1.3.4-1.3.8. 1.3.2 Weak data bits Other old good protection trick is data, which will appear different in subsequent read operations (weak data). Weak data can be caused by either data falling into digital "uncertain area", or by long series of zero data and missing clock bits. In first case, decision of FDC will be driven by random noise. In later case, random variations in drive rotation speed will move bit cell out of synchronization (Such data could not be written without modification of FDC hardware, so we will not discuss them). One good ability to generate weak data is to place them atop of surface defect. Such weak data will not disappear after write sector data command. Unfortunately (hi!), manufacturer surface defects are now rare to occur, so one should make defects manually. I'd seen a lot of such techniques, ranging from disk scratching with a rusty nail to careful evaporation of surface layer by 1 kVA infrared laser. Nevertheless, it's hardly a software issue. Weak data bits could be created by software, too. First approach is to manipulate drive select/deselect bits in digital output register (3F2h). For example, if you wish to create weak byte on drive A:, you should start write operation, wait until desired byte will be transferred to disk drive (not to FDC!) and repeat sending to digital register values 1Dh (select drive 1) and 1Ch (select drive 0) while byte being transferred. Such operation will modulate all data (including clock bits) written to disk with square wave, moving them into uncertain region. Second technique requires almost the same operation with diskette control register (3F7h). Data rate switching will misplace data and clock bits and deform them in shape, also moving into uncertain area. Bit copier encountering weak data faces an interesting dilemma: whether weak bits are consequence of unrecognized surface defect, and operation should be repeated until original data will be recovered or is it a protection mark, which should be reproduced in all it's glory? Of all bit-copiers i'd encountered, CopyWrite only was able to cope with weak data, although it converts single weak byte into something of 10 to 12 bytes in length, so original mark still can be easily distinguished from copy. Wherefore, weak data is not such a bad thing for cheap protection and will obviously pop-up in homemade SU software. 1.3.3 Data in gap One can easily store small amount of data in gap after sector data field (GAP 3). Provided that sector is not overwritten, mark will reside in gap completely safe. Upper margin for number of data bytes, which will fit into GAP 3 given by GPL value of track format command. Verification of such mark is simple (at least for the first sector on track) - read a track command with N one large then actual value in sector ID will load gap data into memory. Storing data in gap requires more sophisticated procedure. Assume someone wishes to store 10 bytes of data into gap of first 512-bytes sector on track 0 head 0. He should first format track 0, specifying length code 3 (1024 bytes) for the first sector ID but length code 2 for the format parameters. Then he should start write operation on his dummy 1024-bytes sector, but stop it after transfer of 526 bytes (512-byte sector data + 2-byte CRC + 10-byte gap data + 4 byte safety margin). Then he should start format track operation with length code 2 (both format parameters and sector ID) and stop it somewhere inside GAP 2 (sector ID already written, but data field still not affected). Both format and write operations can be stopped by either controller reset (sending 0 to digital output register, 3F2h) or by changing selected drive (see 1.3.2). Unfortunately, it can sometimes be difficult to differentiate between "empty" gap and gap containing protection data. Older floppy drives have had a relatively large write signal attenuation times, so gaps written on such drives are filled with random garbage, which can be misinterpreted as binary protection data. Protection scheme designer can enhance these difficulties, using weak bits (1.3.2) inside gap protection data. Among mentioned bit-copiers only CopyWrite was able to detect data in gap. Single curious exception is first sector of track 0, head 0, which is deliberately ignored by CopyWrite as place for gap data. 1.3.4 Sectors with no data address mark Sectors without data address mark will generate missing data AM error (MA bit in ST0 and MD bit it ST2 will be set) during data read and write operations. Read sector ID command will terminate normally on such sector. Storing sector with no data AM requires simple format operation, which should be stopped after writing sector ID AM but before writing data AM (as in 1.3.3). Special care should be taken to eliminate early existed data AM, either by using electromagnetically erased disks or by preliminary format at different data transfer rate. Alternative way (which will not work for first sector on track) is: First, format track with GPL value selected to place data field where the data AM sync field should start on target disk. Second, reformat track with desired GPL value and stop before sector AM is written. 1.3.5 Sectors with no sector ID address mark Sectors without sector ID AM can be written in the following fashion: Format track, storing length code N+1 for the sector before one of interest. Then read content of this dummy sector and write it back, stopping operation then sector ID AM already overwritten but data AM still Ok. Now you had got sector with no ID AM. Such sector will NOT raise any exceptions in any FDC operations. It can't be, generally speaking, read by any command without special care taken, so it almost does not exist. No one of tested bit-copiers was able to recognize such sectors (but any hardware bit-copier should be able to do it), so missing ID AM can be considered as good protection. Nevertheless, verification difficulties make appearance of such mark in "live" protection scheme highly unlikely. (But see 1.3.10). 1.3.6 Sectors with bad sector ID address mark This mark differs from 1.3.5 only by extent of ID AM corruption. Here, FDC is still able to recognize ID AM, but CRC on it verifies incorrectly. This mark can't be detected by read sector ID command, but will set DE bit in ST1 and clear DD bit in ST2 during execution of read sector command, so with values C/H/R/N been known, verification presents no problems. Sector with bad ID AM will nevertheless appear in read a track command. Then exact C/H/R/N values are not known, they still can be obtained by the following procedure: Knowing exact position of data field from time measurements, one can deduce approximate position of ID AM and read it, using technique of adjusting bit cell (See 1.2.4). Valuable for copy protection designer modification of this mark has invalid CRC of sector ID and no data AM. Such sector will cause termination of read a track command, thus preventing detection of "normal" marks of such type placed after it by bit-copier. In order to write bad ID AM, one should stop format operation while sector ID AM CRC being written. (Let me again note, that FDC has internal buffer for something about 3 bytes, so controller starts write CRC not then last ID byte been fed to DR, but some time after that). CopyWrite will recognize sector with bad ID AM and copy it. 1.3.7 Data field passing over index address mark Protection marks of this type had appeared when someone asked: That FDC will do if format a track command will specify total data length on track to be slightly more then track can hold? Consider the following results obtained by formatting DD disk in HD drive with 13h 256-bytes sectors and different GAP 3 values (Sector offsets measured from physical index hole). Note that revolution time of drive used is 166.52 ms. Table 1.3.7 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ GAP 3 value ³ Sector 1 offset ³ Sector 13h offset ³ ³ ³ Start ³ Start End ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ 01h ³ 3.849 ³ 156.981 165.46 ³ ³ 08h ³ 3.844 ³ 160.334 2.29 ³ ³ 10h ³ missing ³ 164.180 6.14 ³ ³ 14h ³ missing ³ missing ³ ³ 18h ³ missing ³ 1.519 10.00 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ One can see that there is small area at the beginning of track, which is not used by sector data (actually, its used by index address mark). This area can be overwritten by last sector on track (as on second line of table 1.3.7), but if last sector data overlaps with beginning of track too much, sector 1 will be erased (line 3). If the start of data field of last sector will pass over index hole (line 4), controller will write GAP 4 until next occurrence if index hole, thus overwriting all existing sectors on track. If the start of sector ID AM passes over index hole, too (line 5), this sector will be preserved, overwriting all previously written sectors. Sector passing over IAM can cause significant problems for bit-copier unaware of their existence, because many protection marks are generated by repeated format operation, which will destroy data in over-IAM sector. No one of tested bit-copiers was able to reproduce such sectors (i.e., retain both sector data and sector position), so this mark being extensively used in SU copy protection schemes. 1.3.8 Multirate tracks As we have seen in previous section, FDC ignores IAM at the beginning of track, so sectors can appear at any position inside track. It's therefore an obvious idea to have different parts of track written at different data transfer rates. (This is best done not by switching transfer rate during format operation, but by two subsequent formats at different rates). For example, one can have 9 sectors of 512 bytes on track 0 at 300 KBPS (HD drive) and single 512-bytes sectors at 500 KBPS. (Because this is an outermost floppy track, using high transfer rate on DD disks will not push data safety too far). Although different data transfer rates are entirely in AT domain, similar mark can be generated with FM and MFM data formats (i.e., 9 MFM sectors and 1 FM one) on PC and XT. No one of tested bit-copiers was able to reproduce multirate track, so it's a good trick for a while. Nevertheless, I'd not seen floppy protection based on such mark still. 1.3.9 Data access over gap Now we'd come to a most popular (and possibly the best) floppy protection trick, data access over the gaps. Because all sector ID and data fields are synchronized separately, two bit cells in two subsequent fields can be shifted arbitrary. This shifts are driven by random variations in WR CLK and drive rotation speed, so they can't be controlled. (Of course, one can imagine ANALOG copying device, what will be able to do it. I'd never heard about such birds.) Any read track operation with sufficiently large length code (say 6) will give "track footprint". Number of different "footprints" can be roughly estimated in the following fashion: Assume that each joint of separately synchronized fields can have 2 different states (obviously, it's underestimation). On the track of an ordinary DD floppy there are 19 such joints (9 ID AMs, 9 data AMs, 1 IAM), so number of different footprints for each track is at least 2^19 ÷ 500,000. To make life more interesting for analog copying devices, one can further enlarge length code (say to 7). This will not increase number of footprints, but will include track more then once. Because even best device should start and stop operation somewhere, it will partially corrupt data. This mark sets single restriction on use of protected disk: key track can't be overwritten. Other, less interesting variation of this idea, is to read next sector ID AM over the GAP 3 and check whether it changed. Such check forbids write access to a single sector only. Obviously, protection designer does not restricted to obtaining "footprints" with read a track command (and thus to chip-level access to hardware). It can be done simply by adding dummy sector with length code 6 or 7 at end of track, and job will be done by BIOS. Neither one of these checks can be reproduced on standard PC equipment. Nevertheless, many programs using second variation can be outsmarted by enlarging GAP 3 after sector of interest and storing sector ID AM, as it appears for over-gap read, into this gap. If program does not check exact sectors position on track, it will accept such "copy" as a key disk. 1.3.10 Crazy ideas All previously discussed protection tricks had permitted non-destructive verification. Now let me imagine protection mark, which can't be checked or detected by bit-copier without preliminary write access to key disk. Remember sectors with no ID AM (1.3.5). What will we get if no other sectors exists on track of interest? (At least, at the same transfer rate). This sector can't be read until format a track operation, which will supply ID AM. Any attempt to step inside such program with debugger will destroy protection mark, because precious timing of stopping format operation will be affected by debugging. This simple example shows that there are protection marks, which can't be baited out key disk without destroying part of it content or without inside knowledge of protection check. 1.4 Timer-based protection tricks All PCs are equipped with a relatively good timer chip, Intel 8253 or its functional equivalent. Operating at 1,193,180 Hz, it permits to measure time intervals with 840 ns resolution (i.e., it can measure execution time of SINGLE div instruction on 16 MHz 386, which can take up to 2.4 æs). Such timer is more then adequate for floppy timing measurements (Transmission of single data byte on fastest possible rate (500 KBS) will take 16 æs), so precision of such measurements will be limited not by timer resolution, but by random rotation speed variations. 1.4.1 Sector ordering (interleave) checks Measuring completion time of subsequently issued read track commands, one can obtain exact position of each sector on track. In terms of data bits, you can obtain sector position exact at least to one bit. Because FDC's format a track command controls sector position with byte resolution, it can't reproduce such exact sector ordering. So, sectors position alone can serve as protection mark. Nevertheless, this check will be too sensitive to CPU speed and drive rotation stability and will often reject original key disk. Therefore, sector position is ordinary used as supplement to other protection mark(s) (See 1.3.9). 1.4.2 Data transfer rate measurements FDC data transfer rate selected by diskette control register (3F7h) is only the initial, or center, frequency used by FDC for data bits decoding. Special analog circuit, called phase-locked loop (PLL), adjusts it in order to track rate, at which actual data bits arrive. PLL should tolerate at least 4% deviation from central frequency (permitted deviation in drives rotation speed is ñ2%). In practice, PLL will cope with 10% deviation on MFM floppies and almost 100% on FM ones. Rate of data bits arrival is determined by both angular density of floppy data and drive rotation speed, so to determine the disk characteristic (data angular density) one should measure both single sector transfer time and revolution time. Maximum accuracy of such measurement can be easily estimated: Single 512-bytes sector will be transferred at (central) frequency of 500 KBS during 8.2 ms, timer resolution of 0.84 æs gives relative accuracy of 0.01%. Relative error in revolution time determination is less at least by an order of magnitude. Giving a 10 factor for a safety margin, 0.1% seems to be a reasonable estimation. So, all PC floppy drives will fall in 40 (2*2%/0.1%) different groups, and floppies written on drive from one group can be easily distinguished from floppies written on others. Unfortunately (Hi!), most modern drives will fall into ñ0.2% region and thus into 4 groups instead of 40, almost eliminating all "protection". Some FDCs (e.g., my old 1986 WD HDC/FDC) had permitted simple trick with digital output register (3F2h): output 0Ch to 3F2h (stop drive A: motor), wait a while (10 ms), output 1Ch to 3F2h (start drive A: motor) and immediately perform write operation. Drive rotation speed was slightly less when nominal for about 20 ms, permitting to write single sector. My new 1990 IDE HDC/FDC, however, waits until rotation speed reaches nominal, delaying write operation. Interesting variations of this mark can be achieved by minor modifications of PC hardware (See 1.5.3). 1.5 Protection based on special hardware I am not specialist on copy protection hardware, so discussion here will be almost invariably based on rumors and speculations. 1.5.1 Modified MFM formats Intel 8272A FDC chip has no software control over GAP1, GAP2 and GAP5 length, but will still accept floppies with these gaps differ from standard values and has ability to measure actual gap length. For example, GAP2 (post ID gap) can be measured either by read a track command with length code large then actual sector length or by measuring difference in completion time of read sector ID and read data instructions. Floppies with different gap values could be created for PC on other computer systems, which have control over these parameters. (I'd heard that some DEC systems do.) 1.5.2 Misplaced data tracks Some floppy controllers/drives can have more strict control over read/write head placement then PC does. (I was assured that required hardware modifications are not too large.) This can be originally done not for copy protection purposes, but in order to provide ability to read floppies written on badly adjusted drives. (Again, I'd heard that ICL FDC has such ability.) Therefore, key disk for such system can be prepared with non-standard track positions (and software will verify this). Such disk could not be verified on other computer system, so this technique could have only a limited application. 1.5.3 Non-standard transfer rates As we have seen in 1.4.2 FDC will permit significant variations in angular data density on track (and has ability to measure them). Minor modifications of FDC or disk drive give ability to control manually center frequency of WR CLK oscillator or drive rotation speed and thus give ability to write data on slightly non-standard (but still acceptable for most FDCs) data transfer rate. Some hardware manufacturers (e.g., of scientific equipment with built-in microcomputers) do this to "cuff" customers. (I'd seen 360 RPM 3¬ inch drives, which were therefore incompatible with "normal" 300 RPM 3¬ drives.) 1.6 Protection schemes examples Inside knowledge of floppy protection schemes shown here based upon my personal experience with protected programs (unless other specified), so it can't be considered to be complete and can't cover all aspects and all versions of protection software discussed. All protected programs discussed here were examined with Copy Unprotector Toolkit (C.U.T.). 1.6.1 IBM Filing Assistant This is really simple and straightforward protection dated 1986. It has no any practical significance and shown here only to demonstrate development of floppy protection art during last years. This "protected" software checks the presence of sector 8Fh length code 2 on track 39d side 1 of key floppy. No other checks are made. Because first versions of CopyWrite I'd seen were issued in 1985 (and were able to copy such marks), only hopes for dumbness of "these russian apes" can stand behind such protection. 1.6.2 SuperLok Superlok disk I was able to acquire was dated 10 oct 86. Protected disk had contained three tracks with marked "abnormality" (all at head 0). The first one was track 5, which had unusual interleave and two sectors with short data, so sector IDs constitute the following sequence (all values are in hex): 05/00/01/02, 05/00/06/02, 05/00/8A/03, 05/00/02/02, 05/00/07/02, 05/00/65/03, 05/00/03/02, 05/00/08/02, 05/00/04/02, 05/00/09/02, 05/00/05/02 As it turned out, SuperLok does not checks this track at all, so it constitutes the sort of decoy for interested explorer. Second protection track on disk was track 12d. It contained sector with hidden address mark (see 1.3.6) with ID 7B/46/05/00, which SuperLok had verified with read data command. Other protection check on this track, was done by read a track command with length code 6 (single 8192-bytes sector) and 3 (two 4096-bytes sectors). 16-bit checksum of bytes was calculated in both cases and compared with stored value (see 1.3.9). Third protection track contained four special sectors. First of them had hidden sector AM and no data AM, preventing detection of others. Three sectors had hidden sector AM: 21/47/05/00, A5/86/81/04 and EB/76/EE/04. After verification of these, SuperLok performed read a track with codes 6 and 3, again calculating 16-bits checksums. So, SuperLok presents good copy protection. No one of tested bit-copiers was able to copy such disk "literally" without modification of SuperLok data areas (and thus, internal knowledge of program). Probably, such "literal" copy is merely impossible (see 1.3.9). Later, I had a chance to make a quick glance on SuperLok disk dated 1990. Hidden sector AM checks were removed (?), Read a track access to protection mark was substituted (?) by additional sector with length code 6 at the very end of track. All (?) floppy access was done by BIOS. 1.6.3 Cops CopyLock II COPS CopyLock II bases protection checks on timing measurements. It uses additional sector 00/00/6A/01 on track 0 head 0 to store variable protection data. (COPS CopyLock permits "upgrade" protected software releases without key disk upgrade, so it can't store any more then serial number in program body). Second additional sector on track 0 (00/00/F6/02), which had partially overwritten IAM, was used to verify sector 1 ID AM over gap (see 1.3.9). In order to prevent protection bypassing ala 1.3.9, CopyLock verifies position of all (?) sectors on track by read sector ID command timing. Tracks 1 to 6 are very similar: they have two additional sectors at end of track: XX/00/14/01, which is not used (?) and XX/00/13/02, which overwrites IAM and is verified by the same manner as 00/00/F6/02. Tracks 7 to 9 have single additional sector (XX/00/14/01) each. These sectors are not used (?). On floppy I'd examined there was surface defect at track 32 head 1, but CopyLock had not verified its existence, so I didn't think it's another protection mark. This is again example of good protection scheme, although achieved by different means then 1.6.2. Nevertheless, with aid of C.U.T. I was able to recover unprotected version of program of interest (It was Paradisk from JV ParaGraph) during about 2 hours. I didn't think that development of CopyLock took less. Although I have copy of COPS CopyLock III, I still hadn't time to explore it, so it is to appear. . . 1.6.4 PC Shield This (homemade) disk protection scheme, devised by Alex Simkin, got a great advertisement in Soviet mass media. I had an ability to examine half a dozen versions of this product and thus monitor gradual development of the program. First versions of PC Shield had used simple mark of sector, overwriting IAM on track 0 solely. This fooled almost all bit-copiers, which had detected this mark as short data (Half of sector is after index hole, isn't it?) and thus destroyed it. Nevertheless, this mark still can be easily written by ordinary BIOS calls (not speaking of new versions of bit-copiers), and this protection was cracked. Next step taken was to access first sector's ID AM over gap (COPS influence?) Originally, length code 2 (512 bytes) was selected for this additional sector. This mark was cracked by technique described in 1.3.9 (again, nothing more then BIOS required). And now, the final step - length code of additional sector was increased to 6 (SuperLok influence?), making it difficult (but not impossible, still) to reproduce this mark by BIOS. Obviously, it's not an obstacle for a good bit-copier, and C.U.T. will mimic such mark easily. Further development of this protection scheme can go into two directions: inclusion of sector position checks (as in 1.6.3) or full track over-gap read (as in 1.6.2). Second direction, although requires reservation of entire track for protection purposes, seems to be more probable, because such development does not require chip-level access to FDC (all versions of PC Shield known to me use solely BIOS level floppy access routines). 2. Hard Disk based protection Floppy-based keys can provide good level of security, but they are tiresome for everyday use, waste precious disk drive and can be easily damaged by improper handling. Therefore, most copy protected packages can be installed on hard disk, using either hard disk protection marks (this chapter) or motherboard marks (chapter 3). Due to existence of lot of incompatible physical hard disk interfaces, hard disk marks are usually "least common denominator" of various possibilities and are simpler to tamper with. 2.1 Chip-level protection This level of hard disk access is highly unlikely to encounter, so we will briefly discuss AT WDC (Winchester Disk Controller), with which I have little personal experience. Primary AT WDC could be accessed at addresses 1F0-1F7 and 3F6 (This port is in address space of primary AT FDC, and good cause for hardware clashes in systems with FDC and WDC implemented on different add-on boards). Secondary AT WDC occupies addresses 170-177 and 376. AT WDC use IRQ 14 (int 76h with MS-DOS) and do NOT use DMA. Structure of AT WDC looks very alike to Intel 82062 chip operating in extended mode with 4 bytes ECC (Error Correction Code) appended to each sector. (Unfortunately, I have only Advance Information Sheet on 82062, so the description below can't be precious or complete). 1F0 - Data register, used to read/write sector buffer (512 bytes). Although word access can be used for sector data, only byte one is acceptable for ECC bytes read/write. 1F1 - read: Error flags register ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³ BBD ³ CRC ³ 0 ³ ID ³ 0 ³ AC ³ TK0 ³ DM ³ ÀÄÄÂÄÄÁÄÄÂÄÄÁÄÄÄÄÄÁÄÄÂÄÄÁÄÄÄÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÙ ³ ³ ³ ³ ³ ÀÄÄÄ Data AM not found ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄ Recalibrate failed: ³ ³ ³ ³ track 000 not found ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Command aborted ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ID AM not found ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Uncorrectable error ³ or data AM not found ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Bad block detect Fig 2.1a Error flags register (1F1) 1F1 - write: Start reduce write current cylinder / 4, 0FFh disables RWC feature. 1F2 - sector count register. Used to specify number of sectors to transfer in multi-sector operations - 1, i.e., value of 1 means 2 sectors. WDC will accept more then one track worth of sectors, updating head and cylinder number correspondingly. During format a track operation, specifies number of sectors on track (0FFh is 255 sectors). 1F3 - sector number register. During format a track operation, specifies value of GAP 1 and GAP 3 (see description of MFM in 1.1.3) minus 3 bytes. 1F4 - 8 low bits of cylinder number. (Tech Help! 4.0 is wrong here) 1F5 - 2 high bits of cylinder number (bits 0-1 are used). Some never WDCs will accept more then 2 bits in this register, thus supporting hard disks with more then 1023 cylinders, but most BIOSes strip these high bits anyway. 1F6 - Sector/Drive/Head select. ÚÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ EXT ³ SIZE ³ DRV ³ HEAD ³ ÀÄÄÂÄÄÁÄÄÄÄÂÄÄÄÄÄÄÁÄÄÂÄÄÁÄÄÄÄÄÁÄÄÄÄÄÅÄÄÄÄÄÁÄÄÄÄÄÙ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄ Head select (0-15) ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Drive select (0-1) ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Sector size code: ³ 00 = 256 bytes ³ 01 = 512 bytes ³ 10 = 1024 bytes ³ 11 = 128 bytes ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 0: Use CRC 1: Use ECC Fig 2.1b SDH (Sector/Drive/Head) register (1F6). In original 82062 specification, 3 bits were reserved for head select field and 2 bits for drive select, but these signals were processed by external circuits, so it really does not matter. 1F7 - read: Status register ÚÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÄ¿ ³BUSY ³READY³ WF ³ SC ³ DRQ ³ ECC ³ CIP ³ERROR³ ÀÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÁÄÄÂÄÄÙ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄ Error summary (OR of ³ ³ ³ ³ ³ ³ ³ all bits in 1F1) ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄ Command in progress ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Data is ECC-corrected ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Data Request (buffer ³ ³ ³ ³ is waiting for data) ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Seek completed ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Write fault ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ WDC ready ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ WDC busy (all other bits are invalid) Fig 2.1c Status register (1F7) 1F7 - write: Command register. Command code is written here. Instruction set of AT FDC (which is superset of 82062), includes the following commands: 0 0 0 1 R3 - R0 Restore to track 0 ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ 0 1 1 1 R3 - R0 Seek ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ 0 0 1 0 I M E T Read Sector ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 0 1 1 0 M E T Write Sector ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 1 0 0 0 0 0 0 Scan ID ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 0 1 0 1 0 0 0 0 Write Format ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 1 0 0 1 0 0 0 0 Diagnose ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ 1 0 0 1 0 0 0 1 Set drive parameters ÀÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÄÙ R3-R0 determines drive step rate, which is 0.035+0.5*R ms for 5 MHz clock rate. (My experiments with AT WDC indicate that this value is ignored by controller, which positions r/w head at maximum possible speed using Seek Completed hardware interface line). I = 0 requests interrupt on DRQ goes active, as well as after completion of command, I = 1 disables interrupt on DRQ active. M = 1 specifies multi-sector transfer, number of sectors is in sector count register. E = 1 disables data correction and passes 4 bytes of ECC along with sectors data. T = 0 enables transfer retries, i.e., if specified sector was not found after 6 revolutions, WDC performs automatic scan ID command, updates internal cylinder number, performs seek, if necessary, and repeats operation. T = 1 causes error if specified sector was not found after 2 revolutions. 3F6 - write: options register. Write 02h to take WDC IRQ 14 off system bus, 00h to resume normal operations. 04h resets controller. WDC format command scheme is far less flexible then 8272 one, and permits to select manually sector number only. Although sector ID AM contains cylinder, head and size values as well, they are derived from WDC command registers and can't be explicitly specified. Because all WDC commands (except Scan ID command) have implied seek feature, these fields are difficult to modify. Features of AT WDC, being obviously advantageous for normal computer operations, shrinks copy protection possibilities to extra/missing sector (see 1.3.1) and sector ordering (see 1.4.1) checks. ECC data correction permits to implement the third hard disk protection trick, data bit changed in specific position, which will be hidden by ECC. All these marks can be both generated and verified using BIOS-level disk access, and so, chip-level access to WDC have no significant advantages that can justify lack of portability. 2.2 BIOS-level protection This is obviously the basic level for hard disk based protection. Sufficient security from TSR software monitoring BIOS int 13h calls can be reached in this case by tracing int 13h till hard disk BIOS entry point (see example in Appendix B). Other reason for such elimination of watchers is possible necessity for accurate operation timing in interleave determination. 2.2.1 Interleave changes This technique is very alike to the same floppy method described in 1.4.1. Unlike floppies, where sectors are as a rule arranged sequentially (interleave 1:1), hard disks sectors are often preciously arranged by low-level formatters to provide fastest possible data transfer rate. It is therefore more difficult to see interleave mark on hard disk then on floppy. 2.2.2 Changed sector numbers Again, this is a twin of 1.3.1. Nevertheless, hard disks are ordinary tight packed with data sectors, so to add sector with non-standard number, one should remove one of data sectors. This situation can be easily spotted. 2.2.3 Unused disk areas At the BIOS level, there are two unused areas on almost any hard disk: at the very beginning and at the very end of drive. First sector of each hard drive (at least, not SCSI or ESDI one) is occupied by partition table, while all other sectors on cylinder 0 track 0 are not used in IBM and Microsoft partitioning schemes. Still, this area can be occupied by proprietary partitioning software. For example, DiskManager (dmdrvr.bin) uses sector 0/0/8 for extended partition table, Olivetty MS-DOS starts first DOS partition at 0/0/2, etc. Second unused area is the user diagnostic cylinder, which is located at the next to last disk cylinder on AT machines and on last cylinder on PS/2 ones (But they are still compatible, aren't they?) Anything written here has very little chances to last long, because any low-level disk test program has right to treat this track as it pleases. (Norton DiskTreet and Gibbson Research's SpinRite determine optimal interleave here, I believe). 2.3 DOS-level protection BIOS-level protection on hard disk does not provide too much alternative, while DOS has convenient (and relatively portable) ways of accessing DOS partitions (int 25h/26h interface, ExtendedOpen (6Ch) in DOS 4.0+), which could be used for copy protection. Structure of DOS filesystem is of common knowledge, so I will only briefly mention most significant parts of it. Sector 0 is boot sector. It contains code that loads operation system and table describing partition characteristics, such as number of sectors, number of sectors per cluster, number of FATs, number of entries in root directory. File allocation table (FAT), which follows, contains 12 or 16 bit value for each allocation unit (cluster), indicating number of the following cluster in chain. Usually, more then one (two) FATs are present on disk, thus providing data security. (Nevertheless, DOS does not treats FAT copies separately, but merely stores first FAT in additional areas duplicating any error occurred in 1st copy in all FATs, so security is really imaginatory). Root directory (following last copy of FAT) contains 32-byte table (called directory entry) for each file in directory. Directory entry contains name of file, size and modification date of file and starting cluster number. Other directories use the same allocation methods as ordinary files. 2.3.1 Dependence on cluster number Standard DOS tools don't permit control over cluster by cluster location of files, so this information can be used to encode program image and/or data. Starting cluster number of file can be obtained by CP/M-style call 11h (FindFirst via FCB). (CP/M calls can be hidden from most watchers by performing far call to location 0:0C0h with function code in CL instead of AL). Finding out numbers of other clusters requires browsing thru FAT (See example in Appendix C). 2.3.2 Unused (reserved) disk areas Really, there is only one such area at offset 0Ch of directory entry (10 bytes long). Unfortunately, this area is often used by "DOS-compatible" operating systems. For example, Digital Research DOS uses this field to store file password, PC-MOS/386 (Software Links) stores here file owner ID, access rights and creation date/time. Another reserved area, which can exist on disk, is the remainder of last sector in FAT 1, which is preserved by DOS (and even copied to all other copies of FAT). 2.3.3 Unused (allocation unit rounded) disk areas Because DOS allocates disk space in clusters (which contain 2^N sectors), while file size is measured in bytes, most files have unused (and ordinarily invisible on file system level) tail, which can be used for protection purposes. Curious bug in DOS, which permits seeks (DOS function 42h) beyond end-of-file, makes access to this file tail easy even for high-level languages (See Appendix D). 3. Motherboard and system BIOS based protection Other part of PC, which, along with floppy and hard disk, is always available for copy protection, is motherboard. Although motherboards are now manufactured in many thousands series, almost each of them has (or can acquire) individual qualities. 3.1 Data-based tricks Each motherboard has it's own BIOS. So it can be used for copy protection, although we can expect this primarily from hardware manufactures and not from independent software developers. (So the stuffing system BIOS with a lot of cryptic undocumented functions and tables, which is a dear occupation of big blue, is a sort of copy protection). Other data area available on motherboards, is non-volatile CMOS memory, which as a rule has a lot (half a dozen bytes) unused space in it. Some chip sets (e.g., from C&T) can map part of CMOS memory into system ROM address space, thus creating appearance of "software reprogramming system ROM BIOS". 3.2 Time-based tricks More interesting protection marks are ones based on internal timing of system board. Three basic subsystems are available for such measurements: CPU, memory subsystem, I/O subsystem (See appendix E). Differences can be actually surprisingly large (See table 3.2). ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄ¿ ³ System ³ CPU ³ Memory ³ I/O ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄ´ ³ 25 MHz 80386 (A) ³ 35972 ³ 24576 ³ 47292 ³ ³ 25 MHz 80386 (B) ³ 35972 ³ 24576 ³ 49154 ³ ³ 20 MHz 80386 ³ 44958 ³ 30112 ³ 59990 ³ ³ 12 MHz 80286 ³ 3544 ³ 41018 ³ 46646 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÙ Table 3.2 Motherboard marks of four different machines. Values shown in table 3.2 are an average for multiply runs of program from Appendix E. Actual values differ from mean ones by about ñ4. Systems (A) and (B) have had two sequential manufacturer's numbers, but still can be easily distinguished by I/O mark (Port 0Ch, 1st DMA controller was used). It should be also noted, what I/O mark is very sensitive to CPU mode of operation (real vs. protected), while CPU and memory marks are almost equal in both modes. Glossary 82062 Intel WDC 8237A Intel DMA controller 8253 Intel timer chip 8259A Intel interrupt controller 8272A Intel FDC BC IBM bad track error, bit in ST2 BIOS Basic Input/Output System CB Controller busy, bit in MSR Cluster Allocation unit in FAT filesystem, See 2.3 CM Control mark, bit in ST2 CPU Central Processing Unit, e.g., 8086, 80286, . . . CRC Cyclic Redundancy Code DxB Drive x busy, bit in MSR DD Data error, bit in ST2 DE Data error, bit in ST1 DIO Data Input/Output, bit in MSR DMA Direct Memory Access Double Density See MFM DR Data Register of 8272A. See 1.2.1 DTL Data transfer length, 8272A command parameter. See 1.2.3 EC Equipment check, bit in ST0 ECC Error correction code EN End of track error, bit in ST1 EOT End of track, 8272A command parameter. See 1.2.3 FAT File allocation table. See 2.3 FDC Floppy disk controller. See 1.1 FM Frequency modulation. See 1.1 FT Fault, bit in ST3. GPL Gap length, 8272A command parameter. See 1.2.3 HDC Hard Disk Controller HLT Head load time, 8272A command parameter. See 1.2.3 HUT Head unload time, 8272A command parameter. See 1.2.3 IAM Index address mark. See 1.1.3 IC Interrupt code, 2 bits in ST0 IRR Interrupt request register of 8259A. IRQ Interrupt request signal JV Joint Venture, "Sovmestnoe predprijatie" Kb Kilobyte, 1024 bytes KBPS Thousands of bits per second LSB Least significant bit MA Missing address mark, bit in ST1 MD Missing data address mark, bit in ST2 MFM Modified frequency modulation. See 1.1 MSB Most significant bit MSR Main Status Register of 8272A. See 1.2.1 ND Sector no found, bit in ST1 or non-DMA, 8272A command parameter. See 1.2.3 NDM non-DMA transfer, bit in MSR NR Not ready, bit in ST0 NW Write protect error, bit in ST1 OR Overrun error, bit in ST1 PLL Phase locked loop, circuit in FDC. See 1.4.2 RDY Ready, bit in ST3 RPM Revolutions per minute RQM Request for master, bit in MSR RWC Reduce write current, technique used in MFM recording SC Sector count, 8272A command parameter. See 1.2.3 SE Seek ended, bit in ST0 SH Scan Hit, bit in ST2 Single Density See FM SN Scan not satisfied, bit in ST2 SRT Step rate interval, 8272A command parameter. See 1.2.3 ST0, ST1, ST2, ST3 Status bytes 0-3 of 8272A. See 1.2.2 STP Step value, 8272A command parameter. See 1.2.3 T0 Track 0, bit in ST3 TC Terminal count - signal raised by 8237A when channel transfer count reaches zero TS Two sided, bit in ST3 WC Cylinder address error, bit in ST2 WDC Winchester disk controller WP Write protect, bit in ST3 Appendix A. Simple 8272A program Program sample text is in test_fdc.c. It requires Turbo C 2.0 and Turbo Assembler (any version) to compile. Minimum hardware required to run this sample is 8 MHz/0 WS 80286 machine equipped with at least one floppy drive, floppy drive to run test on is specified by program argument (0 for A:, 1 for B:). This test can be used on secondary FDC as well, provided that FDC_BASE in source file is changed to 0x370. 'T' command (Analyse a track) will work incorrectly with 300 RPM drives (360K, 720K, 1.44M) until REVOLUTION_TIME in program source will not be chnged to 200L*2*1193 (but when it will work incorrectly with 1.2M drives). Appendix B. Simple HDC exerciser program Program sample text is in file hd_scan.c, which again requires TC 2.0 and TASM to compile. It accepts BIOS drive ID (80 for 1st drive, 81 for second). If this test hangs after printing the message: "Cyls = XXX, Heads = XXX, Sectors = XXX", all disk caching programs should be removed from memory prior to running this test. Appendix C. How to find out cluster number Program text is in file cluster.c, again TC 2.0 and TASM are required to compile it. Fully qualified file name (i.e., including drive and directory, even for file in current directory) should be specified as parameter. Although this sample was tested under MS DOS 3.20, 3.30, 4.00 and 5.00 (beta), it may not work under other MS DOS versions or compatible systems, because it relies on structure of undocumented DiskInfoBlock. Appendix D. Accessing file tail Program text is in file tail.c. Although any ANSI compiler should accept it, this sample relies on undocumented behavior of seek() function and may not work with compilers other then TC 2.0. Appendix E. How to distinguish motherboards Program text is in file sysboard.c, TC 2.0 and TASM required to compile. Current value of INSTRUCTIONS parameter (16384) will cause time counter to overflow on anything less then 20 MHz 80386.