我正在调查沙箱中运行的恶意软件发出的一组Windows API系统调用,以便了解其恶意意图。不幸的是,我很难理解文档中描述的ZwMapViewOfSection函数:https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-zwmapviewofsection
现在,我确实理解了这个函数与页表中物理内存到虚拟内存的映射有关。除此之外,我发现文档晦涩难懂,对初学者也不友好。我也不明白为什么他们把物理内存块称为“段”而不是“帧”(如果这就是他们所指的--我不清楚)。有没有人能更直观地解释一下这个系统调用,以及它一般做了什么?这是对程序的常见系统调用,还是仅限于恶意软件?谢谢。
发布于 2018-10-03 15:39:41
对于普通程序来说,进行这种调用(当然不是直接调用)是非常常见的,每个程序至少会在初始化期间多次调用它(ZwMapViewOfSection是在执行用于实现代码本身的可执行部分的内存回退时使用的)。在正常的程序代码中不是很常见,但也不是不常见。当程序执行动态DLL加载时尤其常见,但合法程序也可以出于自己的原因执行内存映射IO。
它操作内存节对象(我也从来没有真正理解过这个名称),内存节是磁盘文件和内存映射区域之间链接的一部分,节是通过ZwCreateSection创建的,或者用ZwOpenSection打开,然后另一部分用ZwMapViewOfSection开始发挥作用。
到底是哪一部分让你感到困惑呢?了解这一点将使提供信息性回复变得容易得多。
发布于 2021-02-10 20:13:47
据我所知,您必须打开文件并获取一个文件句柄,然后将其映射到CreateFileMapping
,后者将调用NtCreateSection
,后者将调用MmCreateSection
。如果文件是第一次映射,则首先创建新的段对象和控制区,然后根据是为数据、图像还是页面文件支持的MiCreateDataFileMap
创建节,调用MiCreateImageFileMap
或MiCreatePagingFileMap
。
MiCreateDataFileMap
设置子对象和截面对象。在正常情况下,只创建一个子部分,但在某些特殊情况下会创建multiple subsections are used,例如,如果文件非常大。对于数据文件,子对象字段SubsectionBase
留空。取而代之的是,片段对象的SegmentPteTemplate
字段被正确设置,必要时可以使用它来创建PPTE。这将PPTE的创建推迟到第一次映射视图,从而避免了在映射非常大的数据文件时浪费内存。注意: PTE是充当原型PTE的PTE,而_MMPTE_PROTOTYPE
是指向原型的PTE。
MiCreateImageFileMap
创建section对象,加载指定文件的PE头并验证它,然后为PE头创建一个子节,为每个PE节创建一个子节。如果映射了一个非常小的图像文件,则只会为整个文件创建一个子部分。除了子区段之外,还创建用于每个子区段的相关PPTE,并且根据相关PE区段的保护设置来设置其页面保护标志。当映射和访问视图时,这些PPTE将用作构建真实PTE的模板。
在创建一个段之后,可以通过从它创建一个视图将它映射到地址空间。传递给CreateFileMapping
的flProtect
指定了节对象的保护。对象的所有映射视图必须与此保护兼容。将dwMaximumSizeLow
和dwMaximumSizeHigh
指定为0,以便将dwMaximumSizeHigh
自动设置为文件的长度。
然后将返回的节对象句柄传递给MapViewOfFile
,它将在其上调用NtMapViewOfSection
,后者调用MmMapViewOfSegment
,后者调用MmCreateMemoryArea
,这是将视图映射到进程的VAD的位置,并将保护dwDesiredAccess
提供给MapViewOfFile
,作为VAD条目涵盖的所有PTE的保护类型。MapViewOfFile
中的dwNumberOfBytesToMap = 0
和dwFileOffsetLow = 0
映射整个文件。
当映射一个视图时,我相信所有的PPTE都指向原型PPTE,并受到PPTE的保护。对于图像文件,PPTE已经初始化为子PTE。对于数据文件,视图的PPTE需要初始化为子PTE。现在创建了视图的VAD条目。VAD条目保护并不总是反映它所覆盖的PTE的保护,因为它可以覆盖多个子部分和这些子部分中的多个块。
当映射中的地址第一次被实际访问时,子部分原型PTE被按需填充,分配的物理页被该范围的I/O写填充,并且进程PTE被填充该相同的地址。对于图像,在创建子部分以及从图像中的节头特征导出的保护信息时,PPTE已经填充,它只是使用该地址和其中的保护信息填充PTE。
当PTE从进程工作集被修整时,工作集管理器访问PFN以定位PPTE地址,减少共享计数,并将PPTE地址插入PTE中。
我不确定何时发生VAD PTE (其原型位和原型地址为0xFFFFFFFF0000
,并且无效)。我认为PPTE总是在它们的虚拟地址上,只要创建了VAD条目就可以指向它们。
https://stackoverflow.com/questions/52621403
复制相似问题