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的位置,可能不同的系统版本,偏移会有区别。
PsSetCreateProcessNotifyRoutine监控进程创建_第1张图片
再来看PsGetProcessImageFileName函数的反汇编,是不是也贼简单:
PsSetCreateProcessNotifyRoutine监控进程创建_第2张图片
效果:
在这里插入图片描述

完整代码:

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;
}

你可能感兴趣的:(内核开发)