用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

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第1张图片

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

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第2张图片

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

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第3张图片

 

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

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第4张图片

 

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

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第5张图片

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

 

用Visual studio2012在Windows8上开发内核驱动监视线程创建_第6张图片


插入下列代码实现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;
}







你可能感兴趣的:(thread,windows,null,extension,代码分析)