Unsorted Bin Attack
Last updated
Last updated
Вивчайте та практикуйте хакінг AWS: Навчання AWS Red Team Expert (ARTE) від HackTricks Вивчайте та практикуйте хакінг GCP: Навчання GCP Red Team Expert (GRTE) від HackTricks
Для отримання додаткової інформації про те, що таке несортований бін, перегляньте цю сторінку:
Bins & Memory AllocationsНесортовані списки можуть записувати адресу у unsorted_chunks (av)
в адресу bk
частинки. Тому, якщо зловмисник може змінити адресу вказівника bk
в частинці всередині несортованого біна, він може записати цю адресу в довільну адресу, що може бути корисним для витоку адрес Glibc або обхіду деяких захистів.
Отже, в основному, ця атака дозволяє встановити велике число за довільною адресою. Це велике число - це адреса, яка може бути адресою купи або адресою Glibc. Типовою ціллю є global_max_fast
, щоб дозволити створювати швидкі бін-біни з більшими розмірами (і перейти від атаки на несортований бін до атаки на швидкий бін).
Подивившись на приклад, наведений за посиланням https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle та використовуючи 0x4000 та 0x5000 замість 0x400 та 0x500 як розміри частинок (щоб уникнути Tcache), можна побачити, що в наші дні спрацьовує помилка malloc(): unsorted double linked list corrupted
.
Отже, ця атака на несортований бін тепер (поміж інших перевірок) також вимагає можливості виправити подвійний зв'язаний список, щоб це було обхідно victim->bk->fd == victim
або ні victim->fd == av (arena)
, що означає, що адреса, куди ми хочемо записати, повинна мати адресу фальшивої частинки у своїй позиції fd
, і що фальшива частина fd
вказує на арену.
Зауважте, що ця атака порушує несортований бін (тому малі та великі теж). Тому ми можемо використовувати виділення лише зі швидкого біна тепер (складніша програма може робити інші виділення та аваріювати), і для того, щоб спровокувати це, ми повинні виділити такий самий розмір, або програма аваріює.
Зауважте, що перезапис global_max_fast
може допомогти в цьому випадку, довіряючи, що швидкий бін зможе доглядати за всіма іншими виділеннями до завершення експлойту.
Код від guyinatuxedo добре пояснює це, хоча, якщо ви зміните виклики malloc для виділення пам'яті достатньо великого розміру, щоб уникнути потрапляння в Tcache, ви побачите, що згадана вище помилка заважає цій техніці: malloc(): unsorted double linked list corrupted
Це насправді дуже просте поняття. Частинки в несортованому біні матимуть вказівники. Перша частина в несортованому біні фактично матиме fd
та bk
посилання на частину основної арени (Glibc).
Отже, якщо ви можете помістити частинку всередину несортованого біна та прочитати її (використання після вивільнення) або виділити її знову без перезаписування принаймні 1 з посилань, щоб потім прочитати її, ви можете отримати витік інформації Glibc.
Схожий атака, використана в цьому описі, полягала в зловживанні структури з 4 частинок (A, B, C та D - D призначено лише для запобігання консолідації з верхньою частиною) таким чином, що переповнення нульовим байтом в B використовувалося для того, щоб C вказувала, що B не використовується. Також, в B дані prev_size
були змінені, так що розмір замість розміру B був A+B.
Потім C було вивільнено та консолідовано з A+B (але B все ще був у використанні). Було виділено нову частинку розміром A, і тоді адреси, витікнуті з бібліотеки, були записані в B, звідки вони витікали.
Мета полягає в перезаписі глобальної змінної значенням більше 4869, щоб отримати прапорець, і PIE не увімкнено.
Можливо створювати частинки довільних розмірів, існує переповнення купи з бажаним розміром.
Атака починається створенням 3 частинок: частина 0 для зловживання переповненням, частина 1 для переповнення та частина 2, щоб верхня частина не консолідувалася з попередніми.
Потім частина 1 вивільнюється, і частина 0 переповнюється, так що вказівник bk
частинки 1 вказує на: bk = magic - 0x10
Потім частина 3 виділяється з таким самим розміром, як частина 1, що спровокує атаку на несортований бін та змінить значення глобальної змінної, що дозволить отримати прапорець.
Функція злиття є вразливою, оскільки якщо обидва передані індекси однакові, вона перерозподілить їх, а потім вивільнить, але поверне вказівник на ту вивільнену область, яку можна використовувати.
Тому створюються 2 частинки: частина 0, яка буде злита з собою, та частина 1, щоб запобігти консолідації з верхньою частиною. Потім викликається функція злиття з частиною 0 двічі, що призведе до використання після вивільнення.
Потім викликається функція view
з індексом 2 (індекс частинки після вивільнення), яка витікає адресу бібліотеки.
Оскільки бінарний файл має захисти, що дозволяють виділяти лише розміри більше global_max_fast
, тому не використовується fastbin, буде використано атаку на несортований бін для перезапису глобальної змінної global_max_fast
.
Потім можливо викликати функцію редагування з індексом 2 (вказівник після вивільнення) та перезаписати вказівник bk
, щоб вказував на p64(global_max_fast-0x10)
. Потім, створюючи нову частинку, буде використана раніше скомпрометована адреса вивільнення (0x20) та спровокує атаку на несортований бін, перезаписуючи global_max_fast
значенням дуже великого числа, що дозволяє тепер створювати частинки в швидких бінах.
Тепер виконується атака на швидкий бін:
По-перше, виявлено, що можна працювати зі швидкими частинками розміром 200 в місці __free_hook
:
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
Якщо нам вдасться отримати швидкий чанк розміром 0x200 у цьому місці, буде можливо перезаписати вказівник функції, який буде виконаний
Для цього створюється новий чанк розміром 0xfc
і функція зливається з цим вказівником двічі, таким чином ми отримуємо вказівник на вивільнений чанк розміром 0xfc*2 = 0x1f8
у швидкому біні.
Потім в цьому чанку викликається функція редагування для модифікації адреси fd
цього швидкого біна, щоб вказувати на попередню функцію __free_hook
.
Потім створюється чанк розміром 0x1f8
, щоб отримати зі швидкого біна попередній непотрібний чанк, тому створюється ще один чанк розміром 0x1f8
, щоб отримати швидкий чанк у __free_hook
, який перезаписується адресою функції system
.
І, нарешті, вивільняється чанк, що містить рядок /bin/sh\x00
, викликаючи функцію видалення, що спричиняє виклик функції __free_hook
, яка вказує на систему з параметром /bin/sh\x00
.
Ще один приклад зловживання переливанням 1B для консолідації чанків у неупорядкованому біні та отримання інформації про libc, а потім виконання швидкого біну атаки для перезаписування гачка malloc адресою одного гаджета
Ми можемо виділяти лише чанки розміром більше 0x100
.
Перезаписати global_max_fast
, використовуючи атаку на неупорядкований бін (працює 1/16 раз через ASLR, оскільки нам потрібно змінити 12 бітів, але ми повинні змінити 16 бітів).
Атака швидкого біна для модифікації глобального масиву чанків. Це надає примітив читання/запису, що дозволяє модифікувати GOT та встановлювати деякі функції для вказівки на system
.