0x01 简介
1.各种段的作用
ELF .plt:库函数插桩所在;
ELF .got:输入符号指针
.bss:未初始化 数据;
2.mmap缺点
- 1.分配字节数必须是4096字节的倍数,只能以内存页为单元管理内存,经过内核很慢。
3.按需分配内存,
dllmaloc,Doug Lea开发并发布到公共社区;
Linux的glibc里的ptmalloc(Posix Thred aware fork of dllmalloc),
malloc的多线程实现
FreeBSD里的jemalloc(被用在Firefox,Android)
Windows里的Segment heap,NT heap
kmalloc(linux内核内存分配器),kalloc(ios内存分配器)
有动态分配器管理的内存—>堆。
C++程序,函数scanf、printf都要使用堆。
4.ptmalloc/glibc提供的对堆的管理函数
1 | malloc() 分配内存 |
为什么要有calloc?因为未初始化的数据可能导致data disclosure。
5.现代化的技术
ASLR(Adress Space Layout Randomlization, 地址空间布局随机化)
NX
PIE
RELRO
Stack Canary
6.Data Segment
ptmalloc在分配小内存时不使用mmap,用另一种内存管理方法brk() ;在大片分配时使用mmap;
一开始从零开始
- 由系统调用
brk
和sbrk
管理,或许这两个 系统调用不再遵循POSIX标准。- sbrk(NULL) return 数据段的当前末尾
- sbrk(num) 扩充当前数据段num个字节
- brk(addr ) 扩充当前数据段一直到addr位置
写一段测试代码,捕捉malloc的场景,不要使用printf和puts,因为其内部可能会使用malloc;
1 | char msg[]="Start malloc()!"; |
7.为什么堆带来了危险?
程序员:
忘记释放内存?
忘记指针所指;
忘记已经释放的内存有哪些;
堆管理器:追求性能,安全之后再考虑。
8.一些检测和防御手段
Valgrind使用测试样例找到一些通常 错误,比如忘记释放内存,资源耗尽;
glibc的严格模式: 会让程序变慢
- export MALLOC_CHECK=1
- export MALLOC_PERTURB=1
- export MALLOC_MMAP_THRESHOLD=1 #所有内存分配都通过,仍旧可以绕过
0x02 Dynamic Allocator Misuse
任何分配器、库和函数的使用都有开销overhead,分配器开发者为了速度引入optimization和cache,只保证速度,正确的使用堆由程序员确保,由此便带来安全问题。