• 用Visual studio2012在Windows8上开发内核驱动监视线程创建


    在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层驱动监视创建线程,请见代码分析


    #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;
    }







  • 相关阅读:
    30个实例详解TOP命令
    CentOS6 启动流程图文解剖
    Linux常用性能检测命令解释
    Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity) 转
    linux系统中如何查看日志 (常用命令2)
    Linux下常用的shell命令记录1
    python import as from
    内存的大小端模式
    opencv笔记1
    代码不仅仅考虑性能
  • 原文地址:https://www.cnblogs.com/new0801/p/6177731.html
Copyright © 2020-2023  润新知