从Win7开始,创建进程的函数变为了nt!NtCreateUserProcess(R0),看了科锐的《64位Windows创建64位进程逆向分析》受到了一些启发,由于自己研究了内存管理很久,所以我想尽自己一点薄力(我不是科锐的...hhhh),填补这个过程中文件映射的部分,同时也填补我上一篇《XX之NTDLL随机化“逆向”(XP系统)》文章中所留下的一些空白。
重要的事情说三遍:大佬勿喷、大佬勿喷、大佬勿喷! 自己是个业余选手..hh..,为了写这篇文章,怕嘴闲着,去买了一扎葡萄28元!!! 我家的猪都不敢这么卖....
由于是文件映射,所以必然少不了这几位主角:FILE_OBJECT、SEGMENT、SECTION、CONTROL_AREA,外加用户层访问内存的入口VAD(BITMAP就不提了它只是VAD的一种“缓存”方式)。由于上述文章中没有过多的提及关于文件映射的这块内容,所以我必须自己在nt!NtCreateUserProcess函数流程的海洋中寻找与这些对象相关的函数影子。
研究系统:由于头铁,所以直接拿了一个Win10 x64 1909或20HX的版本研究(搭建虚拟机太麻烦),所以我就以此版本为研究对象。
寻找相关函数的思路有两种:
第一种,对特定对象中的特定字段进行下断点(这种需要知道相关对象的创建时机),然后进行栈回溯查看周围的堆栈情况。
第二种,直接从头开始从下找,人肉筛选其重点函数(参考之前一些前辈的文章)。
我选择的是第二种,但是也引用了一些技巧。首先我对nt!NtCreateUserProcess函数进行下断点,断下后,使用 uf /c /D 地址,查看此函数的的下一层的函数调用关系,然后进行人肉筛选一些不重要的函数。
uf /c /D 地址
结果如下图:
筛选规则很简单,就是对一些解引用、内存操作、参数检查的函数一律PASS掉,因为我们的核心是文件映射相关(这里参考《64位Windows创建64位进程逆向分析》系列)。
经过筛选最终如下图(此时还没有动态调试哦~):
开始调试验证流程和探究其细节:
提出问题和猜想:
由于在《XX之NTDLL随机化“逆向”(XP系统)》文章中我提到了,在Win7乃至Win10中,有3种情况:
将一个exe程序重复启动,查看其基址
第一次启动:
在桌面移动一下坐标再次启动:
将一个exe移动一下再回到原来位置启动,查看其基址。
第一次启动:
此时,我将这个exe移动(剪切的方式)到某个盘符下,再移动回来。
很明显,此时,对于同一个软件这个基址就发生了变化。
3. 通过修改exe一些字节,进行重新运行
没改之前运行:
修改一些字节:
很明显,此时,exe在一个位置,但是其内容发生了变化,也会导致其基址改变。
通过这三个实验我想提出的观点是:对于文件加载是存在“缓存”机制的。而问题是如何进行缓存呢?这是下文开始探讨的问题。
首先我给出各个对象的框架关系图:
接下来按照所过滤的函数流程开始逐层分析,验证上面图片中对象的关系和寻找如何进行“缓存”?
第一个分析的便是:IoCreateFileEx函数,该函数会生成一个FILE_OBJECT对象。通过分析可以得出IopCreateFile的第一个参数是file_object的Handle,所以只需跟踪即可。
经过分析会得出以下结果:
此时已经产生FILE_OBEJCT、SEGMENT、CONTROL_AREA对象。此时图形更新为:
由于此时还没有创建EPROCESS和SECTION对象,所以用户层是无法看到映射的内容的。所以重点就在于nt!MmCreateSpecialImageSection函数的身上。
我先简单的划分一下,可以看的更清楚一些,最终图如下:
由于我是直接运行了一个exe程序,所以必然流程走的是MiCreateImageOrDataSection函数。
伪代码参考:https[:]//github.com/jxy-s/herpaderping/blob/main/res/DivingDeeper.md
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-8-10 22:29
被烟花易冷丶编辑
,原因: