python读写磁盘扇区数据有什么用_技术分享 - 编程实现对硬盘全盘数据进行读写数据擦除...

本文介绍了在Windows 7及以上系统中如何绕过限制,通过锁定或卸载请求对磁盘扇区进行读写操作。详细阐述了锁定请求显式锁定卷和卸载请求显式锁定卷的实现步骤,并提供了相关函数的代码实现。需要注意的是,这些方法不适用于系统盘,且存在可能导致其他程序崩溃的风险。
摘要由CSDN通过智能技术生成

背景

在 XP 系统下下,我们可以直接调用 WirteFile 函数对磁盘写入数据,但到了 Windows 7 以及 Windows 7 版本以上的系统,就已经开始变得不那么简单了。

在 Windows 7 及以上版本中,对文件系统和存储堆栈进行的更改,限制对磁盘和卷的直接访问,但是,在以下情况,存储驱动器可以写入磁盘句柄:

正要写入的扇区不位于卷内(空隙块与分区表)。注意:程序使用卷之外的扇区来存储元数据。分区表也位于卷之外的扇区中。由于这些扇区不受任何文件系统的控制,因此没有理由阻止对这些扇区的访问

已经通过锁定请求或卸载请求显式锁定卷

正要写入的扇区位于未安装或者无文件系统的卷内(这个是原生磁盘块,没有受操作系统的管理,当然可以随便写)

本文介绍的是使用第 2 种方法,通过锁定请求或卸载请求显式锁定卷来实现对磁盘数据的读写。现在把实现过程的实现原理整理成文档,分享给大家。

实现原理

我们对于磁盘空隙块与分区表等磁盘位置是可以像 XP 系统那样直接使用 WriteFile 函数写的,但对于盘的数据区的写入则应该采用显式锁定的已安装卷或卸载请求显式锁定卷。

一般是采用 FSCTL_DISMOUNT_VOLUME,FSCTL_LOCK_VOLUME 的前提是没有程序占用该盘的文件,所以可能会失败,FSCTL_DISMOUNT_VOLUME 是强制型的,当我们强制卸载请求显式锁定卷后,一些正在占用磁盘的程序会出现崩溃,原因是它不能读盘上资源。但是,要注意的是,对于FSCTL_DISMOUNT_VOLUME, 如果指定的卷是系统卷或包含页面文件,则操作失败,所以不能对系统盘强制卸载成功。

首先,我们先介绍第一种方式:锁定请求显式锁定卷。

首先,我们使用 CreateFile 打开逻辑卷,获取句柄

然后,我们就可以使用 DeviceIoControl 传递 FSCTL_LOCK_VOLUME 控制码,锁定请求显式锁定卷

那么,这时,我们就可以通过 SetFilePointer 一定文件指针,使用 WriteFile 函数对磁盘数据进行写入

写入完成后,还需使用 DeviceIoControl 传递 FSCTL_UNLOCK_VOLUME 控制码,解锁请求显式锁定卷

最后,我们便可以关闭文件句柄,完成操作

然后,我们介绍第二种方式:卸载请求显式锁定卷。

首先,我们使用 CreateFile 打开逻辑卷,获取句柄

然后,我们就可以使用 DeviceIoControl 传递 FSCTL_DISMOUNT_VOLUME 控制码,卸载请求显式锁定卷

那么,这时,我们就可以通过 SetFilePointer 一定文件指针,使用 WriteFile 函数对磁盘数据进行写入

最后,我们便可以关闭文件句柄,完成操作

这就是本文介绍的两种方法。要注意,使用CreateFile打开设备的时候,名称不能为\\\\.\\PHYSICALDRIVEn(n为0-256),即物理磁盘,只能对逻辑分区锁定与卸载操作。而且,这两种方法,都不能对系统盘进行操作。

编码实现

数据读取// 读取指定扇区数据

BOOLReadDisk(charcDriver,ULONGLONG ullOffsetSector,BYTE*pData)

{

DWORD dwRet=0;

BOOL bRet=FALSE;

charszDriver[MAX_PATH]={0};

// \\\\.\\C:

::wsprintf(szDriver,"\\\\.\\%c:",cDriver);

// 打开硬盘物理设备

HANDLE hDisk=::CreateFile(szDriver,GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,

FILE_ATTRIBUTE_ARCHIVE,NULL);

if(INVALID_HANDLE_VALUE==hDisk)

{

ShowError("CreateFile");

returnFALSE;

}

// 移动文件指针到指定扇区偏移

LARGE_INTEGER li={0};

li.QuadPart=SECTOR_SIZE*ullOffsetSector;

::SetFilePointer(hDisk,li.LowPart,&li.HighPart,FILE_BEGIN);

// 读取数据

bRet=::ReadFile(hDisk,pData,SECTOR_SIZE,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("ReadFile");

returnFALSE;

}

// 关闭句柄

::CloseHandle(hDisk);

returnTRUE;

}

锁定请求显式锁定卷方式写入数据// 写入指定扇区数据 方法一 锁定请求显式锁定卷

BOOLWriteDisk_Lock(charcDriver,ULONGLONG ullOffsetSector,BYTE*pData)

{

DWORD dwRet=0;

BOOL bRet=FALSE;

charszDriver[MAX_PATH]={0};

// \\\\.\\C:

::wsprintf(szDriver,"\\\\.\\%c:",cDriver);

// 打开硬盘物理设备

// 这里名称不能为\\\\.\\PHYSICALDRIVEn(n为0-256),即物理磁盘,只能对逻辑分区锁定与DISMOUNT操作

HANDLE hDisk=::CreateFile(szDriver,GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,

FILE_ATTRIBUTE_ARCHIVE,NULL);

if(INVALID_HANDLE_VALUE==hDisk)

{

ShowError("CreateFile");

returnFALSE;

}

// 锁定请求显式锁定卷

bRet=::DeviceIoControl(hDisk,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("DeivceIoControl");

returnFALSE;

}

// 移动文件指针到指定扇区偏移

LARGE_INTEGER li={0};

li.QuadPart=SECTOR_SIZE*ullOffsetSector;

::SetFilePointer(hDisk,li.LowPart,&li.HighPart,FILE_BEGIN);

// 写入数据

bRet=::WriteFile(hDisk,pData,SECTOR_SIZE,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("WriteFile");

returnFALSE;

}

// 解锁请求显式锁定卷

bRet=::DeviceIoControl(hDisk,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("DeivceIoControl");

returnFALSE;

}

// 关闭句柄

::CloseHandle(hDisk);

returnTRUE;

}

卸载请求显式锁定卷方式写入数据// 写入指定扇区数据 方法二 卸载请求显式锁定卷

BOOLWriteDisk_Dismount(charcDriver,ULONGLONG ullOffsetSector,BYTE*pData)

{

DWORD dwRet=0;

BOOL bRet=FALSE;

charszDriver[MAX_PATH]={0};

// \\\\.\\C:

::wsprintf(szDriver,"\\\\.\\%c:",cDriver);

// 打开硬盘物理设备

// 这里名称不能为\\\\.\\PHYSICALDRIVEn(n为0-256),即物理磁盘,只能对逻辑分区锁定与DISMOUNT操作

HANDLE hDisk=::CreateFile(szDriver,GENERIC_READ|GENERIC_WRITE,

FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,

FILE_ATTRIBUTE_ARCHIVE,NULL);

if(INVALID_HANDLE_VALUE==hDisk)

{

ShowError("CreateFile");

returnFALSE;

}

// 卸载请求显式锁定卷

bRet=::DeviceIoControl(hDisk,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("DeivceIoControl");

returnFALSE;

}

// 移动文件指针到指定扇区偏移

LARGE_INTEGER li={0};

li.QuadPart=SECTOR_SIZE*ullOffsetSector;

::SetFilePointer(hDisk,li.LowPart,&li.HighPart,FILE_BEGIN);

// 写入数据

bRet=::WriteFile(hDisk,pData,SECTOR_SIZE,&dwRet,NULL);

if(FALSE==bRet)

{

ShowError("WriteFile");

returnFALSE;

}

// 关闭句柄

::CloseHandle(hDisk);

returnTRUE;

}

程序测试

我们在 main 函数中调用上面的函数进行测试,向非系统盘 E 盘读取并使用 3 种方式写入数据,测试结果如下所示:

e3f32f3c9f309e6670f2ec5cdba64285.png

a814654e88fe6ea3759693331a1957e0.png

数据读取成功,直接调用 WriteFile 函数写入数据方式失败;使用锁定请求显式锁定卷方式失败;使用卸载请求显式锁定卷方式成功。

总结

要注意两点:一是使用 CreateFile 打开设备的时候,名称不能为\\\\.\\PHYSICALDRIVEn(n为0-256),即物理磁盘,只能对逻辑分区锁定与卸载操作。二是,本文介绍的这两种方法,都不能对系统盘进行操作。

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值