Pointer Redirecting

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

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

String pointers

Якщо виклик функції збирається використовувати адресу рядка, що знаходиться в stack, можна зловживати buffer overflow щоб перезаписати цю адресу і помістити всередині binary адресу іншого рядка.

Наприклад, якщо виклик функції system збирається використати адресу рядка для виконання команди, атакуючий може помістити адресу іншого рядка в stack, export PATH=.:$PATH і створити в поточному каталозі скрипт з імʼям першої літери нового рядка — цей скрипт буде виконано бінарою.

На реальних цілях перенаправлення stack string pointer зазвичай цікавіше, ніж просто зміна виведеного тексту:

  • Redirect a later system/popen/execl* argument to an existing "/bin/sh" or attacker-controlled command string already present in memory.
  • Redirect a later read sink such as puts("%s", ptr) or write(fd, ptr, len) to leak stack, heap or binary data.
  • Redirect a later write sink such as strcpy(dst, ...), memcpy(dst, src, len), or a structure field assignment through ptr->field = value to turn the stack overflow into a second-stage arbitrary write.

Під час аудиту віддавайте пріоритет локальним змінним на stack, таким як char *cmd, char *path, char *buf, FILE *fp, або вказівникам всередині тимчасових request/response structʼів, які використовуються після overflow, але до повернення функції. Це особливо корисно, коли overflow не може безпечно дістатися до saved return address через canary або коли пошкодження сусіднього вказівника вже достатнє.

Якщо корупція обмежується partial overwrite (наприклад через те, що баг додає 0x00), спробуйте перенаправити вказівник на:

  • Близький рядок у тому ж stack frame
  • Інший обʼєкт у тому ж module / non-PIE image
  • Контролюваний регіон, чийі high bytes залишаються незмінними

Для повʼязаного ASLR-орієнтованого випадку, коли trailing NUL змінює існуючий stack pointer замість виділеної локальної змінної, див. Ret2ret & Reo2pop.

Приклад цього можна знайти в:

Function pointers

Аналогічно до string pointer, але застосовано до функцій: якщо у stack міститься адреса функції, яка буде викликана, її можна змінити (наприклад, щоб викликати system).

Корисні цілі — це не лише явні callback-змінні на кшталт void (*fp)(). На практиці шукайте:

  • Callback-и, збережені в локальних structʼах, що передаються пізніше до допоміжних функцій
  • Destructor / cleanup handlers, що викликаються на шляхах помилок
  • Parser dispatch tables або state-machine handlers, скопійовані на stack
  • Локальні structʼи / обʼєкти, які пізніше виконують dispatch через непрямий виклик

У сучасній експлуатації pointer redirection часто є останнім примітивом, доступним перед торканням canary. Допис 2024 року по експлуатації CVE-2024-20017 демонструє типовий патерн: overflow досягає кількох локальних змінних перед stack canary, атакуючий корумпує stack pointer разом з повʼязаною довжиною/значенням, і пізніший присвоєння через цей вказівник стає arbitrary write, не потребуючи повернення через корумпований фрейм.

Pointer corruption to second-stage primitives

Якщо близький вказівник пізніше дереференсується для запису, мета зазвичай не в тому, щоб одразу зробити jump першим overflow, а в тому, щоб підняти примітив:

  1. Переповніть локальний буфер і пошкодьте вказівник разом з будь-якою повʼязаною length / integer / index.
  2. Зачекайте, поки функція не виконає post-overflow dereference, такий як ptr->len = x, memcpy(ptr, src, n) або *ptr = value.
  3. Використайте отриманий write-what-where щоб перезаписати GOT slot, callback, config pointer або інше indirect callsite.

Це хороший варіант, коли:

  • Баг зупиняється на canary
  • Сам function pointer безпосередньо недоступний
  • 4-byte або 8-byte data write легше отримати, ніж миттєве захоплення control-flow

Ту сама ідея працює і для read примітивів, якщо пошкоджений вказівник пізніше передається в логування, друк або network send helper-и.

Modern AArch64 note: PAC / BTI

На сучасних AArch64 цілях класичне saved return address overwrite може не вдатися, бо epilogue автентифікує x30 за допомогою PAC. У таких випадках більш привабливими стають non-return hijacks, наприклад корумповані локальні function pointers або callback pointers.

Однак, якщо BTI ввімкнено, перезаписана ціль непрямого виклику все одно має потрапити на валідний landing pad (зазвичай це entry функції з bti c, або у PAC-enabled коді пролог, що починається з paciasp/pacibsp). Тому при перенаправленні stack function pointer на AArch64 віддавайте перевагу:

  • Реальним function entries замість mid-function gadgets
  • Цілям, чиї прологи вже задовольняють BTI
  • Цілям, де indirect-call pointer не додатково автентифікується перед використанням

Для повʼязаного AArch64 stack-overflow контексту див. ret2win-arm64.

Приклад можна знайти в:

References

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

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