Stack Overflow
Що таке переповнення стеку
Переповнення стеку — це вразливість, яка виникає, коли програма записує більше даних у стек, ніж йому виділено. Ці надмірні дані перезапишуть сусідній простір пам'яті, що призведе до пошкодження дійсних даних, порушення контролю потоку виконання та потенційного виконання шкідливого коду. Ця проблема часто виникає через використання небезпечних функцій, які не виконують перевірку меж на вхідних даних.
Основна проблема цього перезапису полягає в тому, що збережений вказівник інструкцій (EIP/RIP) та збережений базовий вказівник (EBP/RBP) для повернення до попередньої функції зберігаються в стеці. Тому зловмисник зможе перезаписати їх і контролювати потік виконання програми.
Вразливість зазвичай виникає, оскільки функція копіює в стек більше байтів, ніж виділено для неї, тим самим здатна перезаписати інші частини стеку.
Деякі загальні функції, вразливі до цього, це: strcpy
, strcat
, sprintf
, gets
... Також функції, такі як fgets
, read
та memcpy
, які приймають аргумент довжини, можуть бути використані в уразливий спосіб, якщо вказана довжина перевищує виділену.
Наприклад, наступні функції можуть бути вразливими:
Знаходження зсувів стекових переповнень
Найпоширеніший спосіб знайти стекові переповнення - це ввести дуже великий вхід з A
s (наприклад, python3 -c 'print("A"*1000)'
) і очікувати Segmentation Fault
, що вказує на те, що адресу 0x41414141
намагалися отримати доступ.
Більше того, як тільки ви виявите, що існує вразливість стекового переповнення, вам потрібно буде знайти зсув, поки не стане можливим перезаписати адресу повернення, для цього зазвичай використовується послідовність Де Брюйна. Яка для даного алфавіту розміру k і підпослідовностей довжини n є циклічною послідовністю, в якій кожна можлива підпослідовність довжини _n_** з'являється точно один раз** як безперервна підпослідовність.
Таким чином, замість того, щоб вручну з'ясовувати, який зсув потрібен для контролю EIP, можна використовувати в якості заповнювача одну з цих послідовностей, а потім знайти зсув байтів, які закінчилися перезаписом.
Можна використовувати pwntools для цього:
або GEF:
Використання переповнень стеку
Під час переповнення (якщо розмір переповнення достатньо великий) ви зможете перезаписати значення локальних змінних всередині стеку, поки не досягнете збереженого EBP/RBP та EIP/RIP (або навіть більше). Найпоширеніший спосіб зловживання цим типом вразливості - це модифікація адреси повернення, щоб, коли функція закінчується, управлінський потік буде перенаправлений туди, куди вказав користувач у цьому вказівнику.
Однак у інших сценаріях може бути достатньо просто перезаписати деякі значення змінних у стеку для експлуатації (як у простих CTF викликах).
Ret2win
У цьому типі CTF викликів є функція всередині бінарного файлу, яка ніколи не викликається і яку вам потрібно викликати, щоб виграти. Для цих викликів вам просто потрібно знайти зсув для перезапису адреси повернення та знайти адресу функції, яку потрібно викликати (зазвичай ASLR буде вимкнено), щоб, коли вразлива функція повертається, прихована функція буде викликана:
Ret2winСтековий Shellcode
У цьому сценарії зловмисник може помістити shellcode у стек і зловживати контрольованим EIP/RIP, щоб стрибнути до shellcode і виконати довільний код:
Stack ShellcodeROP та Ret2... техніки
Ця техніка є основною основою для обходу основного захисту попередньої техніки: Не виконавчий стек (NX). І вона дозволяє виконувати кілька інших технік (ret2lib, ret2syscall...), які закінчаться виконанням довільних команд, зловживаючи існуючими інструкціями в бінарному файлі:
ROP - Return Oriented ProgramingПереповнення купи
Переповнення не завжди буде в стеку, воно також може бути в купі, наприклад:
Heap OverflowТипи захисту
Існує кілька захистів, які намагаються запобігти експлуатації вразливостей, перевірте їх у:
Common Binary Exploitation Protections & BypassesLast updated