Rust, Хакинг на Rust

Курс — Хакинг на Rust. #13 Низкоуровневое программирование. Взаимодействие с памятью — стек vs. куча

Здравствуйте, дорогие друзья.

Понимание работы памяти — ключевой навык для любого хакера. В Rust, несмотря на автоматическое управление ресурсами, низкоуровневые операции требуют чёткого разделения данных между стеком и кучей . Эти две области памяти служат разным целям, а их неправильное использование может привести к уязвимостям или крахам программ. Разберём, как они устроены, и как их эксплуатировать (или защищаться от таких эксплойтов).

4.1 Стек: Быстрая, но ограниченная память

Стек — это область памяти, которая работает по принципу LIFO (Last In, First Out). Данные добавляются и удаляются строго в порядке «последним пришёл — первым вышел».

Особенности стека:

  • Автоматическое управление: Память выделяется при входе в область видимости и освобождается при выходе.
  • Высокая скорость: Операции с стеком выполняются за константное время O(1).
  • Ограниченный размер: Обычно стек составляет несколько мегабайт (зависит от ОС).

Пример размещения данных в стеке:

Когда использовать стек:

  • Для переменных с известным размером на этапе компиляции.
  • В коротких функциях, где данные не требуется сохранять долго.

Риски:

  • Переполнение стека (Stack Overflow): Возникает при выделении слишком больших данных (например, массива из 1 млн элементов).

4.2 Куча: Гибкость за счет сложности

Куча — это область памяти для динамического выделения данных. Здесь хранятся объекты, размер которых неизвестен заранее или которые должны существовать дольше, чем их область видимости.

Особенности кучи:

  • Ручное управление: В Rust память освобождается, когда владелец данных выходит из области видимости.
  • Медленнее стека: Выделение и освобождение требуют работы аллокатора.
  • Неограниченный размер: Ограничен только физической памятью системы.

Пример работы с кучей через Box:

Сценарии использования кучи:

  • Контейнеры с динамическим размером (Vec, String).
  • Объекты, переживающие создающую их функцию (например, синглтоны).

4.3 Ручное управление памятью через unsafe

Для низкоуровневых операций Rust предоставляет инструменты для прямого доступа к памяти.

Выделение памяти в куче:

Работа с сырыми указателями:

Опасности:

  • Use-after-free: Использование указателя после освобождения памяти.
  • Double Free: Попытка освободить уже освобождённую память.

4.4 Практические примеры для хакеров

Пример 1: Переполнение буфера

Хотя Rust предотвращает многие виды buffer overflow, использование unsafe может обойти защиту:

Пример 2: Чтение памяти процесса

Для анализа уязвимостей можно читать память по произвольному адресу (только в учебных целях!):

4.5 Инструменты для анализа памяти

  • Valgrind: Проверка на утечки и невалидные операции.
  • AddressSanitizer: Обнаружение buffer overflow и use-after-free.
  • GDB: Отладка с просмотром содержимого стека и кучи.

Заключение

Стек и куча — основа работы с памятью в Rust. Понимание их различий и нюансов критически важно для написания безопасного кода и анализа уязвимостей. В следующих главах мы применим эти знания для создания эксплойтов, анализа бинарников и защиты систем.

Задачи для самостоятельного решения:

  1. Напишите функцию, которая копирует данные из стека в кучу.
  2. Создайте пример buffer overflow в unsafe блоке и проверьте его через AddressSanitizer.
  3. Реализуйте дамп памяти процесса с помощью сырых указателей.
Хакинг на языке программирования Rust

На этом все. Всем хорошего дня!

Цикл статей по курсу — «Хакинг на Rust».