BROP - Blind Return Oriented Programming
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Мета цієї атаки полягає в тому, щоб зловживати ROP через переповнення буфера без будь-якої інформації про вразливий двійковий файл. Ця атака базується на наступному сценарії:
Вразливість стека та знання про те, як її викликати.
Серверний додаток, який перезапускається після збою.
Ви можете знайти більше інформації про ці процеси тут (BF Forked & Threaded Stack Canaries) та тут (BF Addresses in the Stack).
Цей гаджет в основному дозволяє підтвердити, що щось цікаве було виконано гаджетом ROP, оскільки виконання не призвело до збою. Зазвичай цей гаджет буде чимось, що зупиняє виконання і розташоване в кінці ланцюга ROP, коли шукають гаджети ROP, щоб підтвердити, що конкретний гаджет ROP був виконаний.
Ця техніка використовує гаджет ret2csu. І це тому, що якщо ви отримуєте доступ до цього гаджета посеред деяких інструкцій, ви отримуєте гаджети для контролю rsi
та rdi
:
Це будуть гаджети:
pop rsi; pop r15; ret
pop rdi; ret
Зверніть увагу, як з цими гаджетами можна контролювати 2 аргументи функції для виклику.
Також зверніть увагу, що гаджет ret2csu має дуже унікальний підпис, оскільки він буде витягувати 6 регістрів зі стека. Тому відправляючи ланцюг, як:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
Якщо STOP виконується, це в основному означає, що адреса, яка витягує 6 регістрів зі стека, була використана. Або що використана адреса також була адресою STOP.
Щоб усунути цю останню опцію, виконується новий ланцюг, як наступний, і він не повинен виконувати гаджет STOP, щоб підтвердити, що попередній дійсно витягнув 6 регістрів:
'A' * offset + canary + rbp + ADDR
Знаючи адресу гаджета ret2csu, можна вивести адресу гаджетів для контролю rsi
та rdi
.
Таблицю PLT можна шукати з 0x400000 або з витягнутої адреси RIP зі стека (якщо PIE використовується). Записи таблиці відокремлені на 16B (0x10B), і коли викликається одна функція, сервер не зривається, навіть якщо аргументи неправильні. Також перевірка адреси запису в PLT + 6B також не призводить до збою, оскільки це перший код, що виконується.
Отже, можна знайти таблицю PLT, перевіряючи наступні поведінки:
'A' * offset + canary + rbp + ADDR + STOP
-> немає збою
'A' * offset + canary + rbp + (ADDR + 0x6) + STOP
-> немає збою
'A' * offset + canary + rbp + (ADDR + 0x10) + STOP
-> немає збою
Функція strcmp
встановлює регістр rdx
на довжину рядка, що порівнюється. Зверніть увагу, що rdx
є третім аргументом, і нам потрібно, щоб він був більшим за 0, щоб пізніше використовувати write
для витоку програми.
Можна знайти місце розташування strcmp
в PLT на основі його поведінки, використовуючи той факт, що ми тепер можемо контролювати 2 перші аргументи функцій:
strcmp(<non read addr>, <non read addr>) -> збій
strcmp(<non read addr>, <read addr>) -> збій
strcmp(<read addr>, <non read addr>) -> збій
strcmp(<read addr>, <read addr>) -> немає збою
Це можна перевірити, викликавши кожен запис таблиці PLT або використовуючи PLT повільний шлях, який в основному полягає в виклику запису в таблиці PLT + 0xb (який викликає dlresolve
) з наступним у стеку номер запису, який потрібно перевірити (починаючи з нуля), щоб просканувати всі записи PLT з першого:
strcmp(<non read addr>, <read addr>) -> збій
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
-> Виникне збій
strcmp(<read addr>, <non read addr>) -> збій
b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
strcmp(<read addr>, <read addr>) -> немає збою
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
Пам'ятайте, що:
BROP + 0x7 вказує на pop RSI; pop R15; ret;
BROP + 0x9 вказує на pop RDI; ret;
PLT + 0xb вказує на виклик dl_resolve.
Знайшовши strcmp
, можна встановити rdx
на значення більше 0.
Зверніть увагу, що зазвичай rdx
вже міститиме значення більше 0, тому цей крок може бути не обов'язковим.
Нарешті, потрібен гаджет, який ексфільтрує дані, щоб ексфільтрувати двійковий файл. І в цей момент можна контролювати 2 аргументи та встановити rdx
більше 0.
Є 3 загальні функції, які можна зловживати для цього:
puts(data)
dprintf(fd, data)
write(fd, data, len(data)
Однак оригінальна стаття згадує лише про write
, тому давайте поговоримо про це:
Поточна проблема полягає в тому, що ми не знаємо де функція write знаходиться всередині PLT і ми не знаємо номер fd, щоб надіслати дані до нашого сокета.
Однак ми знаємо де знаходиться таблиця PLT і можна знайти write на основі його поведінки. І ми можемо створити кілька з'єднань з сервером і використовувати високий FD, сподіваючись, що він відповідає деяким з наших з'єднань.
Поведінкові сигнатури для знаходження цих функцій:
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Якщо є дані, що виводяться, тоді знайдено puts
'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Якщо є дані, що виводяться, тоді знайдено dprintf
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Якщо є дані, що виводяться, тоді знайдено write
Оригінальна стаття: https://www.scs.stanford.edu/brop/bittau-brop.pdf
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)