本来以hook方式hook系统api函数,后来发现不同的进程启动走的函数api是不同的,特别的对于父进程不是explorer的,比如在cmd下启动的exe这样hook的方式就不能够实现的。linux下有do_fork函数。win只能走内核去监控,幸好,微软为我们考虑了这层。开放了PsSetCreateProcessNotifyRoutine函数来实现进程线程的监控.
#include "ntddk.h"
#include "windef.h"
#include "define.h"
#define SYSNAME "System"
#define VERSIONLEN 100
const WCHAR devLink[] = L"\\DosDevices\\MyEvent";
const WCHAR devName[] = L"\\Device\\MyEvent";
UNICODE_STRING devNameUnicd;
UNICODE_STRING devLinkUnicd;
PVOID gpEventObject = NULL; // 与应用程序通信的 Event 对象
ULONG ProcessNameOffset = 0;
PVOID outBuf[255];
BOOL g_bMainThread;
ULONG g_dwParentId;
CHECKLIST CheckList;
ULONG BuildNumber; //系统版本号
ULONG SYSTEMID; //System进程的ID
PWCHAR Version[VERSIONLEN];
NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);
ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;
curproc = PsGetCurrentProcess();
for (i = 0; i < 3 * PAGE_SIZE; i++)
{
if (!strncmp(SYSNAME, (PCHAR)curproc + i, strlen(SYSNAME)))
{
return i;
}
}
return 0;
}
NTSTATUS GetRegValue(PCWSTR RegPath, PCWSTR ValueName, PWCHAR Value)
{
int ReturnValue = 0;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP;
ULONG valueInfoLength, returnLength;
UNICODE_STRING UnicodeRegPath;
UNICODE_STRING UnicodeValueName;
RtlInitUnicodeString(&UnicodeRegPath, RegPath);
RtlInitUnicodeString(&UnicodeValueName, ValueName);
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeRegPath,
OBJ_CASE_INSENSITIVE, // Flags
NULL, // Root directory
NULL); // Security descriptor
Status = ZwOpenKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (Status != STATUS_SUCCESS)
{
DbgPrint("ZwOpenKey Wrong\n");
return 0;
}
valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)+VERSIONLEN;
valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool
(NonPagedPool, valueInfoLength);
Status = ZwQueryValueKey(KeyHandle,
&UnicodeValueName,
KeyValuePartialInformation,
valueInfoP,
valueInfoLength,
&returnLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwQueryValueKey Wrong:%08x\n", Status);
return Status;
}
else
{
RtlCopyMemory((PCHAR)Value, (PCHAR)valueInfoP->Data, valueInfoP->DataLength);
ReturnValue = 1;
}
if (!valueInfoP);
ExFreePool(valueInfoP);
ZwClose(KeyHandle);
return ReturnValue;
}
VOID ThreadCreateMon(IN HANDLE PId, IN HANDLE TId, IN BOOLEAN bCreate)
{
PEPROCESS EProcess, PEProcess;
NTSTATUS status;
HANDLE dwParentPID;
status = PsLookupProcessByProcessId((ULONG)PId, &EProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return;
}
if (bCreate)
{
dwParentPID = PsGetCurrentProcessId();
status = PsLookupProcessByProcessId(
(ULONG)dwParentPID,
&PEProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return;
}
if (PId == 4) //System进程创建的东东我们不管
//在2000下是0,在XP后是4
return;
if ((g_bMainThread == TRUE)
&& (g_dwParentId != dwParentPID)
&& (dwParentPID != PId)
)
{
g_bMainThread = FALSE;
sprintf(outBuf, "=============================="
"Remote Thread :"
"=============================="
"\nT:%18s%9d%9d%25s%9d\n"
"======================================"
"======================================\n",
(char *)((char *)EProcess + ProcessNameOffset),
PId, TId,
(char *)((char *)PEProcess + ProcessNameOffset), dwParentPID);
if (gpEventObject != NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
if (CheckList.ONLYSHOWREMOTETHREAD) //只显示远线程
return;
DbgPrint("T:%18s%9d%9d%25s%9d\n",
(char *)((char *)EProcess + ProcessNameOffset),
PId, TId,
(char *)((char *)PEProcess + ProcessNameOffset), dwParentPID);
sprintf(outBuf, "T:%18s%9d%9d%25s%9d\n",
(char *)((char *)EProcess + ProcessNameOffset),
PId, TId,
(char *)((char *)PEProcess + ProcessNameOffset), dwParentPID);
if (gpEventObject != NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
else if (CheckList.SHOWTERMINATETHREAD)
{
DbgPrint("TERMINATED == THREAD ID: %d\n", TId);
sprintf(outBuf, "TERMINATED == THREAD ID: %d\n", TId);
if (gpEventObject != NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
}
VOID ProcessCreateMon(HANDLE hParentId, HANDLE PId, BOOLEAN bCreate)
{
PEPROCESS EProcess, PProcess;
NTSTATUS status;
HANDLE TId;
g_dwParentId = hParentId;
status = PsLookupProcessByProcessId((ULONG)PId, &EProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return;
}
status = PsLookupProcessByProcessId((ULONG)hParentId, &PProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return;
}
if (bCreate)
{
g_bMainThread = TRUE;
DbgPrint("P:%18s%9d%9d%25s%9d\n",
(char *)((char *)EProcess + ProcessNameOffset),
PId, PsGetCurrentThreadId(),
(char *)((char *)PProcess + ProcessNameOffset),
hParentId
);
sprintf(outBuf, "P:%18s%9d%9d%25s%9d\n",
(char *)((char *)EProcess + ProcessNameOffset),
PId, PsGetCurrentThreadId(),
(char *)((char *)PProcess + ProcessNameOffset),
hParentId
);
if (gpEventObject != NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
else if (CheckList.SHOWTERMINATEPROCESS)
{
DbgPrint("TERMINATED == PROCESS ID: %d\n", PId);
sprintf(outBuf, "TERMINATED == PROCESS ID: %d\n", PId);
if (gpEventObject != NULL)
KeSetEvent((PRKEVENT)gpEventObject, 0, FALSE);
}
}
NTSTATUS OnUnload(IN PDRIVER_OBJECT pDriverObject)
{
DbgPrint("OnUnload called\n");
return STATUS_SUCCESS;
}
NTSTATUS DeviceIoControlDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
PVOID inputBuffer;
ULONG inputLength;
PVOID outputBuffer;
ULONG outputLength;
OBJECT_HANDLE_INFORMATION objHandleInfo;
status = STATUS_SUCCESS;
// 取出IOCTL请求代码
irpStack = IoGetCurrentIrpStackLocation(pIrp);
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DbgPrint("Call IRP_MJ_CREATE\n");
break;
case IRP_MJ_CLOSE:
DbgPrint("Call IRP_MJ_CLOSE\n");
break;
case IRP_MJ_DEVICE_CONTROL:
DbgPrint("IRP_MJ_DEVICE_CONTROL\n");
inputLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_PASSEVENT: //用事件做通信
inputBuffer = pIrp->AssociatedIrp.SystemBuffer;
DbgPrint("inputBuffer:%08x\n", (HANDLE)inputBuffer);
status = ObReferenceObjectByHandle(*(HANDLE *)inputBuffer,
GENERIC_ALL,
NULL,
KernelMode,
&gpEventObject,
&objHandleInfo);
if (status != STATUS_SUCCESS)
{
DbgPrint("wrong\n");
break;
}
break;
case IOCTL_UNPASSEVENT:
if (gpEventObject)
ObDereferenceObject(gpEventObject);
DbgPrint("UNPASSEVENT called\n");
break;
case IOCTL_PASSBUF:
RtlCopyMemory(pIrp->UserBuffer, outBuf, outputLength);
break;
case IOCTL_PASSEVSTRUCT:
inputBuffer = pIrp->AssociatedIrp.SystemBuffer;
memset(&CheckList, 0, sizeof(CheckList));
RtlCopyMemory(&CheckList, inputBuffer, sizeof(CheckList));
DbgPrint("%d:%d\n", CheckList.ONLYSHOWREMOTETHREAD, CheckList.SHOWTHREAD);
break;
default:
break;
}
break;
default:
DbgPrint("Call IRP_MJ_UNKNOWN\n");
break;
}
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING theRegistryPath)
{
NTSTATUS Status;
PDEVICE_OBJECT pDevice;
DbgPrint("DriverEntry called!\n");
g_bMainThread = FALSE;
if (1 != GetRegValue(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CSDVersion", Version))
{
DbgPrint("GetRegValueDword Wrong\n");
}
PsGetVersion(NULL, NULL, &BuildNumber, NULL);
DbgPrint("[[[%d]]]:[[[%ws]]]", BuildNumber, Version);
RtlInitUnicodeString(&devNameUnicd, devName);
RtlInitUnicodeString(&devLinkUnicd, devLink);
Status = IoCreateDevice(pDriverObject,
0,
&devNameUnicd,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&pDevice);
if (!NT_SUCCESS(Status))
{
DbgPrint(("Can not create device.\n"));
return Status;
}
Status = IoCreateSymbolicLink(&devLinkUnicd, &devNameUnicd);
if (!NT_SUCCESS(Status))
{
DbgPrint(("Cannot create link.\n"));
return Status;
}
ProcessNameOffset = GetProcessNameOffset();
pDriverObject->DriverUnload = OnUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIoControlDispatch;//irp有27个派遣例程 具体参照相关的头文件
Status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("PsSetCreateProcessNotifyRoutine()\n");
return Status;
}
Status = PsSetCreateThreadNotifyRoutine(ThreadCreateMon);
if (!NT_SUCCESS(Status))
{
DbgPrint("PsSetCreateThreadNotifyRoutine()\n");
return Status;
}
return STATUS_SUCCESS;
}#include "stdio.h"
#define FILE_DEVICE_EVENT 0x8000
// Define Interface reference/dereference routines for
// Interfaces exported by IRP_MN_QUERY_INTERFACE
#define EVENT_IOCTL(index) \
CTL_CODE(FILE_DEVICE_EVENT, index, METHOD_BUFFERED, FILE_READ_DATA)
#define IOCTL_PASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSBUF \
CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_UNPASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSEVSTRUCT \
CTL_CODE(FILE_DEVICE_EVENT, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct
{
int SHOWTHREAD;
int ONLYSHOWREMOTETHREAD;
int SHOWTERMINATEPROCESS;
int SHOWTERMINATETHREAD;
}CHECKLIST, *PCHECKLIST;
win2003 部分头找不到
用这个
#include "stdio.h"
#define FILE_DEVICE_EVENT 0x8000
#define FILE_ANY_ACCESS 0
#define METHOD_BUFFERED 0
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
// Define Interface reference/dereference routines for
// Interfaces exported by IRP_MN_QUERY_INTERFACE
#define EVENT_IOCTL(index) \
CTL_CODE(FILE_DEVICE_EVENT, index, METHOD_BUFFERED, FILE_READ_DATA)
#define IOCTL_PASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSBUF \
CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_UNPASSEVENT \
CTL_CODE(FILE_DEVICE_EVENT, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PASSEVSTRUCT \
CTL_CODE(FILE_DEVICE_EVENT, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct
{
BOOL SHOWTHREAD;
BOOL ONLYSHOWREMOTETHREAD;
BOOL SHOWTERMINATEPROCESS;
BOOL SHOWTERMINATETHREAD;
}CHECKLIST, *PCHECKLIST;
可以参考0day安全