首页 > 解决方案 > 从映射的 NULL 指针读取数据

问题描述

检查此代码:

#include <sys/mman.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    char *addr = mmap(NULL, 6, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        return 1;
    }
    strcpy(addr, "abcxyz");
    printf("Mapped into addr=0x%X\n", addr);
    printf("%s\n", addr);
    printf("%s\n", NULL);
}

fd是包含字符串的文件的文件描述符abcxyz 我希望程序在访问 NULL 指针时应该收到 SIGSEGV 但具有讽刺意味的是,我得到了

Mapped into addr=0x0
abcxyz
abcxyz

发生了什么?为什么可以将可访问的数据映射到地址 NULL?有了这种行为,我如何使用它来利用系统?

注意:程序必须在root权限下运行。

注2:行为产生于 Linux XXXXXX 4.4.0-174-generic #204-Ubuntu SMP Wed Jan 29 06:41:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

标签: clinuxlinux-kernelnullmmap

解决方案


发生了什么?

通常,在 处没有映射页面0x0,因此取消引用空指针段错误。但是您在那里明确映射了一个页面,因此它不再出现段错误。

为什么可以将可访问的数据映射到地址 NULL?

您在没有意识到的情况下回答了自己的问题:

注意:程序必须在root权限下运行。

sysctl 通常通过设置为高于 0的vm.mmap_min_addr值来防止这种情况发生。但是,该 sysctl 不适用于以 root 身份运行的进程。

有了这种行为,我如何使用它来利用系统?

你不能,因为如果你能做到mmap,那么你已经在密闭舱口的另一边了

顺便说一句,您的代码在技术上是未定义的行为,因为即使那里有某些东西,您仍在取消引用 NULL。事实上,对于大多数常见的 libcs​​,只有编译器的优化printf才能puts使其工作。


推荐阅读