mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
49 lines
8.8 KiB
Markdown
49 lines
8.8 KiB
Markdown
# Heap Overflow
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## Basic Information
|
||
|
||
Переповнення купи - це як [**переповнення стеку**](../stack-overflow/index.html), але в купі. В основному це означає, що деякий простір було зарезервовано в купі для зберігання деяких даних, і **збережені дані були більшими за зарезервований простір.**
|
||
|
||
У випадку переповнень стеку ми знаємо, що деякі регістри, такі як вказівник інструкцій або стековий фрейм, будуть відновлені зі стеку, і це може бути можливим для зловживання. У випадку переповнень купи **немає жодної чутливої інформації, що зберігається за замовчуванням** в купі, яка може бути переповнена. Однак це можуть бути чутливі дані або вказівники, тому **критичність** цієї вразливості **залежить** від **того, які дані можуть бути перезаписані** і як зловмисник може цим зловживатися.
|
||
|
||
> [!TIP]
|
||
> Щоб знайти зсуви переповнення, ви можете використовувати ті ж шаблони, що й у [**переповненнях стеку**](../stack-overflow/index.html#finding-stack-overflows-offsets).
|
||
|
||
### Stack Overflows vs Heap Overflows
|
||
|
||
У переповненнях стеку розташування та дані, які будуть присутні в стеку в момент, коли вразливість може бути активована, є досить надійними. Це пов'язано з тим, що стек є лінійним, завжди зростаючим у зіткненні пам'яті, у **конкретних місцях виконання програми стекова пам'ять зазвичай зберігає подібні дані** і має певну структуру з деякими вказівниками в кінці частини стеку, що використовується кожною функцією.
|
||
|
||
Однак у випадку переповнення купи використовувана пам'ять не є лінійною, а **використовувані шматки зазвичай знаходяться в окремих позиціях пам'яті** (не один біля одного) через **контейнери та зони**, які розділяють алокації за розміром, і через те, що **попередньо звільнена пам'ять використовується** перед алокацією нових шматків. Це **складно знати об'єкт, який буде зіткненням з вразливим** до переповнення купи. Тому, коли виявляється переповнення купи, потрібно знайти **надійний спосіб зробити так, щоб бажаний об'єкт був наступним у пам'яті** після того, що може бути переповнене.
|
||
|
||
Одна з технік, що використовуються для цього, - це **Heap Grooming**, яка використовується, наприклад, [**в цьому пості**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). У пості пояснюється, як у ядрі iOS, коли зона вичерпується пам'яттю для зберігання шматків пам'яті, вона розширюється на сторінку ядра, і ця сторінка ділиться на шматки очікуваних розмірів, які будуть використовуватися в порядку (до версії iOS 9.2, потім ці шматки використовуються випадковим чином, щоб ускладнити експлуатацію цих атак).
|
||
|
||
Отже, у попередньому пості, де відбувається переповнення купи, щоб змусити переповнений об'єкт зіткнутися з об'єктом жертви, кілька **`kallocs` примушуються кількома потоками, щоб спробувати забезпечити заповненість усіх вільних шматків і створити нову сторінку**.
|
||
|
||
Щоб примусити це заповнення об'єктами певного розміру, **алокація поза лінією, пов'язана з iOS mach port**, є ідеальним кандидатом. Шляхом формування розміру повідомлення можна точно вказати розмір алокації `kalloc`, і коли відповідний mach port знищується, відповідна алокація буде негайно звільнена назад до `kfree`.
|
||
|
||
Тоді деякі з цих заповнювачів можуть бути **звільнені**. **Список вільних `kalloc.4096` звільняє елементи в порядку останній прийшов - перший пішов**, що в основному означає, що якщо деякі заповнювачі звільнені, і експлойт намагається алокувати кілька об'єктів жертви, намагаючись алокувати об'єкт, вразливий до переповнення, ймовірно, що цей об'єкт буде слідувати за об'єктом жертви.
|
||
|
||
### Example libc
|
||
|
||
[**На цій сторінці**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) можна знайти базову емуляцію переповнення купи, яка показує, як перезаписуючи біт prev in use наступного шматка та позицію prev size, можна **консолідувати використаний шматок** (змушуючи його думати, що він не використовується) і **потім знову алокувати його**, маючи можливість перезаписати дані, які використовуються в іншому вказівнику.
|
||
|
||
Ще один приклад з [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) показує дуже базовий приклад CTF, де **переповнення купи** може бути використано для виклику функції переможця, щоб **отримати прапор**.
|
||
|
||
У прикладі [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) можна побачити, як зловживаючи переповненням буфера, можна **перезаписати в сусідньому шматку адресу**, куди **будуть записані довільні дані від користувача**.
|
||
|
||
### Example ARM64
|
||
|
||
На сторінці [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) ви можете знайти приклад переповнення купи, де команда, яка буде виконана, зберігається в наступному шматку від переповненого шматка. Таким чином, можна змінити виконувану команду, перезаписавши її простим експлойтом, таким як:
|
||
```bash
|
||
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
|
||
```
|
||
### Інші приклади
|
||
|
||
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
|
||
- Ми використовуємо вразливість цілочисельного переповнення, щоб отримати переповнення купи.
|
||
- Ми корумпуємо вказівники на функцію всередині `struct` переповненого блоку, щоб встановити функцію, таку як `system`, і отримати виконання коду.
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|