ASLR in Windows
众所周知,ASLR会使得PE文件的加载基址随机化,但有时候我们还是能够利用固定的地址,指向kernel32.dll ntdll.dll等dll文件中的特定指令,这是为什么呢?
参考资料:
前言
Windows和Linux下的ASLR区别很大。
在Linux下,ASLR的实现分为两个部分
- 系统部分,根据
/proc/sys/kernel/randomize_va_space中设置的等级,影响栈、库、mmap、堆(stack .so mmap heap)基址的随机性。 - 编译器部分,由
PIE选项决定编译得到程序是否是地址无关的,如果是,程序加载基址和全局数据地址(.text .data .bss)就可以随机化。
在Windwos下,ASLR可由 Visual Studio 下的一个链接器选项——随机基址(/DYNAMICBASE)控制。
开始实验
ASLR与程序基址的关系
开启ASLR
使用visual studio生成一个可执行程序Exploime.exe,开启随机基址

使用windbg加载Exploime.exe,然后使用lm命令查看已加载模块的基址

重启windbg,重复上面操作

发现,和之前一样。
重启电脑,再来一次,得到

发现各个基址出现变化。
关闭ASLR
关闭随机基址,重新生成Exploime.exe

使用windbg加载Exploime.exe,然后使用lm命令查看已加载模块的基址

重启windbg,重复上面操作

和上面一致,重启电脑,再来一次,得到

发现关闭了ASLR的模块(Exploitme)基址没有变化,其余默认开启了ASLR的系统模块基址发生了变化。
ASLR与堆栈基址的关系
开启ASLR
开启ASLR后,可以看出两次运行堆栈地址的变化:


关闭ASLR
未开启ASLR时,两次运行程序,查看堆栈地址结果如下,完全一致,不过可以看出其他模块的ASLR还是发挥了作用的:


静态比较
使用Lord PE查看开启ASLR与不开启ASLR程序节的区别,发现前者比后者多一个.reloc节,用于存储重定位信息。


结论
ASLR与程序基址之间的关系
Windows(至少Win10)下的ASLR机制,对程序基址的影响,只在系统启动时发挥作用,系统运行过程中,各个模块的基址不会变化。
(和我预想中不太一样,本来以为只有特定的dll是这样,但是上面可以看到一个普通的可执行程序Exploitme也是这样)。
ASLR与堆栈基址之间的关系
Windows(至少Win10)下,开启ASLR后,程序的堆栈基址每次运行时都是随机的。