【问题标题】:mach_header 64bit and __PAGEZERO segment 64bitmach_header 64bit 和 __PAGEZERO 段 64bit
【发布时间】:2014-04-20 22:37:27
【问题描述】:
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);
}

当我以 32 位运行此代码时,我得到正常输出:

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

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

【问题讨论】:

  • 为什么这是一个需要解决的问题?
  • well 0x100000000 大约是 4.29 GB。我运行它的文件大约是 107kb,这意味着某处一定有错误的计数。
  • 还是对虚拟内存地址的理解有误
  • 正好是 4GB。但是考虑到总内存是 64 位的(实际上,它可能不是完整的 64 位,但无论如何),即使是现在的大型机器也没有超过 1TB 的 RAM,浪费了第一个4GB 的地址空间(我相信不是物理内存)作为“捕获 NULL 指针访问”)就可以了。

标签: c++ ios objective-c c


【解决方案1】:

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

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

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

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

可能会成功,因为代码空间在 0x400000 (4MB) 处开始(尝试写入这样的位置可能会崩溃,但读取会起作用 - 当然假设代码空间实际上是从那里开始而不是在某个地方else 在地址范围内。

编辑:

This presentation 表明,最新进入 64 位处理器空间的 ARM 也在使用 48 位虚拟地址空间,并强制执行规范地址(前 16 位必须是相同的值),因此它可以将来会扩大。换句话说,64 位 ARM 处理器上可用的虚拟空间也是 256TB。

【讨论】:

  • 除了捕获NULL 取消引用之外,在64 位中使用0x100000000 的大小意味着没有32 位指针是有效的。这有助于捕获已编译为 64 位但不是 64 位安全的有缺陷的软件。例如,它复制一个指向int 的指针,然后返回一个指针变量,将其截断。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2014-08-26
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多