Stack Overflow

Support HackTricks

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

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

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

Вразливість зазвичай виникає, оскільки функція копіює в стек більше байтів, ніж виділено для неї, тим самим здатна перезаписати інші частини стеку.

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

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

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 буде вимкнено), щоб, коли вразлива функція повертається, прихована функція буде викликана:

Ret2win

Стековий Shellcode

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

Stack Shellcode

ROP та Ret2... техніки

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

ROP - Return Oriented Programing

Переповнення купи

Переповнення не завжди буде в стеку, воно також може бути в купі, наприклад:

Heap Overflow

Типи захисту

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

Common Binary Exploitation Protections & Bypasses
Підтримати HackTricks

Last updated