• 虚拟内存地址

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。

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

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

  • 在驱动中使用链表

DDK提供了一个双向链表结构

作为指向链表的一个表头,而节点的结构都要由程序员自己定义,如这里定义的结构如下:

链表操作代码如下:

运行会输出:

  • Lookaside结构

频繁申请内存会导致一个问题,就是内存中产生“空洞”。如下图所示,如果内存中先后申请了三块,某时刻内存2被回收后,如果再想分配一块略微大于内存块2的内存,就会申请失败。

DDK提供了一种机制类解决这个问题,就是使用Lookaside。可以把Lookaside对象想象成一个内存容器,在初始的时候,它先向Windows申请了一块比较大的内存,以后程序员每次申请内存的时候不是直接向Windows申请,而是向Lookaside对象申请内存。Lookaside一般会在以下情况使用:(1)程序员每次申请固定大小的内存;(2)申请和回收的操作十分频繁。

相应代码如下:

有输出结果:

《Windows驱动开发技术详解》之Windows内存管理的更多相关文章

  1. Windows驱动——读书笔记《Windows驱动开发技术详解》

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...

  2. 《Windows驱动开发技术详解》之分层驱动程序

    分层驱动程序概念 分层的目的是将功能复杂的驱动程序分解成多个简单的驱动程序.一般来说,他们是指两个或两个 以上的驱动程序,它们分别创建设备对象,并且形成一个由高到低的设备对象栈.IRP请求一般会被传送 ...

  3. 《Windows驱动开发技术详解》之IRP的同步

    应用程序对设备的同步异步操作: 大部分IRP都是由应用程序的Win32 API函数发起的.这些Win32 API本身就支持同步和异步操作.例如,ReadFile.WriteFile和DeviceIoC ...

  4. 《Windows驱动开发技术详解》之HelloDDK

    编写如下代码:

  5. 【原创】《windows驱动开发技术详解》第4章实验总结二

    1 实验要求(WDM驱动)     2 编写过程   2.1 确立整体架构   2.1.1 入口函数——DriverEntry   (1)作用 设置pDriverObject结构体,注册AddDevi ...

  6. 《Windows驱动开发技术详解》之自定义StartIO

    自定义StartIO 系统定义的StartIO队列只能使用一个队列(DDK提供的StartIO内部只有一个队列),这个队列将所有的IRP进行处理化.例如,读.写操作都会混在一起进行串行处理.然而,有时 ...

  7. 《Windows驱动开发技术详解》之驱动程序的同步处理

    中断请求级 中断请求被分为软件中断和硬件中断两种,这些中断都映射成不同级别的中断请求级.每个中断请求都有各自的优先级别,正在运行的线程随时都可以被中断打断,进入到中断处理程序.优先级高的中断来临时,处 ...

  8. 《Windows驱动开发技术详解》之驱动程序调用驱动程序——通过设备指针调用其他驱动程序

    本节介绍“手动”构造各个IRP,然后将IRP传递到相应驱动程序的派遣函数里. 获得设备指针 每个内核中的句柄都会和一个内核对象的指针联系起来.ZwCreateFile内核函数可以通过设备名打开设备句柄 ...

  9. 《Windows驱动开发技术详解》之读写操作

    缓冲区方式读写操作 设置缓冲区读写方式:

随机推荐

  1. 删除和创建ms sql的分区文件

    今天测试ms sql 的表分区的时候,不小心搞错了分区的条件.然后我想重新做一次,操作流程如下(按顺序) 1:删除SCHEME DROP  PARTITION SCHEME TestSPScheme ...

  2. 关于scanf的返回值

    今天写一个小程序时误用while(scanf("%d",&b)!=a),以为scanf的返回值就是输入的值. 其实真相是: scanf返回接收到的变量值的个数. int a ...

  3. How to use php serialize() and unserialize()

    A PHP array or object or other complex data structure cannot be transported or stored or otherwise u ...

  4. 顺序栈和链式栈(C++实现)

    顺序栈,是一种基于数组的存储表示. 实现类代码如下: template<class T> class SeqStack{ T *element; int top; int maxSize; ...

  5. SpringMVC通过注解获得参数

    SpringMVC可以通过RequestParam注解来映射获得参数,具体用法如下: 例子: 配置过程省略 1.新建controller类 package com.loger.controller; ...

  6. Link方式导入java项目

    一.环境说明 我用的是eclipse3.3.2,并安装了myeclipse的插件. 二.工程文件说明 一共三个文件夹: javacode:存放Java源文件,包含多个子文件夹,每个子文件夹表示一个单独 ...

  7. android 5.0 -- Ripple 效果

    Ripple 水波纹效果,也就是涟漪效果. 波纹效果有两种: 1,波纹有边界:波纹涟漪效果只是显示在控件内部 android:background="?android:attr/select ...

  8. 第七十七节,CSS3前缀和rem长度单位

    CSS3前缀和rem长度单位 学习要点: 1.CSS3前缀 2.长度单位rem 本章主要探讨HTML5中CSS在发展中实行标准化的一些问题,重点探讨CSS3中新属性前缀问题和新的单位rem. 一 CS ...

  9. 使用jQuery的hover事件在IE中不停闪动的解决方法

    在使用jQuery的hover事件时,经常会因为鼠标滑动过快导致菜单不停闪动的情况,相信很多朋友都遇到过自己做的纵向下拉菜单不停的收缩,非常的讨厌.今天在给一个网站设计菜单时也遇到了这个情况,结果在百 ...

  10. C socket指南

    1.介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措? ...