hacktricks/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
2024-12-12 11:39:29 +01:00

7.8 KiB

WWW2Exec - GOT/PLT

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Basic Information

GOT: Global Offset Table

The Global Offset Table (GOT) is a mechanism used in dynamically linked binaries to manage the addresses of external functions. Since these addresses are not known until runtime (due to dynamic linking), the GOT provides a way to dynamically update the addresses of these external symbols once they are resolved.

Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a function is first called, its actual address is resolved by the dynamic linker and stored in the GOT. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.

PLT: Procedure Linkage Table

The Procedure Linkage Table (PLT) works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary calls an external function for the first time, control is passed to an entry in the PLT associated with that function. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the GOT.

Therefore, GOT entries are used directly once the address of an external function or variable is resolved. PLT entries are used to facilitate the initial resolution of these addresses via the dynamic linker.

Get Execution

Check the GOT

Get the address to the GOT table with: objdump -s -j .got ./exec

Observe how after loading the executable in GEF you can see the functions that are in the GOT: gef➤ x/20x 0xADDR_GOT

Using GEF you can start a debugging session and execute got to see the got table:

GOT2Exec

In a binary the GOT has the addresses to the functions or to the PLT section that will load the function address. The goal of this arbitrary write is to override a GOT entry of a function that is going to be executed later with the address of the PLT of the system function for example.

Ideally, you will override the GOT of a function that is going to be called with parameters controlled by you (so you will be able to control the parameters sent to the system function).

If system isn't used by the binary, the system function won't have an entry in the PLT. In this scenario, you will need to leak first the address of the system function and then overwrite the GOT to point to this address.

You can see the PLT addresses with objdump -j .plt -d ./vuln_binary

libc GOT entries

The GOT of libc is usually compiled with partial RELRO, making it a nice target for this supposing it's possible to figure out its address (ASLR).

Common functions of the libc are going to call other internal functions whose GOT could be overwritten in order to get code execution.

Find more information about this technique here.

Free2system

In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the free GOT address to point to system and to write inside a chunk "/bin/sh". This way when this chunk is freed, it'll execute system("/bin/sh").

Strlen2system

Another common technique is to overwrite the strlen GOT address to point to system, so if this function is called with user input it's posisble to pass the string "/bin/sh" and get a shell.

Moreover, if puts is used with user input, it's possible to overwrite the strlen GOT address to point to system and pass the string "/bin/sh" to get a shell because puts will call strlen with the user input.

One Gadget

{% content-ref url="../rop-return-oriented-programing/ret2lib/one-gadget.md" %} one-gadget.md {% endcontent-ref %}

Abusing GOT from Heap

A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to overwrite the pointer of a function, usually free.
Then, pointing free to system and freeing a chunk where was written /bin/sh\x00 will execute a shell.

It's possible to find an example here.

Protections

The Full RELRO protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the GOT table read only after it:

{% content-ref url="../common-binary-protections-and-bypasses/relro.md" %} relro.md {% endcontent-ref %}

References

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}