進程線程創建與退出監視(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.cpp:
#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;
}
進程線程創建與退出監視(DBGVIEW打印)