x64 Linux 操作系统上的 32 位二进制堆栈布局

逆向工程 linux x64
2021-06-18 09:07:09

堆栈布局在许多方面都有很好的记录。特别是对于x86系统,因为多年前有许多关于如何在旧的 32 位系统上利用堆栈溢出的教程。

至此我们可以知道,在32位系统上,用户栈从0xc0000000地址开始(这是usermode和kernelmode之间的界限)。

如果我们拿一个运行在x86-64 linux 系统Elf32,这个地址就不一样

我找不到这个地址,但我可以通过 gdb找出它是0xffffe000

(gdb) x $esp 0xffffd4bc: 0xf7e16a83 (gdb) x/w 0xffffdffc 0xffffdffc: 0x00000000 (gdb) x/w 0xffffe000 0xffffe000: Cannot access memory at address 0xffffe000

我们实际上可以看到0xffffe000地址指向一个无效的位置(或者至少该进程没有访问该内存页的适当权限)。

然而,我找不到一个相关的来源,告诉我们x64 linux 上的 x86 程序的 gnu 堆栈从 0xffffe000 开始我做错了吗?

我可以找到告诉我们有关linux-gate.so.1 的消息来源,但我认为这不是重点。

任何想法,逆行者?

2个回答

可以通过查看其内存映射来查看(32 位或 64 位)进程的有效堆栈访问范围我们可以观察id为pidby的进程的内存映射,我的64位机器上cat /proc/pid/maps的a示例32-bit process

...
09b58000-09b79000 rw-p 00000000 00:00 0                    [heap]
...
f7785000-f7787000 rw-p 001c7000 00:23 592106               /usr/lib/libc-2.20.so
...
f77c2000-f77c4000 r--p 00000000 00:00 0                    [vvar]
f77c4000-f77c5000 r-xp 00000000 00:00 0                    [vdso]
...
f77e8000-f77e9000 rw-p 00022000 00:23 592099               /usr/lib/ld-2.20.so
fff9b000-fffbc000 rw-p 00000000 00:00 0                    [stack]

然后,有效范围stack[0xfff9b000, 0xfffbc000),存储器访问的地址高于或等于比0xfffbc000将触发memory access violation异常。根据这篇文章,这个范围是在内核将二进制文件映射到内存时计算的,并且通过几个 函数,对它们来说有趣的输入STACK_TOPTASK_SIZE32 位进程定义的

我有一个部分的答案。

由于个性系统调用,可以确定内存布局最终是0xc0000000还是0xffffe000通过读取ADDR_LIMIT_3GB标志,可以确定32 位进程是映射到0xc0000000还是0xffffe000

我不知道为什么0xffffe000是相关的,除了它比4GB 内存空间的末尾短 8192 字节也许它与内核堆栈大小有关。