上QQ阅读APP看书,第一时间看更新
1.6 地址空间布局随机化
地址空间布局随机化(ASLR,Address Space Layout Randomization)能够让每次加载时的二进制文件、动态库文件、代码段以及数据段的内存地址都是随机的。使用 _dyld_get_image_vmaddr_slide
函数可以获取模块的 ASLR 偏移地址,使用 _dyld_get_image_header
函数可以获取模块的基址。我们编写如下代码获取第一个模块的 ASLR 偏移地址和基址:
intptr_t slide_addr = _dyld_get_image_vmaddr_slide(0);
struct mach_header *mh_addr = _dyld_get_image_header(0);
printf("slide_addr: 0x%x\n", slide_addr);
printf("mh_addr: 0x%x\n",mh_addr);
可以发现,第一次运行上述代码得到的 ASLR 偏移地址是 0x94000
,基址是 0x100094000
。这也可以通过 LLDB(Low Level Debugger,详见 2.5 节)查看:
slide_addr: 0x94000
mh_addr: 0x100094000
(lldb) image list -o -f
[ 0] 0x0000000000094000 /var/containers/Bundle/Application/9B2F1512-812E-4C3A-BBA7-A15DB63FFB1F/
getBaseAddress.app/getBaseAddress(0x0000000100094000)
我们退出程序后再次运行,这次得到的 ASLR 偏移地址是 0xe8000
,基址是 0x1000e8000
。可以看出,程序每次运行的偏移地址和基址都是随机的,一般不会和上次运行时一样:
slide_addr: 0xe8000
mh_addr: 0x1000e8000
(lldb) image list -o -f
[ 0] 0x00000000000e8000 /var/containers/Bundle/Application/9B2F1512-812E-4C3A-BBA7-A15DB63FFB1F/
getBaseAddress.app/getBaseAddress(0x00000001000e8000)
另外,每次重启手机之后,内核中模块的基址也是随机的。