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
后,程序的堆栈基址每次运行时都是随机的。