Skip to content

Address leak

Tek bir runtime pointer (libc, heap, stack ya da PIE base) elde et; böylece diğer tüm adresler sabit offset ile çıkar ve ASLR/PIE yenilir.

Mechanism

Note

ASLR/PIE her çalıştırmada bir object'in (libc, PIE binary, heap, stack) yüklendiği base'i randomize eder; bu yüzden adresler hardcode edilemez. Ama randomization sadece base'i kaydırır — map'lenmiş bir object'in içindeki her symbol ondan sabit bir offset'te kalır. Dolayısıyla kimliği bilinen tek bir leak'lenmiş pointer base'i açığa çıkarır: base = leaked - known_offset, ve tüm address space hesaplanabilir hale gelir.

GOT, kanonik leak target'ıdır: binary'nin içinde yaşar (PIE base'den sabit offset) ama her imported fonksiyonun canlı, randomize edilmiş libc adresini saklar. Bir GOT entry'sini leak'lemek libc base'ini verir.

Walkthrough

puts@plt üzerinden GOT leak (ret2plt, x86-64) — bir GOT entry'sini yazdır, sonra libc base bilinerek yeniden exploit yapmak için main'e dön:

from pwn import *
payload = flat(
    b'A'*padding,
    POP_RDI, elf.got['puts'],   # rdi = &GOT[puts]
    elf.plt['puts'],            # puts(&GOT[puts]) -> prints live libc addr
    elf.symbols['main'],        # loop back to re-exploit
)
p.sendline(payload)
leak = u64(p.recvline().strip().ljust(8, b'\x00'))
libc.address = leak - libc.sym['puts']
log.info("libc base: %#x", libc.address)

Format-string %p leak — stack'i gez ve stack/PIE/libc pointer'ı olan slot'u seç:

input:  %6$p
output: 0x7ffff7a5d780     # a libc pointer; subtract its known offset

Uninitialized-memory leak — programın hiç sıfırlamadığı bir struct/buffer field'ını okumak, kalıntı (geride kalmış) libc/heap pointer'larını döndürür (uninitialized pointer access ile örtüşür).

Her durumda beklenen davranış: program ham bir runtime pointer yayar; base'i geri kazanmak için symbol'ün offset'ini çıkar, sonra hardcode edilmiş target'larla bir ret2libc / ROP chain kur.

Mitigation

  • Leak, bug'ın kendisi değil enabler'dır — savunmalar altta yatan güvenlik açığını hedef alır (format string, OOB read, uninitialized memory).
  • Full RELRO + kısıtlı output (attacker adreslerinin puts'lanmaması) ve hassas buffer'ların sıfırlanması leak yüzeyini azaltır.
  • Tek başına bir leak zararsızdır; bir control-flow primitive'i ile eşleşmesi gerekir.

References