是否可以将elf标头中的默认虚拟地址更改为0?

时间:2013-10-18 02:42:49

标签: linux elf

我可以将elf中的默认虚拟地址(ph_vaddr)更改为0x0。这会允许访问空指针??或者内核不允许加载地址0?

我只是想知道,如果我将某些部分的p_vaddr更改为.text为0x0,linux是否允许这样做?是否存在一些约束,即虚拟地址只能在某个值之后才能启动?每当我尝试使用ld --section-start设置.text vaddr时,它会在0到9999之间的任何地方被杀死。我想知道发生了什么事?

2 个答案:

答案 0 :(得分:2)

  

我可以将elf中的默认虚拟地址(ph_vaddr)更改为0x0。

是的,事实上,PIE(位置无关)可执行文件通常是如何链接的。

echo "int main() { return 0; }" | gcc -xc - -fPIE -pie -o a.out
readelf -l a.out | grep LOAD | head -1

LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000

注意:上面创建了ET_DYN类型的可执行文件。

  

这会允许访问空指针吗?

没有。当内核发现可执行文件的.e_type == ET_DYN时,它会将其所有段重新定位到其他位置。

您还可以使用ET_EXEC制作.p_vaddr == 0类型的可执行文件,如下所示:

echo "int main() { return 0; }" | gcc -xc - -o a.out -Wl,-Ttext=0
readelf -l a.out | grep LOAD | head -1
  LOAD           0x0000000000200000 0x0000000000000000 0x0000000000000000

内核将拒绝运行它:

./a.out
Killed

答案 1 :(得分:0)

您可以mmap(2) MAP_FIXED(void*)0开始,但我认为您不应该这样做。

我不知道更改elf(5)中的虚拟地址是否会有效。您是否在某段中谈到p_vaddr

实际上,你真的不应该在Linux上的应用程序代码中使用NULL地址,特别是如果其中一些代码是用C编码的,因为NULL指针具有非常特殊的含义,包括编译器。特别是,基于NULL不可解除引用的事实,进行了一些优化。

众所周知,GCC确实优化了,例如,

 x = *p;
 if (!p) goto wasnull;

只是x= *p;,因为如果p被取消引用,则不能NULL; GCC正确地对应用程序代码进行优化(不适用于独立的代码)。

内核通常也在进行Address Space Layout Randomization