zoukankan      html  css  js  c++  java
  • 用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,选择驱动编译,

     


    插入下列代码实现内核的进程创建

    #include "ProcMon.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		ProcessEventString;
    	PDEVICE_EXTENSION	deviceExtension;
    	PDEVICE_OBJECT		deviceObject = NULL;
    	
    	KdPrint(("[ProcMon] DriverEntry: %wZ\n", RegistryPath));
    	
    	//
    	// 创建设备对象
    	//
    	RtlInitUnicodeString(&ntDeviceName, PROCMON_DEVICE_NAME_W);
    	
    	Status = IoCreateDevice(
    						DriverObject, 
    						sizeof(DEVICE_EXTENSION),		// DeviceExtensionSize
    						&ntDeviceName,					// DeviceName
    						FILE_DEVICE_PROCMON,			// DeviceType
    						0,								// DeviceCharacteristics
    						TRUE,							// Exclusive
    						&deviceObject					// [OUT]
    						);
    
    	if(!NT_SUCCESS(Status))
    	{
    		KdPrint(("[ProcMon] 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, PROCMON_DOS_DEVICE_NAME_W);
    	
    	Status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);
    	
    	if(!NT_SUCCESS(Status))
    	{
    		KdPrint(("[ProcMon] IoCreateSymbolicLink Error Code = 0x%X\n", Status));
    
    		IoDeleteDevice(deviceObject);
    		
    		return Status;
    	}
    	
    	//
    	// 分发IRP
    	//
    	DriverObject->MajorFunction[IRP_MJ_CREATE]			= ProcmonDispatchCreate;
    	DriverObject->MajorFunction[IRP_MJ_CLOSE]			= ProcmonDispatchClose;
    	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]	= ProcmonDispatchDeviceControl;
    	DriverObject->DriverUnload							= ProcmonUnload;
    	
    	//
    	// 保存设备对象指针
    	//
    	g_pDeviceObject = deviceObject;
    
    	//
    	// 创建事件对象与应用层通信
    	//
    	RtlInitUnicodeString(&ProcessEventString, EVENT_NAME);
    	
    	deviceExtension->ProcessEvent = IoCreateNotificationEvent(&ProcessEventString, &deviceExtension->hProcessHandle);
    	KeClearEvent(deviceExtension->ProcessEvent);			// 非受信状态
    
    	//
    	// 设置回调例程
    	//
    	Status = PsSetCreateProcessNotifyRoutine(ProcessCallback, FALSE);
    
    	return Status;
    }
    
    NTSTATUS
    ProcmonDispatchCreate(
    	IN PDEVICE_OBJECT		DeviceObject,
    	IN PIRP					Irp
    )
    {
    	NTSTATUS Status = STATUS_SUCCESS;
    	
    	Irp->IoStatus.Information = 0;
    	
    	KdPrint(("[ProcMon] IRP_MJ_CREATE\n"));
    	
    	Irp->IoStatus.Status = Status;
    	IoCompleteRequest(Irp, IO_NO_INCREMENT);
    	
    	return Status;
    }
    
    NTSTATUS
    ProcmonDispatchClose(
    	IN PDEVICE_OBJECT		DeviceObject,
    	IN PIRP					Irp
    )
    {
    	NTSTATUS Status = STATUS_SUCCESS;
    	
    	Irp->IoStatus.Information = 0;
    	
    	KdPrint(("[ProcMon] IRP_MJ_CLOSE\n"));
    	
    	Irp->IoStatus.Status = Status;
    	IoCompleteRequest(Irp, IO_NO_INCREMENT);
    	
    	return Status;
    }
    
    NTSTATUS
    ProcmonDispatchDeviceControl(
    	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_PROC_MON:
    		{
    			KdPrint(("[ProcMon] IOCTL: 0x%X", ioControlCode));
    
    			if (outBufLength >= sizeof(PCALLBACK_INFO))
    			{
    				pCallbackInfo->hParentId = deviceExtension->hParentId;
    				pCallbackInfo->hProcessId = deviceExtension->hProcessId;
    				pCallbackInfo->bCreate = deviceExtension->bCreate;
    
    				Irp->IoStatus.Information = outBufLength;
    			} 
    			break;
    		}
    		
    	default:
    		{
    			Status = STATUS_INVALID_PARAMETER;
    			Irp->IoStatus.Information = 0;
    			
    			KdPrint(("[ProcMon] 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
    ProcmonUnload(
    	IN PDRIVER_OBJECT		DriverObject
    )
    {
    	UNICODE_STRING dosDeviceName;
    	
    	//
    	// Free any resources
    	//
    
    	// 卸载回调例程
    	PsSetCreateProcessNotifyRoutine(ProcessCallback, TRUE);
    	
    	//
    	// Delete the symbolic link
    	//
    	
    	RtlInitUnicodeString(&dosDeviceName, PROCMON_DOS_DEVICE_NAME_W);
    	
    	IoDeleteSymbolicLink(&dosDeviceName);
    	
    	//
    	// Delete the device object
    	//
    	
    	IoDeleteDevice(DriverObject->DeviceObject);
    	
    	KdPrint(("[ProcMon] Unloaded"));
    }
    
    VOID
    ProcessCallback(
    	IN HANDLE				ParentId,			// 父进程ID
    	IN HANDLE				ProcessId,			// 发生事件的进程ID
    	IN BOOLEAN				Create				// 进程是创建还是终止
    )
    {
    	PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension;
    
    	deviceExtension->hParentId = ParentId;
    	deviceExtension->hProcessId = ProcessId;
    	deviceExtension->bCreate = Create;
    
    	// 触发事件,通知应用程序
    	KeSetEvent(deviceExtension->ProcessEvent, 0, FALSE);
    	KeClearEvent(deviceExtension->ProcessEvent);
    }
    
    //
    //////////////////////////////////////////////////////////////////////////


    ring3实现应用层的调用,搞定进程创建的监视


    #include "windows.h"
    #include "winioctl.h"
    #include "stdio.h"
    #include "../inc/ioctls.h"
    
    #define SYMBOL_LINK "\\\\.\\ProcMon"
    //#define SYMBOL_LINK "\\\\.\\slNTProcDrv"
    
    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;
    
    		bRet = ::DeviceIoControl(
    							hDriver,
    							IOCTL_PROC_MON,
    							NULL,
    							0,
    							&cbkinfo,
    							sizeof(cbkinfo),
    							&dwRet,
    							NULL);
    
    		if (bRet)
    		{
    			if (cbkinfo.hParentId != cbktemp.hParentId || \
    				cbkinfo.hProcessId != cbktemp.hProcessId || \
    				cbkinfo.bCreate != cbktemp.bCreate)
    			{
    				if (cbkinfo.bCreate)
    				{
    					printf("有进程被创建,PID = %d\n", cbkinfo.hProcessId);
    				} 
    				else
    				{
    					printf("有进程被终止,PID = %d\n", cbkinfo.hProcessId);
    				}
    
    				cbktemp = cbkinfo;
    			}
    		} 
    		else
    		{
    			printf("\n获取进程信息失败!\n");
    			break;
    		}
    	}
    
    	::CloseHandle(hDriver);
    
    	return 0;
    }



  • 相关阅读:
    如何编写属于自己的事件集合
    Android文件操作(可应用于JAVA)
    Share Point 2007 copy webservices overwrite exist file
    cnBlog的windows live writer 客户端配置
    VS 2012 找回消失的“创建单元测试”
    Oracle函数参考
    哲理小故事(一)
    输入框信息提示
    实现记住用户登陆名
    常用正则表达式
  • 原文地址:https://www.cnblogs.com/new0801/p/6177730.html
Copyright © 2011-2022 走看看