码迷,mamicode.com
首页 > Windows程序 > 详细

《Windows驱动开发技术详解》之Windows内存管理

时间:2016-05-23 22:31:50      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:

  • 虚拟内存地址

Windows所有的程序(Ring0和Ring3层)可以操作的都是虚拟内存。有一部分单元会和物理内存对应起来,但并非一一对应,多个虚拟内存页可以映射同一个物理内存页。还有一部分单元会被映射成磁盘上的文件,并标记为的。读取这段虚拟内存的时候,系统会发出一个异常,此时会出发异常处理函数,异常处理函数会将这个页的磁盘文件读入内存,并将其标记为不脏。可以让那些经常不读写的内存页交换成文件,并设置为脏。

Windows之所以如此设计,第一是虚拟的增加了内存的大小;第二是使不同进程的虚拟内存互不干扰。

虚拟地址在0-0x7FFFFFFF范围内的虚拟内存,被称为用户模式地址。而0x80000000-0xFFFFFFFF范围内的虚拟内存,被称为内核模式地址。Windows运行在用户态的程序只能访问用户模式地址,而运行在核心态的程序可以访问整个4G的虚拟内存。

  • 驱动和进程的关系

驱动程序可以看做是一个特殊的DLL文件被应用程序加载到虚拟内存中,只不过加载的地址是在内核模式地址,而非用户模式地址。它只能访问这个进程的虚拟内存,而不能使其它进程的虚拟地址。DriverEntry和AddDevice例程是运行在系统进程(System)中的。而其它的例程,诸如IRP_MJ_READ、IRP_MJ_WRITE的派遣函数会运行与应用程序的上下文中,即运行于某个进程的环境中,所能访问的虚拟地址是这个进程的虚拟地址。

下面写一段代码来获取代码所运行的当前进程。我在写这段代码时遇到了一个问题。起初,我的代码如下:

技术分享

技术分享

但是这样加载驱动之后没有输出我想要的数据:

技术分享

我一开始以为是找ImageFileName的偏移不对,于是我用Windbg去查:

技术分享

发现就是0x2e0,没错。后来,网上有人告诉我要用PsGetProcessImageFileName,这是一个微软的已经导出的但是没有文档化的API。意思就是,这个函数你可以直接用,但是它并没有在某个头文件中声明,所以需要你自己声明一下,然后才能使用。

先声明:

技术分享

再使用:

技术分享

竟然输出了我想要的结果:

技术分享

我很纳闷,这是为什么,于是反汇编下这个API,发现它只有两条汇编代码:

技术分享

如果进入这个API单步跟踪我们可以看到:

技术分享

技术分享

其实传入的参数就是Eprocess地址,没错。

我们在程序这里下断点:

技术分享

单步运行观察局部变量的值:

技术分享

二者正好相差0x2e0,说明我们定位EPROCESS的地址和ImageFileName的地址都没错啊。那么为什么前边那样用就得不到正确的结果呢?

这时候我们再去单步刚才出问题的那段代码:

技术分享

同样的方式单步,发现ImageFileName的位置不可读

技术分享

发现为什么不可读了么,仔细一看,因为正常情况下你应该获得地址0xfffffa80`01923320,而你这里是0x00000000`01923329。

所以如果要在这种方法基础上进行修改,就要改为:

技术分享

这样再运行就可以正常输出结果了。

 

《Windows驱动开发技术详解》之Windows内存管理

标签:

原文地址:http://www.cnblogs.com/predator-wang/p/5521573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!