法证PE下,内置磁盘不会自动加载,需要手动将磁盘联机,通过手动操作磁盘管理器中磁盘实现联机,磁盘具备读写权限,但多个磁盘情况下,有的磁盘无法通过手动操作方式联机(但可以通过DiskPart工具实现将该磁盘连接,但联机后的磁盘为只读,并且无法抹掉磁盘的readonly属性),该种情况下如何实现所有磁盘联机并且具备读写权限呢?
首先在DiskPart中设置磁盘san策略为onlineall,如下图所示:
然后在设备管理器中卸载磁盘,如下图所示:
最后再“扫描检测硬件改动”,之前卸载的磁盘会自动重新装载。
此时在看看磁盘管理中,所有磁盘为自动联机,且具备读写权限。
以下是根据磁盘序列号卸载磁盘、扫描检测硬件改动的参考代码:
#include <cfgmgr32.h>
#include <SetupAPI.h>
#pragma comment(lib, "setupapi.lib")
int scan_device_change()
{
DEVINST devInst;
CONFIGRET status;
int ret = -1;
do
{
status = CM_Locate_DevNodeW(&devInst, NULL, CM_LOCATE_DEVNODE_NORMAL);
if ( status != CR_SUCCESS)
{
printf("get_locate_devnode failed %d \r\n", GetLastError() );
break;
}
status = CM_Reenumerate_DevNode(devInst, 0);
if ( status != CR_SUCCESS)
{
printf("get reenumerate_devnode failed, %d \r\n", GetLastError());
break;
}
ret = 0;
} while (0);
return ret;
}
int get_device_serial_number(wchar_t *device_path, char *serial_number, int serial_number_len)
{
int ret = -1;
HANDLE hDevice = NULL;
DWORD nDiskBytesRead = 0;
DWORD nDiskBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION)+sizeof(PARTITION_INFORMATION)* 104;//26*4
BYTE* pOutBuffer = NULL;
do
{
PDRIVE_LAYOUT_INFORMATION lpDiskPartInfo = (PDRIVE_LAYOUT_INFORMATION)malloc(nDiskBufferSize);
hDevice = CreateFile(device_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == NULL)
{
break;
}
STORAGE_PROPERTY_QUERY storagePropertyQuery;
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
storagePropertyQuery.PropertyId = StorageDeviceProperty;
storagePropertyQuery.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned = 0;
if (!::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytesReturned, NULL))
{
break;
}
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
pOutBuffer = (BYTE *)malloc(dwOutBufferSize + 1);
ZeroMemory(pOutBuffer, dwOutBufferSize);
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer, dwOutBufferSize, &dwBytesReturned, NULL))
{
break;
}
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer;
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
strncpy(serial_number, (char *)(pOutBuffer + dwSerialNumberOffset), serial_number_len );
// 去掉空格
for(int i=0; i<strlen(serial_number); i++)
{
if (serial_number[i] == (char)0x20)
{
serial_number[i] = '\0';
}
}
}
ret = 0;
} while (0);
if (pOutBuffer)
{
free(pOutBuffer);
}
CloseHandle(hDevice);
return ret;
}
int remove_device_by_serial(char *device_serial)
{
int ret = -1;
int dev_index = 0;
int inf_index = 0;
unsigned long errcode = 0;
HDEVINFO hdev = NULL;
SP_DEVINFO_DATA devinfo_data = {0};
wchar_t dev_desc[1024] = {0};
wchar_t class_name[1024] = {0};
wchar_t class_guid[1024] = {0};
wchar_t instance_id[1024] = {0};
SP_DEVICE_INTERFACE_DATA inf_data = {0};
PSP_DEVICE_INTERFACE_DETAIL_DATA_W pinf_detail_data = NULL;
unsigned long inf_detail_size = 0;
char serial_number[1024] = {0};
if (device_serial == NULL)
{
return -1;
}
do
{
hdev = SetupDiGetClassDevsW(&DiskClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdev == INVALID_HANDLE_VALUE)
{
break;
}
for (;;)
{
// 枚举设备
ZeroMemory(&devinfo_data, sizeof(devinfo_data));
devinfo_data.cbSize = sizeof(devinfo_data);
if (!SetupDiEnumDeviceInfo(hdev, dev_index++, &devinfo_data))
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
break;
}
continue;
}
// 只关心类名为DiskDrive的设备
SetupDiGetDeviceRegistryPropertyW(hdev, &devinfo_data, SPDRP_CLASS, NULL, (PBYTE)class_name, sizeof(class_name), NULL);
if (wcsicmp(class_name, L"DiskDrive"))
{
continue;
}
// 以下获取磁盘序列号
inf_data.cbSize = sizeof(inf_data);
if ( !SetupDiEnumDeviceInterfaces(hdev, &devinfo_data, &DiskClassGuid, inf_index, &inf_data) )
{
break;
}
SetupDiGetDeviceInterfaceDetailW(hdev, &inf_data, NULL, 0, &inf_detail_size, NULL);
if (pinf_detail_data) HeapFree(GetProcessHeap(), 0, pinf_detail_data);
pinf_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, inf_detail_size);
if (!pinf_detail_data)
{
break;
}
pinf_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
if ( !SetupDiGetDeviceInterfaceDetailW(hdev, &inf_data, pinf_detail_data, inf_detail_size, &inf_detail_size, NULL))
{
break;
}
if( get_device_serial_number(pinf_detail_data->DevicePath, serial_number, sizeof(serial_number)/sizeof(serial_number[0])) != 0 )
{
break;
}
// 比较设备序列号是否为指定的序列号
// 卸载该设备(这里为磁盘驱动器设备)
if (strcmpi(serial_number, device_serial) == 0)
{
if( SetupDiRemoveDevice(hdev, &devinfo_data) )
{
ret = 0;
break;
}
}
}
ret = 0;
} while (0);
if (pinf_detail_data)
{
HeapFree(GetProcessHeap(), 0, pinf_detail_data);
}
if (hdev)
{
SetupDiDestroyDeviceInfoList(hdev);
}
return ret;
}