一個檔案系統過濾驅動的demo
因為沒寫過FSD過濾驅動,所以拿來練練手,沒有什麼技術含量。參考自Win核心安全與驅動開發。
先梳理一下大概的流程,就是怎麼去繫結裝置棧、怎麼去過濾各種請求的。
首先肯定是要繫結裝置棧的,來看下怎麼繫結的裝置棧。
先確定繫結的物件是什麼,檔案系統的裝置是分兩個部分的,分別是卷裝置和控制裝置。其中,卷裝置是每有一個卷就會對應有一個卷裝置,這麼說可能不太清楚我畫了一張圖。
注意,這裡的卷裝置並不是磁碟的卷裝置。而是檔案系統生成的,用來對應每一個卷的卷裝置。一定要區分開這兩者。繫結這些個卷裝置也不能夠直接進行,因為這些由檔案系統生成的卷裝置是無名的裝置,根本沒法直接繫結。這裡使用的辦法是先繫結FSD的控制裝置,當控制裝置接收到新建卷裝置的請求這時就是可以繫結到卷裝置上了。但是,FSD的控制裝置也不是直接就可以繫結上的,所以也要想辦法去獲取下,這裡用的是註冊檔案系統變動回撥函式的方法。IoRegisterFsRegistrationChange()函式就是用來註冊FSD過濾驅動的,這個回撥在檔案系統發生變動時會被呼叫,比如說檔案系統被掛載時。回撥函式和其他的系統事件通知類似都是有固定格式的,函式原型如下。
1 VOID NotifyFunction(PDEVICE_OBJECT DeviceObject,BOOLEAN Type) 2 { 3 //其中DeviceObject就可以是FSD載入時的控制裝置指標,Type參數列示是解除安裝還是載入 4 }
註冊了這個回撥函式後,在裡面對DeviceObject進行一下判斷看一下是不是自己想要的檔案系統,因為一個電腦上有很多的檔案系統。
小結一下,目前為止我們知道了要進行這麼一個流程:
分三步才能實現最終繫結。而我們的目的只是為了去繫結FSD卷裝置,因為這個卷裝置才是真正去接受和處理讀寫請求的裝置。
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegPath) { UNICODE_STRING DeviceName; DEVICE_OBJECT DeviceObject; NTSTATUS Status; FilterDriver=DriverObject;//全域性變數 RtlInitUnicodeString(&DeviceName,L"\\FileSystem\\Filters\\DemoDriver"); Status=IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject); if(!NT_STATUS(Status)) { //裝置建立失敗 return Status; } for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION) { DriverObject->MajorFunction[i]=CallNextIrpLocation; } //DriverObject->MajorFunction[] //當前裝置繫結到檔案系統的控制裝置(CDO)上 //註冊一個檔案系統變動回撥函式 Status=IoRegisterFsRegistrationChange(DriverObject,FsChangeCallBack); if(!NT_STATUS(Status)) { IoDeleteDevice(DeviceObject); return Status; } }
我這裡把MajorFunctionp[]的分發函式一些給省略了,後面會寫出來。再來看一下FsChangeCallBack也就檔案系統變動回撥函式的內容,這個函式的目的是要繫結FSD控制裝置。
1 VOID FsChangeCallBack(PDEVICE_OBJECT DeviceObject,BOOLEAN Create) 2 { 3 NTSTATUS Status; 4 UNICODE_STRING CompareName; 5 UNICODE_STRING DriverName; 6 DEVICE_OBJECT FilterDevice; 7 RtlInitUnicodeString(&CompareName,L"\\FileSystem\\Fs_Rec"); 8 if(Create) 9 { 10 //附加當前過濾驅動到CDO上去 11 //附加前要注意兩點 12 //1.是不是自己想要的CDO型別 13 //2.是不是檔案識別器 14 if(IS_WANTED_DEVICE_TYPE(DeviceObject->DriverObject->type)) 15 { 16 // 17 GetDriverNameFromDeviceObject(&DriverName,DeviceObject); 18 if(!RtlCompareUnicodeString(&DriverName,&CompareName)) 19 { 20 Status=IoCreateDevice(FilterDriver, 21 sizeof(DEVICE_EXTENSION), 22 NULL, 23 DeviceObject->DeviceType, 24 0, 25 FALSE, 26 &FilterDevice); 27 if(!NT_SUCCESS(Status)) 28 { 29 return Status; 30 } 31 FilterDevice->Flags=DeviceObject->Flags; 32 Status=(PVOID)IoAttachDeviceToDeviceStack(FilterDevice,DeviceObject); 33 if(!Status) 34 { 35 IoDeleteDevice(FilterDevice); 36 return Status; 37 } 38 DeviceObject->DeviceExtension->NextDevice=(PDRIVER_OBJECT)Status; 39 40 } 41 42 } 43 } 44 else 45 { 46 return 0; 47 } 48 return 0; 49 }
做了簡單的判斷:
- 判斷是掛載檔案系統的通知
- 判斷是想要的檔案系統型別
- 判斷不是檔案識別器
這裡FSD的控制裝置就被繫結上了,然後再去過濾FSD控制裝置識別器接受的卷掛載請求。過濾請求這裡有一點要注意的,因為當請求發下來時卷裝置還沒真正建立,所以不能去繫結,要等Irp返回後才能去繫結。這一點跟處理過濾驅動過濾讀請求時的處理是很像的,因為讀請求下發下來時,還沒有正在的讀動作,只有等到Irp返回後才能進行過濾。具體的做法就是用完成函式,但是畢竟特殊的一點是書上是用完成函式去啟用事件然後在分發例程中等待事件來進行的處理,等待事件後進行繫結。書中的解釋是完成函式處於DPC的IRQL,其實我覺得放在完成函式里應該不會有問題吧,又使用了完成函式又使用了等待事件感覺好重複。這種寫法以前好像沒寫過。
1 NTSTATUS FilterAddToMount(PDEVICE_OBJECT DeviceObject,PIRP Irp) 2 { 3 //從DeviceObject中獲取VPB,再從VPB中獲取卷的資訊 4 PIO_STACK_LOCATION irpSP; 5 PDEVICE_OBJECT RealDevice; 6 PDEVICE_OBJECT FilterDevice; 7 KEVENT NotifyEvent; 8 NTSTATUS Status; 9 PVPB vpb; 10 irpSP=IoGetCurrentIrpStackLocation(Irp); 11 RealDevice=irpSP->Parameters.MountVolume.Vpb->RealDevice; 12 IoCreateDevice(FilterDriver, 13 sizeof(DEVICE_EXTENSION), 14 NULL, 15 DeviceObject->DeviceType, 16 0, 17 FALSE, 18 &FilterDevice); 19 KeInitializeEvent(&NotifyEvent, 20 NotificationEvent, 21 FALSE); 22 IoCopyCurrentIrpStackLocationToNext(Irp); 23 IoSetCompletionRoutine(Irp, 24 SetEventRoutine, 25 &NotifyEvent, 26 TRUE, 27 TRUE, 28 TRUE); 29 IoCallDriver(Device,Irp); 30 31 KeWaitForSingleObject(&NotifyEvent, 32 Executive, 33 KernelMode, 34 FALSE, 35 NULL); 36 if(NT_SUCCESS(irpSP->IoStatus.Status)) 37 { 38 vpb=RealDevice->Vpb; 39 Status=IoAttachDeviceToDeviceStack(vpb->DeviceObject,FilterDevice); 40 } 41 IoCompleteRequest(Irp,IO_NO_INCREMENT); 42 return STATUS_SUCCESS; 43 44 45 } 46 47 NTSTATUS SetEventRoutine(PDEVICE_OBJECT DeviceObject, 48 PIRP Irp, 49 PVOID Context) 50 { 51 KeSetEvent((PKEVENT)Context,IO_NO_INCREMENT,FALSE); 52 return STATUS_MORE_PROCESSING_REQUIRED; 53 54 }
到這裡已經繫結了卷裝置,這時只要設定好分發函式就可以完成過濾了。
接下來要說的就是具體的針對每種資訊的處理了,要分類來說了。
0x0 過濾檔案的開啟
檔案開啟請求的主功能號是IRP_MJ_CREATE
首先,在Irp棧中可以獲得檔案物件指標。FileObject=irpsp->FileObject;目錄和檔案都是用檔案物件表示的,直接是看不出來兩者的分別的。irpsp->Parameters.Create的結構如下
struct{ PIO_SECURITY_CONTEXT SecurityContext; ULONG Options; USHORT FileAttributes; USHORT ShareAccess; ULONG EaLength; }
注意,開啟請求是一種嘗試性動作,就是說開啟只有當返回成功時才有過濾的意義,獲取結果要用完成函式才行。
0x1 過濾檔案的刪除
檔案刪除是分三步請求的,所以不是過濾一次就行的。刪除的三步如圖
開啟檔案的請求上面已經說過了。設定刪除標誌是主功能號為IRP_MJ_SET_INFORMATION的設定請求中的一種,其中irpsp->Parameters.SetFile.FileInformationClass為FileDispositionInformation。然後irp->AssociatedIrp.SystemBuffer指向如下結構
typdef struct _FILE_DISPOSITION_INFORMATION{ BOOLEAN DeleteFile; } FILE_DISPOSITION_INFORMATION;
0x2 過濾檔案的路徑
我們使用檔案系統過濾驅動很多時候都是為了根據路徑來進行操作,要不就使用磁碟過濾驅動就可以了完全沒必要使用FSD過濾驅動。
(未完待續)
相關文章
- 驅動開發 鍵盤過濾驅動程式--
傳統的鍵盤過濾2015-07-02
- 檔案系統修復的一個過程2018-08-04
- 作業系統——裝置驅動和檔案系統2018-08-21作業系統
- win10系統下檔案過濾器的使用教程【圖文】2020-02-02Win10過濾器
- 基於sys檔案系統的LED驅動的移植【原創】2017-06-05
- 用 tr 過濾檔案2011-10-18
- 檔案字尾名的過濾2011-12-08
- git上傳過濾檔案2018-03-27Git
- 一個microsoft的.exe程式檔案的啟動過程 (轉)2007-12-13ROS
- java--FilenameFilter檔案過濾器2011-11-18JavaFilter過濾器
- struts中配置過濾檔案! (轉)2007-08-16
- 在一個系統上編譯多個核心版本的驅動模組(轉)2007-08-12編譯
- 用Python寫一個FUSE(使用者態檔案系統)檔案系統2013-12-02Python
- 在指定的檔案過濾想要的內容2016-06-06
- Django模板系統 — 過濾器2013-07-03Django過濾器
- 進一步學習WDK驅動程式的SOURCES檔案、WMI驅動程式的mof檔案和wmidata.h標頭檔案2021-01-03
- 過濾鉤子驅動程式一(微軟DDK文件,FLASHSKY翻譯) (轉)2008-03-02微軟
- liunx核心移植(三)——核心、驅動、應用程式、根檔案系統的關係2017-11-19
- input檔案選擇框檔案過濾引數accept2020-11-19
- 各檔案系統對單個檔案大小的限制2015-05-15
- 檔案系統(十):一文看懂 UBI 檔案系統2024-07-24
- 過濾器實現檔案的gzip壓縮2014-03-12過濾器
- linux過濾空檔案的命令總結2014-11-26Linux
- iozone 一個檔案系統的效能檢測工具。2011-03-27
- truncate一個linux作業系統檔案2012-03-02Linux作業系統
- 自己動手打造企業垃圾郵件過濾系統2017-11-15
- 裝置驅動程式INF檔案——INF檔案的節2013-07-19
- 一個嵌入式Linux系統的鍵盤驅動實現(轉)2007-08-15Linux
- 驅動除錯—還原 QQ 過濾驅動對關鍵核心設施所做的修改(Part II)2018-05-30除錯
- 設計一個健壯的大型檔案下載系統2017-04-14
- 如何用一個 Excel 過濾另一個 Excel2020-05-12Excel
- 【ZIP】打包過濾指定目錄和檔案2018-12-02
- java中listFiles(Filefilter filter)檔案過濾器的實現過程2020-12-16JavaFilter過濾器
- Win10系統安裝驅動怎麼生成cat檔案和簽名2017-07-28Win10
- 【Datawhale】推薦系統-協同過濾2020-10-22
- linux下系統啟動時,幾個配置檔案 /etc/profile、~/.bash_profile 等幾個檔案的執行過程,先後順序2017-12-13Linux
- 為媒體資產構建一個雲原生的檔案系統2022-06-14
- 用Akka構建一個簡易的分散式檔案系統2013-12-08分散式