Access via the CD-ROM Driver

Access via SPTI

One of the most interesting architectural features of the Windows NT operating system is its ability to interact with IDE devices via the SCSI interface! Unfortunately , this technology is poorly documented. For instance, sources such as Platform SDK, MSDN, and DDK contain only odds and ends. Thus, only a true professional or very clever and inquisitive beginner can make sense of this information.

As one could conclude from reading most discussions in teleconferences, most programmers haven t properly mastered the techniques of device management via the SCSI interface. Therefore, it is useful to cover this problem in more detail.

To solve this problem, we ll need the following items:

  • Description of the SCSI interface (see the SCSI Architecture Model ”3 document, which describes the main concepts of SCSI architecture, and the SCSI Primary Commands ”3 document that determines the basic set of commands for all SCSI devices; draft versions of both documents are available for downloading from: http://www.t10.org/ftp/t10/drafts/sam3/sam3r08.pdf and http://www.t10.org/ftp/t10/drafts/spc3/spc3r14.pdf, respectively. As a quick-start manual, a good recommendation is to study the The Linux SCSI programming HOWTO document, which can be downloaded from http://www. ibiblio .org/pub/Linux/docs/HOWTO/other-formats/pdf/SCSI-Programming-HOWTO.pdf).

  • Description of SCSI commands specific for CD-ROM drives (see the Multimedia Commands ”4 document describing the principles of programming CD-ROM/R/RW drives. The electronic version of this document can be found here: http://www.t10.org/ftp/t10/drafts/mmc4/mmc4r02b.pdf).

  • Description of ATAPI interface for CD-ROM/DVD drives (for instance, see the ATA Packet Interface for CD-ROMs and Specification for ATAPI DVD Devices documents. Note that DVD specifications provide better and more comprehensive descriptions of the CD-ROM architecture than native documentation written specially for CD-ROM. Versions of these documents (not the newest, but still quite suitable revisions) can be found here: www. stanford .edu/~csapuntz/ specs /INF-8020.PDF and ftp.seagate.com/sff/INF-8090.PDF. Descriptions of SCSI and ATAPI commands duplicate each other in many respects. However, some particularly difficult aspects are sometimes described better in one document than the other. Therefore, professional programmers should have both of them on hand.

  • Description of data storage formats, used with CDs (see the Data interchange on read-only 120 mm optical data disks ECMA-130 standard, known as the Yellow Book), which can be found here: http://www.ecma-international.org/ publications /files/ecma-st/Ecma-130.pdf. This is a basic standard for CD-ROM drives.

  • Besides this, any literature that in any way considers the aspects of CD-ROM programming is useful. So, what is SCSI? It is the standardized, platform-independent interface that ensures coordinated interaction of different devices and high-level applications. In fact, the acronym SCSI stands for Small Computer System Interface . Thanks to SCSI for low-level device management, it is not necessary to write custom drivers (writing a driver with the only purpose to overcome API limitations is absolutely senseless), and this task can be solved at the application level by means of sending special CDB blocks to the device. These CDB blocks might contain either standard or device-specific control commands, along with all of the parameters that they require. In fact, CDB stands for Command Descriptor Block . An example of such a block is provided below.

Table 4.2: An example of a CDB which, being transmitted to a SCSI device, makes it read sector 0 —69

Offset, bytes

Contents

0 —0

0 —28

Code of the read sector command

0 —1

0 —00

Reserved

0 —2

0 —00

Sector number ”0 —69

0 —3

0 —00

0 —4

0 —00

0 —5

0 —69

0 —6

0 —00

Number of sectors

0 —7

0 —01

0 —8

0 —00

Reserved

0 —9

0 —00

Reserved

0 —A

0 —00

Reserved

The first byte of the block stands for the operation command (in our case: 28 ” read one or more sectors), and all other bytes of the block are parameters of this command . Pay special attention to the fact that the least significant byte of the word resides at higher address, i.e., the exact opposite to what you are accustomed to on the IBM PC! Therefore, if you transmit the 69 0 00 0 00 0 00 sequence as the number of the first sector, the sector with the number 6900000 will be read instead of sector 00000069 , as would be expected.

A brief description of standard SCSI commands can be found in the The Linux SCSI programming HOWTO document mentioned earlier. However, this is unlikely to be sufficient for our purposes. Therefore, the commands specific to CD-ROM drives will be covered separately. Nevertheless, you must first understand how CDB blocks are encapsulated in SRB envelopes (SRB stands for SCSI Request Block ). Without these envelopes, the operating system will simply be unable to understand what you are going to do (as a matter of fact, any computer program only does the things that it is instructed to do. Sometimes, this is exactly the thing that the user wanted it to do, but not always).

The structure of the SRB block is described in detail in NT DDK. Therefore, you won t cover it here in detail but, rather, will only briefly consider its main fields.

Listing 4.6: Brief description of the SCSI_REQUEST_BLOCK structure
image from book
 typedef struct _SCSI_REQUEST_BLOCK {          USHORT Length;  // The length of the SCSI_REQUEST_BLOCK structure  UCHAR Function;  // Function (usually, SRB_FUNCTION_EXECUTE_SCSI == 0,   // e.g., send the command for execution to the device)  UCHAR SrbStatus;  // Here, the device displays the command execution   // progress. The most frequently encountered values are:   // SRB_STATUS_SUCCESS == 01 - the command   // completed successfully.   // SRB_STATUS_PENDING == 00 - the command   // is being executed.   // SRB_STATUS_ERROR == 04 - an error was encountered.   // Other values are also possible,   // for a complete list see DDK.  UCHAR ScsiStatus;  // Here the device returns the command completion status.   // If the command didn't return SUCCESS,   // then there was an ERROR.  UCHAR PathId  // SCSI port to which the device controller is attached.   // For virtual SCSI devices, this is always set to 0.  UCHAR TargetId;  // Controller of the device on the bus.   // For IDE devices usually set to the following values:   // 0 - primary, 1 - secondary  UCHAR Lun;  // Logical device ID within the controller   // For IDE devices usually set to the following values:   // 0 - master, 1 - slave  CHAR QueueTag;  // Not used, as a rule, and must be equal to zero  CHAR QueueAction;  // Not used, as a rule, and must be equal to zero  CHAR CdbLength;  // Length of the CDB block.   // For ATAPI devices always set to 12 (0Ch)  CHAR SenseInfoBufferLength;  // the length of the SENSE buffer (see later)  LONG SrbFlags;  // Flags that usually take two values:   // SRB_FLAGS_DATA_IN == 040 - data move from   // device to computer (read)   // SRB_FLAGS_DATA_OUT == 080 - data move from   //                   computer to device (write)  ULONG DataTransferLength;  // Length of data block to be read or written  LONG TimeOutValue;  // Time-out value in seconds  PVOID DataBuffer;  // The pointer to the buffer containing   // data to be read/written  PVOID SenseInfoBuffer;  // The pointer to the SENSE buffer (see later)  struct _SCSI_REQUEST_BLOCK *NextSrb;  // The pointer to the next SRB.   // Not executed, as a rule  PVOID OriginalRequest;  // The pointer to IRP. Practically not used  PVOID SrbExtension;  // Not used, as a rule, and must be equal to zero   UCHAR Cdb[16];       // The CDB block per sec  } SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK; 
image from book
 

After filling the fields of the SCSI_REQUEST_BLOCK structure appropriately, you can pass the SRB to the chosen device by calling on the DeviceIoControl function. All you have to do is specify an appropriate IOCTL code. That s it! Having swallowed the bait, the operating system will pass the CDB block to the appropriate device, and that device will (or won t) carry out the command contained in the CDB block. Pay special attention: The CDB block is not processed by the device driver . Instead, it is the device itself that processes the CDB. Because of this, you have virtually unlimited capabilities for device management. Note that you get all of these capabilities from the application level.

However, everything has its dark side. The device management procedure is rather capricious. A single error in filling in one of the fields can result in that the device will refuse to carry out the commands passed to it. Instead of command execution, it will either return an error code, or nothing at all. Besides this, even the slightest negligence can ruin all of the data on all of the hard drives. Therefore, it is necessary to be especially careful when choosing the TargetID and lun values! ( To determine automatically the CD-ROM address, it is possible to use the SCSI_INQUIRY command ”see the DDK demo example, which you can find in the \NTDDK\src\win_me\block\wnaspi32 file ) . However, let s forget about the dangers (after all, the life would be boring without them). Now you are going to discuss the most interesting aspect of our problem, namely, searching the IOCTL code passed on in the specific SRB.

As it turns out, it isn t easy to carry out this procedure directly. In fact, using only legal tools, it is simply impossible ! For a number of reasons, the Windows developers decided only to provide full access to the fields of the SCSI_REQUEST_BLOCK structure to driver developers. As for application developers, they are limited to using structures such as SCSI_PASS_THROUGH and SCSI_PASS_THROUGH_DIRECT . Actually, these structures have a goal similar to SRB, but are somewhat limited in their functionality. Fortunately, there are no limitations on the contents of CDB blocks and, therefore, there is still the possibility of low-level control over the hardware. Further details on this topic can be found in the section 9.2 SCSI Port I/O Control Codes in the Windows NT DDK documentation and in the source code of the demo example that can be found in the \NTDDK\src\storage\class\spti directory. Also, pay special attention to the image from book  spti.h tm file in the same directory. This file provides a detailed description of how to control the device via the SCSI interface.

In line with the name of the directory containing this demo example, this method of interaction with the device is known as SPTI (standing for SCSI Pass Through IOCTLs ). Let us briefly list the main, specific features and limitations of SPTI.

First, you must have administrative privileges for passing CDBs to devices. This isn t always convenient (although it is a positive situation from the security point of view).

Second, using of multi-target commands is not permitted (it means that you cannot issue the command for copying data from device A to device B that bypasses the processor ”although, contemporary drives support such commands and it would be wonderful if it were possible to copy CDs without loading the processor).

Third, there is no support for the reversible (i.e., bidirectional) movement of data. At any given moment, data can be moved either from device to the computer or from computer to the device, but simultaneous bidirectional data movement is impossible).

Fourth, if a class driver has been installed for the target device, CDBs must be directed to the class driver, rather than to the SCSI device itself. This means that to control the CD-ROM drive, you must interact with it via the \\.\X: device, where x is the letter representing the CD-ROM drive. An attempt to access the \\.\Scsi0 : device will return error code. As experience has shown, this is the main stumbling block for all inexperienced programmers who rush ahead without reading the documentation first.

Note  

It is possible to address to the device as \\.\CdRom0 or \\.\CdRom1, without the terminating colon , where 0 or 1 stands for the ordinal number of the CD-ROM drive in the system. In contrast to a common fallacy, stating that the \\.\cdRom0 device is located at the lower level as compared to \\.\X: . From the operating system s point of view, these are synonyms. To make sure that this is true, it is enough to view the contents of the object table ( objdir \DosDevice ), which shows that \\.\X: is just a symbolic link to \\.\CdRom N .

Fifth, there are strict limitations on the maximum size of the data being sent ( MaximumTransferLength ). These limitations are imposed by specific features of the hardware device and the miniport driver serving it. The limitations relate to the maximum size allowed for the data block and to the number of physical pages that it takes up. In order to determine specific characteristics, it is necessary to send the IOCTL_SCSI_GET_CAPABILITIES command to the device. This command will return the IO_SCSI_CAPABILITIES structure (its definition can be found in the NTDDSCSI.h file). Along with other information, this structure contains the MaximumTransferLength and MaximumPhysicalPages_in_bytes values. The maximum size of the data to be sent is calculated using the following formula: largest transfer = min (MaximumTransferLength , MaximumPhysicalPages_in_bytes ). Another way is to limit the data blocks to 64 Kbytes, which, guaranteed , will be supported by all devices. The buffer must be aligned by the value equal to AlignmentMask , which is returned in the IO_SCSI_CAPABILITIES structure. The alignment level ensured by the malloc function is sufficient for this, and no problems will arise when using it. The situation is different where memory allocation is carried out by the char buf [BUF_SIZE] construction ”in this case, there is no guarantee that your program will operate properly.

Sixth, the SCSI_PASS_THROUGH_DIRECT structure itself contains a significantly smaller number of fields and, at the same time, the values contained in fields such as PathId , TargetId , and Lun are simply ignored ! The physical address of the device on the bus is determined directly by the operating system by means of the symbolic name of the descriptor for the device, to which the SCSI_PASS_THROUGH_DIRECT request is sent.

Listing 4.7: The format of the SCSI_PASS_THROUGH_DIRECT structure (the SCSI_PASS_THROUGH structure is similar to it in many respects. However, it doesn t ensure data transmission through DMA)
image from book
 typedef struct _SCSI_PASS_THROUGH_DIRECT {          USHORT Length;  // Structure size SCSI_PASS_THROUGH_DIRECT  UCHAR ScsiStatus;  // Status of the command execution   // by SCSI device  UCHAR PathId;  // Ignored  UCHAR TargetId;  // Ignored  UCHAR Lun;  // Ignored  UCHAR CdbLength;  // Length of the CDB packet sent to the   // device (in bytes)  UCHAR SenseInfoLength;  // Length of the SENSE buffer   // to return error  UCHAR *DataIn;  // Direction of the data transmission  ULONG DataTransferLength;  // Size of the data exchange buffer   // (in bytes)  ULONG TimeOutValue;  // Time-out value  PVOID DataBuffer;  // Pointer to the data exchange buffer  ULONG SenseInfoOffset;  // Pointer to the SENSE buffer   // with error information  UCHAR Cdb[16];  // Buffer containing CDB packet   // (16 bytes maximum)  }SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; 
image from book
 

Fortunately, the censorship mainly relates to fields that are rarely used in practice anyway. Therefore, nothing has been lost. Just fill the remaining fields, and the structure will be ready!

Naturally, before passing it to the device, it is necessary to first get the descriptor for the required device. This can be done as follows :

Listing 4.8: Opening the drive in order to get its descriptor, which will be used for device control
image from book
 HANDLE hCD = CreateFile ("\\.\X:", GENERIC_WRITE  GENERIC_READ,                     FILE_SHARE_READ  FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); 
image from book
 

Making sure that hCD is not equal to INVALID_HANDLE_VALUE , pass the received descriptor along with the IOCTL_SCSI_PASS_THROUGHT_DIRECT structure to DeviceIoControl function. The function can be called as follows:

Listing 4.9: Passing the IOCTL_SCSI_PASS_THROUGH structure
image from book
 DeviceIoControl(hCD, 0x4D014h /  * IOCTL_SCSI_PASS_THROUGH_DIRECT */, &srb,  sizeof(SCSI PASS THROUGH DIRECT), sense buf, SENSE SIZE, &returned, 0); 
image from book
 

Here, srb is the filled instance of the IOCTRL_SCSI_PASS_THROUGHT_DIRECT structure, and returned is the variable, to which the number of bytes returned by the device will be written. The sense_buf is the buffer, in which the filled instance of the IOCTL_SCSI_PASS_THROUGHT_DIRECT structure will be returned, along with the sense info ”error code of the operation being executed. If the operation is completed without errors, sense info is not returned, and sense_buf contains only IOCTL_SCSI_PASS_THROUGHT . The position of the sense info location within the buffer is determined by the contents of the SenseInfoOffset field. The value of this field must be chosen in such a way as to avoid overlapping with the IOCTRL_SCSI_ PASS_THROUGHT structure. Simply speaking, the minimum possible offset of the Sense Info is equal to: srb.SenseInfoOffset = sizeof (SCSI_PASS_THROUGH_DIRECT) . Note that SenseInfoOffset is not a pointer to the sense info but, rather, it is the index of the first byte of sense info in the returned buffer!

To detect an error, it is necessary to analyze the number of bytes returned by the DeviceIoControl function in the returned variable. If it exceeds the size of the IOCTL_SCSI_PASS_THROUGHT structure, then the buffer contains sense info. If this is the case, the sense info presence indicates that there is an error! The sense info format is shown in Fig. 4.1.

image from book
Fig. 4.1: SENSE INFO format. Sense info is returned by the device in case of error

The first byte specifies the error type and usually takes the value of 70h (current error) or 71h (deferred error) . Error codes from 72h to 7Eh are reserved, and errors with the code 7Eh indicate vendor-specific sense-info format. Error codes from 00h to 6Fh are not defined in the ATAPI CD-ROM specification. Therefore, their use is undesirable (this warning is intended mainly to hardware developers, and not programmers).

Error description is encoded by the following three numbers : Sense Key, Additional Sense Code (ASC for short) and Additional Sense Code Qualifier (ASCQ). On top of this hierarchy is the Sense Key, containing the generic error categories, followed by the ASC, which describes the error in more detail. At the lowest hierarchical level, there is the ASCQ, which qualifies the additional sense code itself. If the error is exhaustively described only by the Sense Key and ASC, the ASCQ is missing (or, to be more precise, is undefined).

Description of the main error codes is provided in two tables below. It should be pointed out that the Sense Key value is not critical for error analysis, since each ASC will belong to the one Sense Key value. In contrast to this, the same ASCQ can belong to different ASCs and, therefore, it makes no sense without the precisely specified ASC value.

Table 4.3: Main Sense Key values (error categories) and their descriptions

Sense Key

Description

00h

NO SENSE. No additional sense info. The operation was completed successfully.

01h

RECOVERED ERROR. The operation has completed successfully. However, some problems were encountered in the course of its execution. These problems were eliminated by the drive itself. Additional information is provided by ASC and ASCQ.

02h

NOT READY. The device is not ready.

03h

MEDIUM ERROR. An irrecoverable error was encountered in the course of operation execution. Most probably, this error was caused by medium defects or incorrect data. This sense key may also be returned in cases when the drive is unable to distinguish the medium defect from hardware failure.

04h

HARDWARE ERROR. Irrecoverable hardware error (for instance, controller failure).

05h

ILLEGAL REQUEST. Illegal parameters passed to the drive in the CDB packet (for instance, the starting address is larger than the ending address).

06h

UNIT ATTENTION. The medium has been replaced or the device controller has been reset.

07h

DATA PROTECT. An attempt at reading protected data.

8h “0Ah

Reserved.

0Bh

ABORTED COMMAND. Command execution was for some reason aborted.

0Eh

MISCOMPARE. Source data do not correspond to the data read from the medium.

0Fh

Reserved.

Table 4.4: Main ASC and ASCQ codes

ASC

ASCQ

DROM

Description

00

00

DROM

No additional sense information

00

11

R

Play operation in progress

00

12

R

Play operation paused

00

13

R

Play operation successfully completed

00

14

R

Play operation stopped due to error

00

15

R

No current audio status to return

01

00

R

Mechanical positioning or changer error

02

00

DROM

No seek complete

04

00

DROM

Logical drive not ready ”cause not reportable

04

01

DROM

Logical drive not ready ”in progress of becoming ready

04

02

DROM

Logical drive not ready ”initializing command required

04

03

DROM

Logical drive not ready ”manual intervention required

05

01

DROM

Media load ”eject failed

06

00

DROM

No reference position found

09

00

DRO

Track following error

09

01

RO

Tracking servo failure

09

02

RO

Focus servo failure

09

03

RO

Spindle servo failure

11

00

DRO

Unrecovered read error

11

06

RO

CIRC unrecovered error

15

00

DROM

Random positioning error

15

01

DROM

Mechanical positioning or changer error

15

02

DRO

Positioning error detected by read of medium

17

00

DRO

Recovered data with no error correction applied

17

01

DRO

Recovered data with retries

17

02

DRO

Recovered data with positive head offset

17

03

DRO

Recovered data with negative head offset

17

04

RO

Recovered data with retries and/or CIRC applied

17

05

DRO

Recovered data using previous sector ID

18

00

DRO

Recovered data with error correction applied

18

01

DRO

Recovered data with error correction & retries applied

18

02

DRO

Recovered data ”the data were auto-reallocated

18

03

R

Recovered data with CIRC

18

04

R

Recovered data with L-EC

1A

00

DROM

Parameter list length error

20

00

DROM

Invalid command operation code

21

00

DROM

Logical block address out of range

24

00

DROM

Invalid field in command packet

26

00

DROM

Invalid field in parameter list

26

01

DROM

Parameter not supported

26

02

DROM

Parameter value invalid

28

00

ROM

Not ready to ready transition, medium may have changed

29

00

ROM

Power on, reset, or bus device reset occurred

2A

00

ROM

Parameters changed

2A

01

ROM

Mode parameters changed

30

00

ROM

Incompatible medium installed

30

01

RO

Cannot read medium ”unknown format

30

02

RO

Cannot read medium ”incompatible format

39

00

ROM

Saving parameters not supported

3A

00

ROM

Medium not present

3F

00

ROM

ATARI CD-ROM drive operating conditions have changed

3F

01

ROM

Microcode has been changed

40

NN

ROM

Diagnostic failure on component NN ( 80h “FFh )

44

00

ROM

Internal ATARI CD-ROM drive failure

4E

00

ROM

Overlapped commands attempted

53

00

ROM

Media load or eject failed

53

02

ROM

Medium removal prevented

57

00

R

Unable to recover table of contents

5A

00

DROM

Operator request or state change input (unspecified)

5A

01

DROM

Operator medium removal request

63

00

R

End of user area encountered on this track

64

00

R

Illegal mode for this track

B9

00

R

Play operation aborted

BF

00

R

Loss of streaming

As you can see, it s easy! The only thing you have yet to clarify is ATAPI. Since you aren t going to interact with ATAPI directly (thanks to Windows architects , you don t have this capability), let us consider its main aspects and features only briefly. As a matter of fact, ATAPI specification was adopted in 1996 for devices logically different from hard disks, including optical, magneto-optical, and tape drives. This is a packet extension of the interface, which allows for the reception of blocks of control information whose structure was borrowed from SCSI, via ATA bus. This fact allows us to understand why Windows is so dashing when turning ATAPI devices into SCSI ones. If you neglect the hardware differences between interfaces, which are not visible at the application level, ATAPI will be very similar to SCSI. Control over ATAPI devices is carried out using the same CDBs that you have considered earlier.

Naturally, in order to control the device, it is necessary to know its controlling commands. To get this information, you ll need the ATAPI Packet Commands for CD-ROM devices reference manual. Open this manual to the description of the READ CD command ( BEh code), and you ll find the following table.

image from book
Fig. 4.2: Description of the READ CD command

Let s try to clarify this table. The first byte, representing the code of the command being executed, doesn t raise any questions. However, it is followed by the Expected Sector Type field specifying the type of required sector. If you jump ahead a few pages, you ll find the codes corresponding to all of the existing sector types: CDDA, Mode 1, Mode 2, Mode 2 Form 1, and Mode 2 Form 2. If sector type is not known beforehand, pass the 0x0 value in this field, meaning that any type of sector is acceptable.

The next four bytes contain the address of the first sector to be ready specified in the LBA (Logical Block Address) format. This abbreviation hides elegant method of pass-through sector numbering. If you have ever programmed ancient hard disks, you ll recall the bulky computations that had to be carried out in order to determine to which head, cylinder, and sector each byte belongs. Now it is possible to do this without all that fuss. The first sector has the number 0, followed by 1, 2, 3 and so on, until the last sector of the disk is reached. The only important thing that you should bear in mind is that the byte order in this double word is inverse, which means that the most significant byte of the most significant word comes first.

Bytes with numbers from six to eight are occupied by the parameter specifying the number of sectors to be read. Note that for sector address, four bytes are allocated, while for the number of sectors to be read ”there are only three. However, you are not going to read the entire disc in one operation! Byte order in this case is also inverse, so be careful to avoid errors. Otherwise, you ll request a reading of half of the entire disc when attempting to read only a single sector.

The ninth byte is especially interesting, because it stores flags that determine which parts of the sector must be read. Besides user data, you can request sync bytes, the header, EDC/ECC codes, and even read error flags (for cracking some protection mechanisms, this information is indispensable , although, unfortunately, not every drive supports this feature).

The tenths bit is responsible for retrieving subchannel data. However, since the same data are already present in the header, it is possible, in principle, to do without this information.

Finally, the last (eleventh, counting from zero) byte, isn t used because it is reserved. Therefore, in order to ensure compatibility with newer drive models, it must be set to zero.

Naturally, depending on the type and volume of the requested data, the length of the returned sector can vary to a great degree.

Table 4.5: Interrelation between the type of requested data and the length of the returned sector

Data to be transferred

Flag Bits

CD-DA

Mode1

Mode 2 nonXA

Mode 2 Form1

Mode 2 Form 2

User Data

10h

2352

2048

2336

2048

2338

User Data+ EDC/ECC

18h

(10h)

2336

(10h)

2336

(10h)

Header Only

20h

(10h)

4

4

4

4

Header Only+ EDC/ECC

28h

(10h)

Illegal

Illegal

Illegal

Illegal

Header & User Data

30h

(10h)

2052

2340

Illegal

Illegal

Header & User Data + EDC/ECC

38h

(10h)

2344

(30h)

Illegal

Illegal

Sub Header Only

40h

(10h)

8

8

8

8

Sub Header Only+ EDC/ECC

48h

(10h)

Illegal

Illegal

Illegal

Illegal

Sub Header & User Data

50h

(10h)

(10h)

(10h)

2056

2336

Sub Header & User Data+ EDC/ECC

58h

(10h)

(10h)

(10h)

2344

(50h)

All Header Only

60h

(10h)

12

12

12

12

All Header Only+ EDC/ECC

68h

(10h)

Illegal

Illegal

Illegal

Illegal

All Header & User Data

70h

(10h)

(30h)

(30h)

2060

2340

All Header & User Data + EDC/ECC

78h

(10h)

(30h)

(30h)

2340

2340

Sync & User Data

90h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & User Data+ EDC/ECC

98h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & Header Only

A0h

(10h)

16

16

16

16

Sync & Header Only+ EDC/ECC

A8h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & Header & User Data

B0h

(10h)

2064

2352

Illegal

Illegal

Sync & Header & User Data+ EDC/ECC

B8h

(10h)

2344

(30h)

Illegal

Illegal

Sync & Sub Header Only

C0h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & Sub Header Only+ EDC/ECC

C8h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & Sub Header & User Data

D0h

(10h)

(10h)

(10h)

Illegal

Illegal

Sync & Sub Header & User Data+ EDC/ECC

D8h

(10h)

(10h)

(10h)

Illegal

Illegal

Sync & All Headers Only

E0h

(10h)

24

24

24

24

Sync & All Headers Only +EDC/ECC

E8h

(10h)

Illegal

Illegal

Illegal

Illegal

Sync & All Headers & User Data

F0h

(10h)

2064

2352

2072

2352

Sync & All Headers & User Data+ EDC/ECC

F8h

(10h)

2352

(F0h)

2352

(F0h)

Repeat All Above and Add Error Flags

02h

294

294

294

294

294

Repeat All Above and Add Block & Error Flags

04h

296

296

296

296

296

Note  

At the application level, IDE devices are interpreted as SCSI devices. Naturally, the drive doesn t undergo any changes at the physical level. Therefore, IDE CD-ROM drive remains an IDE drive, with all of its advantages and drawbacks. However, IRP requests to these drivers, while passing via the Storage Class Driver, are translated into SRBs (SCSI request blocks). SRB requests then go to the Storage port driver (e.g., directly to the device driver), where they are once again translated into physical commands specific to that device (see Fig. 4.3). Detailed information on this absorption process are provided in NT DDK (see section 1.1 Storage Driver Architecture ). Here, it is enough to emphasize the fact that, beside the commands from the IRP_MJ_EEE family, you can also pass SRB requests, which provide significantly more freedom and flexibility, to the device. However, it is impossible to organize this interaction directly from the application level because IRP commands are private ones, while the DeviceIoControl API function passes only public commands that can be explicitly processed by the driver in IRP_MJ_DEVICE_CONTROL manager.

image from book
Fig. 4.3: Windows NT internals

Now, to get some practical experience, let us create a program reading raw sectors from CDs. The key fragment of such a program (along with the required comments) is provided below:

Listing 4.10: [/SPTI.raw.sector.read.c] The function that reads raw sectors via SPTI
image from book
 #define RAW_READ_CMD     0xBE  // ATAPI RAW READ  #define WHATS_READ       0xF8  // Sync & All Headers & User Data + EDC/ECC  #define PACKET_LEN       2352  // length of one sector  //#define WHATS_READ     0x10  // User Data  //#define PACKET_LEN     2048  // length of one sector   //-[SPTI_RAW_SECTOR_READ]------------------------------------------------------------------------------------   //   The function reads one or more sectors from the CDROM in RAW format,   //   according to the flags passed to it.   //   //   ARG:   //         CD     - The drive to be opened   //                  (something like "\\.\X:" or "\\.\CdRom0")   //   buf          - The buffer, to which the data must be read   //   buf_len      - Buffer size in bytes   //   StartSec     - Number of the starting sector, counting from zero   //   N_SECTOR     - Number of sectors to read   //   flags        - What information must be read   //                  (see SCSI/ATAPI specification)   //   //   RET:   //        != 0    - The function was executed successfully   //        == 0    - The function returned error  //  //  NOTE:   //       - Works only under NT/W2K/XP and requires   //         administrative privileges   //   //       - 64 K of data per operation at maximum   //-------------------------------------------------------------------------   SPTI_RAW_SECTOR_READ (char *CD,char *buf,int buf_len,int StartSec,int N_SEC,char flags)  {          HANDLE               hCD;          SCSI_PASS_THROUGH_DIRECT srb;          DWORD                returned, length, status;  // OPENING THE DEVICE  hCD = CreateFile (driver, GENERIC_WRITEGENERIC_READ,                                FILE_SHARE_READFILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);          if (hCD == INVALID_HANDLE_VALUE) {printf("-ERR: open CD\n"); return 0;}  // FORMING SRB  memset(&srb,0,sizeof(SCSI PASS THROUGH DIRECT));  // Initialization  srb.Length = sizeof (SCSI_PASS_THROUGH_DIRECT);          srb.PathId = 0;  // SCSI controller ID  srb.TargetId = 6;  // Ignored  srb.Lun = 9;  // Ignored  srb.CdbLength = 12;  // Length of the CDB   // packet  srb.SenseInfoLength = 0;  // SenseInfo not needed  srb.DataIn = SCSI_IOCTL_DATA_IN;  // We are going to read.  srb.DataTransferLength = PACKET_LEN*N_SECTOR;  // Length of data   // to read  srb.TimeOutValue = 200;  // TimeOut value  srb.DataBufferOffset = buf;  // Pointer to the   // buffer  srb.SenseInfoOffset = 0;  // SenseInfo is   // not needed   // CDB packet containing ATAPI commands  srb.Cdb[0] = RAW_READ_CMD;  // Read RAW sector.  srb.Cdb[1] = 0x0;  // Any type of the disk   // format is acceptable.   // The number of the first sector to be read. Most significant byte   // of the most significant word goes first, least significant byte   // of the least significant word goes last  srb.Cdb[2] = HIBYTE(HIWORD(StartSector));          srb.Cdb[3] = LOBYTE(HIWORD(StartSector));          srb.Cdb[4] = HIBYTE(LOWORD(StartSector));          srb.Cdb[5] = LOBYTE(LOWORD(StartSector));  // Number of sectors to be read  srb.Cdb[6] = LOBYTE(HIWORD(N_SECTOR));          srb.Cdb[7] = HIBYTE(LOWORD(N_SECTOR));          srb.Cdb[8] = LOBYTE(LOWORD(N_SECTOR));          srb.Cdb[9] = flags;     // What should be read          srb.Cdb[10] = 0;        // Subchannel Data Bits          srb.Cdb[11] = 0;        // Reserved  // SENDING SRB TO ATAPI device  status = DeviceIoControl(hCD, IOCTL_SCSI_PASS_THROUGH_DIRECT,                        &srb, sizeof (SCSI_PASS_THROUGH_DIRECT), &srb, 0, &returned, 0);          return 1;  } 
image from book
 

It only remains to note that protection mechanisms that interact with the disc via SPTI can be cracked easily by setting a breakpoint to the CreateFile/ DeviceIoControl functions. To prevent extra popups of the debugger, the breakpoint filter must react only to those calls to the CreateFile function, whose leftmost argument is set to \\.\x: or to \\.\CdRomN . The second left argument of the DeviceIoControl must automatically represent either IOCTL_SCSI_PASS_ THROUGHT , or IOCTL_SCCI_PASS_THROUGHT_DIRECT , the hex codes of which are equal to 0x4D004 and 0x4D014 , respectively.



CD Cracking Uncovered. Protection against Unsanctioned CD Copying
CD Cracking Uncovered: Protection Against Unsanctioned CD Copying (Uncovered series)
ISBN: 1931769338
EAN: 2147483647
Year: 2003
Pages: 60

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net