1. 程式人生 > >【windows核心驅動開發】檔案系統微過濾驅動Minifilter——獲取程序資訊

【windows核心驅動開發】檔案系統微過濾驅動Minifilter——獲取程序資訊

【我的】檔案系統微過濾驅動Minifilter——獲取程序資訊

作者:zcr214 時間:2016/4/22

在編寫檔案系統微過濾驅動minifilter的時候,除了繫結指定的磁碟分卷,對於指定的檔案很可能還會有指定的應用程式,例如txt檔案可以有很多編輯器可以使用,如wordpad,notepad,sublime,vim,notepad+等,doc文件可以使用office word或WPS,圖片檔案就更多了。雖然僅靠過濾程序名來篩選出指定程式的方式不太安全,黑客可以通過偽裝程序名的方式繞過,但是獲取程序資訊(程序ID,程序名等)對於minifilter驅動所需的基本功能的開發有著重要的作用。

1.    設定載入程序通知PsSetCreateProcessNotifyRoutine()

可以使用PsSetCreateProcessNotifyRoutine()來設定一個通知回撥函式。每當作業系統建立或者關閉一個程序的時候,回撥都會被呼叫。

NTSTATUS

PsSetCreateProcessNotifyRoutine(

_In_PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,

_In_BOOLEAN Remove  );

返回狀態值,表示設定通知回撥是否成功,引數中包含一個設定的通知回撥函式的指標和是否移除的標記,移除標記設為false表示設定通知回撥,true表示解除安裝通知回撥,當驅動啟動時在DriverEntry中需要設定通知回撥,驅動停止時當然也要在FilterUnload中解除安裝這個通知回撥。

通知回撥函式的原型為:

VOID

(*PCREATE_PROCESS_NOTIFY_ROUTINE)(

_In_HANDLE ParentId,

_In_HANDLE ProcessId,

_In_BOOLEAN Create    );

顯而易見的,可以在通知回撥函式中獲取到這個程序的ID和父程序ID,以及建立或關閉的標記。

2.    設定載入映像通知PsSetLoadImageNotifyRoutine()

可以使用PsSetLoadImageNotifyRoutine()設定一個通知回撥函式,每當作業系統新載入一個映像檔案的時候,設定的回撥函式就會被呼叫。

PsSetLoadImageNotifyRoutine()函式原型如下:

NTSTATUS

PsSetLoadImageNotifyRoutine(

_In_PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine

);

返回一個狀態值,表示設定通知回撥函式是否成功,引數只有一個,即通知回撥函式的指標。在驅動啟動時在DriverEntry設定通知回撥,驅動停止時也需要在FilterUnload中解除安裝通知回撥,使用另一個相對應的函式PsRemoveLoadImageNotifyRoutine(),函式原型和Set函式類似。

載入映像的通知回撥函式的原型如下:

VOID

(*PLOAD_IMAGE_NOTIFY_ROUTINE)(

_In_PUNICODE_STRING FullImageName,

_In_HANDLE ProcessId,// pid into which image is being mapped

_In_PIMAGE_INFO ImageInfo

);

顯而易見的,可以在通知回撥函式中得到完整的映像名稱,程序ID,和其他的映像相關資訊。

3.    實際使用一下

(1)   DriverEntry中,啟動過濾之前,設定通知回撥。

//啟動獲取程序,映像資訊的回撥

PsSetCreateProcessNotifyRoutine(ProcessNotify,FALSE);

PsSetLoadImageNotifyRoutine(LoadImageNotify);

// Start filtering i/o

(2)   FilterUnload中,停止過濾之前,取消通知回撥。

// 驅動關閉,移除程序和映像資訊獲取的回撥

PsSetCreateProcessNotifyRoutine(ProcessNotify,TRUE);

PsRemoveLoadImageNotifyRoutine(LoadImageNotify);

// Unregister from FLT mgr

(3)   編寫程序通知回撥函式,列印程序資訊。

VOID

ProcessNotify(

INHANDLEParentId,

INHANDLEProcessId,

INBOOLEANCreate)

{

DbgPrint("FilterProcessNotify,pid: %d, tid: %d, create: %d\n",ParentId,ProcessId,Create);

}

(4)   編寫映像通知回撥函式,儲存程序ID和映像名稱資訊(這裡事先已經定義了一個全域性的ProcessList陣列用於儲存映像名)。

VOID

LoadImageNotify(

__in_optPUNICODE_STRINGFullImageName,

__inHANDLEProcessId,

__inPIMAGE_INFOImageInfo)

{

UNREFERENCED_PARAMETER(ImageInfo);

__try{

ProcessList[(int)ProcessId]=FullImageName;

DbgPrint("image name :%wZ pid is:%d",ProcessList[(int)ProcessId],ProcessId);

}

__except(EXCEPTION_EXECUTE_HANDLER){

DbgPrint("pid:%d,cannot insert to ProcessList",ProcessId);

   }

}

當然上述的儲存方法相對簡單,在具體應用中應該視具體的需求而定,也可自定義一個表,將所有程序資訊都儲存起來,需要檢查的時候再利用程序ID將具體資訊取出來。