驱动级监控进程

技术讲解

说明:技术仅供学习使用,如恶意利用,与作者无关!

有时候我们希望能够动态监视系统中任意进程/线程的创建与销毁。为了达到此目的我翻阅了 DDK 手册,发现其提供的 PsSetCreateProcessNotifyRoutine(),PsSetCreateThreadNotifyRoutine(),等函数可以实现此功能。这两个函数可以通过向系统注册一个 CALLBALCK 函数来监视进程/线程等操作。函数原形如下:

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

VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE) (
    IN HANDLE  ParentId,
    IN HANDLE  ProcessId,
    IN BOOLEAN  Create
    );


NTSTATUS
  PsSetCreateThreadNotifyRoutine(
  IN PCREATE_THREAD_NOTIFY_ROUTINE  NotifyRoutine
  );

VOID
(*PCREATE_THREAD_NOTIFY_ROUTINE) (
    IN HANDLE  ProcessId,
    IN HANDLE  ThreadId,
    IN BOOLEAN  Create
    );

通过原形可以看出,其 CALLBACK 函数只提供了进程ID/线程ID。并没有提供进程名。那么我们要进一步通过进程ID来获取进程名。这需要用到一个未公开的函数 PsLookupProcessByProcessId()。函数原形如下:

NTSTATUS PsLookupProcessByProcessId(
     IN ULONG ulProcId, 
     OUT PEPROCESS * pEProcess
     );

函数输出的 EPROCESS 结构也是未公开的内核进程结构,很多人称其为 KPEB。EPROCESS 结构中的偏移 0x1FC 指向当前进程名的偏移。(这个结构虽然可以在驱动程序中直接使用。但没有公布其结构,网上有不少高手已将其结构给出。有兴趣可以自行搜索,或去 IFS DDK 中获取,这里因为结构太长,就不贴出来了)有了这个结构我们就可以从中得到进程名。NT系统还提供了一个函数可以动态监视进程装载映像。此函数可以得到进程加栽时所调用的 DLL 名称与全路径,还有一些映像信息。为我们获得更详细的进程装载信息提供了更好的帮助。

函数原形如下:

NTSTATUS
  PsSetLoadImageNotifyRoutine(
  IN PLOAD_IMAGE_NOTIFY_ROUTINE  NotifyRoutine
  );

VOID
(*PLOAD_IMAGE_NOTIFY_ROUTINE) (
    IN PUNICODE_STRING  FullImageName,
    IN HANDLE  ProcessId, // where image is mapped
    IN PIMAGE_INFO  ImageInfo
    );

typedef struct  _IMAGE_INFO {
    union {
        ULONG  Properties;
        struct {
            ULONG ImageAddressingMode  : 8; //code addressing mode
            ULONG SystemModeImage      : 1; //system mode image
            ULONG ImageMappedToAllPids : 1; //mapped in all processes
            ULONG Reserved             : 22;
        };
    };
    PVOID  ImageBase;
    ULONG  ImageSelector;
    ULONG  ImageSize;
    ULONG  ImageSectionNumber;
} IMAGE_INFO, *PIMAGE_INFO;

利用以上提供的函数与结构,我们便能实现一个进程/线程监视器。下面这段
代码演示了如何实现此功能。

大家可以本地编译,测试效果!

代码区

以下是我的测试代码(ProcessNameOffset因为系统不同所以我用的是win7 x86的,具体请自行修改):

/*****************************************************************
文件名        : WssProcMon.c
描述          : 进程/线程监视器
作者          : caizhe666
最后修改日期  : 2020-3-11

*****************************************************************/

#include "ntddk.h"
#include "string.h"

#define ProcessNameOffset  0x1fc

static NTSTATUS  MydrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS* pEProcess);
VOID ProcessCreateMon(IN HANDLE  hParentId, IN HANDLE PId, IN BOOLEAN bCreate);
VOID ThreadCreateMon(IN HANDLE  PId, IN HANDLE TId, IN BOOLEAN  bCreate);
VOID ImageCreateMon(IN PUNICODE_STRING  FullImageName, IN HANDLE  ProcessId, IN PIMAGE_INFO  ImageInfo);

// 驱动入口
NTSTATUS  DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING  nameString, linkString;
    PDEVICE_OBJECT  deviceObject;
    NTSTATUS        status;
    int                i;

    //建立设备
    RtlInitUnicodeString(&nameString, L"\\Device\\WssProcMon");

    status = IoCreateDevice(DriverObject,
        0,
        &nameString,
        FILE_DEVICE_UNKNOWN,
        0,
        TRUE,
        &deviceObject
    );

    if (!NT_SUCCESS(status))
        return status;

    RtlInitUnicodeString(&linkString, L"\\DosDevices\\WssProcMon");

    status = IoCreateSymbolicLink(&linkString, &nameString);

    if (!NT_SUCCESS(status))
    {
        IoDeleteDevice(DriverObject->DeviceObject);
        return status;
    }

    status = PsSetLoadImageNotifyRoutine(ImageCreateMon);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("PsSetLoadImageNotifyRoutine()\n");
        return status;
    }

    status = PsSetCreateThreadNotifyRoutine(ThreadCreateMon);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("PsSetCreateThreadNotifyRoutine()\n");
        return status;
    }

    status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("PsSetCreateProcessNotifyRoutine()\n");
        return status;
    }

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = MydrvDispatch;
    }

    return STATUS_SUCCESS;
}

//处理设备对象操作

static NTSTATUS MydrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0L;
    IoCompleteRequest(Irp, 0);
    return Irp->IoStatus.Status;
}

VOID ProcessCreateMon(IN HANDLE hParentId, IN HANDLE PId, IN BOOLEAN bCreate)
{
    PEPROCESS  EProcess;
    ULONG      ulCurrentProcessId;
    LPTSTR       lpCurProc;
    NTSTATUS   status;

    status = PsLookupProcessByProcessId((ULONG)PId, &EProcess);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("PsLookupProcessByProcessId()\n");
        return;
    }

    if (bCreate)
    {
        lpCurProc = (LPTSTR)EProcess;
        lpCurProc = lpCurProc + ProcessNameOffset;

        DbgPrint("CREATE PROCESS = PROCESS NAME: %s , PROCESS PARENTID: %d, PROCESS ID: %d, PROCESS ADDRESS %x:\n",
            lpCurProc,
            hParentId,
            PId,
            EProcess);
    }

    else
    {
        DbgPrint("TERMINATED == PROCESS ID: %d\n", PId);
    }
}

VOID ThreadCreateMon(IN HANDLE PId, IN HANDLE TId, IN BOOLEAN  bCreate)
{
    PEPROCESS   EProcess;
    ULONG        ulCurrentProcessId;
    LPTSTR        lpCurProc;
    NTSTATUS    status;

    status = PsLookupProcessByProcessId((ULONG)PId, &EProcess);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("PsLookupProcessByProcessId()\n");
        return;
    }

    if (bCreate)
    {
        lpCurProc = (LPTSTR)EProcess;
        lpCurProc = lpCurProc + ProcessNameOffset;

        DbgPrint("CREATE THREAD = PROCESS NAME: %s PROCESS ID: %d, THREAD ID: %d\n", lpCurProc, PId, TId);
    }

    else
    {
        DbgPrint("TERMINATED == THREAD ID: %d\n", TId);
    }
}

VOID ImageCreateMon(IN PUNICODE_STRING  FullImageName, IN HANDLE  ProcessId, IN PIMAGE_INFO  ImageInfo)
{
    DbgPrint("FullImageName: %S,Process ID: %d\n", FullImageName->Buffer, ProcessId);
    DbgPrint("ImageBase: %x,ImageSize: %d\n", ImageInfo->ImageBase, ImageInfo->ImageSize);
}

结尾

代码已经贴出,没有很多,就不放下载链接了qwq
如遇任何问题,可以加我QQ:2513881812
喜欢的话不妨打赏一下[滑稽]


   转载规则

请联系作者付费转载。
 上一篇
驱动级强制结束进程 驱动级强制结束进程
驱动级监控进程说明:技术仅供学习使用,如恶意利用,与作者无关!依然已经走到驱动这一层了,那么通常结束掉一个进程不是什么难的事情。同时因为win64 位的各种保护,导致大家慢慢的已经不敢HOOK了,当然这指的是产品。作为学习和破解的话当然可以
2020-03-12
下一篇 
驱动注册表回调(监控注册表) 驱动注册表回调(监控注册表)
回调监控注册表说明:技术仅供学习使用,如恶意利用,与作者无关! 在 WIN32 平台上,监控注册表的手段通常是 SSDT HOOK。不过用 SSDT HOOK的方式监控注册表实在是太麻烦了,要 HOOK 一大堆函数,还要处理一些 NT6 系
2020-03-11
  目录