ELF,PIE ASLR以及介于两者之间的所有内容,特别是在Linux中

som*_*iam 5 linker compilation elf aslr

好吧,所以在问我的问题之前,我想介绍一些技术细节,我想确保我是正确的:

位置无关可执行文件 - PIE,是一个无论加载到哪个内存地址都能执行的代码,对吗?

ASLR ------地址空间布局随机化,几乎说明为了保持地址静态,我们会以某种方式随机化它们,

我已经在Linux和基于Unix的系统中特别阅读了实现ASLR是可能的,无论我们的代码是否是PIE,如果它是PIE,所有跳转,调用和偏移是相对的,因此我们没有问题如果不是,请编写一些如何无论代码是可执行的还是共享对象,都会被修改并编辑地址....

对......现在这让我提出几个问题

  1. 如果ASLR可以在不是PIE的代码中实现并且是可执行的并且不共享/可重定位对象(我知道重定位如何在可重定位的对象中工作!!!!)它是如何完成的?,elf格式应该没有任何部分说明代码部分中的函数是什么,所以内核加载器可以修改它,对吧?ASLR应该是内核功能,因此实际上可以是例如包含例如这些指令的可执行文件

    伪代码:

    inc_eax:
     add eax, 5
     ret
    
    main:
     mov eax, 5
     mov ebx, 6
     call ABSOLUTE_ADDRES{inc_eax}
    
    Run Code Online (Sandbox Code Playgroud)

    如果内核可执行加载器没有存储在elf文件中的某个可重定位表中并且不是相对的,以便将可执行文件加载到某个随机地址,那么内核可执行加载器如何知道如何更改地址?

  2. 假设我错了,为了实现ASLR,你必须有一个PIE可执行文件,所有段都是相对的,如何编译C++ OOP代码并使其工作,例如,如果我有一个类的实例使用指向其结构中的虚拟表的指针,并且该虚拟表应该保存绝对地址,因此我无法为使用运行时虚拟表的C++程序编译纯PIE,并且不能再使用ASLR. ...我怀疑虚拟表是否包含相对地址,并且对于某些虚拟函数的每次调用都会有不同的虚拟表...

  3. 我的最后一个也是最不重要的问题是关于ELF和PIE,是否有一些特殊的方法来检测ELF可执行文件是PIE?我对ELF格式很熟悉所以我怀疑它有一种方法但是我可能错了,无论如何如果没有办法,内核加载器如何知道我们的可执行文件是否是PIE,因此它可以在其上使用ASLR

我已经把这一切搞砸了,如果有人能在这里帮助我,我会很感激,感谢提前

Emp*_*ian 15

你的问题似乎是混乱和误解的混乱.

位置无关可执行文件 - PIE,是一个无论加载到哪个内存地址都能执行的代码,对吗?

几乎.甲PIE二进制通常不能被装载到在存储器的任意地址,作为其PT_LOAD分段将有一些对准要求(例如0x400的,或为0x10000).但它可以加载,如果在满足对齐要求的地址加载到内存中,它将正确运行.

ASLR ------地址空间布局随机化,几乎说明为了保持地址静态,我们会以某种方式随机化它们,

我不能以任何有意义的方式解析上述陈述.

ASLR是一种随机化地址空间各部分的技术,以使"已知地址"攻击更加困难.

请注意,ASLR 早于 PIE二进制文件,并且不以任何方式要求PIE.引入ASLR时,它随机放置堆栈,堆和共享库.(非PIE)主要可执行文件的放置不能随机化.

ASLR被认为是成功的,因此扩展为也支持PIE主二进制文件,它实际上是一个特制的共享库(并且具有ET_DYN文件类型).

  1. call ABSOLUTE_ADDRES{inc_eax} 内核可执行加载器如何知道如何更改地址>如果>它们没有存储在某些可重定位表中

简单:在x86上,没有指令call ABSOLUTE_ADDRESS- 所有调用都是相对的.

2 ...我无法为使用运行时虚拟表的C++程序编译纯PIE,而ASLR也不可能.

PIE二进制文件需要重定位,就像共享库一样.PIE二进制文件中的虚拟表的工作方式与它们在共享库中的工作方式完全相同:在将控制权转移到二进制文件之前ld-linux.so.2更新GOT(全局偏移表)PIE.

3 ...是否有一些特殊的方法来检测ELF可执行文件是PIE

简单:PIE二进制文件的ELF文件类型设置为ET_DYN(非PIE二进制文件具有类型ET_EXEC).如果你运行file a.out一个PIE可执行文件,你会发现它是一个"共享库".