如何在Windows 7中写入物理驱动器?
我正在尝试写入Windows 7中的物理磁盘(例如\\.\PhysicalDrive0
)。
此问题已被问及 to death ,但从未得到过回答。它曾经在Windows XP中运行,但微软故意在Windows Vista中破解。微软提供了关于如何做到这一点的提示,但是没有人能够解决这个问题。
在过去,允许写入物理磁盘(只要您是管理员)。执行此操作的方法甚至记录在知识库文章中:
INFO: Direct Drive Access Under Win32
要在基于Win32的应用程序中打开直接磁盘访问(原始I / O)的物理硬盘驱动器,请使用表单的设备名称
\\.\PhysicalDriveN
其中N为0,1,2等,表示系统中的每个物理驱动器。
您可以使用具有这些设备名称的CreateFile()应用程序编程接口(API)打开物理或逻辑驱动器,前提是您具有对驱动器的适当访问权限(即,您必须是管理员)。必须同时使用CreateFile()FILE_SHARE_READ和FILE_SHARE_WRITE标志才能访问驱动器。
在增加安全限制的情况下,Windows Vista中的所有内容都发生了变化。
很多人和许多答案,在许多stackoverflow问题上都很混乱:
\\.\PhysicalDrive0
)和\\.\C$
)Microsoft注意到restrictions placed on both kinds of operations:
阻止对卷和磁盘的直接写入操作
如果符合以下条件,DASD(直接访问存储设备)卷句柄上的写操作将成功:
- 未安装文件系统,或
- 正在写入的扇区是引导扇区。
- 写入的扇区驻留在文件系统空间之外。
- 通过请求独占写访问权来隐式锁定文件系统。
- 通过发送锁定/卸载请求明确锁定了文件系统。
- 写入请求已由内核模式驱动程序标记,指示应绕过此检查。该标志称为SL_FORCE_DIRECT_WRITE,它位于IrpSp-> flags字段中。文件系统和存储驱动程序都会检查此标志。
就我而言,我要求写一个 Physical ,而不是一个 Logical 。 Microsoft注意到写入物理磁盘句柄的新限制:
如果出现以下情况,磁盘句柄上的写操作将成功:
- 写入的扇区不属于文件系统。
- 写入的扇区属于明确锁定的已装入文件系统。
- 写入的扇区属于未装入的文件系统或卷没有文件系统。
关于如何使其发挥作用的提示围绕着:
但问题是如何卸载文件系统?你如何锁定文件系统?
我能够读取磁盘的所有物理扇区;那没问题。问题是当我想写到磁盘的物理扇区时。
我当前的代码是伪代码:
void ZeroSector(Int64 PhysicalSectorNumber)
{
String diskName := '\\.\PhysicalDrive0';
DWORD desiredAccess := GENERIC_READ or GENERIC_WRITE;
//INFO: Direct Drive Access Under Win32
//https://support.microsoft.com/en-us/kb/100027
//says you nedd both
DWORD shareMode := FILE_SHARE_READ or FILE_SHARE_WRITE;
//Open the physical disk
hDisk := CreateFile(diskName, desiredAccess, shareMode,
nil, OPEN_EXISTING, 0, 0);
if hDisk = INVALID_HANDLE_VALUE
RaiseLastWin32Error();
try
{
Int32 bytesPerPhysicalSector := 4096; //Determined elsewhere using IOCTL_STORAGE_QUERY_PROPERTY+STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
//Setup buffer for what we will be writing
Byte[] buffer = new Byte[bytesPerPhysicalSector];
//Calculate the byte offset of where the sector is
Int64 byteOffset = PhysicalSectorNumber * bytesPerPhysicalSector;
//Seek to that byte offset
SetFilePointer(hDisk, byteOffset.Lo, byteOffset.Hi, FILE_BEGIN);
//Write the buffer
DWORD numberOfBytesWritten;
if (!WriteFile(hDisk, buffer, bytesPerPhysicalSector, out numberOfBytesWritten, nil))
RaiseLastWin32Error();
}
finally
{
CloseHandle(hDisk);
}
}
令人惊讶的:
GENERIC_READ
+ GENERIC_WRITE
访问直到实际的WriteFile
失败后才会失败:
ERROR_ACCESS_DENIED
如果出现以下情况,磁盘句柄上的写操作将成功:
- 写入的扇区属于明确锁定的已装入文件系统。
除非我不知道如何做到这一点。
我知道我可能必须使用DeviceIoControl
和其中一个IOCTLS
来"锁定" 一个卷。但这带来了三个挑战:
忽略这些问题,我盲目地尝试了LockFile
API。在致电WriteFile
之前:
//Try to lock the physical sector we will be writing
if (!LockFile(DiskHandle, byteOffset.Lo, byteOffset.Hi, bytesPerPhysicalSector, 0)
RaiseLastWin32Error();
失败了:
ERROR_INVALID_FUNCTION (1)
答案 0 :(得分:5)
检查FSCTL_LOCK_VOLUME,FSCTL_DISMOUNT_VOLUME控制代码。我相信您必须枚举磁盘上的所有卷,然后卸载并锁定它们。锁定成功后,磁盘就是您的全部。
但您可能无法在系统驱动器上执行此操作。我还猜测会有关于包含页面文件的卷的警告。
完成此操作后,我可以写入相应的\\。\ PhysicalDrive3。我以前不能:
HANDLE hVol = CreateFileA(
"\\\\.\\X:",
FILE_READ_DATA | FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD unused;
BOOL b = DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
if (!b) {
printf("%u", GetLastError());
abort();
}
...
HANDLE h = CreateFileA(
argv[1], // that's my \\physicaldrive3
FILE_READ_DATA | FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
...
bResult = WriteFile(h, buf, cb, &dwWritten, &foo);
if (!bResult) {
// used to fail without messing with vol handle
printf("Failed writing data. Error = %d.\n", GetLastError());
return 0;
}