21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法

阅读 7

2024-03-14


前言 

这个问题是 衍生自 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 的地方 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_glibc

elf 中各个 program headers 加载完成之后, 会有 start_brk, start_code, end_code, start_data, end_data 

之后会有一个 brk 的初始化, 初始化为 elf 中记录的最大的虚拟地址 按照分页上对齐之后的地址 

这个就是 我们 gdb 调试的时候, 看到的初始化的 brk, 我们演示的程序中经常为 0x602000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_glibc_02

然后 最后一个是 elf 加载过程中 有一个 brk 随机初始化的流程, 如下 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_brk_03

brk 的随机初始化具体的处理如下 

也就是在 初始化的 brk 之后的 [0 - 8192) 页, 每一页大小为 4k 

为什么是 8192?, 这是上面 arch_randomize_brk 传入的 range 为 0x2000000, 然后这里 range >>= PAGE_SHIFT 之后, range 为 8192 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_linux_04

我们这次执行, 初始化的 brk 为 0x130d000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_mm_05

然后 测试用例 中 printf 调用 malloc 的时候会调用 brk 来分配空间 

看这里的 addr 即为 brk 初始化之后的值, 可以看一下 和上面 加载 elf 之后随机初始化的 地址是一致的, 均为 0x130d000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_mm_06

再来一次, 初始化的 brk 为 0x762000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_linux_07

printf 调用 malloc 分配空间的时候 brk 也是 0x762000  

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_glibc_08

gdb 或者 gdbserver 启动调试的 brk 初始化

 brk 在 加载 elf 的 program headers 完成之后的初始化 

elf 中映射的虚拟地址的末尾是 6295616 = 0x601040, ALIGN_UP(0x601040, PAGE_SIZE) 根据分页上对齐之后将 brk 初始化为 0x602000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_linux_09

 brk 初始化为 6299648 = 0x602000 

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_brk_10

为什么 gdb/gdbserver 未对 brk 进行随机初始化? 

有可能是没有进这个判断, 或者 有什么因素 影响到了 arch_randomize_brk 的计算??

21 brk 的初始化malloc 虚拟内存分配的调试(1)malloc 虚拟内存分配的调试(2)这个是因为 alsr 机制 Linux下关闭ASLR(地址空间随机化)的方法_glibc_11

这个是因为 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(地址空间随机化)的方法


 

精彩评论(0)

0 0 举报