Access in the Cooked Mode (Block Reading Mode

Access via ASPI

A debugged program is one, for which the failure conditions haven t been found yet.

Programmer folklore

There are two main drawbacks of the above-described SPTI interface: It requires administrative or root privileges for controlling the device and, even worse , it is supported only by operating systems of the Windows NT family. Windows 9x /ME operating systems lack support for this interface. The only legitimate method of accessing the CD-ROM under Windows 9x is using 16-bit thunk for directly accessing the MSCDEX MS-DOS driver, which provides a considerably wider set of functional capabilities than in the Windows driver. Naturally, parallel support of two families of operating systems requires significant efforts from programmers, which results in a considerable increase of the cost of software products.

To simplify the development of cross-platform applications, Adaptec has developed a special system-independent interface allowing for the control of various SCSI devices from the application level. This interface became known as ASPI, which stands for Advanced SCSI Programming Interface (although, unofficially, it is often called Adaptec SCSI Programming Interface).

System independence in ASPI is ensured by the two-layer model of its organization: Architecturally, it comprises the low-level driver and application-level wrapper library. ASPI driver was developed taking into account specific features of the OS. It is responsible for directly controlling the SCSI bus (regardless of whether this bus is physical or virtual). Since the interface between the operating system and drivers changes from system to system, a special ASPI library is used for hiding these differences. This library provides the common unified interface for all operating systems.

Let us consider how ASPI interface is implanted into the OS in the example of Windows ME (see Fig. 4.4). At the highest level of the hierarchy are the WNASPI32.DLL and WINASPI.DLL libraries, intended for 32- and 16-bit applications, respectively. These DLLs export the following three basic ASPI functions: GetASPI32DLLVersion , GetASPI32SupportInfo and SendASPI32Command (the latter being the most important), and three helper functions: GetASPI32Buffer , FreeASPI32Buffer , TranslateASPI32Address (the latter is present only in the 32-bit version of the library).

image from book
Fig. 4.4: Architecture of the Windows 98/ME Input/Output system

By calling the DeviceIoControl function, they communicate with the ASPI driver, which resides lower in the hierarchy. Depending on the OS, this driver is called either APIX.VXD (Windows 9x), or ASPI.SYS (Windows NT). In the course of its initialization, this driver creates the MbMmDp32 device. Don t ask me what this name means, since the answer is buried deep inside the Adaptec company.

Note  

16-bit applications communicate with the driver via the 1868h function of the 2Fh interrupt. The details of this process can be discovered by disassembling the winaspi.dll library. By the way, this DLL is tiny ”its size is just 5 K.

In principle, nothing prevents us from communicating directly with ASPI driver, bypassing the WNASPI32.dll. In fact, most developers of protection mechanisms choose this method. To do so, it is enough to disassemble WNASPI32.dll and discover the correspondence between ASPI commands and IOCTL codes (for obvious reasons, ASPI protocol isn t documented). Actually, nothing could be easier than setting the breakpoint to SendASPI32Command , after which the hacker can easily locate the protection code. With regard to DeviceIoControl calls, they are more difficult to handle, because they are too numerous . Moreover, beginner crackers of protection mechanisms (the most common group of hackers) have only a vague idea of the input/ output architecture, to say nothing about the ASPI protocol. For qualified and experienced hackers, though, this protection doesn t present a serious obstacle (more details are provided in Revealing protection mechanisms ).

The ASPI driver itself connects to SCSI and IDE/ATAPI ports, thanks to which it allows for the control of all these devices (including CD-ROM drives ).

Note  

Client modules (in Fig. 4.4, they are designated by the numbers 1, 2, and 3) send their requests to the Installable File System driver (designated by the number 6). Client modules also have ASPI libraries for 32- and 16-bit applications at their disposal (they are designated by the numbers 4 and 6). They, to a degree, stand apart from the rest of the system because they are optional components developed by a third-party company ” Adaptec. The file system driver redirects a request it has received to one of the following specialized drivers, among which is the CD-ROM driver, CDFS.VxD, designated by the number 8. Its tasks include supporting CD file systems such as ISO 9660, High Sierra, etc. One level below, there is the Volume Tracker (14), which traces events such as disc replacement, and, even lower, there is the driver that supports this particular CD-ROM model itself. This is the so-called CD type-specific driver, implemented by CDVSD.VxD module. Among other tasks, it is responsible for assigning the CD drive letter. In fact, this is the sector level of interaction with the CD, and there are no file systems here. Although this driver is specific to the CD-ROM drive model, it is absolutely independent of its physical interface, because it relies on the CD-ROM device SCSI zer (21), which converts IOP requests arriving from higher-level drivers into SRB packets directed to lower-level drivers (more details on this topic are provided in the section Access via the SCSI Port). The SCSI CD-ROM helper (23) resides even lower, ensuring interaction between the SCSI zer and the SCSI port. The SCSI port itself, created by the SCSI ports manager (26), represents a unified, system-independent tool for organizing the interaction between medium-level drivers and physical (or virtual) devices. The ASPI driver (18) relates to one of these SCSI ports. The ASPI driver is implemented in the APIX.VxD file and goes up to its wrappers ”WNASPI32.DLL and WNASPI.DLL ( numbers 11 and 12, respectively). Below the SCSI manager reside the mini-port drivers, which translate SCSI requests into the language of the specific interface bus. In particular, the driver ensuring support for IDE devices is implemented by the ESDI_506.PDR file (number 29). Naturally, if necessary, you can communicate with IDE devices via IDE/ATAPI ports (25), which are implemented by the same driver ”ESDI_506.PDR (the ASPI driver, due to performance considerations, does exactly this). The left part of the flowchart, representing the hierarchy of drivers of all other disk drives, will not be covered here, since it isn t related to our discussion in any way.

For ASPI programming, at least two things are required: the ASPI driver and ASPI SDK . The driver is freely downloadable from the Adaptec Web server (the drivers for the following operating systems are available: MS-DOS, Novell, Windows 9x , Windows NT/W2K/XP). As for SDK, at some point it ceased to be a freeware, and is distributed on a commercial basis, although its price is relatively small (somewhere around $10). However, all of the materials required for your work, including documentation, header files, and libraries can be borrowed from Windows Me DDK (which is included as part of Windows 2000 DDK). Thus, if you have a copy of W2K DDK, there s no need to worry. If this is not the case, get MSDN library, which is distributed along with Microsoft Visual Studio 6.0. Here, you ll find documentation and header files, while the missing libraries for the appropriate DLLs can be produced on your own ( lib.exe with the /DEF command-line key). Anyway, it is possible to do without these libraries by loading all required functions via LoadLibrary/GetProcAddress .

Since the ASPI interface comes with good documentation (the programmer s manual comprises about 35 pages), mastering it shouldn t cause any serious problems (at least after you have become acquainted with SPTI). Besides, Windows Me DDK includes a completed demo example, which can be found in the \src\win_me\block\ wnaspi32\ folder. Despite the fact that it is intended for Windows Me, it is also suitable for other operating systems, including Windows 98, Windows 2000, Windows XP, etc.

However, this example is extremely awkward , with a large number of errors. In relation to clarity and readability, I have to say that it would be hard to find a less illustrative example demonstrating ASPI operation! It is definitely much better to investigate the source codes of the CD slow program, which can be easily found on the Internet. The only problem is that this program is in Assembly language. Therefore, it is necessary to have previous experience in this language.

Let us briefly list the main drawbacks of the image from book  aspi32ln.c demo example. First, this is not a console application. Therefore, most of its code has no relation to ASPI, since it implements the program s GUI. Second, this example uses the unified function for receiving notifications from two commands: SCSI_INQUIRY and SCSI_READ10 . In 50% of the cases, the latter is replaced by its constant 0x28 , which also doesn t improve code readability. Third, CD-ROM drives are only partially supported by this program. The poorly designed architecture of this application did not allow the developers to achieve their goals. Consequently, the branch responsible for reading from CD-ROM in the ASPI32Post function is specially commented out. If you remove this blocking, there will be read errors, since the program is oriented only towards the drives where sector size equals 0x200 bytes. CD-ROM drives, designed to work with discs having sector size four times greater than this value, do not fall within this category. If you want to avoid redesigning the entire program, the only option is to increase the size of the requested block to 0x800 bytes (in this case, four sectors will be read from hard disks at a time, which is more than acceptable). Finally, the increment (e.g., the computation of the address of the next block to be read) is designed so terribly that it is not usable at all.

There s no point in concentrating on criticisms of demo examples (even an imperfect demo program is still better than nothing), so let s proceed with studying the ASPI interface, or, to be more precise, its most important command ” SendASPI32Command , which ensures the passing of SRB blocks to the device. Hopefully, you ll be able to master all of the other problems on your own, without encountering any difficulties.

The SRB_ExecSCSICmd structure, which contains the data on the SRB request, is almost a twin of SCSI_PASS_THROUGH_DIRECT , as there are more similarities than differences between them. Look at the following:

Listing 4.11: The SRB_ExecSCSICmd structure
image from book
 typedef struct  {  BYTE SRB_Cmd;                 // ASPI command code = SC_EXEC_SCSI_CMD  BYTE SRB_Status               // ASPI command status byte  BYTE SRB_HaId;                // ASPI host adapter number  BYTE SRB_Flags;               // Reserved, MUST = 0  DWORD SRB_Hdr_Rsvd;           // ASPI request flags  BYTE SRB_Target;              // Targets SCSI ID  BYTE SRB_Lun;                 // Targets LUN number  WORD SRB_Rsvd1;               // Reserved for Alignment  DWORD SRB_BufLen;             // Data Allocation Length  LPBYTE SRB_BufPointer;        // Data Buffer Pointer  BYTE SRB_SenseLen;            // Sense Allocation Length  BYTE SRB_CDBLen;              // CDB Length  BYTE SRB_HaStat;              // Host Adapter Status  BYTE SRB_TargStat;            // Target Status  LPVOID SRB_PostProc;          // Post routine  BYTE SRB_Rsvd2[20];           // Reserved, MUST = 0  BYTE CDBByte[16];             // SCSI CDB  BYTE SenseArea[SENSE LEN+2];  // Request Sense buffer  }  SRB ExecSCSICmd, *PSRB ExecSCSICmd; 
image from book
 

Note that in order to control the device, you needn t know its descriptor! It is enough to specify its physical address on the bus (i. e., correctly fill the SRB_HaId and SRB_Target fields). How can you find them? Quite easily. Just send the INQUIRY (code 12h ) command to all physical addresses. The device, physically or virtually associated with that port, will return identification information (among other useful data, it will contain the device name). Non-existent devices won t return anything and the operating system will report an error.

The simplest program for device polling might appear as follows :

Listing 4.12: Sequential polling of ports in order to detect devices connected to them
image from book
 #define MAX_ID          8  #define MAX_INFO_LEN    48  SEND_SCSI_INQUITY()  {          #define MAX_LUN 8 // max. possible number of logical devices          BYTEAdapterCount;          DWORD   ASPI32Status;          unsigned char buf[0xFF];          unsigned char str[0xFF];          unsigned char CDB[ATAPI_CDB_SIZE];          long a, real_len, adapterid, targetid;          // Getting the number of adapters on the bus          ASPI32Status = GetASPI32SupportInfo();          AdapterCount = (LOBYTE(LOWORD(ASPI32Status)));          // Preparing the CDB block          memset(CDB, 0, ATAPI_CDB_SIZE);          CDB[0] = 0x12;         // INQUIRY          CDB[4] = 0xFF;         // Response size          // Spamming the ports in order to find the required device          for (adapterid = 0; adapterid < MAX_LUN; adapterid++)  { // Attention! The use of ^^^^^^^^^^^^^ AdapterCount is not   // permitted here, as recommended in some manuals, because device   // adapter numbers do not necessarily follow one another directly.   // If there is a gap in numbering,   // one or more devices will remain undetected  for (targetid = 0; targetid < MAX_ID; targetid++)               {                       a = SEND_ASPI_CMD(adapterid, targetid, CDB,                                       ATAPI_CDB_SIZE, 0, buf, 0xFF, ASPI_DATA_IN);                       if (a == SS_COMP)                       {                               real_len = (buf[4]>MAX_INFO_LEN)? buf[4]:MAX_INFO_LEN;                               memcpy(str, &buf[8], real_len); str[real_len] = 0;                               printf ("%d.%d <-- %s\n", adapterid, targetid, str);                       }              }         } } 
image from book
 

The result of program execution on the author s computer looks as shown below. (Pay special attention to the fact that the addresses of the devices connected to a virtual SCSI bus created by the ASPI driver might differ from their actual physical addresses. For example, in this case, the PHILIPS drive sitting on the physical IDE port with the number 0, happened to occur on virtual port 1, since the port number 0 was occupied by the Virtual Clone CD driver. Note that if the latter is removed from the system, the mapping between virtual and physical addresses, in principle, should be fully restored. However, this isn t guaranteed .) The leftmost digit represents the adapter ID. The following digit stands for the target ID.

Listing 4.13: Devices connected to the author s computer
image from book
 0.0 <-- ELBY    DVD-ROM          1.0  1.0 <-- IBM-DTLA-307015          TX20  1.1 <-- PHILIPS CDRW2412A        P1.55V01214DM10574  2.0 <-- ST380011A                3.06  2.1 <-- TEAC    CD-W552E         1.09  3.0 <-- AXV     CD/DVD-ROM       2.2a  3.1 <-- AXV     CD/DVD-ROM       2.2a  3.2 <-- AXV     CD/DVD-ROM       2.2a 
image from book
 

Another important advantage of the ASPI interface in comparison to SPTI is support for the asynchronous mode of request processing. Having sent a request to read a certain number of sectors, you can continue the execution of your program without waiting for the sector-reading process to be completed. Of course, to achieve a similar result using SPTI interface it is enough to create another thread. However, this solution is not as elegant as the previous one.

Listing 4.14: [\etc\RAW.CD.READ\aspi32.raw.c]. Demo example of a program that reads raw sectors from the CD
image from book
 #include "scsidefs.h"  #include "wnaspi32.h"  void ASPI32Post (LPVOID);  #define F_NAME      "raw.sector.dat"  /* ASPI SRB packet length */  #define ASPI_SRB_LEN   0x100  #define RAW_READ_CM 0xBE  #define WHATS_READ 0xF8  // Sync & All Headers & User Data + EDC/ECC  #define PACKET_LEN 2352  //#define WHATS_READ    0x10  // User Data  //#define PACKET LEN    2048  #define MY_CMD      RAW_READ_CMD  HANDLE hEvent;  //-[DWORD READ_RAW_SECTOR_FROM_CD] ----------------------------   //      This function reads one or more sectors from the CD-ROM   //      in RAW mode, according to the flags passed to it.   //   // ARG:   //      adapter_id  - Bus number (0 - primary, 1 - secondary)   //      read_id     - Number of the device on the bus   //                    (0 - master, 1 - slave)   //      buf         - Buffer, into which the data must be read   //      buf_len     - Buffer size in bytes   //      StartSector - Starting number of the sector from which to read   //                    (numbering starts from 0)   //      N_SECTOR    - Number of sectors to be read   //      flags       - Information to be read (see the ATAPI specification)   //   //      RET:   //                  - Doesn't return anything   //   //  NOTE:   //      The function returns control before accomplishing the request.   //      Therefore, at the moment of exiting, the data buffer is still   //      empty. It gets filled only when calling   //      the ASPI32Post function (you can modify it as needed).   //      For signaling the operation completion, it is recommended to use   //      events.   //   //      The function operates under Windows 9x/ME/NT/W2K/XP   //      and_doesn't_require administrative privileges.   //      However, ASPI driver must be installed.   //------------------------------------------------------------------------  READ_RAW_SECTOR_FROM_CD(int adapter_id,int read_id,char *buf,int buf_len,                               int StartSector,int N_SECTOR,int flags)  {          PSRB_ExecSCSICmd SRB;          DWORD       ASPI32Status;          // Allocating memory for SRB request          SRB = malloc(ASPI SRB LEN); memset(SRB, 0, ASPI SRB LEN);          // PREPARING SRB block          SRB->SRB_Cmd = SC_EXEC_SCSI_CMD;  // Execute SCSI   // command  SRB->SRB_HaId = adapter_id;  // Adapter ID  SRB->SRB_Flags = SRB_DIR_INSRB_POSTING;  // Asynchronous   // data read  SRB->SRB_Target = read_id;  // Device ID  SRB->SRB_BufPointer = buf;  // Buffer for   // loading data  SRB->SRB_BufLen = buf_len;  // Buffer length  SRB->SRB_SenseLen = SENSE_LEN;  // SENSE buffer   // length  SRB->SRB CDBLen = 12;  // Size of ATAPI   // packet  SRB->CDBByte [0] = MY_CMD;  // ATAPI command  SRB->CDBByte [1] = 0x0;  //CD format - any   // Number of the first sector  SRB->CDBByte [2] = HIBYTE(HIWORD(StartSector));          SRB->CDBByte [3] = LOBYTE(HIWORD(StartSector));          SRB->CDBByte [4] = HIBYTE(LOWORD(StartSector));          SRB->CDBByte [5] = LOBYTE(LOWORD(StartSector));  // Number of sectors to be read  SRB->CDBByte [6] = LOBYTE(HIWORD(N_SECTOR));          SRB->CDBByte [7] = HIBYTE(LOWORD(N_SECTOR));          SRB->CDBByte [8] = LOBYTE(LOWORD(N_SECTOR));          SRB->CDBByte [9] = flags  // What info must be read?  SRB->CDBByte [10] = 0;  // Subchannel data are not needed  SRB->CDBByte [11] = 0;  // Reserved   // Address of the procedure that will receive notifications  SRB->SRB_PostProc = (void *) ASPI32Post;  // Sending an SRB request to the device  // SendASPI32Command(SRB);  // Returning from the function_before_accomplishing   // execution of the request  return 0;  }  //------------------------------------------------------------------   // This callback function is called up by ASPI and gains control   // after the accomplishment of request execution or in case of error.   // As a parameter, it receives the pointer to the instance of   // the PSRB_ExecSCSICmd structure, containing all required information   // (status, pointer to the buffer, etc.)   //---------------------------------------------------------------------  void ASPI32Post (void *Srb)  {        FILE *f;  // Has our request completed successfully?  if ((((PSRB_ExecSCSICmd) Srb) ->SRB_Status) == SS_COMP)        {  // THIS CODE CAN BE MODIFIED AS YOU NEED   //--------------------------------------------------------   // Writes the sector contents into the file.   // ATTENTION:   // PSRB_ExecSCSICmd) Srb) ->SRB_BufLen contains the buffer size   // rather than the actual length of read data. If the number of bytes   // returned by the device is smaller than the buffer size,   // then its tail will contain the garbage!   // Here we use the SRB_BufLen field   // only because when calling the SendASPI32Command function   // we carefully trace the buffer size to ensure   // its correspondence to the volume of returned information.  if (f=fopen(F_NAME, "w"))        {  // Writes the sector into the file  fwrite (((PSRB_ExecSCSICmd) Srb) ->SRB_BufPointer, 1,                              ((PSRB_ExecSCSICmd) Srb) ->SRB_BufLen, f)             fclose (f);  }   // Beeping and "unfreezing" the flow, thus notifying that   // read procedure has been completed  MessageBeep (0); SetEvent (hEvent);  //-----------------------------------------------------------------------  }  }  main (int argc, char **argv)  {        void *p; int buf_len, TIME_OUT = 4000;        if (argc<5)        {            fprintf (stderr, "USAGE: \n\tRAW.CD.READ.EXE adapter_id"\",            read_id, StartSector, n_sec\n"); return 0;        }  // Calculating the buffer length and allocating memory for it   // ATTENTION: proceeding in such a way, you can use blocks   // only up to 64 K.   // If you need larger buffers, use the GetASPI32Buffer function.  buf_len = PACKET_LEN*atol(argv[4]); p = malloc (buf_len) ;  // Creating an event  if ((hEvent = CreateEvent (NULL, FALSE, FALSE, NULL)) == NULL) return -1;  // Reading one or more sectors from the CD  READ_RAW_SECTOR_FROM_CD (atol (argv [1]), atol (argv [2]), p, buf_len,                     atol (argv [3]), atol (argv [4]), WHATS_READ) ;  // Waiting until the operating is completed  WaitForSingleObject (hEvent, TIME_OUT) ;        return 0;  } 
image from book
 

Having compiled and run this example, you can make sure that it runs successfully both under Windows 9 x and under Windows NT without having administrative privileges! On one hand, this is all very well, but, on the other hand the presence of the ASPI driver creates a large hole in security system, which will help malicious software do whatever it is instructed in relation to controlling your hardware. Would you like to infect MBR/boot sectors? Here you are. Or perhaps you d like to wipe the entire hard drive clean? Nothing could be easier. Therefore, if you care about the security of your information, it s advisable to delete the ASPI32 driver from your computer (to do so, you only need to remove the ASPI.SYS file from the WINNT\System32\Drivers directory). Naturally, all of the above-mentioned information relates only to operating systems from the NT family, since, in Windows 9 x, direct access to equipment can be gained even without all of this mess.



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