前言
这个问题是 衍生自 malloc 的问题的调试
malloc 虚拟内存分配的调试(1)
malloc 虚拟内存分配的调试(2)
假设我们使用 gdb 或者 gdbserver 启动调试的该测试用例对应的可执行程序
我们可以观察到的现象是 p1, p2, p3 的地址是固定的, 均是类似于 elf 中最大的虚拟地址 直接向上扩展
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x602010 - 0x602030
p1 : 0x602010 - 0x602030
p3 : 0x602440 - 0x602440
[Inferior 1 (process 63076) exited normally]
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x602010 - 0x602030
p1 : 0x602010 - 0x602030
p3 : 0x602440 - 0x602440
[Inferior 1 (process 63080) exited normally]
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x602010 - 0x602030
p1 : 0x602010 - 0x602030
p3 : 0x602440 - 0x602440
[Inferior 1 (process 63081) exited normally]
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x602010 - 0x602030
p1 : 0x602010 - 0x602030
p3 : 0x602440 - 0x602440
[Inferior 1 (process 63082) exited normally]
但是 假设我们直接执行, 我们会发现 地址是在不断变化的, 呵呵
这个就和 brk 的相关初始化机制存在关联了
root@ubuntu:~/ClionWorkStations/HelloWorld# ./Test01Sum
p1 : 0xc56010 - 0xc56030
p1 : 0xc56010 - 0xc56030
p3 : 0xc56440 - 0xc56440
root@ubuntu:~/ClionWorkStations/HelloWorld# ./Test01Sum
p1 : 0x67d010 - 0x67d030
p1 : 0x67d010 - 0x67d030
p3 : 0x67d440 - 0x67d440
root@ubuntu:~/ClionWorkStations/HelloWorld# ./Test01Sum
p1 : 0x7ec010 - 0x7ec030
p1 : 0x7ec010 - 0x7ec030
p3 : 0x7ec440 - 0x7ec440
root@ubuntu:~/ClionWorkStations/HelloWorld# ./Test01Sum
p1 : 0x1af9010 - 0x1af9030
p1 : 0x1af9010 - 0x1af9030
p3 : 0x1af9440 - 0x1af9440
brk 的随机初始化
我们这里 先来看 brk 的随机初始化相关, 因为 这个比较好构造
brk 的初始化有几个地方, 加载 elf program headers 的地方
elf 中各个 program headers 加载完成之后, 会有 start_brk, start_code, end_code, start_data, end_data
之后会有一个 brk 的初始化, 初始化为 elf 中记录的最大的虚拟地址 按照分页上对齐之后的地址
这个就是 我们 gdb 调试的时候, 看到的初始化的 brk, 我们演示的程序中经常为 0x602000
然后 最后一个是 elf 加载过程中 有一个 brk 随机初始化的流程, 如下
brk 的随机初始化具体的处理如下
也就是在 初始化的 brk 之后的 [0 - 8192) 页, 每一页大小为 4k
为什么是 8192?, 这是上面 arch_randomize_brk 传入的 range 为 0x2000000, 然后这里 range >>= PAGE_SHIFT 之后, range 为 8192
我们这次执行, 初始化的 brk 为 0x130d000
然后 测试用例 中 printf 调用 malloc 的时候会调用 brk 来分配空间
看这里的 addr 即为 brk 初始化之后的值, 可以看一下 和上面 加载 elf 之后随机初始化的 地址是一致的, 均为 0x130d000
再来一次, 初始化的 brk 为 0x762000
printf 调用 malloc 分配空间的时候 brk 也是 0x762000
gdb 或者 gdbserver 启动调试的 brk 初始化
brk 在 加载 elf 的 program headers 完成之后的初始化
elf 中映射的虚拟地址的末尾是 6295616 = 0x601040, ALIGN_UP(0x601040, PAGE_SIZE) 根据分页上对齐之后将 brk 初始化为 0x602000
brk 初始化为 6299648 = 0x602000
为什么 gdb/gdbserver 未对 brk 进行随机初始化?
有可能是没有进这个判断, 或者 有什么因素 影响到了 arch_randomize_brk 的计算??
这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法
在启动 gdb 的时候, 默认 禁用aslr, 将这个配置置为 false, 即可以启动 aslr
然后 这里相关, 影响到的应该是这个 random_va_
(gdb) set disable-randomization off
(gdb) show disable-randomization off
Disabling randomization of debuggee's virtual address space is off.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
Breakpoint 1, main (argc=1, argv=0x7ffc8c89b608) at Test01Sum.c:9
9 char *p1 = (char *)malloc(20);
(gdb) c
Continuing.
p1 : 0x19bf010 - 0x19bf030
p1 : 0x19bf010 - 0x19bf030
p3 : 0x19bf440 - 0x19bf440
[Inferior 1 (process 63432) exited normally]
(gdb) delete 1
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x23d2010 - 0x23d2030
p1 : 0x23d2010 - 0x23d2030
p3 : 0x23d2440 - 0x23d2440
[Inferior 1 (process 63433) exited normally]
(gdb) run
Starting program: /root/ClionWorkStations/HelloWorld/Test01Sum
p1 : 0x1c93010 - 0x1c93030
p1 : 0x1c93010 - 0x1c93030
p3 : 0x1c93440 - 0x1c93440
[Inferior 1 (process 63434) exited normally]
linux 系统上面关闭 ASLR
echo 0 > /proc/sys/kernel/randomize_va_space
彩蛋[2022.11.06]
呵呵 为了测试 aslr, 妈的 安装 pwn 把虚拟机搞挂了
又要重新 安装环境啥的了, 悲剧
完
参考
Linux下关闭ASLR(地址空间随机化)的方法