ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
在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 ![](https://box.kancloud.cn/2016-04-01_56fdf15192479.png) 2.看见满目的驱动开发模板 ![](https://box.kancloud.cn/2016-04-01_56fdf151a72a9.png) 3.选择一个驱动模式,有内核模式与用户模式两种的驱动 ![](https://box.kancloud.cn/2016-04-01_56fdf151e0f15.png)   4.创建一个驱动程序,KMDF DriverMVP ![](https://box.kancloud.cn/2016-04-01_56fdf152053f8.png)   5.我们选择的是内核模式的驱动程序,下面是创建成功后的界面,分别是驱动程序本身,与驱动安装包 ![](https://box.kancloud.cn/2016-04-01_56fdf15221ca7.png) 6.按下F5,选择驱动编译,   ![](https://box.kancloud.cn/2016-04-01_56fdf15236a2b.png) 插入下列代码实现ring0层驱动监视创建线程,请见代码分析 ~~~ #include "ThreadMon.h" #include "../inc/ioctls.h" // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // 全局变量 // PDEVICE_OBJECT g_pDeviceObject; // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // 函数实现 // NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING ntDeviceName; UNICODE_STRING dosDeviceName; UNICODE_STRING ThreadEventString; PDEVICE_EXTENSION deviceExtension; PDEVICE_OBJECT deviceObject = NULL; KdPrint(("[ThreadMon] DriverEntry: %wZ\n", RegistryPath)); // // 创建设备对象 // RtlInitUnicodeString(&ntDeviceName, THREADMON_DEVICE_NAME_W); Status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), // DeviceExtensionSize &ntDeviceName, // DeviceName FILE_DEVICE_THREADMON, // DeviceType 0, // DeviceCharacteristics TRUE, // Exclusive &deviceObject // [OUT] ); if(!NT_SUCCESS(Status)) { KdPrint(("[ThreadMon] IoCreateDevice Error Code = 0x%X\n", Status)); return Status; } // // 设置扩展结构 // deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // // Set up synchronization objects, state info,, etc. // deviceObject->Flags |= DO_BUFFERED_IO; // // 创建符号链接 // RtlInitUnicodeString(&dosDeviceName, THREADMON_DOS_DEVICE_NAME_W); Status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName); if(!NT_SUCCESS(Status)) { KdPrint(("[ThreadMon] IoCreateSymbolicLink Error Code = 0x%X\n", Status)); IoDeleteDevice(deviceObject); return Status; } // // 分发IRP // DriverObject->MajorFunction[IRP_MJ_CREATE] = ThreadMonDispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = ThreadMonDispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ThreadMonDispatchDeviceControl; DriverObject->DriverUnload = ThreadMonUnload; // // 保存设备对象指针 // g_pDeviceObject = deviceObject; // // 创建事件对象与应用层通信 // RtlInitUnicodeString(&ThreadEventString, EVENT_NAME); deviceExtension->ThreadEvent = IoCreateNotificationEvent(&ThreadEventString, &deviceExtension->ThreadHandle); KeClearEvent(deviceExtension->ThreadEvent); // 非受信状态 // // 设置回调例程 // Status = PsSetCreateThreadNotifyRoutine(ThreadCallback); return Status; } NTSTATUS ThreadMonDispatchCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; KdPrint(("[ThreadMon] IRP_MJ_CREATE\n")); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS ThreadMonDispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; KdPrint(("[ThreadMon] IRP_MJ_CLOSE\n")); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS ThreadMonDispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; ULONG inBufLength, outBufLength; ULONG ioControlCode; PCALLBACK_INFO pCallbackInfo; // 获取当前设备栈 irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // 提取信息 pCallbackInfo = Irp->AssociatedIrp.SystemBuffer; inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; // 处理不同的IOCTL switch (ioControlCode) { case IOCTL_THREAD_MON: { KdPrint(("[ThreadMon] IOCTL: 0x%X", ioControlCode)); if (outBufLength >= sizeof(PCALLBACK_INFO)) { pCallbackInfo->ProcessId = deviceExtension->ProcessId; pCallbackInfo->ThreadId = deviceExtension->ThreadId; pCallbackInfo->Create = deviceExtension->Create; Irp->IoStatus.Information = outBufLength; } break; } default: { Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; KdPrint(("[ThreadMon] Unknown IOCTL: 0x%X (%04X,%04X)", \ ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode), \ IoGetFunctionCodeFromCtlCode(ioControlCode))); break; } } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } VOID ThreadMonUnload( IN PDRIVER_OBJECT DriverObject ) { UNICODE_STRING dosDeviceName; // // Free any resources // // 卸载回调例程 PsRemoveCreateThreadNotifyRoutine(ThreadCallback); // // Delete the symbolic link // RtlInitUnicodeString(&dosDeviceName, THREADMON_DEVICE_NAME_W); IoDeleteSymbolicLink(&dosDeviceName); // // Delete the device object // IoDeleteDevice(DriverObject->DeviceObject); KdPrint(("[ThreadMon] Unloaded")); } VOID ThreadCallback( IN HANDLE ProcessId, // 进程ID IN HANDLE ThreadId, // 线程ID IN BOOLEAN Create // 创建还是终止 ) { PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension; deviceExtension->ProcessId = ProcessId; deviceExtension->ThreadId = ThreadId; deviceExtension->Create = Create; // 触发事件,通知应用程序 KeSetEvent(deviceExtension->ThreadEvent, 0, FALSE); KeClearEvent(deviceExtension->ThreadEvent); } // ////////////////////////////////////////////////////////////////////////// ~~~ ring3层调用代码如下 ~~~ #include "windows.h" #include "winioctl.h" #include "stdio.h" #include "../inc/ioctls.h" #define SYMBOL_LINK "\\\\.\\ThreadMon" int main() { CALLBACK_INFO cbkinfo, cbktemp = {0}; // 打开驱动设备对象 HANDLE hDriver = ::CreateFile( SYMBOL_LINK, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDriver == INVALID_HANDLE_VALUE) { printf("打开驱动设备对象失败!\n"); return -1; } // 打开内核事件对象 HANDLE hProcessEvent = ::OpenEventW(SYNCHRONIZE, FALSE, EVENT_NAME); while (::WaitForSingleObject(hProcessEvent, INFINITE)) { DWORD dwRet; BOOL bRet; // printf("收到事件通知!\n"); bRet = ::DeviceIoControl( hDriver, IOCTL_THREAD_MON, NULL, 0, &cbkinfo, sizeof(cbkinfo), &dwRet, NULL); if (bRet) { if (cbkinfo.ProcessId != cbktemp.ProcessId || \ cbkinfo.ThreadId != cbktemp.ThreadId || \ cbkinfo.Create != cbktemp.Create) { if (cbkinfo.Create) { printf("有线程被创建,PID = %d,TID = %d\n", cbkinfo.ProcessId, cbkinfo.ThreadId); } else { printf("有线程被终止,PID = %d,TID = %d\n", cbkinfo.ProcessId, cbkinfo.ThreadId); } cbktemp = cbkinfo; } } else { printf("\n获取进程信息失败!\n"); break; } } ::CloseHandle(hDriver); return 0; } ~~~