• 进程线程创建与退出监视(DBGVIEW打印)


    曾经想着做个自己的主动防御项目,就是监控而已,实现RING3通信,各方参考学习,想着HOOK 来着

    但是有一次知道了无HOOK的方式,感觉这挺方便呀 还是微软承认的函数,那我就实现一套监控的方案,考虑到逆向分析的话就准备后面

    有事没事空闲了就去尽量实现HOOK的方式,希望一切顺利,少蓝屏几次。谢谢胡老师教程指导!

    这里是代码和注意:实现的是监控进程线程创建退出,如果calc创建则阻止创建(W7 64位通过)

    其中注意的是:

    进程监视函数

    PsSetCreateProcessNotifyRoutineEx(MSDN可查)。此函数的原型为:

    NTSTATUS PsSetCreateProcessNotifyRoutineEx(
    __in PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine,
    __in BOOLEAN Remove
    );


    接下来注意回调函数 NotifyRoutine 的原型:

    VOID CreateProcessNotifyEx(
    __inout PEPROCESS Process, //新进程 EPROCESS
    __in HANDLE ProcessId, //新进程 PID
    __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo //新进程详细信息(仅在创建进程时有效)
    );


    接下来看看 PS_CREATE_NOTIFY_INFO 结构体的定义:

    typedef struct _PS_CREATE_NOTIFY_INFO {
    SIZE_T Size;
    union {
    ULONG Flags;
    struct {
    ULONG FileOpenNameAvailable :1;
    ULONG Reserved :31;
    };
    };
    HANDLE ParentProcessId;
    CLIENT_ID CreatingThreadId;
    struct _FILE_OBJECT *FileObject;
    PCUNICODE_STRING ImageFileName;
    PCUNICODE_STRING CommandLine;
    NTSTATUS CreationStatus;
    } PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO;

    父进程 ID,父线ID
    甚至直接包括程序的路径(不用通过 FileObject 来取,路径直接包含在了
    ImageFileName 里)和命令行参数!

    最紧要的是,如果要阻止进程创建,直接把
    此结构体的 CreationStatus 成员改为 STATUS_UNSUCCESSFUL 

    线程监控函数:

    NTKERNELAPI
    NTSTATUS
    PsSetCreateThreadNotifyRoutine(
    _In_ PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
    );(MSDN可查

    他的回调函数如下:

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

    这样很容易就看到进程 线程ID(句柄)了。而且第三位BOOLEAN型代表创建成功与否是一个 yes or no 的选择。

    下面是测试代码

    ProcessDrv.h:

    #include <ntddk.h>

    #define dprintf DbgPrint
    #define DEVICE_NAME L"\Device\monitor_create_process_x64"
    #define LINK_NAME L"\DosDevices\monitor_create_process_x64"
    #define LINK_GLOBAL_NAME L"\DosDevices\Global\monitor_create_process_x64"

    ProcessNotify.h
    NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process);
    NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);

    PCHAR GetProcessNameByProcessId(HANDLE ProcessId)
    {
    NTSTATUS Status=STATUS_UNSUCCESSFUL;
    PEPROCESS ProcessObj=NULL;
    PCHAR StringName =NULL;

    Status = PsLookupProcessByProcessId(ProcessId, &ProcessObj);
    if(NT_SUCCESS(Status))
    {
    StringName = PsGetProcessImageFileName(ProcessObj);
    ObfDereferenceObject(ProcessObj);//EPROCESS 里结构是有ProcessImageFileName
    }
    return StringName;
    }

    VOID MyCreateProcessNotifyEx
    (
    __inout PEPROCESS Process,
    __in HANDLE ProcessId,
    __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
    )
    {

    char v1[16]={0};
    if(CreateInfo!=NULL) //进程创建事件
    {
    DbgPrint("[flame看到进程在创建(x64)][%ld]%s创建进程: %wZ",
    CreateInfo->ParentProcessId,
    GetProcessNameByProcessId(CreateInfo->ParentProcessId),
    CreateInfo->ImageFileName);
    strcpy(v1,PsGetProcessImageFileName(Process));
    if(!_stricmp(v1,"calc.exe"))
    {
    DbgPrint("禁止创建计算器进程!");
    CreateInfo->CreationStatus=STATUS_UNSUCCESSFUL; //禁止创建进程
    }
    }
    else
    {
    DbgPrint("[flame看到进程在退出(x64)]进程退出: %s",PsGetProcessImageFileName(Process));
    }
    }

    VOID MyCreateThreadNotify
    (
    IN HANDLE ProcessId,
    IN HANDLE ThreadId,
    IN BOOLEAN Create
    )
    {
    if (Create)
    {
    DbgPrint("[flame看到线程在创建(x64)]线程创建! PID=%ld;TID=%ld", ProcessId, ThreadId);
    }
    else
    {
    DbgPrint("[flame看到线程在退出(x64)]线程退出! PID=%ld;TID=%ld", ProcessId, ThreadId);
    }

    }

    ProcessDrv.c:

    #include <ntddk.h>
    #include "ProcessDrv.h"
    #include "ProcessNotify.h"

    VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
    {
    UNICODE_STRING strLink;
    RtlInitUnicodeString(&strLink, LINK_NAME);
    IoDeleteSymbolicLink(&strLink);
    IoDeleteDevice(pDriverObj->DeviceObject);
    //remove create process/thread notify
    PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx,TRUE);
    PsRemoveCreateThreadNotifyRoutine(MyCreateThreadNotify);
    }

    NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    {
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    {
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    }

    NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    {
    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
    PIO_STACK_LOCATION pIrpStack;
    ULONG IoControlCode;
    PVOID IoBuffer;
    ULONG InputLength;
    ULONG OutputLength;
    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    IoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    InputLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    OutputLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
    switch(IoControlCode)
    {

    }
    if(Status == STATUS_SUCCESS)
    pIrp->IoStatus.Information = OutputLength;
    else
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = Status;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return Status;
    }

    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
    {
    NTSTATUS V1 = 0;
    NTSTATUS Status = STATUS_SUCCESS;
    UNICODE_STRING LinkName;
    UNICODE_STRING DeviceName;
    PDEVICE_OBJECT DevObject;
    pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
    pDriverObj->DriverUnload = DriverUnload;

    RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
    Status = IoCreateDevice(pDriverObj, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DevObject);
    if (!NT_SUCCESS(Status))
    {
    return Status;
    }

    if (IoIsWdmVersionAvailable(1, 0x10))//WDM YES OR NO
    {
    RtlInitUnicodeString(&LinkName, LINK_GLOBAL_NAME);
    }
    else
    {
    RtlInitUnicodeString(&LinkName, LINK_NAME);
    }

    Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
    if(!NT_SUCCESS(Status))
    {
    IoDeleteDevice(DevObject);
    return Status;
    }

    V1 =PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyCreateProcessNotifyEx,FALSE);
    DbgPrint("PsSetCreateProcessNotifyRoutineEx return: %x", V1);
    V1 =PsSetCreateThreadNotifyRoutine(MyCreateThreadNotify);
    DbgPrint("PsSetCreateThreadNotifyRoutine return: %x", V1);
    return STATUS_SUCCESS;
    }

    打印结果:

  • 相关阅读:
    RFC3489 STUN之客户端所处环境探测流程与部分属性含义说明
    视频直播中用户连麦技术模型与特点分析
    基于网络流量统计与反馈实现边缘机房间媒体流流量调度的一种思路
    基于Flash与window平台本地程序通信实现媒体流发布
    基于Flash ActionScript 实现RTMP发布与播放媒本流
    DirectShow音频采集声音不连续问题分析与解决办法经验总结
    一种高性能与高可用的流媒体系统之媒体流状态管理方法
    复用TCP连接提升流媒体服务器之间流量转发效率
    基于块流协议保证音频优先发送
    LibRTMP优化之调整输出块大小
  • 原文地址:https://www.cnblogs.com/L-Sunny/p/9094927.html
Copyright © 2020-2023  润新知