我正在运行安装了所有更新的64位MS Windows 7。大约1或2周前,我注意到无论何时重新启动OS,与ntdll.dllkernel32.dll之类的系统库相对应的虚拟内存页面(无论进程如何)都略有不同。

我不是在谈论已加载模块的基地址,因为我知道由于ASLR而导致的更改。我说的是已加载模块的实际内容,据我所知,这些内容不受Windows上ASLR实现的影响。比较一个操作系统重新启动之前(上半部)和之后(底部停止)后捕获的ntdll.dll的2个二进制实例:差异不大。但是,还有更多。这些DLL的大小不会改变,只是在特定位置只有一些字节。

我获得了2个二进制实例,它们在上图中使用Process Hacker进行了比较,如下所示:


右键单击一个进程,然后选择“属性”

转到“内存”选项卡并向下滚动,直到找到几个名称为ntdll.dll的条目:Image(Commit)

双击其中一项(我选择了具有856kB的一项)。
按“保存...”按钮将内容存储到HDD上的二进制文件中。
<问题1:是什么导致这些字节更改?

子问题1.1:是某种保护机制吗?

子问题1.2:它是最近引入的吗?

子问题1.3:可以将其禁用吗?

问题2:这些变化的字节在DLL代码中代表什么?

评论

运行dumpbin / relocations ntdll.dll并将列出的地址与更改进行比较。

@IgorSkochinsky我确实按照您的指示运行dumpbin,并将列出的地址与更改进行了比较。实际上,似乎没有将重定位应用于ntdll.dll。我图片中可见的更改是由于系统DLL与/ DYNAMICBASE链接的缘故。

#1 楼


问题1:导致这些字节更改的原因是什么?


这些似乎是基于DLL的重定位表应用的标准重定位修复程序。
子问题1.1:是某种保护机制吗?


否。


子问题1.2:是的



子问题1.3:可以禁用吗?


不容易,不行。


问题2:这些变化的字节在DLL的代码中代表什么?


地址。 />

评论


感谢您的回答。您是否也乐于提及变更的地址?它是所有功能的地址还是仅其中一部分?

–本尼
2014年3月18日14:02

它不仅仅用于函数地址;简而言之,每当代码或数据引用虚拟地址而不是相对虚拟地址时,该引用都需要具有重定位表条目。请参阅download.microsoft.com/download/9/c/5/…的4.2和5.6节。

–詹森·格夫纳(Jason Geffner)
2014年3月18日14:15

感谢您澄清这一点。关于此问题的最后一个问题:是否有Win32 API可以将所有VA映射/转换为映射图像文件的RVA?还是这是stackoverflow的问题?

–本尼
2014年3月18日14:32在

不需要API ... VA-图像基址= RVA(因为“ RVA”的“相对”部分是相对于图像基址的)。

–詹森·格夫纳(Jason Geffner)
2014年3月18日14:35



您在上面的注释中发布的代码未使用“重定位表”。请参考我上面链接到的PE COFF文档,并在stackoverflow.com上询问其他软件开发问题

–詹森·格夫纳(Jason Geffner)
2014年3月19日14:44

#2 楼

您所看到的是修改了偏移量以反映更改后的基地址。如果图像库发生更改,则需要调整所有与基库无关的内容(无论是全局变量,调用还是其他)。

PE文件可以具有用于此的重定位表。可以,就像标准.exe文件中通常没有的那样,因为直到出现ASLR(模块的随机基址)才有必要。

对于DLL,基址很可能会更改为它取决于已加载的其他文件,因此它们几乎总是有一个基本重定位表,该表显示“如果基地址与XYZ不同,则将增量添加到以下位置”。

如果您是古玩基本重定位表的外观如何,我建议您检查以下内容:


请参见以下实现自定义PE文件加载器的代码。
搜索IMAGE_DIRECTORY_ENTRY_BASERELOC以查看代码处理重定位目录。