函数原型:

  1. NTSTATUS PsSetCreateProcessNotifyRoutine(
  2. _In_ PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
  3. _In_ BOOLEAN                        Remove
  4. );
    原文的解释为:The PsSetCreateProcessNotifyRoutine routine adds a driver-supplied callback routine to, or removes it from, a list of
  5. routines to be called whenever a process is created or deleted.
    简单的翻译一下:PsSetCreateProcessNotifyRoutine 例程增加一个"驱动供应"回调例程,在进程创建或消亡的时候回调函数会被调用。
    NotifyRoutine为回调指针:
    定义为:
    VOID
  6. (*PCREATE_PROCESS_NOTIFY_ROUTINE) (
  7. IN HANDLE ParentId,
  8. IN HANDLE ProcessId,
  9. IN BOOLEAN Create
  10. );
NotifyRoutine [in]

Specifies the entry point of a caller-supplied process-creation callback routine.

Remove [in]

Indicates whether the routine specified by NotifyRoutine should be added to or removed from the system's list of notification routines. If FALSE, the specified routine is added to the list. If TRUE, the specified routine is removed from the list.

如果为FALSE 表示在系统通知例程列表中增加此例程,如果为TRUE标志从系统通知例程列表中删除该例程,
驱动卸载时应该时此参数应该为TRUE;
  1. 废话不说了直接上代码框架:
  2.  
  3. #include <ntddk.h>
  4.  
  5. VOID UnloadDriver(PDRIVER_OBJECT pDriver);
  6.  
  7. VOID
  8. CreateProcessRoutineSpy(
  9. IN HANDLE ParentId,
  10. IN HANDLE ProcessId,
  11. IN BOOLEAN Create
  12. );
  13.  
  14. NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING Registry)
  15. {
  16. NTSTATUS status = STATUS_SUCCESS;
  17.  
  18. UNREFERENCED_PARAMETER(pDriver);
  19. UNREFERENCED_PARAMETER(Registry);
  20. KdPrint(("[SysTest] DriverEntry Loading.\n"));
  21.  
  22. status = PsSetCreateProcessNotifyRoutine(CreateProcessRoutineSpy, FALSE);
  23. if (!NT_SUCCESS(status))
  24. {
  25. KdPrint(("[SysTest] PsSetCreateProcessNotifyRoutine failed status:(%x).\n", status));
  26. return status;
  27. }
  28.  
  29. pDriver->DriverUnload = UnloadDriver;
  30. return status;
  31. }
  32.  
  33. VOID
  34. CreateProcessRoutineSpy(
  35. IN HANDLE ParentId,
  36. IN HANDLE ProcessId,
  37. IN BOOLEAN Create
  38. )
  39. {
  40. if (Create)
  41. {
  42. KdPrint(("[SysTest] Process Created. ParentId:(%d) ProcessId:(%d).\n", ParentId, ProcessId));
  43. }
  44. else
  45. {
  46. KdPrint(("[SysTest] Process Terminated ProcessId:(%d).ParentId:(%d) .\n", ProcessId, ParentId));
  47. }
  48.  
  49. return;
  50. }
  51.  
  52. VOID UnloadDriver(PDRIVER_OBJECT pDriver)
  53. {
  54. UNREFERENCED_PARAMETER(pDriver);
  55.  
  56. NTSTATUS status;
  57.  
  58. status = PsSetCreateProcessNotifyRoutine(CreateProcessRoutineSpy, TRUE);
  59. if (NT_SUCCESS(status))
  60. {
  61. KdPrint(("[SysTest] UnloadDriver.\n"));
  62. }
  63.  
  64. return;
  65. }

Dbgview查看结果:

可以看到每当有一个进程创建的时候就会被回调函数监视到,在这里我们打印出进程的ID和父进程的ID,每当一个进程消亡时也将其ID打印出来。这个简单的进程监视框架就做好了。

  1. 扩展 CreateProcessNotifyEx
    PsSetCreateProcessNotifyRoutine只能记录进程创建或消亡,不能阻止进程的创建,
    PsSetCreateProcessNotifyRoutineEx可以阻止进程的创建,先看一下相关函数:
  2.  
  3. 注册函数:
    NTSTATUS PsSetCreateProcessNotifyRoutineEx(
  4. _In_ PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine,
  5. _In_ BOOLEAN  Remove
  6. );
  7.  
  8. 回调函数:
    VOID
      CreateProcessNotifyEx(
        __inout PEPROCESS  Process,
        __in HANDLE  ProcessId,
        __in_opt PPS_CREATE_NOTIFY_INFO  CreateInfo
        );

可知,回调函数有所变化,在回调函数中,CreateInfo为NULL时,表示一个进程在结束,否则为进程创建,看一下CreateInfo结构:

typedef struct _PS_CREATE_NOTIFY_INFO {
    _In_ SIZE_T Size;
    union {
        _In_ ULONG Flags;
        struct {
            _In_ ULONG FileOpenNameAvailable : 1;
            _In_ ULONG Reserved : 31;
        };
    };
    _In_ HANDLE ParentProcessId;      //父进程ID
    _In_ CLIENT_ID CreatingThreadId;   //父进程信息  ,包括父进程ID,父进程的主线程ID
    _Inout_ struct _FILE_OBJECT *FileObject;    //进程有关的文件对象
    _In_ PCUNICODE_STRING ImageFileName;   //进程名
    _In_opt_ PCUNICODE_STRING CommandLine; //进程命令行参数,有时候为NULL
    _Inout_ NTSTATUS CreationStatus;//返回结果,修改这个结果可以改变进程的创建
} PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO;

现在举一例,利用此回调来阻止记事本的创建:

  1. #include <ntddk.h>
  2.  
  3. VOID UnloadDriver(PDRIVER_OBJECT driver);
  4.  
  5. VOID
  6. CreateProcessNotifyEx(
  7. __inout PEPROCESS Process,
  8. __in HANDLE ProcessId,
  9. __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
  10. );
  11.  
  12. BOOLEAN bSuccess = FALSE;
  13.  
  14. NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING registry)
  15. {
  16. NTSTATUS status = STATUS_UNSUCCESSFUL;
  17.  
  18. UNREFERENCED_PARAMETER(registry);
  19.  
  20. KdPrint(("[systest] Driver Loading.\n"));
  21.  
  22. driver->DriverUnload = UnloadDriver;
  23.  
  24. status = PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx, FALSE);
  25. if (!NT_SUCCESS(status))
  26. {
  27. KdPrint(("[systest] PsSetCreateProcessNotifyRoutineEx error code:(%x).\n", status));
  28. return status;
  29. }
  30.  
  31. bSuccess = TRUE;
  32.  
  33. return status;
  34.  
  35. }
  36.  
  37. VOID
  38. CreateProcessNotifyEx(
  39. __inout PEPROCESS Process,
  40. __in HANDLE ProcessId,
  41. __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
  42. )
  43. {
  44. UNREFERENCED_PARAMETER(ProcessId);
  45. UNREFERENCED_PARAMETER(Process);
  46.  
  47. PWCHAR pSub = NULL;
  48. //为NULL表示进程退出
  49. if (NULL == CreateInfo)
  50. {
  51. DbgPrint(("[systest]:process exits.\n"));
  52. return;
  53. }
  54.  
  55. KdPrint(("[systest]process create:(%wZ).\n", CreateInfo->ImageFileName));
  56. pSub = wcswcs(CreateInfo->ImageFileName->Buffer, L"notepad.exe");
  57. if (NULL != pSub)
  58. {
  59. //修改返回结果为拒绝访问,使得创建进程失败
  60. CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
  61. }
  62.  
  63. return;
  64. }
  65.  
  66. VOID UnloadDriver(PDRIVER_OBJECT driver)
  67. {
  68. UNREFERENCED_PARAMETER(driver);
  69.  
  70. KdPrint(("[systest]:driver unload.\n"));
  71.  
  72. if (bSuccess)
  73. {
  74. PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx, TRUE);
  75. }
  76.  
  77. return;
  78. }

需要注意的是,PsSetCreateProcessNotifyRoutineEx编译的时候可能会出现拒绝访问,解决办法是在工程属性中的连接器-->CommandLine,添加“/IntegrityCheck ”即可。

进程监控驱动 PsSetCreateProcessNotifyRoutine的更多相关文章

  1. 【SFTP】使用Jsch实现Sftp文件下载-支持断点续传和进程监控

    参考上篇文章: <[SFTP]使用Jsch实现Sftp文件下载-支持断点续传和进程监控>:http://www.cnblogs.com/ssslinppp/p/6248763.html  ...

  2. linux 进程监控

    linux 进程监控 supervise Supervise是daemontools的一个工具,可以用来监控管理unix下的应用程序运行情况,在应用程序出现异常时,supervise可以重新启动指定程 ...

  3. linux 进程监控和自动重启的简单实现

    目的:linux 下服务器程序会因为各种原因dump掉,就会影响用户使用,这里提供一个简单的进程监控和重启功能. 实现原理:由定时任务crontab调用脚本,脚本用ps检查进程是否存在,如果不存在则重 ...

  4. linux 进程监控和自动重启的简单实现(转)

    目的:linux 下服务器程序会因为各种原因dump掉,就会影响用户使用,这里提供一个简单的进程监控和重启功能. 实现原理:由定时任务crontab调用脚本,脚本用ps检查进程是否存在,如果不存在则重 ...

  5. Prometheus — Process-exporter进程监控

    由于我们常用的node_exporter并不能覆盖所有监控项,这里我们使用Process-exporter 对进程进行监控. 安装process-exporter wget https://githu ...

  6. linux驱动编写之进程独占驱动

    一.描述 嵌入式开发系统中,有各种硬件资源,而有些硬件资源使用时候是需要进程独占的.也就是说,同一时刻只有一个进程允许使用这个硬件资源,其他的进程只能放弃执行或者挂起等待.在设计其对应驱动的时候,就需 ...

  7. Zabbix4.0添加端口和进程监控

    一:Zabbix设置主动模式: vim /etc/zabbix/zabbix_agent.conf Server=192.168.1.10 #被动模式的serverip地址,如果设置纯被动模式,可以注 ...

  8. 【321】python进程监控:psutil

    参考:Python进程监控-MyProcMonitor 参考:Python3.6 安装psutil 模块和功能简介 参考:psutil module (Download files) 参考:廖雪峰 - ...

  9. Windows下tomcat进程监控批处理程序

    在Windows下tomcat进程监控批处理程序脚本如下: @echo off ::tomcat安装目录 set _tomcatDir=E:\myFiles\apache-tomcat-8.5.31 ...

随机推荐

  1. sqlserver 获取实例上用户数据库的数据字典

    原理很简单:将获取数据字典信息(通过动态视图获取)存入到目标表(数据字典表)中即可. 本人自用实例 1)创建相关的字典表 use YWMonitor GO SET ANSI_NULLS ON GO S ...

  2. (转)python之函数介绍及使用

    为什么要用函数? 1.减少代码量 2.保持一致性 3.易维护 一.函数的定义和使用 ? 1 2 3 4 5 6 def test(参数):              ...     函数体     . ...

  3. scanf 与getchar区别

    #include<stdio.h> void main() {    int c; c=getchar(); //scanf("%c",&c); if(c!=' ...

  4. canvas前端压缩图片和视频首屏缩略图并上传到服务器

    图片: var img = document.createElement('img') img.src = window.URL.createObjectURL(fileObj.file) // 加载 ...

  5. 协方差及matlib绘制

    转自http://www.cnblogs.com/chaosimple/p/3182157.html 一.统计学的基本概念 统计学里最基本的概念就是样本的均值.方差.标准差.首先,我们给定一个含有n个 ...

  6. NEERC 1999 Advertisement /// oj22646

    题目大意: 输入k,n :k为每位慢跑者最少应看到的广告牌数 接下来n行 描述第 i 位慢跑者的途径路段 输出需要设立的广告牌数 接下来每行为设立地点 Sample Input 5 101 1020 ...

  7. 我也可以独立(引用JS外部文件)

    我也可以独立(引用JS外部文件) 通过前面知识学习,我们知道使用<script>标签在HTML文件中添加JavaScript代码,如图: JavaScript代码只能写在HTML文件中吗? ...

  8. C# 调用java的Webservice时关于非string类型处理

    比如webservice地址是:http://wdft.com:80/services/getOrderService1.0?wsdl 方法是:getOrder 1.首先添加引用: 2. 3.引用完成 ...

  9. redis config

    网络上抄袭过来的 然后顺序自己做点笔记 http://chembo.iteye.com/blog/2054021 这里有各个key 详细的描述 # redis 配置文件示例 # 当你需要为某个配置项指 ...

  10. 【JZOJ2867】Contra

    description 偶然间,chnlich 发现了他小时候玩过的一个游戏"魂斗罗",于是决定怀旧.但是这是一个奇怪的魂斗罗 MOD. 有 N 个关卡,初始有 Q 条命. 每通过 ...