Skip to content

Instantly share code, notes, and snippets.

@GXTX

GXTX/blah.c Secret

Last active November 11, 2023 21:47
Show Gist options
  • Save GXTX/f501911ab216cc7569b0576f773bd520 to your computer and use it in GitHub Desktop.
Save GXTX/f501911ab216cc7569b0576f773bd520 to your computer and use it in GitHub Desktop.
#define REPS 200
// http://www.ioctls.net/
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014
#define SCSI_IOCTL_DATA_IN 1 // read data
#define SCSIOP_READ 0x28
typedef struct _SCSI_PASS_THROUGH_DIRECT
{
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
#pragma pack(push, scsi, 1)
typedef union _CDB
{
struct _CDB10 {
UCHAR OperationCode;
UCHAR RelativeAddress : 1;
UCHAR Reserved1 : 2;
UCHAR ForceUnitAccess : 1;
UCHAR DisablePageOut : 1;
UCHAR Lun : 3;
//UCHAR LBA[4];
ULONG LBA;
UCHAR Reserved2;
//UCHAR TransferBlocks[2];
USHORT TransferBlocks;
UCHAR Control;
} CDB10, *PCDB10;
} CDB, *PCDB;
#pragma pack(pop, scsi)
FILE_FS_SIZE_INFORMATION GetGeometry(ANSI_STRING dev_name)
{
HANDLE handle;
NTSTATUS status;
IO_STATUS_BLOCK io_status;
OBJECT_ATTRIBUTES obj_attr;
FILE_FS_SIZE_INFORMATION size = {};
InitializeObjectAttributes(&obj_attr, &dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile(&handle, GENERIC_READ | SYNCHRONIZE, &obj_attr, &io_status, FILE_SHARE_READ, FILE_OPEN_FOR_FREE_SPACE_QUERY | FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(status)) {
debugPrint("Couldn't open device for reading\n");
return size;
}
NtQueryVolumeInformationFile(handle, &io_status, &size, sizeof(size), FileFsSizeInformation);
NtClose(handle);
debugPrint("%lld %lld %lu %lu\n", size.TotalAllocationUnits.QuadPart, size.AvailableAllocationUnits.QuadPart, size.SectorsPerAllocationUnit, size.BytesPerSector);
Sleep(1000);
return size;
}
void DoRawRead()
{
NTSTATUS status;
LARGE_INTEGER freq, start, end;
PDEVICE_OBJECT pDevice;
ULONG returnSize;
ANSI_STRING name;
char *abc = "\\Device\\CdRom0";
RtlInitAnsiString(&name, abc);
status = ObReferenceObjectByName(&name, 0, &IoDeviceObjectType, 0, (void**)&pDevice);
if (!NT_SUCCESS(status)) {
debugPrint("Couldn't open %s for reading\n", name.Buffer);
goto cleanup;
}
FILE_FS_SIZE_INFORMATION geometry = GetGeometry(name);
int size = 1 * geometry.BytesPerSector;
int max_sectors = geometry.TotalAllocationUnits.QuadPart / 6;
char *buffer = malloc(size + MAX_READ_SECTORS);
if (!buffer) {
debugPrint("Couldn't allocate buffer memory!\n");
goto cleanup;
}
SCSI_PASS_THROUGH_DIRECT direct;
memset(&direct, 0, sizeof(SCSI_PASS_THROUGH_DIRECT));
direct.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
direct.DataIn = SCSI_IOCTL_DATA_IN;
direct.DataBuffer = buffer;
direct.DataTransferLength = size;
PCDB cdb = (PCDB)&direct.Cdb;
cdb->CDB10.OperationCode = SCSIOP_READ;
cdb->CDB10.ForceUnitAccess = 1;
cdb->CDB10.LBA = __builtin_bswap32(0);
cdb->CDB10.TransferBlocks = __builtin_bswap16(1);
QueryPerformanceFrequency(&freq);
for (int i = 0; i < REPS; i++) {
if (__builtin_bswap32(cdb->CDB10.LBA) == max_sectors) {
cdb->CDB10.LBA = __builtin_bswap32(0);
} else {
cdb->CDB10.LBA = __builtin_bswap32(max_sectors);
}
QueryPerformanceCounter(&start);
status = IoSynchronousDeviceIoControlRequest(IOCTL_SCSI_PASS_THROUGH_DIRECT, pDevice, &direct, sizeof(SCSI_PASS_THROUGH_DIRECT), NULL, 0, &returnSize, FALSE);
QueryPerformanceCounter(&end);
if (!NT_SUCCESS(status)) {
debugPrint("\nFailed. %lX\n", status);
Sleep(10000);
goto cleanup;
} else {
double speed = size * freq.QuadPart;
speed /= (end.QuadPart - start.QuadPart);
//speed /= 1000;
//speed /= 1024; // KB/s is more useful than B/s
debugPrint("Read Block: %lu %lu\n", (ULONG)speed, returnSize);
}
}
cleanup:
free(buffer);
debugPrint("Finished.\n");
Sleep(10000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment