我的一些同事开发了一个微型端口驱动程序,该驱动程序在将数据写入卷时对数据进行加密,并在读取数据时对其进行解密。对于用户来说,此时可能发生的一个问题是确定数据是否实际上在磁盘上加密。为了解决这个问题,我编写了一个程序,当给定完整的文件路径时,它将打印硬盘上存在的文件的数据,从而向用户显示文件数据的加密版本。当卷属于单个磁盘时,我已经成功处理该卷,但当该卷是跨区卷时,我遇到了问题。获取文件的逻辑地址后,我将其转换为物理偏移量,从而读取数据,但在跨区卷的情况下,我无法推断出该物理偏移量属于哪个硬盘,因为该卷现在驻留在多个磁盘上。有什么方法可以推断出这一点,还是我需要将其添加为我的程序的限制?
到目前为止我的代码是这样的。
void fetchData(string filenameWithPath) {
string driveLetter = "\\\\.\\" + filenameWithPath.substr(0, 2);
map<int, pair<unsigned long long, unsigned long long>> volStruct;
wstring wdriveLetter = wstring(driveLetter.begin(), driveLetter.end());
wstring wfilenameWithPath = wstring(filenameWithPath.begin(), filenameWithPath.end());
HANDLE volHandle = CreateFile(wdriveLetter.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (volHandle == INVALID_HANDLE_VALUE) {
cerr << "Failed to open volume. Error code: " << GetLastError() << std::endl;
return;
}
HANDLE handle = CreateFileW(wfilenameWithPath.c_str(), GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED |
FILE_FLAG_NO_BUFFERING, NULL);
if (handle == INVALID_HANDLE_VALUE) {
cerr << "Failed to open file Handle. Error code: " << GetLastError() << endl;
return;
}
VOLUME_DISK_EXTENTS* diskExtents = nullptr;
DWORD buffersize = sizeof(diskExtents)*4;
DWORD bytesReturned = 0;
while (true) {
diskExtents = (VOLUME_DISK_EXTENTS*)malloc(buffersize);
if(DeviceIoControl(volHandle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
diskExtents,
buffersize,
&bytesReturned,
NULL)){
break;
}
if (GetLastError() != ERROR_MORE_DATA) {
cout << endl << "FAILED TO GET VOLUME DISK EXTENTS DATA. ERROR CODE [" << GetLastError() << "]";
CloseHandle(handle);
break;
}
buffersize = buffersize * 2;
free(diskExtents);
}
CloseHandle(volHandle);
CloseHandle(handle);
for (DWORD i = 0; i < diskExtents->NumberOfDiskExtents; i++) {
pair<unsigned long long, unsigned long long> temp;
temp.first = diskExtents->Extents[i].StartingOffset.QuadPart;
temp.second = diskExtents->Extents[i].ExtentLength.QuadPart;
volStruct[diskExtents->Extents[i].DiskNumber] = temp;
}
cout << endl << "Exiting";
free(diskExtents);
return;
}
好吧,我找到了如何确定跨区卷的特定逻辑偏移量驻留在哪个磁盘上。我所要做的就是创建一个 VOLUME_LOGICAL_OFFSET 缓冲区。然后将此缓冲区传递给 IOCTL IOCTL_VOLUME_LOGICAL_TO_PHYSICAL。这给出了 VOLUME_PHYSICAL_OFFSET 类型的输出缓冲区。该缓冲区包含物理偏移量以及与该物理偏移量相关的磁盘号。
VOLUME_LOGICAL_OFFSET logicalOff;
logicalOff.LogicalOffset = 16049504256;
VOLUME_PHYSICAL_OFFSETS physicalOff;
DWORD bytesReturned2;
if (!DeviceIoControl(
volHandle,
IOCTL_VOLUME_LOGICAL_TO_PHYSICAL,
&logicalOff,
sizeof(VOLUME_LOGICAL_OFFSET),
&physicalOff,
sizeof(VOLUME_PHYSICAL_OFFSETS),
&bytesReturned2,
NULL)) {
cout << endl << "Error converting Logical address to physical address...";
cout << endl << "The last error is " << GetLastError();
CloseHandle(volHandle);
return;
}
CloseHandle(volHandle);
cout << endl << "The logical offset " << logicalOff.LogicalOffset
<< " belongs to disk " << physicalOff.PhysicalOffset[0].DiskNumber
<< " and the physical offset is " << physicalOff.PhysicalOffset[0].Offset;