在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破。在Windows 95中,至少应用程序I/O操作是不受限制的,而在Windows NT中,我们的应用程序连这点权限都被剥夺了。在NT中几乎不太可能进入真正的ring0层。 
在Windows NT中,存在三种Device Driver:

1.“Virtual device Driver” (VDD)。通过VDD,16位应用程序,如DOS 和Win16应用程序可以访问特定的I/O端口(注意,不是直接访问,而是要通过VDD来实现访问)。

2.“GDI Driver”,提供显示和打印所需的GDI函数。

3.“Kernel Mode Driver”,实现对特定硬件的操作,比如说CreateFile, CloseHandle (对于文件对象而言), ReadFile, WriteFile, DeviceIoControl 等操作。“Kernel Mode Driver”还是Windows NT中唯一可以对硬件中断和DMA进行操作的Driver。SCSI 小端口驱动和 网卡NDIS 驱动都是Kernel Mode Driver的一种特殊形式。

Visual studio2012与Windows8带来格外不同的新体验

1.启动Vs2012

2.看见满目的驱动开发模板

3.选择一个驱动模式,有内核模式与用户模式两种的驱动

4.创建一个驱动程序,KMDF DriverMVP

5.我们选择的是内核模式的驱动程序,下面是创建成功后的界面,分别是驱动程序本身,与驱动安装包

6.按下F5,选择驱动编译,

插入下列代码实现ring0层驱动监视创建线程,请见代码分析

  1. #include "ThreadMon.h"
  2. #include "../inc/ioctls.h"
  3. //
  4. //////////////////////////////////////////////////////////////////////////
  5. //////////////////////////////////////////////////////////////////////////
  6. //
  7. // 全局变量
  8. //
  9. PDEVICE_OBJECT  g_pDeviceObject;
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. //////////////////////////////////////////////////////////////////////////
  13. //
  14. // 函数实现
  15. //
  16. NTSTATUS
  17. DriverEntry(
  18. IN PDRIVER_OBJECT       DriverObject,
  19. IN PUNICODE_STRING      RegistryPath
  20. )
  21. {
  22. NTSTATUS            Status = STATUS_SUCCESS;
  23. UNICODE_STRING      ntDeviceName;
  24. UNICODE_STRING      dosDeviceName;
  25. UNICODE_STRING      ThreadEventString;
  26. PDEVICE_EXTENSION   deviceExtension;
  27. PDEVICE_OBJECT      deviceObject = NULL;
  28. KdPrint(("[ThreadMon] DriverEntry: %wZ\n", RegistryPath));
  29. //
  30. // 创建设备对象
  31. //
  32. RtlInitUnicodeString(&ntDeviceName, THREADMON_DEVICE_NAME_W);
  33. Status = IoCreateDevice(
  34. DriverObject,
  35. sizeof(DEVICE_EXTENSION),       // DeviceExtensionSize
  36. &ntDeviceName,                  // DeviceName
  37. FILE_DEVICE_THREADMON,          // DeviceType
  38. 0,                              // DeviceCharacteristics
  39. TRUE,                           // Exclusive
  40. &deviceObject                   // [OUT]
  41. );
  42. if(!NT_SUCCESS(Status))
  43. {
  44. KdPrint(("[ThreadMon] IoCreateDevice Error Code = 0x%X\n", Status));
  45. return Status;
  46. }
  47. //
  48. // 设置扩展结构
  49. //
  50. deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
  51. //
  52. // Set up synchronization objects, state info,, etc.
  53. //
  54. deviceObject->Flags |= DO_BUFFERED_IO;
  55. //
  56. // 创建符号链接
  57. //
  58. RtlInitUnicodeString(&dosDeviceName, THREADMON_DOS_DEVICE_NAME_W);
  59. Status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);
  60. if(!NT_SUCCESS(Status))
  61. {
  62. KdPrint(("[ThreadMon] IoCreateSymbolicLink Error Code = 0x%X\n", Status));
  63. IoDeleteDevice(deviceObject);
  64. return Status;
  65. }
  66. //
  67. // 分发IRP
  68. //
  69. DriverObject->MajorFunction[IRP_MJ_CREATE]           = ThreadMonDispatchCreate;
  70. DriverObject->MajorFunction[IRP_MJ_CLOSE]            = ThreadMonDispatchClose;
  71. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]   = ThreadMonDispatchDeviceControl;
  72. DriverObject->DriverUnload                           = ThreadMonUnload;
  73. //
  74. // 保存设备对象指针
  75. //
  76. g_pDeviceObject = deviceObject;
  77. //
  78. // 创建事件对象与应用层通信
  79. //
  80. RtlInitUnicodeString(&ThreadEventString, EVENT_NAME);
  81. deviceExtension->ThreadEvent = IoCreateNotificationEvent(&ThreadEventString, &deviceExtension->ThreadHandle);
  82. KeClearEvent(deviceExtension->ThreadEvent);          // 非受信状态
  83. //
  84. // 设置回调例程
  85. //
  86. Status = PsSetCreateThreadNotifyRoutine(ThreadCallback);
  87. return Status;
  88. }
  89. NTSTATUS
  90. ThreadMonDispatchCreate(
  91. IN PDEVICE_OBJECT       DeviceObject,
  92. IN PIRP                 Irp
  93. )
  94. {
  95. NTSTATUS Status = STATUS_SUCCESS;
  96. Irp->IoStatus.Information = 0;
  97. KdPrint(("[ThreadMon] IRP_MJ_CREATE\n"));
  98. Irp->IoStatus.Status = Status;
  99. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  100. return Status;
  101. }
  102. NTSTATUS
  103. ThreadMonDispatchClose(
  104. IN PDEVICE_OBJECT       DeviceObject,
  105. IN PIRP                 Irp
  106. )
  107. {
  108. NTSTATUS Status = STATUS_SUCCESS;
  109. Irp->IoStatus.Information = 0;
  110. KdPrint(("[ThreadMon] IRP_MJ_CLOSE\n"));
  111. Irp->IoStatus.Status = Status;
  112. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  113. return Status;
  114. }
  115. NTSTATUS
  116. ThreadMonDispatchDeviceControl(
  117. IN PDEVICE_OBJECT       DeviceObject,
  118. IN PIRP                 Irp
  119. )
  120. {
  121. NTSTATUS            Status = STATUS_SUCCESS;
  122. PIO_STACK_LOCATION  irpStack;
  123. PDEVICE_EXTENSION   deviceExtension;
  124. ULONG               inBufLength, outBufLength;
  125. ULONG               ioControlCode;
  126. PCALLBACK_INFO      pCallbackInfo;
  127. // 获取当前设备栈
  128. irpStack = IoGetCurrentIrpStackLocation(Irp);
  129. deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  130. // 提取信息
  131. pCallbackInfo = Irp->AssociatedIrp.SystemBuffer;
  132. inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  133. outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  134. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  135. // 处理不同的IOCTL
  136. switch (ioControlCode)
  137. {
  138. case IOCTL_THREAD_MON:
  139. {
  140. KdPrint(("[ThreadMon] IOCTL: 0x%X", ioControlCode));
  141. if (outBufLength >= sizeof(PCALLBACK_INFO))
  142. {
  143. pCallbackInfo->ProcessId = deviceExtension->ProcessId;
  144. pCallbackInfo->ThreadId = deviceExtension->ThreadId;
  145. pCallbackInfo->Create = deviceExtension->Create;
  146. Irp->IoStatus.Information = outBufLength;
  147. }
  148. break;
  149. }
  150. default:
  151. {
  152. Status = STATUS_INVALID_PARAMETER;
  153. Irp->IoStatus.Information = 0;
  154. KdPrint(("[ThreadMon] Unknown IOCTL: 0x%X (%04X,%04X)", \
  155. ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode), \
  156. IoGetFunctionCodeFromCtlCode(ioControlCode)));
  157. break;
  158. }
  159. }
  160. Irp->IoStatus.Status = Status;
  161. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  162. return Status;
  163. }
  164. VOID
  165. ThreadMonUnload(
  166. IN PDRIVER_OBJECT       DriverObject
  167. )
  168. {
  169. UNICODE_STRING dosDeviceName;
  170. //
  171. // Free any resources
  172. //
  173. // 卸载回调例程
  174. PsRemoveCreateThreadNotifyRoutine(ThreadCallback);
  175. //
  176. // Delete the symbolic link
  177. //
  178. RtlInitUnicodeString(&dosDeviceName, THREADMON_DEVICE_NAME_W);
  179. IoDeleteSymbolicLink(&dosDeviceName);
  180. //
  181. // Delete the device object
  182. //
  183. IoDeleteDevice(DriverObject->DeviceObject);
  184. KdPrint(("[ThreadMon] Unloaded"));
  185. }
  186. VOID
  187. ThreadCallback(
  188. IN HANDLE               ProcessId,          // 进程ID
  189. IN HANDLE               ThreadId,           // 线程ID
  190. IN BOOLEAN              Create              // 创建还是终止
  191. )
  192. {
  193. PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension;
  194. deviceExtension->ProcessId = ProcessId;
  195. deviceExtension->ThreadId = ThreadId;
  196. deviceExtension->Create = Create;
  197. // 触发事件,通知应用程序
  198. KeSetEvent(deviceExtension->ThreadEvent, 0, FALSE);
  199. KeClearEvent(deviceExtension->ThreadEvent);
  200. }
  201. //
  202. //////////////////////////////////////////////////////////////////////////

ring3层调用代码如下

    1. #include "windows.h"
    2. #include "winioctl.h"
    3. #include "stdio.h"
    4. #include "../inc/ioctls.h"
    5. #define SYMBOL_LINK "\\\\.\\ThreadMon"
    6. int main()
    7. {
    8. CALLBACK_INFO cbkinfo, cbktemp = {0};
    9. // 打开驱动设备对象
    10. HANDLE hDriver = ::CreateFile(
    11. SYMBOL_LINK,
    12. GENERIC_READ | GENERIC_WRITE,
    13. 0,
    14. NULL,
    15. OPEN_EXISTING,
    16. FILE_ATTRIBUTE_NORMAL,
    17. NULL);
    18. if (hDriver == INVALID_HANDLE_VALUE)
    19. {
    20. printf("打开驱动设备对象失败!\n");
    21. return -1;
    22. }
    23. // 打开内核事件对象
    24. HANDLE hProcessEvent = ::OpenEventW(SYNCHRONIZE, FALSE, EVENT_NAME);
    25. while (::WaitForSingleObject(hProcessEvent, INFINITE))
    26. {
    27. DWORD   dwRet;
    28. BOOL    bRet;
    29. //      printf("收到事件通知!\n");
    30. bRet = ::DeviceIoControl(
    31. hDriver,
    32. IOCTL_THREAD_MON,
    33. NULL,
    34. 0,
    35. &cbkinfo,
    36. sizeof(cbkinfo),
    37. &dwRet,
    38. NULL);
    39. if (bRet)
    40. {
    41. if (cbkinfo.ProcessId != cbktemp.ProcessId || \
    42. cbkinfo.ThreadId != cbktemp.ThreadId || \
    43. cbkinfo.Create != cbktemp.Create)
    44. {
    45. if (cbkinfo.Create)
    46. {
    47. printf("有线程被创建,PID = %d,TID = %d\n", cbkinfo.ProcessId, cbkinfo.ThreadId);
    48. }
    49. else
    50. {
    51. printf("有线程被终止,PID = %d,TID = %d\n", cbkinfo.ProcessId, cbkinfo.ThreadId);
    52. }
    53. cbktemp = cbkinfo;
    54. }
    55. }
    56. else
    57. {
    58. printf("\n获取进程信息失败!\n");
    59. break;
    60. }
    61. }
    62. ::CloseHandle(hDriver);
    63. return 0;
    64. }

最新文章

  1. [翻译]AKKA笔记 - DEATHWATCH -7
  2. Java子类属性继承父类属性
  3. nodejs与模块soap的用法
  4. Android——android学习(android目录与AndroidManifest解析)
  5. The Dangers of JavaScript’s Automatic Semicolon Insertion
  6. MySql命令行命令和SQL语句
  7. 金蝶K3管理软件PDA条码解决方式,盘点机与金蝶K3无缝对接
  8. Wise Registry Cleaner Pro(智能注册表清理) V9.31 绿色版
  9. 使用hexo搭建个人博客
  10. Linux服务器上安装MySql数据库(默认安装,密码为空),首次使用需要修改密码
  11. C# Winform 国际化
  12. thinkphp或thinkcmf 《文章编辑,文章添加》 访问另一个表的分类,添加入另一个表时将id值以(,)逗号分隔储存,编辑时以(,)逗号分隔并且相等的id值被选中
  13. SQL server 清除缓存
  14. Zend 缓存
  15. hdu2886 Lou 1 Zhuang 数学/快速幂
  16. 返回xml过长时被nginx截断的解决办法
  17. 【bzoj4520】 Cqoi2016—K远点对
  18. 7-Linq查询语言
  19. ASP.NET MVC 必备开发环境
  20. springboot以jar包方式启动、关闭、重启脚本

热门文章

  1. Switching regulator forms constant-current source
  2. [置顶] 解决Firefox/Opera 不支持 onselectstart事件
  3. WinForm中DataGridView验证单元格输入的是数字
  4. 为什么Scrum不行?
  5. 用 C# 做人脸检测(基于EmguCV)
  6. java序列化 SerializeUtil
  7. React的第一个例子
  8. Gulp插件less的使用
  9. appium+python自动化58-xpath定位
  10. java集合(ArrayList,Vector,LinkedList,HashSet,TreeSet的功能详解)