PsSetCreateProcessNotifyRoutine監控進程創建

PsSetCreateProcessNotifyRoutine函數用來註冊一個進程創建的回調函數,當有新從進程被創建時,就把父進程的ID,和子進程(被創建的進程)ID傳給回調函數,通過回調函數,可以監控新創建的進程

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

想要實現的功能:新進程被系統創建時,打印出父進程和子進程的名字

在回調函數中可以直接獲取兩個進程的PID,但是要想通過PID得到進程名字,也有很多種方式。
但最簡單的是還是通過PsLookupProcessByProcessId函數來根據PID獲取EPROCESS結構體,然後可以直接通過結構體+偏移的方式讀取到該進程的名字。

需要注意的是,在使用PsLookupProcessByProcessId得到一個 EPROCESS結構以後,系統會對該進程的引用計數累加1,需要在不使用該結構時,及時調用ObDereferenceObject解除引用計數

也可以使用PsGetProcessImageFileName函數來獲取,其內部實現原理也是通過EPROCESS+偏移的方式得到的進程名字

進程名字在EPROCESS結構體偏移0x16C的位置,可能不同的系統版本,偏移會有區別。
在這裏插入圖片描述
再來看PsGetProcessImageFileName函數的反彙編,是不是也賊簡單:
[圖片]
效果:
在這裏插入圖片描述

完整代碼:

extern NTSYSAPI PUCHAR NTAPI PsGetProcessImageFileName(PEPROCESS Process);


// 監控進程創建回調函數
VOID CreateProcessNotify(IN HANDLE  ParentId, IN HANDLE  ChildId, IN BOOLEAN  Create)
{
    PEPROCESS ParentEprocess = NULL;
    PEPROCESS ChildEprocess = NULL;
    NTSTATUS status;
    if (Create)
    {
        
        // 獲取EPROCESS結構體
        status = PsLookupProcessByProcessId(ParentId, &ParentEprocess);
        if (!NT_SUCCESS(status))
        {
            KdPrint(("Get Parent Eprocess Failed\n"));
            return;
        }
        status = PsLookupProcessByProcessId(ChildId, &ChildEprocess);
        if (!NT_SUCCESS(status))
        {
            KdPrint(("Get Child Eprocess Failed\n"));
            return;
        }

        // 通過EPROCESS獲取進程名
        KdPrint((
            "ParentName:%s---> ChildName:%s\n",
            PsGetProcessImageFileName(ParentEprocess),
            PsGetProcessImageFileName(ChildEprocess)
            ));

        ObDereferenceObject(ParentEprocess);
        ObDereferenceObject(ChildEprocess);
    }
}


VOID DriverUnload(PDRIVER_OBJECT driver)
{
    // 卸載時,移除回掉
    PsSetCreateProcessNotifyRoutine(CreateProcessNotify, TRUE);
    DbgPrint("first: Our driver is unloading...\r\n");
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{
    DbgBreakPoint();

    PsSetCreateProcessNotifyRoutine(CreateProcessNotify, FALSE);
   
    pDriver->DriverUnload = DriverUnload;

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