轉載自http://blog.csdn.net/yushiqiang1688/article/details/5209597windows
最近要作一個進程監控的程序,功能很簡單,就是建立和退出進程的時候,能觸發咱們的事件。函數
首先的第一想法,是Hook ZwCreateProcess,結果調試的時候發現,不少建立進程的動做,並無經過這個API執行,因此天然就是沒辦法監控進程的建立,因而回到本質,從建立進程的動做過程來分析,建立新的進程,其大體要經歷如下步驟:.net
(1)打開可執行文件,以FILE_EXECUTE權限打開;線程
(2)將可執行文件加載到內存空間;調試
(3)進程的活動結構將被建立,如(EPROCESS,KPROCESS和PEB結構);blog
(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等。