mach_ header 64位和__PAGE_ZERO段64位

mach_header 64bit and __PAGEZERO segment 64bit

本文关键字:64位 ZERO PAGE mach header      更新时间:2023-10-16
const struct mach_header *mach = _dyld_get_image_header(0);
struct load_command *lc;
struct segment_command_64 *sc64;
struct segment_command *sc;
if (mach->magic == MH_MAGIC_64) {
    lc = (struct load_command *)((unsigned char *)mach + sizeof(struct mach_header_64));
    printf("[+] detected 64bit ARM binary in memory.n");
} else {
    lc = (struct load_command *)((unsigned char *)mach + sizeof(struct mach_header));
    printf("[+] detected 32bit ARM binary in memory.n");
}
for (int i = 0; i < mach->ncmds; i++) {
    if (lc->cmd == LC_SEGMENT) {
        sc = (struct segment_command *)lc;
        NSLog(@"32Bit: %s (%x - 0x%x)",sc->segname,sc->vmaddr,sc->vmsize);
    } else if (lc->cmd == LC_SEGMENT_64) {
        sc64 = (struct segment_command_64 *)lc;
        NSLog(@"64Bit: %s (%llx - 0x%llx)",sc64->segname,sc64->vmaddr,sc64->vmsize);
    }
    lc = (struct load_command *)((unsigned char *)lc+lc->cmdsize);
}

当我在32Bit中运行此代码时,我得到正常输出:

__PAGEZERO (0 - 0x1000) 
But on 64Bit: __PAGEZERO (0 - 0x100000000) 

__PAGEZERO goes from 0x1000 to over 0x100000000的大小,是否有任何修复方法或解决方案可以解决为什么会出现这种情况?

在64位体系结构中制作一个大的__PAGEZERO非常有意义。64位系统的地址范围,即使像x86_64那样"裁剪"了高16位,也允许大量内存(x86_64的48位地址空间为256TB的内存地址空间(。在未来的某个时候,这很可能会被认为是"小"的,但现在,最大的服务器有1-4TB,所以有很大的增长空间,更普通的机器有16-32GB。

还要注意,实际上没有内存被占用。它只是"保留的虚拟空间"(也就是说,"它永远不会被使用"(。它占用的资源绝对为零,因为它没有映射在页面表中,物理上也不存在。它只是文件中的一个条目,它告诉加载器为它保留这个空间,永远不能使用,因此"受到保护"。这一部分的实际"数据"大小为零,因为实际上什么都没有,只是"确保没有使用"。因此,如果这个部分的大小发生变化,您的实际文件大小不会变大或变小。如果它根本不存在,它会小几个字节(节描述的大小(。但这确实是唯一能产生任何影响的东西。

__PAGEZERO的目的是捕获NULL指针取消引用。通过在内存开始时保留一大块内存,通过NULL指针进行的任何访问都将被捕获,应用程序将中止。在32位体系结构中,类似于:

int *p = NULL;
int x = p[0x100000]; 

很可能会成功,因为在0x400000(4MB(时,代码空间开始(试图写入这样的位置可能会崩溃,但读取会起作用——当然,假设代码空间实际上是从那里开始的,而不是地址范围内的其他地方

编辑:

该演示文稿显示,ARM是64位处理器sapce的最新加入者,它也在使用48位虚拟地址空间,并强制执行规范地址(前16位需要都是相同的值(,以便在未来进行扩展。换句话说,64位ARM处理器上可用的虚拟空间也是256TB。