Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux executable memory mapping

Tags:

elf

An elf executable contains a section table. This sections are mapped to segments when the program is loaded in memory. I think it is the compiler which decide the segments address in memory ? Do you think it is possible for the operating system to change the segments address when the program is loaded.

I am talking about a single elf executable. This is not a library. In fact, i have a binary. I know a function address in memory and i want to hook this function from an external program. I just want to be sure that this address will never change. I won t recompile or change anything in the target program.

like image 910
Bob5421 Avatar asked Oct 25 '25 22:10

Bob5421


1 Answers

An elf executable contains a section table.

False: it is perfectly valid for section table to be stripped from a fully-linked ET_EXEC or ET_DYN binary.

This sections are mapped to segments when the program is loaded in memory.

False: section to segment mapping happens at static link time, not at runtime.

I think it is the compiler which decide the segments address in memory ?

False: it the static linker that decides this for ET_EXEC. For ET_DYN, static linker and runtime loader cooperate.

Do you think it is possible for the operating system to change the segments address when the program is loaded.

For ET_EXEC, the binary is always loaded at the address at which static linker linked that binary. Loading it anywhere else will make the program crash.

For ET_DYN, also known as PIE binary, loading at random address is both possible and expected.

i have a binary. I know a function address in memory and i want to hook this function from an external program. I just want to be sure that this address will never change.

If the binary is of type ET_EXEC, all segments are always loaded at the linked-at address, so yes.

Update:

In a PIE binary, everything will move together (main, foo, _start, etc.) by the same relocation (the relocation will normally vary from run to run; but GDB disables address space randomization, so one must do (gdb) set disable-randomization off).

To find the relocation in GDB, you can do:

(gdb) p &main
(gdb) start
(gdb) p &main

The first value of &main before the process starts should be the same as output from nm test | grep main. The second value (after process started) should be relocated value (where main landed in memory). The difference between the two is (page-aligned) relocation.

To find this relocation at runtime (from within the program itself), one needs to use dl_iterate_phdr() and use dlpi_addr. Documentation.

like image 149
Employed Russian Avatar answered Oct 29 '25 00:10

Employed Russian