main.c gcc -std=c99-6ren">
gpt4 book ai didi

linux - 在 Linux 中如何确定 PIE 可执行文件的文本部分的地址?

转载 作者:行者123 更新时间:2023-12-04 05:10:53 25 4
gpt4 key购买 nike

首先,我尝试对其进行一些逆向工程:

printf '
#include <stdio.h>
int main() {
puts("hello world");
}
' > main.c
gcc -std=c99 -pie -fpie -ggdb3 -o pie main.c
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
readelf -s ./pie | grep -E 'main$'
gdb -batch -nh \
-ex 'set disable-randomization off' \
-ex 'start' -ex 'info line' \
-ex 'start' -ex 'info line' \
-ex 'set disable-randomization on' \
-ex 'start' -ex 'info line' \
-ex 'start' -ex 'info line' \
./pie \
;

输出:
64: 000000000000063a    23 FUNC    GLOBAL DEFAULT   14 main
Temporary breakpoint 1, main () at main.c:4
4 puts("hello world");
Line 4 of "main.c" starts at address 0x5575f5fd263e <main+4> and ends at 0x5575f5fd264f <main+21>.
Temporary breakpoint 2 at 0x5575f5fd263e: file main.c, line 4.

Temporary breakpoint 2, main () at main.c:4
4 puts("hello world");
Line 4 of "main.c" starts at address 0x55e3fbc9363e <main+4> and ends at 0x55e3fbc9364f <main+21>.
Temporary breakpoint 3 at 0x55e3fbc9363e: file main.c, line 4.

Temporary breakpoint 3, main () at main.c:4
4 puts("hello world");
Line 4 of "main.c" starts at address 0x55555555463e <main+4> and ends at 0x55555555464f <main+21>.
Temporary breakpoint 4 at 0x55555555463e: file main.c, line 4.

Temporary breakpoint 4, main () at main.c:4
4 puts("hello world");
Line 4 of "main.c" starts at address 0x55555555463e <main+4> and ends at 0x55555555464f <main+21>.

这表明它是 0x555555554000 + 随机偏移 + 63e .

但后来我尝试 grep Linux 内核和 glibc 源代码 555555554并且没有命中。

哪个代码的哪一部分计算该地址?

我在回答时遇到了这个: What is the -fPIE option for position-independent executables in gcc and ld?

最佳答案

一些互联网搜索 0x555555554000 给出了提示:ThreadSanitizer 存在问题 https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual

Q: When I run the program, it says: FATAL: ThreadSanitizer can not mmap the shadow memory (something is mapped at 0x555555554000 < 0x7cf000000000). What to do? You need to enable ASLR:

 $ echo 2 >/proc/sys/kernel/randomize_va_space

This may be fixed in future kernels, see https://bugzilla.kernel.org/show_bug.cgi?id=66721 ...

 $ gdb -ex 'set disable-randomization off' --args ./a.out


https://lwn.net/Articles/730120/ “稳定的内核更新。”由 hmh(订阅者)于 2017 年 8 月 7 日 20:40 UTC(周一)发布 https://marc.info/?t=150213704600001&r=1&w=2
( https://patchwork.kernel.org/patch/9886105/ , commit c715b72c1ba4 )

Moving the x86_64 and arm64 PIE base from 0x555555554000 to 0x000100000000 broke AddressSanitizer. This is a partial revert of:



恢复的代码是:

b/arch/arm64/include/asm/elf.h
/*
* This is the base location for PIE (ET_DYN with INTERP) loads. On
- * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * 64-bit, this is above 4GB to leave the entire 32-bit address * space open for things that want to use the area for 32-bit pointers. */
-#define ELF_ET_DYN_BASE 0x100000000UL
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)


+++ b/arch/x86/include/asm/elf.h
/*
* This is the base location for PIE (ET_DYN with INTERP) loads. On
- * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * 64-bit, this is above 4GB to leave the entire 32-bit address
* space open for things that want to use the area for 32-bit pointers.
*/
#define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \
- 0x100000000UL)
+ (TASK_SIZE / 3 * 2))


因此,0x55​​5555554000 与 ELF_ET_DYN_BASE macro 有关(在 fs/binfmt_elf.c for ET_DYN as not randomized load_bias 中引用)并且对于 x86_64 和 arm64,它就像 TASK_SIZE 的 2/3。当没有 CONFIG_X86_32 , x86_64 的 TASK_SIZE 为 2^47 - one page in arch/x86/include/asm/processor.h
/*
* User space process size. 47bits minus one guard page. The guard
* page is necessary on Intel CPUs: if a SYSCALL instruction is at
* the highest possible canonical userspace address, then that
* syscall will enter the kernel with a non-canonical return
* address, and SYSRET will explode dangerously. We avoid this
* particular problem by preventing anything from being mapped
* at the maximum canonical address.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)

旧版本:
/*
* User space process size. 47bits minus one guard page.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)

较新的版本也支持 5level __VIRTUAL_MASK_SHIFT of 56 bit - v4.17/source/arch/x86/include/asm/processor.h (但 don't want to use it before enabled by user + commit b569bab78d8d ".. Not all user space is ready to handle wide addresses") )。

因此, 0x555555554000 从公式 向下舍入(通过 load_bias = ELF_PAGESTART(load_bias - vaddr); ,vaddr 为零) (2^47-1page)*(2/3) (或 2^56 用于 larger systems ):
$ echo 'obase=16; (2^47-4096)/3*2'| bc -q
555555554AAA
$ echo 'obase=16; (2^56-4096)/3*2'| bc -q
AAAAAAAAAAA000

2/3 * TASK_SIZE 的一些历史记录:
  • commit 9b1bbf6ea9b2 "use ELF_ET_DYN_BASE only for PIE"有有用的评论:“ELF_ET_DYN_BASE 位置最初是为了让加载程序远离 ET_EXEC 二进制文件......”
  • 不要用 2*TASK_SIZE "[uml-user] [PATCH] x86, UML: fix integer overflow in ELF_ET_DYN_BASE", 2015 溢出 32 位和 "ARM: 8320/1: fix integer overflow in ELF_ET_DYN_BASE", 2015 :

  • Almost all arches define ELF_ET_DYN_BASE as 2/3 of TASK_SIZE. Though it seems that some architectures do this in a wrong way. The problem is that 2*TASK_SIZE may overflow 32-bits so the real ELF_ET_DYN_BASE becomes wrong. Fix this overflow by dividing TASK_SIZE prior to multiplying: (TASK_SIZE / 3 * 2)


  • 在 4.x、3.y、2.6.z 中相同,(davej-history git repo 在哪里?archiveat or.cz)2.4.z,...added in 2.1.54 1997 年 9 月 6 日

  • diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
    +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
    + use of this is to invoke "./ld.so someprog" to test out a new version of
    + the loader. We need to make sure that it is out of the way of the program
    + that it will "exec", and that there is sufficient room for the brk. */
    +
    +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)

    关于linux - 在 Linux 中如何确定 PIE 可执行文件的文本部分的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51343596/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com