hacktricks/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md

10 KiB
Raw Blame History

Stack Overflow

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Що таке переповнення стеку

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

Основна проблема цього перезапису полягає в тому, що збережений вказівник інструкцій (EIP/RIP) та збережений базовий вказівник (EBP/RBP) для повернення до попередньої функції зберігаються в стеці. Тому зловмисник зможе перезаписати їх і контролювати потік виконання програми.

Вразливість зазвичай виникає, оскільки функція копіює в стек більше байтів, ніж виділено для неї, тим самим здатна перезаписати інші частини стеку.
Деякі загальні функції, вразливі до цього, це: strcpy, strcat, sprintf, gets... Також функції, такі як fgets або read, які приймають аргумент довжини, можуть бути використані в уразливий спосіб, якщо вказана довжина перевищує виділену.

Наприклад, наступні функції можуть бути вразливими:

void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

Знаходження переповнень стеку

Найпоширеніший спосіб знайти переповнення стеку - це ввести дуже великий вхід з As (наприклад, python3 -c 'print("A"*1000)') і очікувати Segmentation Fault, що вказує на те, що адресу 0x41414141 намагалися отримати доступ.

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

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

Можна використовувати pwntools для цього:

from pwn import *

# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)

# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)  # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")

або GEF:

#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp

Використання переповнень стеку

Під час переповнення (якщо розмір переповнення достатньо великий) ви зможете перезаписати значення локальних змінних всередині стеку, поки не досягнете збереженого EBP/RBP та EIP/RIP (або навіть більше).
Найпоширеніший спосіб зловживання цим типом вразливості - це модифікація адреси повернення, щоб, коли функція закінчується, управлінський потік перенаправлявся туди, куди вказав користувач у цьому вказівнику.

Однак у інших сценаріях просто перезапис деяких значень змінних у стеку може бути достатньо для експлуатації (як у простих CTF викликах).

Ret2win

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

{% content-ref url="ret2win.md" %} ret2win.md {% endcontent-ref %}

Стековий Shellcode

У цьому сценарії зловмисник може помістити shellcode у стек і зловживати контрольованим EIP/RIP, щоб стрибнути до shellcode та виконати довільний код:

{% content-ref url="stack-shellcode.md" %} stack-shellcode.md {% endcontent-ref %}

ROP

Ця техніка є основною основою для обходу основного захисту попередньої техніки: Не виконуваний стек (NX). І вона дозволяє виконувати кілька інших технік (ret2lib, ret2syscall...), які закінчать виконання довільних команд, зловживаючи існуючими інструкціями в бінарному файлі:

{% content-ref url="rop-return-oriented-programing.md" %} rop-return-oriented-programing.md {% endcontent-ref %}

Типи захисту

Існує кілька захистів, які намагаються запобігти експлуатації вразливостей, перевірте їх у:

{% content-ref url="../common-binary-protections-and-bypasses/" %} common-binary-protections-and-bypasses {% endcontent-ref %}

{% hint style="success" %} Вчіться та практикуйте Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Підтримати HackTricks
{% endhint %}