ASLR 地址空间随机化
ASLR,全称为 Address Space Layout Randomization,地址空间布局随机化。该技术在 kernel 2.6.12 中被引入到 Linux 系统,它将进程的某些内存空间地址进行随机化来增大入侵者预测目的地址的难度,从而降低进程被成功入侵的风险。当前 Linux、Windows 等主流操作系统都已经采用该项技术。
Linux 平台上 ASLR 分为 0,1,2 三级,用户可以通过内核参数 randomize_va_space 进行等级控制,不同级别的含义如下:
- 0 = 关
- 1 = 半随机;共享库、栈、mmap() 以及 VDSO 将被随机化
- 2 = 全随机;除了 1 中所述,还会随机化 heap
注:系统默认开启 2 全随机模式,PIE 会影响 heap 的随机化。
通过读写 /proc/sys/kernel/randomize_va_space 内核文件可以查看或者修改 ASLR 等级:
1 2 | $ cat /proc/sys/kernel/randomize_va_space # 查看 ASLR $ echo 0 > /proc/sys/kernel/randomize_va_space # 关闭 ASLR |
开启 ASLR,在每次程序运行时的时候,装载的可执行文件和共享库都会被映射到虚拟地址空间的不同地址处;而关掉 ASLR,则可以保证每次运行时都会被映射到虚拟地址空间的相同地址处。
关掉 ASLR,可以保证在可执行程序和共享库不发生变更的情况下,每次执行时的进程地址空间映射表的一致。我们可通过运行时某动态符号(不知其名)的地址,减去其所在的共享库在地址映射表中起始地址,算出它相对于共享库数据段中的偏移,然后借助 objdump、readelf, nm 等工具查看对应 ELF 文件中全局符号的相对偏移,就可以反推出该符号的名字。这种调试手段对于那些被 strip 掉符号表的程序而言非常有效。
当使用 gdb 调试一个程序时,GDB 会自动关掉 ASLR。可以通过以下命令将它打开:
1 2 | $ (gdb) set disable-randomization off $ (gdb) info poc map # 查看进程地址映射表 |