Due to the nature of the PIE binary, all data in binary cannot be accessed by absolute address.
So, there are two ways to access the data relatively
TWO Way
During execution, loader loads the data's location at
GOT
entry.
And binary access to that address.Calculate the address of data using
_GLOBAL_OFFSET_TABLE
location, and access to it.
But, I saw another way to access data relatively.
In below binary, binary changed <.text>
section's code.
It was very weird.
.global main
main:
push stderr
I compiled it into pie binary.
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
As you can see above disassembly, push stderr
assembled into pushl 0x0
.
And.. When I execute the binary,
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
The <.text> section changed to point the stderr
!
I think It's very weird because <.text>
section has -WX
permission in general application.
But In this case, <.text>
is RWX
permission.
Question:
- Why this happens? Why compiler choose to use this weird way, instead of above TWO Way?
- Is this common situation in pie binary..?
Position independent executable is produced by combined work of compiler and linker, not just by the linker. In your case, you passed
GCC
an already assembled code, probably not what the compiler would have produced with thePIE
flag.The linker is not the one who produces relative load and store instructions, the compiler does that, and the linker makes sure proper relocation sections are placed correctly and such.