Heap Overflow

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

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

Переповнення купи схоже на переповнення стеку, але відбувається в купі. Основна ідея полягає в тому, що було зарезервовано певний простір в купі для зберігання даних, і збережені дані були більшими, ніж зарезервований простір.

У випадку переповнення стеку ми знаємо, що деякі регістри, такі як вказівник інструкцій або рамка стеку, будуть відновлені зі стеку, і можливо, це можна злоупотребити. У випадку переповнення купи за замовчуванням в купі не зберігається ніяка чутлива інформація, яка може бути переповнена. Однак це може бути чутлива інформація або вказівники, тому критичність цієї уразливості залежить від даних, які можуть бути перезаписані, і від того, як зловмисник може цим скористатися.

Для пошуку зміщень переповнення ви можете використовувати ті ж шаблони, що й у переповненнях стеку.

Переповнення стеку проти переповнення купи

У випадку переповнення стеку організація та дані, які будуть присутні в стеці в момент спрацювання уразливості, досить надійні. Це тому, що стек є лінійним, завжди збільшується в колізійній пам'яті, в конкретних місцях виконання програми пам'ять стеку зазвичай зберігає схожий тип даних, і він має певну структуру з деякими вказівниками в кінці частини стеку, яку використовує кожна функція.

Однак у випадку переповнення купи використована пам'ять не є лінійною, але виділені частини зазвичай знаходяться в окремих позиціях пам'яті (не одна поруч з іншою) через біни та зони, які розділяють виділення за розміром, і через те, що попередню вільну пам'ять використовують перед виділенням нових частин. Складно визначити об'єкт, який буде зіштовхуватися з уразливим об'єктом у випадку переповнення купи. Тому, коли виявляється переповнення купи, потрібно знайти надійний спосіб зробити бажаний об'єкт наступним у пам'яті від того, що може бути переповнено.

Однією з технік, які використовуються для цього, є формування купи, яке використовується, наприклад, у цьому пості. У пості пояснюється, що коли в ядрі iOS закінчується зона пам'яті для зберігання частин пам'яті, вона розширюється на сторінку ядра, і ця сторінка розбивається на частини очікуваних розмірів, які будуть використовуватися по порядку (до версії iOS 9.2, після цього ці частини використовуються випадковим чином, щоб ускладнити експлуатацію цих атак).

Отже, у попередньому пості, де відбувається переповнення купи, для того щоб змусити переповнений об'єкт зіштовхуватися з об'єктом-жертвою, кілька kallocs змушуються кількома потоками, щоб забезпечити заповнення всіх вільних частин і створення нової сторінки.

Для забезпечення цього заповнення об'єктами певного розміру виділення поза лінією, пов'язане з iOS mach port, є ідеальним кандидатом. Складаючи розмір повідомлення, можна точно вказати розмір виділення kalloc, і коли відповідний mach port буде знищений, відповідне виділення буде негайно повернуто назад до kfree.

Потім деякі з цих заповнювачів можуть бути звільнені. Список вільних елементів kalloc.4096 вивільняє елементи у порядку останній-в-перший, що в основному означає, що якщо деякі заповнювачі звільнені, і експлойт намагається виділити кілька об'єктів-жертв під час спроби виділити об'єкт, вразливий на переповнення, ймовірно, що цей об'єкт буде слідувати за об'єктом-жертвою.

Приклад libc

На цій сторінці можна знайти базове емуляцію переповнення купи, яка показує, як перезаписуючи попередній біт використання наступного чанка та позицію попереднього розміру можна консолідувати використаний чанк (зробивши його невикористаним) і потім виділити його знову, здатний перезаписувати дані, які використовуються в іншому вказівнику.

Інший приклад з protostar heap 0 показує дуже простий приклад CTF, де переповнення купи може бути використане для виклику функції-переможця для отримання прапорця.

У прикладі protostar heap 1 можна побачити, як зловживанням переповненням буфера можна перезаписати в недалекому чанку адресу, куди буде записано довільні дані від користувача.

Приклад ARM64

На сторінці https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/ можна знайти приклад переповнення купи, де команда, яка буде виконана, зберігається в наступному чанку від переповненого чанку. Таким чином, можна змінити виконувану команду, перезаписавши її простим експлойтом, наприклад:

python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt

Інші приклади

  • Ми використовуємо уразливість переповнення цілочисельного типу, щоб отримати переповнення купи.

  • Ми порушуємо вказівники на функцію всередині struct переповненого фрагмента, щоб встановити функцію, таку як system, і отримати виконання коду.

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

Last updated