内核驱动中改写寄存器值

来源:互联网 发布:中国进口粮食数据 编辑:程序博客网 时间:2024/06/13 02:22

在Kernel Model的驱动程序中向给定的寄存器地址、内存地址或IO端口地址等16进制的地址写入指定的值。

主要依靠的是MSDN中提供的MmMapIoSpace函数进行的。该函数将一个十六进制的物理地址映射到一个指针,然后针对该指针进行操作即可改变对应的物理单元内的数据。该函数的具体描述可参看微软的MSDN:

https://msdn.microsoft.com/zh-cn/office/ff554618(v=msdn.10).aspx

以下是使用该方法操作物理地址的代码示例:

LARGE_INTEGER memAddress;

PULONG pMemAddress;

memAddress.QuadPart= 0xFED0D048;

pMemAddress = (PULONG) MmMapIoSpace(memAddress,

sizeof(ULONG), MmNonCached);

*pMemAddress= 0x00000000;

KeStallExecutionProcessor(300* 1000);

*pMemAddress= 0x00000003;

KeStallExecutionProcessor(50 * 1000);

 

目前在驱动中,我们可以通过系统函数MmMapIoSpace,将指定的内存地址映射为一个指针,然后通过该指针即可实现对内存的读写;

 

但由于驱动中操作的内存地址很可能是直接与某个物理端口直接对应,它所指向的值是一个volatile的,所以在使用指针所指向的值时,必须先将其赋值给一个局部变量,以防数据访问错误。

 

我们在反汇编对比两个版本的程序后,发现由于Release版本对代码进行了优化而导致的问题。

 

一、如下代码,使用Debug模式进行编译时

*deviceContext->pMemAddress,是个ULONG型的指针,此时该指针所指向的对象的值为:0x02或0x03,当有外接键盘时该址为0x02,否则该值为0x03。此时该指针的值与0x00000001按位与时,可以正确地反馈出键盘状态的变化;

 

二、在Release模式下进行编译时

编译器对代码进行了优化,当使用指针所指向的值与0x00000001进行按位与操作时,由于0x00000001前3个字节都为0,按位与的结果永远为0,编译器认为没必要再进行计算,只使用最低位的01进行计算即可。所以编译器在编译时,把*deviceContext->pMemAddress_homekeyWanlida这个指针优化成了一个BYTE型的指针。但当使用BYTE型指针去访问0xFED0E258这个地址时取到的值永远都是0xFF,这就导致了在Release版本的驱动中,第一个if判断永远都是生效的。

 

if (((*deviceContext->pMemAddress)& 0x00000001) == 1) 

deviceContext->homekeyInvalid = FALSE;//Homekey
有效 
WriteLogFormat(device, "***homekeyInvalid_Wanlida status:%d\r\n",deviceContext->homekeyInvalid); 

else 

deviceContext->homekeyInvalid = TRUE;//Homekey
失效 
WriteLogFormat(device, "***homekeyInvalid_Wanlida status:%d\r\n",deviceContext->homekeyInvalid); 
}

 

三、最根本的原因

根本原因还是0xFED0E258这个地址的访问,当使用BYTE型指针和WORD型指针访问时,取到的值永远都是0xFF跟0xFFFF,只有当使用DWORD/ULONG型的指针访问该地址时才可以取到正确的值。

0 0