64位64位和64位__PAGEZERO段

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大小__PAGEZERO goes from 0x1000 to over 0x100000000 ,是否有任何修复它或任何解决scheme,为什么发生这种情况?

在64位体系结构中创build一个大型的__PAGEZERO使得整个过程非常有意义。 64位系统的地址范围,甚至当高级16位像x86_64那样被“裁剪掉”时,允许大量的内存(x86_64的48位地址空间是256TB的存储器地址空间)。 很有可能在未来的某个时候,这会被认为是“小”,但现在最大的服务器有1-4TB,所以有足够的空间成长,而更多的普通机器有16-32GB。

还要注意,没有内存实际上是OCCUPIED。 这只是“保留的虚拟空间”(即“永远不会使用”)。 它占用绝对零的资源,因为它没有映射到页面表中,它不是物理上的。 这只是文件中的一个入口,它告诉加载程序保留这个空间,永远不会被使用,从而“受到保护”。 本节的实际“数据”大小为零,因为实际上没有任何内容,只是“确保这个不被使用”。 因此,如果此部分的大小已更改,则实际文件大小将不会更大或更小。 如果根本不存在的话,它将会变小几个字节(节描述的大小)。 但是这真的是唯一能够改变的地方。

__PAGEZERO的目的是捕获NULL指针的解引用。 通过在内存开始处预留大量内存,通过NULL指针的任何访问都将被捕获,并且应用程序中止。 在32位体系结构中,如下所示:

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

很可能会成功,因为在0x400000(4MB)的代码空间开始(试图写入这样一个位置很可能会崩溃,但阅读将工作 – 当然假设代码空间实际上是从那里开始,而不是在其他地方地址范围。

编辑:

此演示文稿显示,最近进入64位处理器sapce的进入者ARM也使用48位虚拟地址空间,并强制执行规范地址(前16位需要全部为相同的值),因此可以在未来。 换句话说,64位ARM处理器上的虚拟空间也是256TB。