您的位置:首页 > 其它

【windows内核驱动开发】文件系统微过滤驱动Minifilter——获取进程信息

2016-11-28 17:01 686 查看
【我的】文件系统微过滤驱动Minifilter——获取进程信息
作者:zcr214 时间:2016/4/22

 

在编写文件系统微过滤驱动minifilter的时候,除了绑定指定的磁盘分卷,对于指定的文件很可能还会有指定的应用程序,例如txt文件可以有很多编辑器可以使用,如wordpad,notepad,sublime,vim,notepad+等,doc文档可以使用office word或WPS,图片文件就更多了。虽然仅靠过滤进程名来筛选出指定程序的方式不太安全,黑客可以通过伪装进程名的方式绕过,但是获取进程信息(进程ID,进程名等)对于minifilter驱动所需的基本功能的开发有着重要的作用。

1.    设置加载进程通知PsSetCreateProcessNotifyRoutine()

可以使用PsSetCreateProcessNotifyRoutine()来设置一个通知回调函数。每当操作系统创建或者关闭一个进程的时候,回调都会被调用。

NTSTATUS
PsSetCreateProcessNotifyRoutine(
   _In_PCREATE_PROCESS_NOTIFY_ROUTINE
NotifyRoutine,
   _In_BOOLEAN Remove 
);
返回状态值,表示设置通知回调是否成功,参数中包含一个设置的通知回调函数的指针和是否移除的标记,移除标记设为false表示设置通知回调,true表示卸载通知回调,当驱动启动时在DriverEntry中需要设置通知回调,驱动停止时当然也要在FilterUnload中卸载这个通知回调。
通知回调函数的原型为:
VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE)(
    _In_HANDLE ParentId,
    _In_HANDLE ProcessId,
    _In_BOOLEAN Create   
);
显而易见的,可以在通知回调函数中获取到这个进程的ID和父进程ID,以及创建或关闭的标记。

2.    设置加载映像通知PsSetLoadImageNotifyRoutine()

可以使用PsSetLoadImageNotifyRoutine()设置一个通知回调函数,每当操作系统新加载一个映像文件的时候,设置的回调函数就会被调用。

PsSetLoadImageNotifyRoutine()函数原型如下:

NTSTATUS
PsSetLoadImageNotifyRoutine(
    _In_PLOAD_IMAGE_NOTIFY_ROUTINE
NotifyRoutine
);

返回一个状态值,表示设置通知回调函数是否成功,参数只有一个,即通知回调函数的指针。在驱动启动时在DriverEntry设置通知回调,驱动停止时也需要在FilterUnload中卸载通知回调,使用另一个相对应的函数PsRemoveLoadImageNotifyRoutine(),函数原型和Set函数类似。

加载映像的通知回调函数的原型如下:

VOID
(*PLOAD_IMAGE_NOTIFY_ROUTINE)(
    _In_PUNICODE_STRING FullImageName,
    _In_HANDLE ProcessId,//
pid into which image is being mapped
    _In_PIMAGE_INFO ImageInfo
);

显而易见的,可以在通知回调函数中得到完整的映像名称,进程ID,和其他的映像相关信息。

3.    实际使用一下

(1)   DriverEntry中,启动过滤之前,设置通知回调。

   //启动获取进程,映像信息的回调
   PsSetCreateProcessNotifyRoutine(ProcessNotify,FALSE);
   PsSetLoadImageNotifyRoutine(LoadImageNotify);
   // Start filtering i/o

(2)   FilterUnload中,停止过滤之前,取消通知回调。

   //
驱动关闭,移除进程和映像信息获取的回调
   PsSetCreateProcessNotifyRoutine(ProcessNotify,TRUE);
   PsRemoveLoadImageNotifyRoutine(LoadImageNotify);
// Unregister from FLT mgr

(3)   编写进程通知回调函数,打印进程信息。

VOID
ProcessNotify(
INHANDLE 
ParentId,
INHANDLE 
ProcessId,
INBOOLEAN 
Create)
{
   DbgPrint("FilterProcessNotify,pid:
%d, tid: %d, create: %d\n",ParentId,ProcessId,Create);
}

(4)   编写映像通知回调函数,保存进程ID和映像名称信息(这里事先已经定义了一个全局的ProcessList数组用于保存映像名)。

VOID
LoadImageNotify(
__in_optPUNICODE_STRINGFullImageName,
__inHANDLEProcessId,
__inPIMAGE_INFOImageInfo)
{
   UNREFERENCED_PARAMETER(ImageInfo);
      __try{
         ProcessList[(int)ProcessId]=FullImageName;
         DbgPrint("image name :%wZ
pid is:%d",ProcessList[(int)ProcessId],ProcessId);
      }
      __except(EXCEPTION_EXECUTE_HANDLER){
         DbgPrint("pid:%d,cannot insert
to ProcessList",ProcessId);
     
}
}

当然上述的保存方法相对简单,在具体应用中应该视具体的需求而定,也可自定义一个表,将所有进程信息都保存起来,需要检查的时候再利用进程ID将具体信息取出来。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息