ptmalloc堆概述-mmap系统调用
1 概述
malloc 会使用 mmap来创建独立的匿名映射段。匿名映射的目的主要是可以申请以0填充的内存,并且这块内存仅被调用进程所使用。
Malloc分配大于128KB时,直接使用mmap进行分配。
2 Mmap
2.1 API
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length);
#define PROT_READ 0x1 /* Page can be read. */ #define PROT_WRITE 0x2 /* Page can be written. */ #define PROT_EXEC 0x4 /* Page can be executed. */ #define PROT_NONE 0x0 /* Page can not be accessed. */
#define MAP_SHARED 0x01 /* Share changes. */ #define MAP_PRIVATE 0x02 /* Changes are private. */ #define MAP_ANONYMOUS 0x20 /* Don't use a file. */ #define MAP_ANON MAP_ANONYMOUS |
系统调用
#define __NR_mmap 90
#define __NR_mmap2 192
#define __NR_munmap 91
strace显示mmap函数调用的是__NR_mmap2系统调用
2.2 查看内存映射
l cat /proc/<pid>/maps
millionsky@ubuntu-16:~$ cat /proc/`pgrep mmap`/maps 08048000-08049000 r-xp 00000000 08:01 11143393 /home/millionsky/tmp/mmap 08049000-0804a000 r--p 00000000 08:01 11143393 /home/millionsky/tmp/mmap 0804a000-0804b000 rw-p 00001000 08:01 11143393 /home/millionsky/tmp/mmap 09a4c000-09a6d000 rw-p 00000000 00:00 0 [heap] f75c3000-f75c4000 rw-p 00000000 00:00 0 f75c4000-f7771000 r-xp 00000000 08:01 29491224 /lib32/libc-2.23.so f7771000-f7772000 ---p 001ad000 08:01 29491224 /lib32/libc-2.23.so f7772000-f7774000 r--p 001ad000 08:01 29491224 /lib32/libc-2.23.so f7774000-f7775000 rw-p 001af000 08:01 29491224 /lib32/libc-2.23.so f7775000-f7779000 rw-p 00000000 00:00 0 f7794000-f7796000 r--p 00000000 00:00 0 [vvar] f7796000-f7798000 r-xp 00000000 00:00 0 [vdso] f7798000-f77ba000 r-xp 00000000 08:01 29491203 /lib32/ld-2.23.so f77ba000-f77bb000 rw-p 00000000 00:00 0 f77bb000-f77bc000 r--p 00022000 08:01 29491203 /lib32/ld-2.23.so f77bc000-f77bd000 rw-p 00023000 08:01 29491203 /lib32/ld-2.23.so fff85000-fffa6000 rw-p 00000000 00:00 0 [stack] |
第二列是相关的权限:
PROT_NONE = Page can not be accessed
PROT_READ r = read
PROT_WRITE w = write
PROT_EXEC x = execute
MAP_SHARED s = shared
MAP_PRIVATE p = private (copy on write)
第三列表示文件偏移,0表示不是从文件中映射得到的;
第四列表示主从(Major/mirror)的设备号,0表示不是从文件中映射得到的;
第五列表示表示着Inode 号,0表示不是从文件中映射得到的;
2.3 实例
Ubuntu 16.04 64上测试
Mmap.c
测试
millionsky@ubuntu-16:~/tmp$ gcc -m32 mmap.c -o mmap millionsky@ubuntu-16:~/tmp$ ./mmap Welcome to private anonymous mapping example::PID:9329 Before mmap After mmap, addr=0xf74f2000 After munmap |
Mmap调用之前
可以看到程序、libc、ld都有mmap的内存块,大小分别为4K、16K、4K。
millionsky@ubuntu-16:~/tmp$ cat /proc/`pgrep mmap`/maps 08048000-08049000 r-xp 00000000 08:01 11143393 /home/millionsky/tmp/mmap 08049000-0804a000 r--p 00000000 08:01 11143393 /home/millionsky/tmp/mmap 0804a000-0804b000 rw-p 00001000 08:01 11143393 /home/millionsky/tmp/mmap 0857a000-0859b000 rw-p 00000000 00:00 0 [heap] f7513000-f7514000 rw-p 00000000 00:00 0 f7514000-f76c1000 r-xp 00000000 08:01 29491224 /lib32/libc-2.23.so f76c1000-f76c2000 ---p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c2000-f76c4000 r--p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c4000-f76c5000 rw-p 001af000 08:01 29491224 /lib32/libc-2.23.so f76c5000-f76c9000 rw-p 00000000 00:00 0 f76e4000-f76e6000 r--p 00000000 00:00 0 [vvar] f76e6000-f76e8000 r-xp 00000000 00:00 0 [vdso] f76e8000-f770a000 r-xp 00000000 08:01 29491203 /lib32/ld-2.23.so f770a000-f770b000 rw-p 00000000 00:00 0 f770b000-f770c000 r--p 00022000 08:01 29491203 /lib32/ld-2.23.so f770c000-f770d000 rw-p 00023000 08:01 29491203 /lib32/ld-2.23.so ffa06000-ffa27000 rw-p 00000000 00:00 0 [stack] |
Mmap之后
可以看到,新分配的内存和已存在的内存合并了
millionsky@ubuntu-16:~/tmp$ cat /proc/`pgrep mmap`/maps 08048000-08049000 r-xp 00000000 08:01 11143393 /home/millionsky/tmp/mmap 08049000-0804a000 r--p 00000000 08:01 11143393 /home/millionsky/tmp/mmap 0804a000-0804b000 rw-p 00001000 08:01 11143393 /home/millionsky/tmp/mmap 0857a000-0859b000 rw-p 00000000 00:00 0 [heap] f74f2000-f7514000 rw-p 00000000 00:00 0 f7514000-f76c1000 r-xp 00000000 08:01 29491224 /lib32/libc-2.23.so f76c1000-f76c2000 ---p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c2000-f76c4000 r--p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c4000-f76c5000 rw-p 001af000 08:01 29491224 /lib32/libc-2.23.so f76c5000-f76c9000 rw-p 00000000 00:00 0 f76e4000-f76e6000 r--p 00000000 00:00 0 [vvar] f76e6000-f76e8000 r-xp 00000000 00:00 0 [vdso] f76e8000-f770a000 r-xp 00000000 08:01 29491203 /lib32/ld-2.23.so f770a000-f770b000 rw-p 00000000 00:00 0 f770b000-f770c000 r--p 00022000 08:01 29491203 /lib32/ld-2.23.so f770c000-f770d000 rw-p 00023000 08:01 29491203 /lib32/ld-2.23.so ffa06000-ffa27000 rw-p 00000000 00:00 0 [stack] |
unmap之后
申请的内存段已经没有了
millionsky@ubuntu-16:~/tmp$ cat /proc/`pgrep mmap`/maps 08048000-08049000 r-xp 00000000 08:01 11143393 /home/millionsky/tmp/mmap 08049000-0804a000 r--p 00000000 08:01 11143393 /home/millionsky/tmp/mmap 0804a000-0804b000 rw-p 00001000 08:01 11143393 /home/millionsky/tmp/mmap 0857a000-0859b000 rw-p 00000000 00:00 0 [heap] f7513000-f7514000 rw-p 00000000 00:00 0 f7514000-f76c1000 r-xp 00000000 08:01 29491224 /lib32/libc-2.23.so f76c1000-f76c2000 ---p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c2000-f76c4000 r--p 001ad000 08:01 29491224 /lib32/libc-2.23.so f76c4000-f76c5000 rw-p 001af000 08:01 29491224 /lib32/libc-2.23.so f76c5000-f76c9000 rw-p 00000000 00:00 0 f76e4000-f76e6000 r--p 00000000 00:00 0 [vvar] f76e6000-f76e8000 r-xp 00000000 00:00 0 [vdso] f76e8000-f770a000 r-xp 00000000 08:01 29491203 /lib32/ld-2.23.so f770a000-f770b000 rw-p 00000000 00:00 0 f770b000-f770c000 r--p 00022000 08:01 29491203 /lib32/ld-2.23.so f770c000-f770d000 rw-p 00023000 08:01 29491203 /lib32/ld-2.23.so ffa06000-ffa27000 rw-p 00000000 00:00 0 [stack] |
3 附件
4 参考文档
1. https://ctf-wiki.github.io/ctf-wiki/pwn/heap/heap_overview/