来源:远方网络 | 2005-5-22 9:16:03 | (有3113人读过)
*有时候我们希望能够动态监视系统中任意进程/线程的创建与销毁。为了达
到此目的我翻阅了 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 "windef.h" #include "string.h" #define SYSNAME "System" //#define ProcessNameOffset 0x1fc
ULONG GetProcessNameOffset(); VOID Unload(IN PDRIVER_OBJECT DriverObject); 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 );
// 驱动入口 ULONG ProcessNameOffset =0; 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;
} ProcessNameOffset = GetProcessNameOffset(); /*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; } DriverObject->DriverUnload = Unload; return STATUS_SUCCESS; }
VOID Unload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING linkString; PsRemoveCreateThreadNotifyRoutine(ThreadCreateMon); PsSetCreateProcessNotifyRoutine(ProcessCreateMon, TRUE); RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssProcMon" ); IoDeleteSymbolicLink( &linkString ); IoDeleteDevice( DriverObject->DeviceObject ); }
//处理设备对象操作
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; }
HANDLE g_dwProcessId; BOOL g_bMainThread; VOID ProcessCreateMon ( IN HANDLE hParentId, IN HANDLE PId,IN BOOLEAN bCreate ) { PEPROCESS EProcess; ULONG ulCurrentProcessId; LPTSTR lpCurProc; NTSTATUS status; #ifdef _AMD64_ ULONG ProcessId = HandleToUlong(PId); status = PsLookupProcessByProcessId( ProcessId, &EProcess); #else HANDLE ProcessId =PId; status = PsLookupProcessByProcessId( (ULONG)PId, &EProcess); #endif
if (!NT_SUCCESS( status )) { DbgPrint("PsLookupProcessByProcessId()\n"); return ; }
if ( bCreate ) { //g_dwProcessId = ProcessId; g_bMainThread = TRUE; 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,ParentEProcess; LPTSTR lpCurProc,lpParnentProc; NTSTATUS status; #ifdef _AMD64_ ULONG System=4; ULONG dwParentPID=HandleToUlong(PsGetCurrentProcessId());//创建该线程的进程 ULONG ProcessId = HandleToUlong(PId); status = PsLookupProcessByProcessId( ProcessId, &EProcess); status = PsLookupProcessByProcessId( dwParentPID, &ParentEProcess); #else HANDLE System=(HANDLE)4;//under xp, in win2k is 8 HANDLE dwParentPID=PsGetCurrentProcessId();//创建该线程的进程 HANDLE ProcessId =PId;//ProcessId 是进程号,这里的进程号是指向包括该线程的进程,而不是创建该线程的进程 status = PsLookupProcessByProcessId( (ULONG)ProcessId, &EProcess); status = PsLookupProcessByProcessId( (ULONG)dwParentPID, &ParentEProcess); #endif
if (!NT_SUCCESS( status )) { DbgPrint("PsLookupProcessByProcessId()\n"); return ; }
if ( bCreate ) { if((g_bMainThread==TRUE)&&(ProcessId!=System)&&(ProcessId!=dwParentPID)) { HANDLE dwParentTID=PsGetCurrentThreadId(); lpCurProc = (LPTSTR)EProcess; lpParnentProc= (LPTSTR)ParentEProcess; lpCurProc += ProcessNameOffset; lpParnentProc +=ProcessNameOffset; DbgPrint("caller: Name=%s PID=%d TID=%d\t\tcalled: Name=%s PID=%d TID=%d\n", \ lpParnentProc, dwParentPID, dwParentTID, lpCurProc, ProcessId, TId); g_bMainThread=FALSE; } 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); //}
ULONG GetProcessNameOffset() { PEPROCESS curproc; int i;
curproc = PsGetCurrentProcess();
// // Scan for 12KB, hopping the KPEB never grows that big! // for( i = 0; i < 3*PAGE_SIZE; i++ ) {
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {
return i; } }
// // Name not found - oh, well // return 0; }
根据你的改为C代码,并支持WINXP -64.......
|