mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/libc-heap/use-after-free/first-fit.
This commit is contained in:
parent
62f8061767
commit
e38513bf20
@ -8,14 +8,14 @@
|
||||
|
||||
### Unsorted Bins
|
||||
|
||||
Коли ви звільняєте шматок пам'яті, який не є швидким шматком, він потрапляє до незасортованого контейнера. Цей контейнер діє як список, де нові звільнені шматки додаються на початок (до "голови"). Коли ви запитуєте новий шматок пам'яті, аллокатор дивиться на незасортований контейнер ззаду (до "хвоста"), щоб знайти шматок, який достатньо великий. Якщо шматок з незасортованого контейнера більший, ніж вам потрібно, він розділяється, при цьому передня частина повертається, а залишкова частина залишається в контейнері.
|
||||
Коли ви звільняєте шматок пам'яті, який не є швидким шматком, він потрапляє до незасортованого контейнера. Цей контейнер діє як список, де нові звільнені шматки додаються на початок (до "голови"). Коли ви запитуєте новий шматок пам'яті, аллокатор дивиться на незасортований контейнер ззаду (до "хвоста"), щоб знайти шматок, який достатньо великий. Якщо шматок з незасортованого контейнера більший, ніж вам потрібно, він розділяється, при цьому передня частина повертається, а залишок залишається в контейнері.
|
||||
|
||||
Приклад:
|
||||
|
||||
- Ви виділяєте 300 байт (`a`), потім 250 байт (`b`), потім звільняєте `a` і знову запитуєте 250 байт (`c`).
|
||||
- Коли ви звільняєте `a`, він потрапляє до незасортованого контейнера.
|
||||
- Якщо ви знову запитуєте 250 байт, аллокатор знаходить `a` на хвості і розділяє його, повертаючи частину, яка відповідає вашому запиту, і залишаючи решту в контейнері.
|
||||
- `c` буде вказувати на попереднє `a` і буде заповнено вмістом `a`.
|
||||
- `c` буде вказувати на попереднє `a` і заповнене вмістом `a`.
|
||||
```c
|
||||
char *a = malloc(300);
|
||||
char *b = malloc(250);
|
||||
@ -24,7 +24,7 @@ char *c = malloc(250);
|
||||
```
|
||||
### Fastbins
|
||||
|
||||
Fastbins використовуються для малих обсягів пам'яті. На відміну від несортованих бінів, fastbins додають нові обсяги на початок, створюючи поведінку останній прийшов - перший пішов (LIFO). Якщо ви запитуєте малий обсяг пам'яті, аллокатор витягне з голови fastbin.
|
||||
Fastbins використовуються для малих обсягів пам'яті. На відміну від несортованих бінів, fastbins додають нові обсяги на початок, створюючи поведінку останній прийшов - перший вийшов (LIFO). Якщо ви запитуєте малий обсяг пам'яті, аллокатор витягне з голови fastbin.
|
||||
|
||||
Example:
|
||||
```c
|
||||
@ -44,7 +44,7 @@ d = malloc(20); // a
|
||||
---
|
||||
### 🔥 Сучасні розгляди glibc (tcache ≥ 2.26)
|
||||
|
||||
З glibc 2.26 кожен потік зберігає свій власний **tcache**, який запитується *перед* несортованим біном. Тому сценарій першого підходу буде **досягнуто лише якщо**:
|
||||
З моменту glibc 2.26 кожен потік зберігає свій власний **tcache**, який запитується *перед* несортованим біном. Тому сценарій першого підходу буде **досягнуто лише якщо**:
|
||||
|
||||
1. Запитуваний розмір є **більшим за `tcache_max`** (0x420 на 64-біт за замовчуванням), *або*
|
||||
2. Відповідний бін tcache є **вже заповненим або очищеним вручну** (шляхом виділення 7 елементів і їх використання).
|
||||
@ -55,12 +55,12 @@ d = malloc(20); // a
|
||||
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
|
||||
for(int i = 0; i < 7; i++) free(pool[i]);
|
||||
```
|
||||
Якщо tcache вичерпан, наступні звільнення потрапляють до несортованого бін і класична поведінка first-fit (пошук з хвоста, вставка з голови) може бути знову активована.
|
||||
Якщо tcache вичерпано, наступні звільнення потрапляють до несортованого бін і класична поведінка first-fit (пошук з хвоста, вставка в голову) може бути знову активована.
|
||||
|
||||
---
|
||||
### 🚩 Створення UAF з перекриттям з first-fit
|
||||
|
||||
Фрагмент нижче (перевірено на glibc 2.38) показує, як спліттер у несортованому біні може бути зловжито використаний для створення 2 **перекриваючих вказівників** – потужного примітиву, який перетворює одне звільнення на запис-після-звільнення.
|
||||
Фрагмент нижче (перевірено на glibc 2.38) показує, як спліттер у несортованому біні може бути зловжито для створення 2 **перекриваючих вказівників** – потужного примітиву, який перетворює одне звільнення на запис-після-звільнення.
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -95,19 +95,17 @@ fwrite(C2, 1, 0x10, stdout); // prints Xs
|
||||
1. **Витягніть** tcache для цільового розміру.
|
||||
2. **Звільніть** шматок, щоб він потрапив у несортований бін.
|
||||
3. **Виділіть** трохи менший розмір – аллокатор розділяє несортований шматок.
|
||||
4. **Виділіть** знову – залишкова частина перекривається з існуючим шматком, що використовується → UAF.
|
||||
4. **Виділіть** знову – залишкова частина перекривається з існуючим використовуваним шматком → UAF.
|
||||
5. Перезапишіть чутливі поля (вказівники на функції, FILE vtable тощо).
|
||||
|
||||
Практичний приклад можна знайти в *Setjmp* виклику 2024 HITCON Quals, де цей точний примітив використовується для переходу від UAF до повного контролю над `__free_hook`.{{#ref}}
|
||||
../../../../references/2024_setjmp_firstfit.md
|
||||
{{#endref}}
|
||||
Практичне застосування можна знайти у виклику *Setjmp* 2024 HITCON Quals, де цей точний примітив використовується для переходу від UAF до повного контролю над `__free_hook`.
|
||||
|
||||
---
|
||||
### 🛡️ Заходи захисту та зміцнення
|
||||
|
||||
* **Безпечне з'єднання (glibc ≥ 2.32)** захищає лише односпрямовані списки *tcache*/**fastbin**. Несортовані/малі/великі біни все ще зберігають сирі вказівники, тому перекриття на основі першого підходу залишаються життєздатними, якщо ви можете отримати витік з купи.
|
||||
* **Шифрування вказівників купи та MTE** (ARM64) поки не впливають на x86-64 glibc, але прапори зміцнення дистрибутиву, такі як `GLIBC_TUNABLES=glibc.malloc.check=3`, призупинять роботу при несумісних метаданих і можуть зламати наївні PoC.
|
||||
* **Заповнення tcache при звільненні** (запропоновано в 2024 для glibc 2.41) ще більше зменшить використання несортованих; слідкуйте за майбутніми випусками під час розробки загальних експлойтів.
|
||||
* **Безпечне з'єднання (glibc ≥ 2.32)** захищає лише односпрямовані списки *tcache*/**fastbin**. Несортовані/малі/великі біни все ще зберігають сирі вказівники, тому перекриття на основі першого підходу залишаються життєздатними, якщо ви можете отримати витік купи.
|
||||
* **Шифрування вказівників купи та MTE** (ARM64) поки не впливають на x86-64 glibc, але прапори зміцнення дистрибутиву, такі як `GLIBC_TUNABLES=glibc.malloc.check=3`, призведуть до аварії при несумісних метаданих і можуть зламати наївні PoC.
|
||||
* **Заповнення tcache при звільненні** (запропоновано у 2024 для glibc 2.41) ще більше зменшить використання несортованих; слідкуйте за майбутніми випусками під час розробки загальних експлойтів.
|
||||
|
||||
---
|
||||
## Інші посилання та приклади
|
||||
@ -118,12 +116,12 @@ fwrite(C2, 1, 0x10, stdout); // prints Xs
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
||||
- Програма дозволяє створювати нотатки. Нотатка міститиме інформацію про нотатку в malloc(8) (з вказівником на функцію, яку можна викликати) і вказівник на інший malloc(<size>) з вмістом нотатки.
|
||||
- Атака полягатиме в створенні 2 нотаток (note0 і note1) з більшим вмістом malloc, ніж розмір інформації про нотатку, а потім звільнити їх, щоб вони потрапили в швидкий бін (або tcache).
|
||||
- Потім створіть ще одну нотатку (note2) з розміром вмісту 8. Вміст буде в note1, оскільки шматок буде повторно використано, де ми можемо змінити вказівник функції, щоб вказувати на функцію win, а потім використати Use-After-Free для виклику нового вказівника функції.
|
||||
- Потім створіть ще одну нотатку (note2) з розміром вмісту 8. Вміст буде в note1, оскільки шматок буде повторно використано, де ми можемо змінити вказівник функції, щоб вказувати на функцію win, а потім використати після звільнення note1, щоб викликати новий вказівник функції.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
||||
- Можливо виділити деяку пам'ять, записати бажане значення, звільнити його, повторно виділити, і оскільки попередні дані все ще там, їх буде оброблено відповідно до нової очікуваної структури в шматку, що робить можливим встановлення значення для отримання прапора.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
||||
- У цьому випадку потрібно записати 4 всередині конкретного шматка, який є першим, що виділяється (навіть після примусового звільнення всіх з них). У кожному новому виділеному шматку його номер у масиві індексується. Потім виділіть 4 шматки (+ початково виділений), останній буде містити 4 всередині, звільніть їх і примусьте повторне виділення першого, яке використовуватиме останній звільнений шматок, що містить 4 всередині.
|
||||
- 2024 HITCON Quals Setjmp звіт (Quarkslab) – практична атака на перекриття першого підходу / несортованого розподілу: <https://ctftime.org/writeup/39355>
|
||||
- Angstrom CTF 2024 *heapify* звіт – зловживання розподілом несортованого біна для витоку libc та отримання перекриття: <https://hackmd.io/@aneii11/H1S2snV40>
|
||||
- 2024 HITCON Quals Setjmp write-up (Quarkslab) – практична атака на перекриття першого підходу / несортованого розподілу: <https://ctftime.org/writeup/39355>
|
||||
- Angstrom CTF 2024 *heapify* write-up – зловживання розподілом несортованого біна для витоку libc та отримання перекриття: <https://hackmd.io/@aneii11/H1S2snV40>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user