网页功能: 加入收藏 设为首页 网站搜索  
编写进程/线程监视器
发表日期:2003-10-14作者:[] 出处:  

原始文档:http://www.xfocus.net/articles/200303/495.html

创建时间:2003-03-21

浏览次数:74

原创:sinister (jiasys_at_21cn.com)

来源:http://www.whitecell.org

编写进程/线程监视器

Author : sinister

Email  : sinister@whitecell.org

HomePage: http://www.whitecell.org

(首先说明一下。有不少朋友来信问一些进程/线程监视工具是如何实现的。

我写出来是为了让那些朋友有进一步的了解,也省的我一封封的回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);

}

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 编写进程/线程监视器
本类热点文章
  利用鼠标键盘钩子截获密码
  利用鼠标键盘钩子截获密码
  如何将多个文件捆绑成一个可执行文件
  如何将多个文件捆绑成一个可执行文件
  内核级HOOK的几种实现与应用
  内核级HOOK的几种实现与应用
  书写基于内核的linux键盘纪录器
  书写基于内核的linux键盘纪录器
  CIH病毒原码
  CIH病毒原码
  编写进程/线程监视器
  编写进程/线程监视器
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2019 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00528