首页 电脑 电脑学堂 查看内容

编写进程/线程监视器

2004-9-29 20:05 644 0

摘要: (首先说明一下。有不少朋友来信问一些进程/线程监视工具是如何实现的。 我写出来是为了让那些朋友有进一步的了解,也省的我一封封的回MAIL。如果您 是 NT DRIVER熟手,那么此文提到的方法您可能早...
关键词: nbsp status 进程 函数 HANDLE DbgPrint NTSTATUS ULONG lpCurProc PROCESS

(首先说明一下。有不少朋友来信问一些进程/线程监视工具是如何实现的。 我写出来是为了让那些朋友有进一步的了解,也省的我一封封的回MAIL。如果您 是 NT DRIVER熟手,那么此文提到的方法您可能早已掌握,完全可以略过不看。)   有时候我们希望能够动态监视系统中任意进程/线程的创建与销毁。为了达 到此目的我翻阅了 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?ImageInfo ) {  ? DbgPrint("FullImageName: %S,Process ID: %d\n",FullImageName->Buffer,ProcessId);  ? DbgPrint("ImageBase: %x,ImageSize: %d\n",ImageInfo->ImageBase,ImageInfo->ImageSize);
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部