基本DLL地址始终不同并且哈希不匹配

时间:2014-07-08 14:03:28

标签: c++ winapi dll

我创建了一个程序,它从进程的加载dll(模块)中读取X字节并对它们进行哈希处理,以将它们与硬编码的干净哈希进行比较。该模块的基地址始终相同(在XP和7上由不同的人在几台不同的计算机上测试),并且哈希值也始终相同。

但是对于一个人来说,基地址总是不同的,并且哈希值也总是不同的(每次运行时都不同)。他正在使用Windows 7 Ultimate。

我的问题是:

  1. 为什么模块的基地址总是不同?我知道dll可以加载到不同的地址,但是什么触发了这种行为? (Is DLL always have the same Base Address?)基址始终是0x02XXXXXX类型,而其他人获得的永不改变的地址是0x6F000000。

  2. 为什么哈希不匹配?即使模块加载到不同的地址,我仍然从base + someoffset读取相同数量的字节。哈希不仅不同,每次运行程序时都不同。因此,我怀疑基地址实际上是错误的,并且有些可疑。我比较了我的dd和他的dll的md5,它们是相同的,因此加载的库是完全相同的。

  3. 代码中采取的步骤:

    1. 获取流程处理(CreateToolhelp32SnapshotProcess32Next
    2. 枚举已加载的模块(EnumProcessModules
    3. 按名称(GetModuleFileNameEx)查找特定模块并获取句柄
    4. 向模块基址添加附加偏移量(模块内的偏移量)
    5. 使用ReadProcessMemory(hProcess, base_of_module+some_additional_offset, dllBuffer_to_read_into, 0x100000, &numRead)从模块中读取X字节,其中0x100000 溢出模块大小
    6. 这个程序正在做的是将内存中的dll内容与“干净”哈希进行比较,以发现对恶意软件/黑客/等的篡改。

3 个答案:

答案 0 :(得分:6)

你的方法无法成功。 DLL的基地址只是加载程序的指南。加载程序可以选择在该地址加载DLL。如果它这样做,它不需要修复任何绝对引用。

但是,如果请求的地址不可用(进程中的其他内容已经保留了请求的地址范围)或者加载程序选择不使用请求的地址(例如ASLR),那么DLL将被加载到某些地址其他地址。然后重定位表将用于修改绝对引用。

为了使哈希计算更加健壮,您需要考虑重定位。原则上,您可以读取重定位表,并在执行哈希计算时考虑重定位。但是,要想做到这一点可能会非常棘手。

答案 1 :(得分:2)

  1. 在该系统上加载了一些其他DLL,配置为在每个进程中加载​​。这可以是例如如果您安装网络摄像头或鼠标软件,这些往往会强制他们的DLL在每个进程中加载​​。当然,如果将此DLL加载到阻止您使用首选基址的地址,则会重新定位您的DLL。

  2. 重定位。加载DLL时,加载程序会解析.reloc部分,并将对绝对地址的更正直接写入加载的DLL映像。为了创建正确的哈希,您还必须读取重定位目录并更正DLL的这些加载器修改。

答案 2 :(得分:0)

最可能的原因是EMET,即Microsoft的增强型缓解体验工具包。

EMET所做的一件事就是强制执行A​​SLR(地址空间布局随机化),即强制所有DLL在随机地址加载,即使它们没有配置为使用ASLR。这使攻击者更难以利用漏洞。