非 ASLR DLL 具有每个运行时的随机基数

逆向工程 视窗
2021-07-07 10:33:14

我有一个问题,关于标记为非 ASLR 兼容的 DLL 如何在每次运行加载它的程序时具有不同的基地址。

基本上,这个与 ASLR 不兼容的 DLL(通过 WinDbg-narly 和 确认dumpbin)每次运行时都会显示不同的起始地址。我做了一些研究,我看到的唯一会导致这种行为的事情是加载程序在运行时将库放在不同的地址,以解释具有相同首选基地址的两个库。但是,每次我运行服务(使用相同的配置、相同的启动顺序等)时,我都会为相关库显示不同的基地址,并且这个基地址永远不会重复(在我测试过的 20 多次中) )。我曾假设,如果加载程序为了非 ASLR 目的而移动库,那么最终基地址至少每隔一段时间都会相同,或者在某种程度上是确定性的。

有没有人知道是什么导致了这种行为?

2个回答

位掩码DYNAMIC_BASE标志DllCharacteristics只与系统加载器有关。如果设置,内核实现NtCreateSection将选择一个随机基数,该基数将在每次加载图像时使用,并将继续使用,直到卸载使用这些页面的最后一个剩余图像。

如果在那之后再次重新加载该图像,它的基地址将被重置,并且底层页面将再次重新定位。

但是谁能说内核实现选择的基础是您用户进程中的有效 VA 范围?可能不是,这就是为什么ntdll.dll还要添加自己的重定位层。ntdll.dll装入程序将调用NtMapViewOfSection; 此函数将尝试在底层部分对象指定的基础上映射页面,如果不能,它将无论如何映射它们,但在任何开放的 VA 范围内。在这种情况下NtMapViewOfSection将返回STATUS_IMAGE_NOT_AT_BASE

如果基于用户模式的ntdll.dll加载程序将其视为返回值,它将尝试查找图像的重定位表并处理该表,如果该表不存在,它将(在 Windows 7 的情况下)静默取消映射图像。

因此,在您的情况下,您还需要设置IMAGE_FILE_RELOCS_STRIPPED和删除重定位表 RVA 和大小字段。

我怀疑您正在使用 VS,在这种情况下,DLL的链接器选项/nodynamicbase(请参见此处)实际上除了我上面提到的之外什么都不做,编译器仍然会构建一个重定位表。

因为它是一个 DLL,它可以被加载器自由地重定位,因为 DLL 被设计为可重定位。它还在基本进程被映射后加载,这可能是启用 ASLR 的。如果它是在导入表中后期引用的 DLL,那么它将在它之前的 DLL 之后加载,其中任何一个(或全部)也可能启用了 ASLR。对于所有这些启用 ASLR 的对象,它们中的任何一个最终都可能占用您的 DLL 请求的地址,从而迫使您的 DLL 移动到另一个(随机选择的)位置。