当前位置:首页 > 服务器类 > 安全防护 > > 编写进程/线程监视器

编写进程/线程监视器

点击次数:36 次 发布日期:2008-11-29 17:35:35 作者:源代码网


源代码网供稿.

源代码网推荐

(首先说明一下。有不少朋友来信问一些进程/线程监视工具是如何实现的。
我写出来是为了让那些朋友有进一步的了解,也省的我一封封的回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() ");
  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 )
{

  PEPROCESSEProcess;
  ULONGulCurrentProcessId;
  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 BOOLEANbCreate)
{

  PEPROCESS EProcess;
  ULONGulCurrentProcessId;
  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 THREAD = PROCESS NAME: %s PROCESS ID: %d, THREAD ID: %d ", lpCurProc, PId, TId );
 
  }
 
  else
  {

  DbgPrint( "TERMINATED == THREAD ID: %d ", TId);

  }

}

VOID ImageCreateMon (IN PUNICODE_STRINGFullImageName, IN HANDLEProcessId, IN PIMAGE_INFOImageInfo )
{
  DbgPrint("FullImageName: %S,Process ID: %d ",FullImageName->Buffer,ProcessId);
  DbgPrint("ImageBase: %x,ImageSize: %d ",ImageInfo->ImageBase,ImageInfo->ImageSize);

源代码网整理以下

网友评论 (0)
会员中心
服务器类
本站推荐
服务器类之精华