description |
---|
11/06/2023 |
Libraries are loaded at runtime and function addresses (external) are resolved at the time of calling.
We can actually observe this behavior using lsof /lib/x86_64-linux-gnu/libc.so.6
so we can view which processes a particular library is linked to.
lsof /lib/x86_64-linux-gnu/libc.so.6
COMMAND PID FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1842 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
pipewire 1849 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
pipewire- 1850 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
pulseaudi 1851 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
dbus-daem 1861 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
gnome-key 1867 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
gvfsd 1872 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
gvfsd-fus 1882 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
tracker-m 1899 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
xdg-docum 1900 mem REG 8,3 2216304 1445905 /usr/lib/x86_64-linux-gnu/libc.so.6
Resolving of addresses of shared libraries at runtime is performed by the linker (a.k.a ld-linux.so
); this process is called relocation.
These are essentially "dummy" entries in binaries that are later filled in at runtime.
With readelf --relocs <binary>
, we can see a table of symbol addresses in an entry that will be resolved and patched into a specific offset at runtime.
readelf --relocs aslr1
Relocation section '.rela.dyn' at offset 0x490 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000403ff0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000403ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000404040 000600000005 R_X86_64_COPY 0000000000404040 stdout@GLIBC_2.2.5 + 0
000000404050 000700000005 R_X86_64_COPY 0000000000404050 stdin@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x4f0 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000404018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000404020 000400000007 R_X86_64_JUMP_SLO 0000000000000000 gets@GLIBC_2.2.5 + 0
000000404028 000500000007 R_X86_64_JUMP_SLO 0000000000000000 setvbuf@GLIBC_2.2.5 + 0
.text
,.data
,.rodata
, and.bss
- Relocation sections:
.got
,.plt
,.got.plt
, and.plt.got
This section is where the linker puts the addresses of resolved global variables.
Using the previous readelf
command, you can see a relocation table consisting of relocations inside of the .rela.dyn
section that are of type GLOB_DAT
and COPY
point to offsets in the .got
section of the binary.
This section contains "code stubs" that will either be in charge of jumping to the correct address or will call the linker to resolve the address.
This section is in charge of either containing the right address of the resolved function or points back to .plt
to trigger a look up to resolve a particul address.
Entries in .rela.plt
of type JUMP_SLO
, point to offsets in the .got.plt
.
- Function gets called for the first time and it jumps to an address in the
.plt
which can also be described as (function@plt
). - It will then jump to an address saved in the GOT for PLT (
.got.plt
). - This points back to the next instruction in
.plt
. - After, it will perform a look up and patch the address that is found within
.got.plt
with the right address which can also be described as (function@GLIBC
) and will call it.