基本dll地址总是不同且哈希值不匹配

Base dll address always different and hash mismatch

本文关键字:哈希值 不匹配 是不同 dll 地址 基本      更新时间:2023-10-16

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

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

我的问题是:

  1. 为什么模块的基址总是不同的?我知道dll可以在不同的地址加载,但是是什么触发了这种行为?(DLL总是有相同的基址吗?)基址总是0x02XXXXXX类型,而其他人得到的不变地址是0x6F000000。

  2. 为什么散列不匹配?即使模块在不同的地址加载,我仍然从base+someoffset读取相同数量的字节。不仅哈希值不同,每次运行程序时都不一样。因此,我怀疑基地地址实际上是错误的,一些可疑的事情正在发生。我比较了我的dll和他的dll的md5,它们是相同的,所以正在加载的库是完全相同的。

代码中的步骤:

  1. 获取进程句柄(CreateToolhelp32Snapshot, Process32Next)
  2. 枚举加载模块(EnumProcessModules)
  3. 查找模块名称(GetModuleFileNameEx),获取句柄
  4. 为模块基址添加额外的偏移量(模块内的偏移量)
  5. ReadProcessMemory(hProcess, base_of_module+some_additional_offset, dllBuffer_to_read_into, 0x100000, &numRead)模块读取X字节,其中0x100000 溢出模块大小

这个程序正在做的是将内存中的dll内容与"干净"哈希进行比较,以发现恶意软件/黑客等的篡改

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

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

为了使您的哈希计算健壮,您需要考虑重定位。原则上,您可以读取重定位表,并在执行哈希计算时考虑重定位。然而,这可能是非常棘手的正确。

  1. 配置为在每个进程中加载的其他DLL被加载到该系统上。例如,如果你安装了网络摄像头或鼠标软件,就会发生这种情况,这些软件往往会在每个进程中加载它们的dll。当然,如果这个DLL被加载在一个阻止你的首选基址被使用的地址,你的DLL将被重新定位。

  2. 搬迁。当加载一个DLL时,加载程序解析.reloc段,并将对绝对地址的修正直接写入加载的DLL映像中。为了创建正确的散列,您还必须读取重定位目录并纠正这些加载器对DLL的修改。

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

EMET所做的事情之一是强制ASLR(地址空间布局随机化),也就是说,它强制所有dll在随机地址加载,即使它们没有配置为使用ASLR。这大大增加了攻击者利用漏洞的难度。