|
源代码网推荐
(首先说明一下。有不少朋友来信问一些进程/线程监视工具是如何实现的。 我写出来是为了让那些朋友有进一步的了解,也省的我一封封的回MAIL。如果您 是 NT DRIVER熟手,那么此文提到的方法您可能早已掌握,完全可以略过不看。)
有时候我们希望能够动态监视系统中任意进程/线程的创建与销毁。为了达 到此目的我翻阅了 DDK 手册,发现其提供的 PsSetCreateProcessNotifyRoutine(), PsSetCreateThreadNotifyRoutine(),等函数可以实现此功能。这两个函数可以 通过向系统注册一个 CALLBALCK 函数来监视进程/线程等操作。函数原形如下:
NTSTATUS PsSetCreateProcessNotifyRoutine( IN PCREATE_PROCESS_NOTIFY_ROUTINENotifyRoutine, IN BOOLEANRemove );
VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE) ( IN HANDLEParentId, IN HANDLEProcessId, IN BOOLEANCreate );
NTSTATUS PsSetCreateThreadNotifyRoutine( IN PCREATE_THREAD_NOTIFY_ROUTINENotifyRoutine );
VOID (*PCREATE_THREAD_NOTIFY_ROUTINE) ( IN HANDLEProcessId, IN HANDLEThreadId, IN BOOLEANCreate );
通过原形可以看出,其 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_ROUTINENotifyRoutine );
VOID (*PLOAD_IMAGE_NOTIFY_ROUTINE) ( IN PUNICODE_STRINGFullImageName, IN HANDLEProcessId, // where image is mapped IN PIMAGE_INFOImageInfo );
typedef struct_IMAGE_INFO { union { ULONGProperties; struct { ULONG ImageAddressingMode: 8; //code addressing mode ULONG SystemModeImage: 1; //system mode image ULONG ImageMappedToAllPids : 1; //mapped in all processes ULONG Reserved : 22; }; }; PVOIDImageBase; ULONGImageSelector; ULONGImageSize; ULONGImageSectionNumber; } IMAGE_INFO, *PIMAGE_INFO;
利用以上提供的函数与结构,我们便能实现一个进程/线程监视器。下面这段 代码演示了如何实现此功能。
/***************************************************************** 文件名: WssProcMon.c 描述: 进程/线程监视器 作者: sinister 最后修改日期: 2002-11-02
*****************************************************************/
#include "ntddk.h" #include "string.h"
#define ProcessNameOffset0x1fc
static NTSTATUSMydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess); VOID ProcessCreateMon ( IN HANDLEhParentId, IN HANDLE PId,IN BOOLEAN bCreate); VOID ThreadCreateMon (IN HANDLEPId, IN HANDLE TId, IN BOOLEANbCreate); VOID ImageCreateMon (IN PUNICODE_STRINGFullImageName, IN HANDLEProcessId, IN PIMAGE_INFOImageInfo );
// 驱动入口 NTSTATUSDriverEntry( IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath ) { UNICODE_STRINGnameString, linkString; PDEVICE_OBJECTdeviceObject; NTSTATUSstatus; inti;
//建立设备 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()
"); return status; }
status = PsSetCreateThreadNotifyRoutine(ThreadCreateMon); if (!NT_SUCCESS( status )) { DbgPrint("PsSetCreateThreadNotifyRoutine()
"); return status; }
status = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE); if (!NT_SUCCESS( status )) { DbgPrint("PsSetCreateProcessNotifyRoutine()
"); 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 ) {
PEPROCESSEProcess; ULONGulCurrentProcessId; LPTSTR lpCurProc; NTSTATUS status;
status = PsLookupProcessByProcessId( (ULONG)PId, &EProcess); if (!NT_SUCCESS( status )) { DbgPrint("PsLookupProcessByProcessId()
"); return ; }
if ( bCreate ) { lpCurProc = (LPTSTR)EProcess; lpCurProc = lpCurProc + ProcessNameOffset;
DbgPrint( "CREATE PROCESS = PROCESS NAME: %s , PROCESS PARENTID: %d, PROCESS ID: %d, PROCESS ADDRESS %x:
", lpCurProc, hParentId, PId, EProcess ); } else {
DbgPrint( "TERMINATED == PROCESS ID: %d
", PId);
}
}
VOID ThreadCreateMon (IN HANDLE PId, IN HANDLE TId, IN BOOLEANbCreate) {
PEPROCESS EProcess; ULONGulCurrentProcessId; LPTSTRlpCurProc; NTSTATUSstatus;
status = PsLookupProcessByProcessId( (ULONG)PId, &EProcess); if (!NT_SUCCESS( status )) { DbgPrint("PsLookupProcessByProcessId()
"); return ; }
if ( bCreate ) { lpCurProc= (LPTSTR)EProcess; lpCurProc= lpCurProc + ProcessNameOffset;
DbgPrint( "CREATE THREAD = PROCESS NAME: %s PROCESS ID: %d, THREAD ID: %d
", lpCurProc, PId, TId ); } else {
DbgPrint( "TERMINATED == THREAD ID: %d
", TId);
}
}
VOID ImageCreateMon (IN PUNICODE_STRINGFullImageName, IN HANDLEProcessId, IN PIMAGE_INFOImageInfo ) { DbgPrint("FullImageName: %S,Process ID: %d
",FullImageName->Buffer,ProcessId); DbgPrint("ImageBase: %x,ImageSize: %d
",ImageInfo->ImageBase,ImageInfo->ImageSize);
源代码网整理以下 |