libc
, the C standard library) to provide the bulk of the fucntionality.
For example, each ELF file will not carry their own version of puts
compiled within it - it will instead dynamically link to the puts
of the system it is on. As well as smaller binary sizes, this also means the user can continually upgrade their libraries, instead of having to redownload all the binaries every time a new version comes out.libc
to have a constant base address, i.e. be loaded in the same area of memory every time it's run, but remember that ASLR exists. Hence the need for dynamic linking. Due to the way ASLR works, these addresses need to be resolved every time the binary is run. Enter the PLT and GOT.puts()
in C and compile it as an ELF executable, it is not actually puts()
- instead, it gets compiled as [email protected]
. Check it out in GDB:puts
actually is - so it jumps to the PLT entry of puts
instead. From here, [email protected]
does some very specific things:puts
, it jumps to the address stored there.libc
functions. [email protected]
, for example, will contain the address of puts
in memory. When the PLT gets called, it reads the GOT address and redirects execution there. If the address is empty, it coordinates with the ld.so
(also called the dynamic linker/loader) to get the function address and stores it in the GOT.libc
, and the GOT is within the binary.libc
function, for example system
, we can just redirect execution to its PLT entry and it will be the equivalent of calling system
directly; no need to jump into libc
.libc
function's address. If you perhaps have an arbitrary read, it's trivial to leak the real address of the libc
function and therefore bypass ASLR.[email protected]
and passing the GOT entry of puts as a parameter. This causes puts
to print out its own address in libc
. You then set the return address to the function you are exploiting in order to call it again and enable you toflat()
packs all the values you give it with p32()
and p64()
(depending on context) and concatenates them, meaning you don't have to write the packing functions out all the timelibc
of functions you use and stores them in the GOT[email protected]
is equivalent to calling the function itselflibc
base