// // WinAPI // #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #define _NTSCSI_USER_MODE_ #include #include #include "ScsiStuff.h" #pragma comment(lib, "ws2_32") // // STL // #include #include #include #include #include #include #include std::wstring_convert> converter; // // Sends a sample request, sniffed from the official HP Array Configuration Utility // void SendScsiMiniportRequest(HANDLE handle, PUCHAR Buffer, ULONG BufferLength) { PSRB_IO_CONTROL pIoControl = (PSRB_IO_CONTROL)&Buffer[0]; std::wcout << L"[I] - HeaderLength: " << std::dec << pIoControl->HeaderLength << std::endl; std::wcout << L"[I] - Signature: " << converter.from_bytes((const char*)pIoControl->Signature) << std::endl; std::wcout << L"[I] - Timeout: " << std::dec << pIoControl->Timeout << std::endl; std::wcout << L"[I] - ControlCode: " << std::hex << pIoControl->ControlCode << std::endl; std::wcout << L"[I] - ReturnCode: " << std::dec << pIoControl->ReturnCode << std::endl; std::wcout << L"[I] - Length: " << std::dec << pIoControl->Length << std::endl; std::wcout << std::endl; DWORD bytesReturned = 0; BOOL ret = DeviceIoControl( handle, IOCTL_SCSI_MINIPORT, Buffer, BufferLength, Buffer, BufferLength, &bytesReturned, nullptr ); if (ret) { std::wcout << L"Request succeeded" << std::endl; std::wcout << std::endl; std::wcout << L"[O] - HeaderLength: " << std::dec << pIoControl->HeaderLength << std::endl; std::wcout << L"[O] - Signature: " << converter.from_bytes((const char*)pIoControl->Signature) << std::endl; std::wcout << L"[O] - Timeout: " << std::dec << pIoControl->Timeout << std::endl; std::wcout << L"[O] - ControlCode: " << std::hex << pIoControl->ControlCode << std::endl; std::wcout << L"[O] - ReturnCode: " << std::dec << pIoControl->ReturnCode << std::endl; std::wcout << L"[O] - Length: " << std::dec << pIoControl->Length << std::endl; std::wcout << std::endl; // // Skips sizeof(SRB_IO_CONTROL) and only dumps the data buffer afterwards // const std::vector buffer((PUCHAR)Buffer + pIoControl->HeaderLength, (PUCHAR)Buffer + pIoControl->HeaderLength + pIoControl->Length); std::wostringstream ss; ss << std::hex << std::uppercase << std::setfill(L'0'); std::for_each(buffer.cbegin(), buffer.cend(), [&](int c) { ss << std::setw(2) << (unsigned char)c << L" "; }); const std::wstring hexString = ss.str(); std::wcout << L"Result buffer: " << hexString << std::endl; std::wcout << std::endl; } else { std::wcerr << L"Failed to send request, error: 0x" << std::hex << GetLastError() << std::endl; } } int wmain(int argc, wchar_t* argv[]) { if (argc < 2) { std::wcerr << L"Please specify device index" << std::endl; return -1; } const std::wstring deviceName = std::wstring(L"\\\\.\\Scsi").append(argv[1]).append(L":"); const HANDLE handle = CreateFile( deviceName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ); const DWORD error = GetLastError(); if (handle == INVALID_HANDLE_VALUE) { std::wcerr << L"Failed to open device " << deviceName << ", error: 0x" << std::hex << error << std::endl; return -1; } std::wcout << L"Successfully opened device " << deviceName << std::endl; ULONG length = 0, returned = 0; SCSI_PASS_THROUGH_WITH_BUFFERS sptwb; BYTE cdb[] = { 0x12, 0x00, 0x00, 0x00, 0xFF, 0x00 }; // SCSI Inquiry CDB ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH); sptwb.spt.PathId = 0; sptwb.spt.TargetId = 0; sptwb.spt.Lun = 0; sptwb.spt.CdbLength = sizeof(cdb); sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH; sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN; sptwb.spt.DataTransferLength = SPTWB_DATA_LENGTH; sptwb.spt.TimeOutValue = 120; sptwb.spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf); sptwb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf); memcpy(sptwb.spt.Cdb, cdb, sizeof(cdb)); //sptwb.spt.Cdb[0] = 0x26; // SCSIOP_READ //sptwb.spt.Cdb[6] = 0x11; // //const unsigned short reqSize = htons(sizeof(id_ctlr)); //memcpy(&sptwb.spt.Cdb[7], &reqSize, 2); length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf) + sptwb.spt.DataTransferLength; std::wcout << std::dec << L"Total struct size: " << sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS) << L", Calculated length: " << length << L", Header length: " << sptwb.spt.Length << std::endl; BOOL ret = DeviceIoControl( handle, IOCTL_SCSI_PASS_THROUGH, &sptwb, sizeof(SCSI_PASS_THROUGH) + sptwb.spt.SenseInfoLength, &sptwb, length, &returned, NULL ); if (ret) { std::wcout << L"Request succeeded (bytes returned: " << returned << L")" << std::endl; std::wcout << std::endl; const std::vector buffer(sptwb.ucDataBuf, sptwb.ucDataBuf + length); std::wostringstream ss; ss << std::hex << std::uppercase << std::setfill(L'0'); std::for_each(buffer.cbegin(), buffer.cend(), [&](int c) { ss << std::setw(2) << (unsigned char)c << L" "; }); const std::wstring hexString = ss.str(); std::wcout << L"Result buffer: " << hexString << std::endl; std::wcout << std::endl; } else { const DWORD error = GetLastError(); std::wstring errorCode = L"Unknown"; switch (error) { case ERROR_IO_DEVICE: errorCode = L"ERROR_IO_DEVICE"; break; case ERROR_INVALID_PARAMETER: errorCode = L"ERROR_INVALID_PARAMETER"; break; default: std::wcerr << L"GetLastError(): " << std::hex << GetLastError() << std::endl; break; } std::wcerr << L"Failed to send request, error: " << errorCode << std::endl; } #ifdef ACU_REPLAY UCHAR request01[] = { #include "request01.bin" }; UCHAR request02[] = { #include "request02.bin" }; UCHAR request03[] = { #include "request03.bin" }; UCHAR request04[] = { #include "request04.bin" }; UCHAR request05[] = { #include "request05.bin" }; UCHAR request06[] = { #include "request06.bin" }; UCHAR request07[] = { #include "request07.bin" }; UCHAR request08[] = { #include "request08.bin" }; UCHAR request09[] = { #include "request09.bin" }; UCHAR request10[] = { #include "request10.bin" }; UCHAR request11[] = { #include "request11.bin" }; UCHAR request12[] = { #include "request12.bin" }; UCHAR request13[] = { #include "request13.bin" }; SendScsiMiniportRequest(handle, request01, ARRAYSIZE(request01)); SendScsiMiniportRequest(handle, request02, ARRAYSIZE(request02)); SendScsiMiniportRequest(handle, request03, ARRAYSIZE(request03)); SendScsiMiniportRequest(handle, request04, ARRAYSIZE(request04)); SendScsiMiniportRequest(handle, request05, ARRAYSIZE(request05)); SendScsiMiniportRequest(handle, request06, ARRAYSIZE(request06)); SendScsiMiniportRequest(handle, request07, ARRAYSIZE(request07)); SendScsiMiniportRequest(handle, request08, ARRAYSIZE(request08)); SendScsiMiniportRequest(handle, request09, ARRAYSIZE(request09)); SendScsiMiniportRequest(handle, request10, ARRAYSIZE(request10)); SendScsiMiniportRequest(handle, request11, ARRAYSIZE(request11)); SendScsiMiniportRequest(handle, request12, ARRAYSIZE(request12)); SendScsiMiniportRequest(handle, request13, ARRAYSIZE(request13)); #endif CloseHandle(handle); }