堆溢出必备基础——Glibc内存管理与ptmalloc源码分析(1)
一、什么是glibc?glibc与libc的区别?
glibc和libc都是linux下的c函数库,但是libc是linux下的ANSI C的函数库,glibc是GUN C的函数库。
glibc是gnu发布的libc库,也是c运行库。glibc是linux系统中最底层的API(应用程序开发接口),几乎其他任何的运行库都会依赖于glibc。glibc封装了linux操作系统所提供的系统服务。
延伸问题——ANSI C和GUN C是什么玩意?
ANSI C:美国国家标准协会(ANSI)对C语言发布的标准
GUN C:简单理解为GUN组织对C语言发布的标准
二、linux进程内存布局
32位模式下进程内存经典布局
这种布局是linux内核2.6.7以前的默认进程内存布局形式,mmap区域和栈区域相对增长,这意味着堆中只有1GB的内存地址空间可以使用,继续增长就会进入mmap映射区域,这是该内核版本的缺陷。这是由于32位模式地址空间限制造成的,所以内核引入了另一种虚拟地址空间的布局形式。但是对于64位系统而言,它提供了巨大的虚拟地址空间,这种布局就相当好。
32位模式下进程默认内存布局
从上图可以看到,栈至顶向下扩展,并且栈是有界的。堆至底向上扩展,mmap映射区域至顶向下扩展,直至耗尽虚拟地址空间中的剩余区域,这种结构便于C运行时库使用mmap映射区域和堆进行内存分配。上图的布局形式是在内核2.6.7以后才引入的,这是32位模式下进程的默认内存布局形式。
64位模式下进程内存布局
在64位模式下各个区域的起始位置是什么呢?对于AMD64系统,内存布局采用经典内存布局,text的起始地址为,text的起始地址为0x0000000000400000,堆紧接着BSS段向上增长,mmap映射区域开始位置一般设为TASK_SIZE/3。
下面的图我其实看不懂(不知道怎么算地址)直接贴出来:
上图是X86_64下的linux进程的默认内存布局形式,这只是一个示意图,当前内核默认配置下,进程的栈和mmap映射区域并不是从一个固定地址开始,并且每次启动时的值都不一样,这是程序启动时随机改变这些值的设置,使得使用缓冲区溢出进行攻击更加困难。在CTF中,这种保护叫做ASLR。当然也可以让进程中的栈和mmap映射区域从一个固定位置开始,只需要设置全局变量randomize_va_space的值为0,这个变量默认值为1。用户可以通过设置/proc/sys/kernel/randomize_va_space来停用该特性,也可以用如下命令:
sudo sysctl -w kernel.randomize_va_space=0
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!