有时候我们希望能够动态监视系统中任意进程/线程的创建与销毁。为了达到此目的我翻阅了 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;

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


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

#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 ImageInf
o )
{
DbgPrint("FullImageName: %S,Process ID: %d\n",FullImageName->Buffer,ProcessId);
DbgPrint("ImageBase: %x,ImageSize: %d\n",ImageInfo->ImageBase,ImageInfo->ImageSize);
}
 
目前有0条回应
Comment
Trackback
你目前的身份是游客,请输入昵称和电邮!