The Windows NT operating system is distinguished positively from other systems in that it supports the device block reading mode ”the so-called cooked-mode, in which all disc contents are interpreted as one large file. Within this file , it is possible to carry out navigation by calling on the SetFilePointer function, and to read/write individual sectors by calling on ReadFile/WriteFile functions, respectively. The current pointer position is specified in bytes (not in sectors!); however, the pointer value must be a multiple of the logical sector length (512 bytes for floppy and hard disks, and 2,048 bytes for CD-ROM). Otherwise, an error will occur. The number of bytes read (or written) at one time must also fit within an integer number of sectors. An attempt to read a part of a sector will fail.
Despite all the elegance and ease of implementation, this method of controlling the drive is also not free from serious drawbacks. First, it doesn t support file systems other than ISO 9660/Joliet and High Sierra File System. Put simply, this means that block reading mode is suitable only for processing data discs, and is useless for reading sectors from audio discs. Second, reading raw sectors is impossible in cooked mode, and you will have to do only with those parts of these sectors that contain user data. This situation significantly weakens the protection mechanism and allows it to easily be deceived. For instance, let us assume that protection based on physical defects of the medium surface attempts to read its key sector to check its readability. Since the content of correction codes is unavailable to the protection mechanism, it cannot distinguish actual physical defects from their rough imitation (e.g., from deliberate distortion of ECC/EDC codes by copying in order to emulate unrecoverable read errors).
To check whether or not the protection uses this method of disc access, try the following easy method: Set the breakpoint to the CreateFile function, thus making the debugger to react in those ”and only those ”cases where the first four characters of the filename to be opened are "\\.\" (which means that the function tries to open a device instead of a file). These strings might look similar to the following: bpx CreateFileA if (*esp- > 4== ˜ \\\\. \\ ) . After that, all that remains is to make sure that the last back-slash is followed by the drive letter of the required drive (on my computer, this is the "\\.\G:" drive). Having waited for the exit from the CreateFile function by "p RET" and having viewed the device descriptor returned to it (this descriptor will be loaded into the EAX register), you will be able to tmp all calls to SetFilePointer/ReadFile , the analysis of which will disclose the operating algorithm of the protection mechanism.
The demo example provided below represents a ready-to-use utility for grabbing discs with data at the sector level and writing all grabbed information into a file.
/*---------------------------------------------------------------------------- * * READS SECTORS FROM A CD IN BLOCK MODE * ==================================== * * This program works only under Windows NT, without requiring * administrative privileges * * Build 0x001 @ 19.05.03 ----------------------------------------------------------------------------*/ #include <windows.h> #include <winioctl.h> #include <stdio.h> // DEFAULT PARAMETERS #define DEF_FN "sector" #define DEF_TO 0x666 #define DEF_FROM 0x000 #define CDROM_SECTOR_SIZE 2048 // for MODE1/MODE2PORM1 only! // COMMAND-LINE ARGUMENTS #define argCD (argv[1]) #define argFN ((argc > 2)?argv[2] :DEF_FN) #define argFROM ((argc > 3) ?atol (argv[3]) :DEF_FROM) #define argTO ((argc>4) ? (atol (argv[4]) >argFROM) ?atol (argv[4]) :argFROM:DEF_TO) main(int argc, char **argv) { int a; FILE *f; HANDLE hCD; Char *buf; DWORD x_read; Char buf_n[1024]; // CHECKING ARGUMENTS if (argc<2) { printf("USAGE: cooked. sector. read PhysCD [filename] [from] [to]\n"); printf("\tPhysCD - physical name of CD (\"\\.\G:\")\n"); printf("\tfilename - file name to store follow sector\n"); printf("\tfrom - start sector\n"); printf("\tto - end sector\n"); return 0; } // TITLE fprintf(stderr, "cooked sector reader for NT\n"); // ALLOCATING MEMORY buf = malloc(CDROM_SECTOR_SIZE); if (!buf){printf ("-ERR: low memoryXn"); return -1;} // OPENING THE DEVICE hCD = CreateFile(argCD, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXI STING, 0, 0); if (hCD == INVALID_HANDLE_VALUE) { printf ("-ERR: error CreateFile(%s,....)\n", argCD) ; return -1; } // INFO printf("read sector from %04d to %04d in %s file\n", argFROM, argTO, argFN); // POSITIONING THE POINTER TO THE FIRST SECTOR TO BE READ SetFilePointer (hCD, CDROM_SECTOR_SIZE * argFROM, NULL, FILE_BEGIN); // READING SECTORS ONE BY ONE for (a = argFROM; a <= argTO; a++) { // READING THE NEXT SECTOR if (ReadFile(hCD, buf, CDROM_SECTOR_SIZE, & x_read, NULL) & & x_read) { // WRITING THE SECTOR JUST READ INTO THE FILE sprintf(buf_n, "%s[%04d].dat", argFN, a); if (f=f open(buf_n, "wb")){fwrite(buf, 1, x_read, f); fclose(f);} printf("sector [%04d.%04d] read\r", a, argTO); } else { printf("sector %04d read error\n", a); } } }