# PLT and GOT

The **Procedure Linkage Table (PLT)** and **Global Offset Table (GOT)** are sections within an **Executable and Linkable Format** (**ELF**) file that play a significant role in dynamic linking.&#x20;

The purpose of dynamic linking is to reduce the size of binaries by allowing them to rely on system libraries, such as the C standard library (**libc**), to provide the majority of their functionality.

For example, an ELF file **does not include its own version of the '`printf`' function** compiled within it. Instead, it **dynamically links to the '`printf`' function of the system** it is running on. In addition to **smaller binary sizes**, this also means that users can **upgrade their libraries without having to download all the binaries again** each time a new version is released.

## How it works ?

The linking is performed through the cooperation of the **Procedure Linkage Table** (**PLT**) and the **Global Offset Table** (**GOT**).&#x20;

When the '`printf`' function, for example, is called in C and compiled as an ELF executable, it is not included as '`printf`' in the file. Instead, it is compiled as '`printf@plt`' :&#x20;

```wasm
   0x0804925b <+137>:   push   0x804a012
   0x08049260 <+142>:   call   0x8049040 <printf@plt>
   0x08049265 <+147>:   add    esp,0x10
```

The program does not know the actual location of 'printf', so it jumps to the '`printf@plt`' entry instead. When this occurs, '`printf@plt`' performs some specific actions.

* If there isn't a GOT entry, it will resolve it and jump there.
* If there is a GOT entry for `printf`, it jumps to the address stored there.

The GOT is a *massive* table of addresses; these addresses are the actual locations in memory of the `library` functions. `printf@got`, for example, will contain the address of `printf` 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.

{% hint style="info" %}

* Calling the PLT address of a function is equivalent to calling the function itself
* The GOT address contains addresses of functions in `libraries`, and the GOT is within the binary.
  {% endhint %}

## Read tables

Some tools permits to read the PLT and GOT tables :&#x20;

```bash
$ readelf -r chall

Relocation section '.rel.dyn' at offset 0x3bc contains 1 entry:
 Offset     Info    Type            Sym.Value  Sym. Name
0804bffc  00000606 R_386_GLOB_DAT    00000000   __gmon_start__

Relocation section '.rel.plt' at offset 0x3c4 contains 9 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0804c00c  00000107 R_386_JUMP_SLOT   00000000   strcmp@GLIBC_2.0
0804c010  00000207 R_386_JUMP_SLOT   00000000   printf@GLIBC_2.0
0804c014  00000307 R_386_JUMP_SLOT   00000000   fclose@GLIBC_2.1
0804c018  00000407 R_386_JUMP_SLOT   00000000   fread@GLIBC_2.0
0804c01c  00000507 R_386_JUMP_SLOT   00000000   puts@GLIBC_2.0
0804c020  00000707 R_386_JUMP_SLOT   00000000   __libc_start_main@GLIBC_2.0
0804c024  00000807 R_386_JUMP_SLOT   00000000   fopen@GLIBC_2.1
0804c028  00000907 R_386_JUMP_SLOT   00000000   putchar@GLIBC_2.0
0804c02c  00000a07 R_386_JUMP_SLOT   00000000   __isoc99_scanf@GLIBC_2.7
```

{% code overflow="wrap" %}

```python
from pwn import *

elf = ELF("./chall")

print(elf.plt)
# {'strcmp': 134516784, 'printf': 134516800, 'fclose': 134516816, 'fread': 134516832, 'puts': 134516848, '__libc_start_main': 134516864, 'fopen': 134516880, 'putchar': 134516896, '__isoc99_scanf': 134516912}

print(elf.got)
# {'__gmon_start__': 134529020, 'strcmp': 134529036, 'printf': 134529040, 'fclose': 134529044, 'fread': 134529048, 'puts': 134529052, '__libc_start_main': 134529056, 'fopen': 134529060, 'putchar': 134529064, '__isoc99_scanf': 134529068}
```

{% endcode %}

## Resources

{% embed url="<https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got>" %}
