第一篇 windows驱动之WinRing0.sys的开发及使用(电脑温度监控软件开发)

这篇具有很好参考价值的文章主要介绍了第一篇 windows驱动之WinRing0.sys的开发及使用(电脑温度监控软件开发)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

  从鲁大师的温度监控谈起,现代的CPU、GPU等芯片一般都具有温度监控的功能,比如我们可能会遇到的电脑散热不好导致系统直接关机黑屏,就是cpu检测到当前温度高于额定温度执行的操作。

  鲁大师的温度监控模块就相当于把这些信息从底层硬件读取,然后通过上层UI显示给用户。其核心就是与硬件的通信驱动。现在win10的驱动都可以通过系统更新直接完成,不再需要安装流氓软件“驱动精灵”、“驱动人生”等。我一般只用到温度检测模块,其他功能于我都是鸡肋,为了一个很小的功能,我需要安装一个庞大的鲁大师程序,甚是不划算。故自己动手实现。本文的主题就是如何实现鲁大师的温度检测模块。

  封闭必将导致落后,开放才能共同进步。WinRing0.sys作为一款windows平台下与设备通信的驱动被广泛使用。却由开源成了闭源,由支持读写成了仅支持读。本文花费数个工作日将08年之前开源的文件进行学习整理。便于后期大家的学习和升级优化。

windows驱动预备知识

1.虚拟设备驱动程序

.vxd程序:虚拟设备驱动程序,主要是为了给dos程序提供一个虚拟硬件

dos程序:早于windows的程序,window 3.x时代为了发展就需要兼容这些程序。类似当前鸿蒙兼容安卓,都是为了钱,不磕碜。

.vxd程序:可以把.vxd程序理解为运行在第0级别的dll。

ring0:最高等级权限,可以为所欲为,直接操作硬件。

ring3:用户等级权限,可以调用user32.dll、NTDLL.dll等库间接控制硬件。

WinRing0.vxd:其目的并非要虚拟硬件,只是需要第0级别的权限。

总结一:.vxd程序最新也得win9的系统才能用到,以上当个科普,了解下就行。对应WingRing0驱动的学习聚焦到.sys文件。

2.设备驱动文件

.sys文件:设备驱动文件,常说的声卡、显卡、键盘驱动等,都需要开发这种文件。

.inf文件:驱动安装的配置文件,主要是写注册表,注册接口。必有参数是ClassGUID。

总结二:.sys文件也当做权限等级为0级的.dll文件就行了。.dll文件的使用不熟悉的可以网上了解下。

3.sys驱动使用

.签名:内核级别的驱动都需要微软公司认证过的秘钥进行签名才能直接安装到windows系统中。签名的秘钥文件后缀是.cer。winring0,Windows驱动之WinRing0,windows,windows驱动,DDK,CPU温度
注册:注册仅仅是完成在注册表里写一个项。下图中的小工具是专门用于内核驱动安装运行的。链接: 下载地址
winring0,Windows驱动之WinRing0,windows,windows驱动,DDK,CPU温度
winring0,Windows驱动之WinRing0,windows,windows驱动,DDK,CPU温度

启动:对应缺微软签名或微软认证过的秘钥进行签名的内核级驱动是无法直接启动起来的。这是由于系统对于涉及内核层级的驱动有签名校验导致,简单说就是没有健康码绿码的不能在小区活动。
winring0,Windows驱动之WinRing0,windows,windows驱动,DDK,CPU温度

禁用强制签名校验:通过修改bcdedit来取消掉这个限制。有点类似安卓手机安装APP的时候经常需要“允许安装未知来源的程序”。逐条执行以下命令即可(管理员权限):

"Win7系统"

bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS

bcdedit /set TESTSIGNING ON

bcdedit /set nointegritychecks yes

如果有失败项,一般需要在BIOS里面关闭安全启动

启动按DEL键 进入BIOS 然后把 Secure Boot Policy 选项设置为关闭

重启电脑
"Win10系统"
bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS

bcdedit /set TESTSIGNING ON

bcdedit /set nointegritychecks yes

如果有失败,一般需要在BIOS里面关闭安全启动

启动按DEL键 进入BIOS 然后把 Secure Boot Policy 选项设置为关闭

重启电脑

代码分析

  通过以上的知识大致了解了windows驱动程序是啥,怎么用。接下来就进入较难的实战部分,写代码调用驱动获取有效信息。.sys驱动是用c语言写的,具体代码如下三部分。

1、驱动入口函数


NTSTATUS DriverEntry(	IN PDRIVER_OBJECT  DriverObject,	IN PUNICODE_STRING RegistryPath	)
{
	NTSTATUS		status;
	UNICODE_STRING  ntDeviceName;
	UNICODE_STRING  win32DeviceName;
	PDEVICE_OBJECT  deviceObject = NULL;

	RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);

	status = IoCreateDevice(
		DriverObject,					// Our Driver Object
		0,								// We don't use a device extension
		&ntDeviceName,					// Device name 
		OLS_TYPE,						// Device type  自定义的值
		FILE_DEVICE_SECURE_OPEN,		// Device characteristics
		FALSE,							// Not an exclusive device 非排他性设备
		&deviceObject );				// Returned ptr to Device Object

	if(!NT_SUCCESS(status))
	{
		refCount = (ULONG)-1;
		return status;
	}
	else
	{
		refCount = 0;
	}

	// Initialize the driver object with this driver's entry points.
	// 构造DriverObject这个结构体变量
	DriverObject->MajorFunction[IRP_MJ_CREATE] = OlsDispatch;// 1.注册函数,就是把函数指针告诉操作系统。当操作系统发送 IRP_MJ_CREATE 请求时,会调用这个函数
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = OlsDispatch;// 2.
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OlsDispatch;// 3.
	DriverObject->DriverUnload = Unload;//驱动卸载函数

	// Initialize a Unicode String containing the Win32 name for our device.
	RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

	// Create a symbolic link between our device name  and the Win32 name
	status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);

	if (!NT_SUCCESS(status))
	{
		// Delete everything that this routine has allocated.
		IoDeleteDevice( deviceObject );
	}

	return status;
}

2、调度函数

  实际读取CPU信息的实现代码在此处,主要涉及两个参数,其一是:DEVICE_OBJECT ,其二是:I/O Request Packet (IRP) 。OlsDispatch()这个函数根据传进来的请求信息调用具体的执行函数。

/*++

Routine Description:
	This routine is the dispatch handler for the driver.  It is responsible
	for processing the IRPs.

Arguments:
	
	pDO - Pointer to device object.

	pIrp - Pointer to the current IRP.

Return Value:

	STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
	indicating the reason for failure.

--*/
NTSTATUS OlsDispatch( 	IN	PDEVICE_OBJECT pDO,	IN	PIRP pIrp	)
{
	PIO_STACK_LOCATION pIrpStack;
	NTSTATUS status;
	int index;

	//  Initialize the irp info field.
	//	  This is used to return the number of bytes transfered.
	pIrp->IoStatus.Information = 0;
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

	//  Set default return status
	status = STATUS_NOT_IMPLEMENTED;

	// Dispatch based on major fcn code.
	switch(pIrpStack->MajorFunction)
	{
		case IRP_MJ_CREATE:
			if(refCount != (ULONG)-1){refCount++;}
			status = STATUS_SUCCESS;
			break;
		case IRP_MJ_CLOSE:
			if(refCount != (ULONG)-1){refCount--;}
			status = STATUS_SUCCESS;
			break;

		case IRP_MJ_DEVICE_CONTROL:
			//  Dispatch on IOCTL
			switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
			{
			case IOCTL_OLS_GET_DRIVER_VERSION:
				*(PULONG)pIrp->AssociatedIrp.SystemBuffer = OLS_DRIVER_VERSION;
				pIrp->IoStatus.Information = 4;
				status = STATUS_SUCCESS;
				break;

			case IOCTL_OLS_GET_REFCOUNT:
				*(PULONG)pIrp->AssociatedIrp.SystemBuffer = refCount;
				pIrp->IoStatus.Information = sizeof(refCount);
				status = STATUS_SUCCESS;
				break;

			case IOCTL_OLS_READ_MSR:
				status = ReadMsr(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_WRITE_MSR:
				status = WriteMsr(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_READ_PMC:
				status = ReadPmc(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_HALT:
				__halt();
				status = STATUS_SUCCESS;
				break;

			case IOCTL_OLS_READ_IO_PORT:
			case IOCTL_OLS_READ_IO_PORT_BYTE:
			case IOCTL_OLS_READ_IO_PORT_WORD:
			case IOCTL_OLS_READ_IO_PORT_DWORD:
				status = ReadIoPort(
					pIrpStack->Parameters.DeviceIoControl.IoControlCode,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_WRITE_IO_PORT:
			case IOCTL_OLS_WRITE_IO_PORT_BYTE:
			case IOCTL_OLS_WRITE_IO_PORT_WORD:
			case IOCTL_OLS_WRITE_IO_PORT_DWORD:
				status = WriteIoPort(
					pIrpStack->Parameters.DeviceIoControl.IoControlCode,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;

			case IOCTL_OLS_READ_PCI_CONFIG:
				status = ReadPciConfig(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_WRITE_PCI_CONFIG:
				status = WritePciConfig(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;

			case IOCTL_OLS_READ_MEMORY:
				status = ReadMemory(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;
			case IOCTL_OLS_WRITE_MEMORY:
				status = WriteMemory(
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
					(ULONG*)&pIrp->IoStatus.Information
					);
				break;


			}
			break;
	}

	// We're done with I/O request.  Record the status of the I/O action.
	pIrp->IoStatus.Status = status;

	// Don't boost priority when returning since this took little time.
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}

  下面的代码是具体每个case的实现部分,直接在注释里面做介绍:

//-----------------------------------------------------------------------------
//
// CPU
//
//-----------------------------------------------------------------------------

NTSTATUS
ReadMsr(	void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	__try
	{
		//MSR是CPU的一组64位寄存器,可以分别通过RDMSR和WRMSR 两条指令进行读和写的操作。
		//__readmsr就是生成指令并执行。此函数仅在内核模式下可用,且对应程序仅可用作内部函数,
		//这也就是为啥需要Ring0权限的原因。
		ULONGLONG data = __readmsr(*(ULONG*)lpInBuffer);
		memcpy((PULONG)lpOutBuffer, &data, 8);
		*lpBytesReturned = 8;
		return STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		*lpBytesReturned = 0;
		return STATUS_UNSUCCESSFUL;
	}
}

NTSTATUS
WriteMsr(	void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	__try
	{
		//与上面的__readmsr类似
		OLS_WRITE_MSR_INPUT* param;
		param = (OLS_WRITE_MSR_INPUT*)lpInBuffer;

		__writemsr(param->Register, param->Value.QuadPart);
		*lpBytesReturned = 0;
		return STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		*lpBytesReturned = 0;
		return STATUS_UNSUCCESSFUL;
	}
}

NTSTATUS
ReadPmc(	void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	__try
	{   //pmc 性能计数器
		ULONGLONG data = __readpmc(*(ULONG*)lpInBuffer);
		memcpy((PULONG)lpOutBuffer, &data, 8);
		*lpBytesReturned = 8;
		return STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		*lpBytesReturned = 0;
		return STATUS_UNSUCCESSFUL;
	}
}
//-----------------------------------------------------------------------------
//
// IO Port IO口
//
//-----------------------------------------------------------------------------

NTSTATUS
ReadIoPort( ULONG	ioControlCode,
			void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	ULONG nPort = *(ULONG*)lpInBuffer;
	
	switch(ioControlCode)
	{
		case IOCTL_OLS_READ_IO_PORT_BYTE://从指定的端口地址读取单个字节
			*(PUCHAR)lpOutBuffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort);
			break;
		case IOCTL_OLS_READ_IO_PORT_WORD://从指定的端口地址读取单个字
			*(PUSHORT)lpOutBuffer = READ_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort);
			break;
		case IOCTL_OLS_READ_IO_PORT_DWORD://从指定的端口地址读取双字节
			*(PULONG)lpOutBuffer = READ_PORT_ULONG((PULONG)(ULONG_PTR)nPort);
			break;
		default:
			*lpBytesReturned = 0;
			return STATUS_INVALID_PARAMETER;
			break;
	}
	
	*lpBytesReturned = nInBufferSize;
	return STATUS_SUCCESS;
}

NTSTATUS
WriteIoPort(ULONG	ioControlCode,
			void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	ULONG nPort;
	OLS_WRITE_IO_PORT_INPUT* param;
	
	param = (OLS_WRITE_IO_PORT_INPUT*)lpInBuffer;
	nPort = param->PortNumber;

	switch(ioControlCode)
	{

		case IOCTL_OLS_WRITE_IO_PORT_BYTE:
			WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort, param->CharData);
			break;
		case IOCTL_OLS_WRITE_IO_PORT_WORD:
			WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort, param->ShortData);
			break;
		case IOCTL_OLS_WRITE_IO_PORT_DWORD:
			WRITE_PORT_ULONG((PULONG)(ULONG_PTR)nPort, param->LongData);
			break;
		default:
			return STATUS_INVALID_PARAMETER;
			break;
	}

	return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
//
// PCI
//
//-----------------------------------------------------------------------------

NTSTATUS
ReadPciConfig(	void	*lpInBuffer, 
				ULONG	nInBufferSize, 
				void	*lpOutBuffer, 
				ULONG	nOutBufferSize, 
				ULONG	*lpBytesReturned)
{
	OLS_READ_PCI_CONFIG_INPUT *param;
	NTSTATUS status;

	if(nInBufferSize != sizeof(OLS_READ_PCI_CONFIG_INPUT))
	{
		return STATUS_INVALID_PARAMETER;
	}
	param = (OLS_READ_PCI_CONFIG_INPUT *)lpInBuffer;

	status = pciConfigRead(param->PciAddress, param->PciOffset,
						lpOutBuffer, nOutBufferSize);//最终调用的是HalGetBusDataByOffset,这是硬件抽象层函数,获取总线数据

	if(status == STATUS_SUCCESS)
	{
		*lpBytesReturned = nOutBufferSize;
	}
	else
	{
		*lpBytesReturned = 0;
	}

	return status;
}

NTSTATUS
WritePciConfig(	void *lpInBuffer, 
				ULONG nInBufferSize, 
				void *lpOutBuffer, 
				ULONG nOutBufferSize, 
				ULONG *lpBytesReturned)

{
	OLS_WRITE_PCI_CONFIG_INPUT *param;
	ULONG writeSize;
	NTSTATUS status;

	if(nInBufferSize < offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data))
	{
		return STATUS_INVALID_PARAMETER;
	}

	param = (OLS_WRITE_PCI_CONFIG_INPUT *)lpInBuffer;
	writeSize = nInBufferSize - offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data);
	
	*lpBytesReturned = 0;

	return pciConfigWrite(param->PciAddress, param->PciOffset,
							&param->Data, writeSize);

}

//-----------------------------------------------------------------------------
//
// Support Function
//
//-----------------------------------------------------------------------------

NTSTATUS pciConfigRead(ULONG pciAddress, ULONG offset, void *data, int length)
{
	PCI_SLOT_NUMBER slot;
	int error;
	ULONG busNumber;

	busNumber = PciGetBus(pciAddress);
	slot.u.AsULONG = 0;
	slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
	slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
	error =	HalGetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
									data, offset, length);

	if(error == 0)
	{
		return OLS_ERROR_PCI_BUS_NOT_EXIST;
	}
	else if(length != 2 && error == 2)
	{
		return OLS_ERROR_PCI_NO_DEVICE;
	}
	else if(length != error)
	{
		return OLS_ERROR_PCI_READ_CONFIG;
	}

	return STATUS_SUCCESS;
}

NTSTATUS pciConfigWrite(ULONG pciAddress, ULONG offset, void *data, int length)
{
	PCI_SLOT_NUMBER slot;
	int error;
	ULONG busNumber;

	busNumber = PciGetBus(pciAddress);

	slot.u.AsULONG = 0;
	slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
	slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
	error = HalSetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
									data, offset, length);

	if(error != length)
	{
		return OLS_ERROR_PCI_WRITE_CONFIG;
	}

	return STATUS_SUCCESS;
}

//-----------------------------------------------------------------------------
//
// Physical Memory
//
//-----------------------------------------------------------------------------

NTSTATUS
ReadMemory(	void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
	OLS_READ_MEMORY_INPUT *param;
	ULONG	size;
	PHYSICAL_ADDRESS address;
	PVOID	maped;
	BOOLEAN	error;

	if(nInBufferSize != sizeof(OLS_READ_MEMORY_INPUT))
	{
		return STATUS_INVALID_PARAMETER;
	}

	param = (OLS_READ_MEMORY_INPUT *)lpInBuffer;
	size = param->UnitSize * param->Count;

	if(nOutBufferSize < size)
	{
		return STATUS_INVALID_PARAMETER;
	}

	address.QuadPart = param->Address.QuadPart;

#ifndef _PHYSICAL_MEMORY_SUPPORT

	if(0x000C0000 > address.QuadPart 
	|| (address.QuadPart + size - 1) > 0x000FFFFF)
	{
		return STATUS_INVALID_PARAMETER;
	}

#endif

	maped = MmMapIoSpace(address, size, FALSE);//把物理地址 转为虚拟地址,比如我们要读取物理地址为100的一个字节数据,
	//其通过系统被映射到虚拟内存的地址是200,那我们就通过读虚拟内存的200位置来实现

	error = FALSE;
	switch(param->UnitSize){
		case 1:
			READ_REGISTER_BUFFER_UCHAR(maped, lpOutBuffer, param->Count);//从虚拟地址里间接读物理地址的信息
			break;
		case 2:
			READ_REGISTER_BUFFER_USHORT(maped, lpOutBuffer, param->Count);
			break;
		case 4:
			READ_REGISTER_BUFFER_ULONG(maped, lpOutBuffer, param->Count);
			break;
		default:
			error = TRUE;
			break;
	}

	MmUnmapIoSpace(maped, size);

	if(error)
	{
		return STATUS_INVALID_PARAMETER;
	}

	*lpBytesReturned = nOutBufferSize;

	return STATUS_SUCCESS;
}

NTSTATUS
WriteMemory(void	*lpInBuffer, 
			ULONG	nInBufferSize, 
			void	*lpOutBuffer, 
			ULONG	nOutBufferSize, 
			ULONG	*lpBytesReturned)
{
#ifdef _PHYSICAL_MEMORY_SUPPORT

	OLS_WRITE_MEMORY_INPUT *param;
	ULONG size;
	PHYSICAL_ADDRESS address;
	PVOID	maped;
	BOOLEAN	error;

	if(nInBufferSize < offsetof(OLS_WRITE_MEMORY_INPUT, Data))
	{
		return STATUS_INVALID_PARAMETER;
	}

	param = (OLS_WRITE_MEMORY_INPUT *)lpInBuffer;

	size = param->UnitSize * param->Count;
	if (nInBufferSize < size + offsetof(OLS_WRITE_MEMORY_INPUT, Data))
	{
		return STATUS_INVALID_PARAMETER;
	}

	address.QuadPart = param->Address.QuadPart;

	maped = MmMapIoSpace(address, size, FALSE);

	error = FALSE;
	switch(param->UnitSize){
		case 1:
			WRITE_REGISTER_BUFFER_UCHAR(maped, 
										(UCHAR*)&param->Data, param->Count);
			break;
		case 2:
			WRITE_REGISTER_BUFFER_USHORT(maped,
										(USHORT*)&param->Data, param->Count);
			break;
		case 4:
			WRITE_REGISTER_BUFFER_ULONG(maped,
										(ULONG*)&param->Data, param->Count);
			break;
		default:
			error = TRUE;
			break;
	}

	MmUnmapIoSpace(maped, size);

	if(error)
	{
		return STATUS_INVALID_PARAMETER;
	}

	*lpBytesReturned = 0;

	return STATUS_SUCCESS;

#else

	*lpBytesReturned = 0;
	
	return STATUS_INVALID_PARAMETER;

#endif
}

3、驱动卸载函数

  实际的卸载工作被IRP_MN_REMOVE_DEVICE对应的派发函数处理了,不需要自己实现。这里的DriverUnload主要处理在DriverEntry中申请的内存,也就是“new”出的“win32NameString”。文章来源地址https://www.toymoban.com/news/detail-627952.html

/*++

Routine Description:

	This routine is called by the I/O system to unload the driver.

	Any resources previously allocated must be freed.

Arguments:

	DriverObject - a pointer to the object that represents our driver.

Return Value:

	None
--*/
VOID Unload(	PDRIVER_OBJECT DriverObject	)
{
	PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
	UNICODE_STRING win32NameString;

	PAGED_CODE();

	// Create counted string version of our Win32 device name.
	RtlInitUnicodeString(&win32NameString, DOS_DEVICE_NAME);

	// Delete the link from our device name to a name in the Win32 namespace.
	IoDeleteSymbolicLink(&win32NameString);

	if(deviceObject != NULL)
	{
		IoDeleteDevice(deviceObject);
	}
}

革命尚未成功,以上只是.sys驱动的代码实现,主要目的是获取Ring0权限,为了给开发者使用,需要做一个DLL提供对外的接口。请参阅第二篇。。。

到了这里,关于第一篇 windows驱动之WinRing0.sys的开发及使用(电脑温度监控软件开发)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring进阶系列丨第一篇】初识Spring开发

    小伙伴们大家好,我是陈橘又青,今天起 《Spring进阶系列》 开始更新。本专栏将涵盖Spring框架的核心概念、配置管理、Web开发、AOP、Boot、Security、Data、Integration和Batch等多个主题。通过理论讲解和实际案例的剖析,帮助读者深入理解Spring框架的原理和应用技巧,提升开发人员

    2024年02月05日
    浏览(46)
  • 记录第一篇被”华为开发者联盟鸿蒙专区 “收录的文章

    记录第一篇被”华为开发者联盟鸿蒙专区 “社区收录的文章。 坚持写作的动力是什么? 是记录、分享,以及更好的思考 。  

    2024年02月14日
    浏览(39)
  • 第一篇【传奇开心果系列】beeware开发移动应用:轮盘抽奖移动应用

    一、项目目标 使用beeware的toga写传奇开心果轮盘抽奖安卓手机应用和苹果手机应用 二、开发传奇开心果轮盘抽奖安卓应用编程思路 要使用Beeware的Toga库来编写一个传奇开心果轮盘抽奖安卓应用,你需要按照以下步骤进行操作: 安装Beeware:首先,你需要安装Beeware的开发工具包

    2024年01月20日
    浏览(68)
  • 【SpringBoot】第一篇:redis使用

    背景: 本文是教初学者如何正确使用和接入redis。     好了,到此处就已经介绍完毕了! 如果有什么问题可以问博主的,可以在底下进行留言,看到一定回复你们。

    2024年02月11日
    浏览(38)
  • 第一篇 香橙派刷机和开发环境准备(ubuntu20.04版)

    目录 一、香橙派刷ubuntu系统和SSH登录 1.Ubuntu有趣的Codename 2.刷机步骤(ubuntu20.04) 🔖格式化TF卡 🔖烧写系统到TF卡 🔖调试串口登陆系统 🔖SSH登陆系统  二、开发环境准备 1.香橙派ubuntu20.04换源 2.VNC远程连接香橙派 (1)安装VNC服务 (2)VNC连接香橙派 3.安装wiringPi (1)安装

    2023年04月21日
    浏览(48)
  • 手把手教你区块链java开发智能合约nft-第一篇

    刚接触区块链开发,使用java开发,真的是太难了,自己一步步摸索,从新手小白一路碰壁,动不动就报错,去网上搜索对应错误,还真什么都搜索不到,摸索了三四个月,今天终于有了一些进展,今天开始分享出来,希望能帮助到需要的朋友 我作为一个java后端的程序员,不

    2024年01月23日
    浏览(57)
  • 【第一篇:简介关于OpenAI的使用】

    其实以上都不是我写的,都是chat-GPT自己写的,真的很神奇!

    2024年02月04日
    浏览(47)
  • AI大模型时代下运维开发探索第一篇:ReAct工程初探

    人工智能大模型的出现,已渐渐地影响了我们的日常生活和工作方式。生活中无处不在的AI,使我们的生活变得更加智能和便捷。工作中,AI大模型的高效和精准,极大地提升了我们解决问题的效率。 是的,我们不能忽视AI大模型对运维开发的巨大影响和潜力。本系列文章旨在

    2024年02月16日
    浏览(39)
  • 【标准解读】Autosar 复杂驱动(CDD)开发--看这一篇就够了

    最近看到有朋友提问,“复杂驱动和Linux驱动有啥区别?” 看到几个回答挺好的,“Linux驱动是真正的驱动,复杂驱动只是在autosar范畴的说法,内容不一定是驱动,可能同时包含底层、算法、应用层等其他东西” 简而言之,没办法统一标准的东西,都放在复杂驱动了;例如功

    2024年02月03日
    浏览(75)
  • Hadoop生态圈实战系列:第一篇 Hadoop 集群安装及使用详解

    作者:禅与计算机程序设计艺术 Apache Hadoop 是一款开源的、分布式文件系统和计算平台。它由 Apache 基金会开发,并于 2011 年成为 Apache 顶级项目之一。Hadoop 的主要特性包括: 分布式存储: Hadoop 允许将数据存储在多个服务器上,在同一个集群中,并提供高容错性和可靠性。

    2024年02月08日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包