首页
社区
课程
招聘
[求助]一个疑点:内核模块的SizeOfImage是实际内核模块占用的大小吗?
发表于: 2015-10-26 21:48 9100

[求助]一个疑点:内核模块的SizeOfImage是实际内核模块占用的大小吗?

2015-10-26 21:48
9100
最近做一个驱动,有一个需求是dump一个内核空间的内核模块(比如驱动)的占用的内存,于是我就编写代码先找到这个模块,然后通过模块的LDR_DATA_TABLE_ENTRY结构的SizeOfImage取得模块的大小,再从模块DllBase开始进行memcpy,拷贝这段SizeOfImage大小的内存,但是copy某些模块期间却会发生0x00000050异常,查了该异常的说法:
The PAGE_FAULT_IN_NONPAGED_AREA bug check has a value of 0x00000050. This indicates that invalid system memory has been referenced.
我理解应该是这段内存无效,用windbg 来dd出错的内存,果然都是??号,但是明明内核大小指示这段内存属于这个模块,难道加载器在load模块PE的时候只是把空间留出来却没有实际分配这些内存,本人对内核的内存管理只是粗浅的认识,故望大虾or高手帮忙指点指点。谢谢了啊

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 267
活跃值: (438)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
2
PE 内核加载和应用层的加载是有不同的地方。内核区分分页与非分页以及加载初始化后可丢弃内存段。同时内核加载又区分应用进程空间与系统进程空间内存的交互。你直接 copy  基本没有哪个内核模块可以被你 copy 不蓝屏的!
2015-10-27 09:03
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢楼上的兄弟。
确实如所说。疑问正在这里:
1)如果copy非分页内存,方法是由应用程序调用DeviceIoControl,而驱动用IoControl方式来接受指令执行copy时,IRQL并非DPC_LEVEL,而是在其下,也就是说缺页异常实际上能处理,那么即使内核模块处于分页内存区仍然应该能copy,不知理解对否。
2)加载内核态PE时,可丢弃段是在啥时候丢弃的,最终加载器丢弃该段后为啥不修改SizeOfImage,让内核模块参数更加准确?如果这样,产生一个新的问题,如何确切的知道内核模块的内存分布呢?
2015-10-27 09:43
1
雪    币: 267
活跃值: (438)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
4
分页内存 在不同的进程空间是不同的,这是需要跨进程内存访问
可丢弃段应该是在驱动入口函数返回后丢弃的,你可以在驱动入口函数返回前访问 该驱动的 PE  SizeOfImage  指定大小的空间数据 只要在 DPC_LEVEL 下访问 包括 分页、非分页和可抛弃段以及PE头部信息。

当用户程序 IO 驱动时 就不能访问到可抛弃段以及PE头部信息,除非跨进程访问运行驱动入口函数的进程地址空间(一般是系统进程)才能访问到PE头部信息,但是可抛弃段数据还是不能访问的因为映射已经丢弃这段数据了;同时分页段应该是被映射到用户进程的内核地址空间进行运行,这时对非分页的访问也不会有问题的,非分页在高于3的级别上访问才可能出现问题,但是我们普通的驱动程序一般最高就到3了,除非你搞硬件中断驱动。(我的陈述你需要自己验证,如有错误的地方请指正,我已经好久不编程了,只根据我的记忆说而已)
2015-10-27 16:48
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢指点!
我现在要做的是用一共用户进程调用驱动的IoControl来dump某段内核空间内存。按照我之前理解,内核空间的虚拟内存在各个进程是共享的,即映射到相同的物理内存,系统在建立进程时是把内核空间这部分的PTE完整拷贝到新的进程的内存分配表中的。如果是这样,实际上在驱动中拷贝内核空间的内容和当前进程应该是无关的。
现在遇到的问题是按照枚举出的内核模块的SizeOfImage来作为大小,模块的加载地址作为开始地址拷贝的时候,到某些地址就会出现PAGE_FAULT_IN_NONPAGED_AREA 异常,仔细研究了这个异常,应该是访问到无效内存地址导致的,我猜测是当驱动加载完后,实际有些段就删除了,甚至有些驱动把DriverEntry标记为INITCODE,也会被加载器在加载完成后从内存摘离,但是系统这样做的目的无非是减少内存浪费,也就是说把这些“空洞”释放了,少占物理内存,因为驱动一般都是加载在非分页内存区的。而SizeOfImage只是加载器根据PE文件中段的Size加起来并页对齐后计算的一个数值,并不代表模块实际占用的内存大小(虽然应该代表,但被优化掉了)。
现在的问题是,无论是不是这个原因,内核空间中的模块理论占据的空间中存在无效区域,那么怎么探测这些无效区域而只拷贝有效区域呢,我试过用__try __except来包围拷贝的代码,但是根本捕捉不到异常,几经查找才知道PAGE_FAULT_IN_NONPAGED_AREA这个异常系统根本不分发到SEH:
PAGE_FAULT_IN_NONPAGED_AREA (50)

Invalid system memory was referenced. This cannot be protected by try-except,

it must be protected by a Probe.

但是如何Probe内核空间的内存是否有效呢?ProbeForRead/Write是探测用户空间的。
如果有那位高人知道,望不吝赐教。
2015-10-27 22:09
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不知道Windbg是如何dump整个内存空间的啊啊。
2015-10-27 22:10
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
帮你顺一下,
1,0x50是缺页错误
2,sizeofimage是一个理论最大值,实际加载时会有很多缺页
3,如果你就是单纯的读取内核内存,对于缺页的解决就是以?? 号的形式提供,意思就是空白无法读取,如果你要处理内核缺页,那麻烦就大喽,因为int0E没这功能。遇到NonPage直接三精。我记得原来有人提供了一种通过异常hook来解决的办法,我试了试不太理想。
2015-10-28 04:05
0
雪    币: 267
活跃值: (438)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
8
以前内核好像用 MmIsAddressValid  可以 ,不过PE加载中 sizeofimage 值也不一定就是准确数据,这个需要内存块粒度的校正才是准确值(这个完全是个人曾经遇到的小知识,印象深刻)
2015-10-28 09:00
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢楼上两位的指点!
to:dppdpp,说的没错,哈哈,我其实很想用??提供,可惜内核不给我处理访问异常的机会啊,0x50异常没发按正常思路捕捉,哈哈。我也考虑过直接hook缺页异常,但是这样风险和工作量都不小,暂时放弃。
to:linziqingl。MmIsAddressValid  ,原来一直以为是探测usermode地址,刚又看了下msdn,貌似可用来探测kernelmode地址,我马上试试看。thx了。
现在还有个思路,用分页表来探测模块在内存的布局。
试试看,重在实践。
2015-10-28 10:33
0
雪    币: 1
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
搞定了,原来用MmIsAddressValid检验以下就行了,呵呵。
感谢linziqingl的提点以及所有帮忙的同志;-)
2015-10-29 15:20
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
这样拷贝出来的文件就不完整了
2015-12-28 21:05
0
游客
登录 | 注册 方可回帖
返回