PsSetCreateProcessNotifyRoutine妙用

最近要做一個進程監控的程序,功能很簡單,就是創建和退出進程的時候,能觸發我們的事件。

首先的第一想法,是Hook ZwCreateProcess,結果調試的時候發現,很多創建進程的動作,並沒有通過這個API執行,所以自然就是沒辦法監控進程的創建,於是回到本質,從創建進程的動作過程來分析,創建新的進程,其大致要經歷以下步驟:

(1)打開可執行文件,以FILE_EXECUTE權限打開;

(2)將可執行文件加載到內存空間;

(3)進程的活動結構將被創建,如(EPROCESS,KPROCESS和PEB結構);

(4)爲新創建的進程分配地址空間;

(5)爲進程的主線程創建線程活動結構,如(ETHREAD,KTHREAD和TEB結構);

(6)主線程的棧將會被分配;

(7)進程的主線程的上下文將被創建;

(8)通知windows子系統;

以上總結下來,無非有下面幾種辦法獲取進程創建的消息:

(1)HOOK ZeCreateSection,創建虛擬內存塊的時候,根據傳入的文件句柄,獲取句柄對應的文件名是否爲exe可執行文件;

(2)Hook NtReadVirtualMemory,爲新創建的進程分配地址空間等操作時,需要讀取進程空間,這樣捕獲,就能夠獲取進程的創建動作;

(3)通過windows提供的回調函數,註冊回調事件;

方法對比:

(1)該方法能夠準確的獲取進程創建的操作,但是由於此時進程並沒有創建完畢,一些進程的基本結構還沒有創建,所以進程ID等信息無法獲取;

(2)該方法能夠獲取進程的創建操作,但不準確。因爲除了進程的創建會調用此操作外,人爲的一些操作,例如某外部應用程序想讀取另一個進程的內存空間,也會調用這個函數,這時候也會有事件響應,因此結果不準確;

(3)第三種方法更直觀和簡單。因爲採用的回調事件,並不直接HOOK API,因此更穩定。

重點分析第三種回調方法。

註冊回調事件,是通過PsSetCreateProcessNotifyRoutine來實現的,其函數原型如下:

NTSTATUS PsSetCreateProcessNotifyRoutine( 
IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, 
IN BOOLEAN Remove 
);

NotifyRoutine就是註冊的回調函數,當有進程創建的時候,就會調用這個NotifyRoutine對應的函數,其函數定義原型如下:

VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE) ( 
IN HANDLE ParentId, 
IN HANDLE ProcessId, 
IN BOOLEAN Create 
); 
其中,ParentId是父進程ID,ProcessId爲子進程ID,而Create表示是創建進程還是結束進程,其中True表示創建進程,False表示結束進程。

通過這個函數,我們就能夠完成進程創建和退出的監控,首先調用PsSetCreateProcessNotifyRoutine註冊進程監控回調函數,然後在回調函數裏面,判斷Create參數,分別處理進程創建和退出操作。

其它類似的函數還有PsSetLoadImageNotifyRoutine,PsSetCreateThreadNotifyRoutine等函數,通過函數名,能夠比較清晰的明白函數的意義,在此就不細講了。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yushiqiang1688/archive/2010/01/18/5209597.aspx

寫的太好了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章