1. 程式人生 > >[Win32] 直接讀寫磁盤扇區(磁盤絕對讀寫)

[Win32] 直接讀寫磁盤扇區(磁盤絕對讀寫)

ref return rac cpp sig i/o phy 類型 表示

??本博文由CSDN博主zuishikonghuan所作,版權歸zuishikonghuan全部。轉載請註明出處:http://blog.csdn.net/zuishikonghuan/article/details/50380313

正講著驅動開發呢,這裏突然插一篇Win32的博文。事實上。還是做引子,上一篇博文“IRP與派遣函數”中,我們知道了驅動程序須要處理I/O請求。我們先來看看怎麽發出一個I/O請求。

一般的程序不會直接去訪問磁盤,畢竟有文件系統(FileSystem)幫助我們輕松地組織文件,可是有時候必須訪問磁盤,由於文件系統隱藏了低層次的實現,linux人喜歡把文件系統叫做“虛擬文件系統(VFS)”,事實上原因就在這裏。比方我們把一個文件從一個分區拷貝到還有一個分區(事實上就是從一個分區中讀取文件再向還有一個分區寫入文件,當然通常是分段讀取寫入的,或者是用虛擬內存(線性地址空間)映射文件),我們不須要關心磁盤上分區的組織方法。比方MBR格式或GPT格式,也不須要關心分區對數據的組織方式,無論是FAT32。NTFS,exFAT,ext2/3/4格式等等,這就是文件系統的魅力所在。咳咳,扯的有點遠哈,回歸正題,我們的目的是繞過文件系統,直接訪問磁盤上的扇區,就像市面上的PE盤制作器一樣。能夠把引導程序寫人U盤的主引導扇區(第一個扇區。通常是512字節)。

演示一下將第一塊磁盤的主引導扇區讀出來。寫的話把ReadFile換成WriteFile,再略微改下代碼就能夠了。這些API函數在我之前的一篇博客中有詳解(參見:http://blog.csdn.net/zuishikonghuan/article/details/46926787)。對了。用BIOS引導系統的看官千萬別亂寫啊,寫壞了MBR就引導不了系統了,修復非常麻煩的,用UEFI引導系統的隨便寫,不怕,由於UEFI不從MBR載入引導程序,這也是UEFI天生免疫鬼影病毒的原因之中的一個。


代碼例如以下:

#include "stdafx.h"
#include<Windows.h>

//參數:輸出的字符串指針,開始位置,長度
//返回值:讀取的大小
DWORD ReadDisk(unsigned char* &out,DWORD start,DWORD size)
{
	OVERLAPPED over = { 0 };
	over.Offset = start;
	HANDLE handle = CreateFile(TEXT("\\\\.\\PHYSICALDRIVE0"), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
	if (handle == INVALID_HANDLE_VALUE)return 0;
	unsigned char* buffer = new unsigned char[size + 1];
	DWORD readsize;
	if (ReadFile(handle, buffer, size, &readsize, &over) == 0)
	{
		CloseHandle(handle);
		return 0;
	}
	buffer[size] = 0;
	out = buffer;
	//delete [] buffer;
	//註意這裏須要自己釋放內存
	CloseHandle(handle);
	return size;
}
int _tmain(int argc, _TCHAR* argv[])
{
	unsigned char* a;
	DWORD len=ReadDisk(a, 0, 512);
	if (len){
		for (int i = 0; i < len; i++){
			printf("%02X ", a[i]);
		}
	}
		getchar();
	return 0;
}

效果圖:

技術分享

代碼中須要註意的幾個地方:

1。"\\.\PhysicalDrive0"表示第一個物理磁盤。"\\.\PhysicalDrive1"表示第二個物理磁盤。不區分大寫和小寫,以此類推。另外別忘了C/C++字符串轉義應該寫成\\\\.\\
2。dwCreationDisposition參數必須具有OPEN_EXISTING標誌。不要問我為什麽,微軟就是這麽說的,不信查MSDN。
3。MSDN上說假設讀寫的是卷設備,dwShareMode必需要有FILE_SHARE_WRITE標誌。可是在w10系統上讀寫磁盤設備假設不加這個標誌CreateFile也會失敗,但在w8.1上不會。至於說為什麽別問我。問微軟吧。


4。假設你用的uefi引導。那麽你的mbr前400多個字節可能是空白,博主由於一些特殊原因(方便載入u盤的mbr引導),專門改成了BIOS引導。所以mbr中的引導程序不是空的,所以假設你執行代碼發現前400多字節都是0,不要以為出錯了。

特別提醒:讀寫物理磁盤須要管理員權限,怎樣獲取管理員權限看這裏,別由於沒註意這個導致執行失敗而折騰。

另外,不準學會了後拿去做病毒啊。做病毒後果自負!

我們就好像讀寫一個文件一樣讀寫了“磁盤”這個設備。事實上上就是把讀寫操作的I/O請求發送到了“磁盤”這個設備所在驅動程序註冊的派遣函數中。


對了。Microsoft為Windows提供了基礎的硬件驅動程序。無論磁盤的類型是什麽,是IDE磁盤,SCSI磁盤,SATA磁盤,還是從USB上掛的磁盤,都抽象成統一接口的磁盤設備。所以,僅僅要你用的磁盤是Microsoft支持的類型。或者硬件廠商提供了驅動程序,那麽上面的代碼均可用!

回歸正題,我們通過打開“\\.\PhysicalDrive0”。打開了磁盤設備。假設接著我前幾篇的博文看。你就會發現,這不就是符號連接嗎,沒錯。這就是磁盤設備的符號連接。

同一時候。“卷”也是設備,卷就是Windows對磁盤上的分區創建的設備,就是“此電腦”(文件資源管理器)中列出的a盤。b盤,c盤……。沒錯。卷僅僅是一個邏輯上的概念。我們的電腦上也沒有“卷”這樣的設備,但Windows為其創建了設備(嚴格意義上並不是是操作系統創建的,創建設備不是操作系統的任務,應該說是Microsoft為Windows提供的基礎設備驅動程序創建的)。比方c盤的設備名通常是“\Device\HarddiskVolume1”。符號連接名是“\??\C:”(R0下)和“\\.\C:”(R3下),事實上,我們看到的*盤就是驅動開發中的符號連接!

用設備管理器改動盤符,事實上就是通知卷驅動程序刪除並又一次創建符號連接。

結合上一篇“IRP與派遣函數”和上上篇“NT驅動的基本結構”,想必你已經大致有眉目了吧。下一篇和下下篇就會具體介紹怎樣在驅動程序中處理I/O請求了。

??

[Win32] 直接讀寫磁盤扇區(磁盤絕對讀寫)