0

由于 PIE 二进制的性质,二进制中的所有数据都不能通过绝对地址访问。
所以,有两种相对访问数据的方式

两种方式

  1. 在执行期间,加载程序GOT在入口处加载数据的位置。
    以及对该地址的二进制访问。

  2. 使用位置计算数据的地址_GLOBAL_OFFSET_TABLE,并访问它。



但是,我看到了另一种相对访问数据的方法。
在下面的二进制中,二进制更改了<.text>部分的代码。
这很奇怪。

.global main
main:
 push stderr


我将它编译成 pie 二进制文件。

jiwon@jiwon$ gcc -fPIE -pie -o test test.s
jiwon@jiwon$ objdump -D test_pie | grep "<main>" -A5
000005c0 <main>:
 5c0:   ff 35 00 00 00 00       pushl  0x0
 5c6:   66 90                   xchg   %ax,%ax
 5c8:   66 90                   xchg   %ax,%ax
 5ca:   66 90                   xchg   %ax,%ax


正如你在上面的拆卸中看到的,push stderr组装成pushl 0x0.
而且..当我执行二进制文件时,

pwndbg> disass /r main
Dump of assembler code for function main:
=> 0x004005c0 <+0>: ff 35 48 18 40 00   push   DWORD PTR ds:0x401848
   0x004005c6 <+6>: 66 90   xchg   ax,ax
   0x004005c8 <+8>: 66 90   xchg   ax,ax
   0x004005ca <+10>:    66 90   xchg   ax,ax

<.text> 部分更改为指向stderr!
我认为这很奇怪,因为<.text>部分-WX在一般应用程序中具有权限。
但在这种情况下,<.text>RWX许可。


问题:

  1. 为什么会发生这种情况?为什么编译器选择使用这种奇怪的方式,而不是上面的两种方式
  2. 这是馅饼二进制中的常见情况..?
4

1 回答 1

0

位置无关的可执行文件是由编译器和链接器的组合工作产生的,而不仅仅是由链接器。在您的情况下,您传递GCC了一个已经组装的代码,可能不是编译器使用该PIE标志生成的代码。

链接器不是产生相对加载和存储指令的人,编译器会这样做,并且链接器确保正确放置正确的重定位部分等。

于 2018-10-05T12:45:23.960 回答