Переполнение буфера в heap. Серия вторая

kas1e

Xakep, номер #059, стр. 059-074-1

Практические примеры с переполнением в heap

Вот мы и добрались до второй части статьи, посвященной проблеме переполнения буфера в heap. Сегодня мы рассмотрим непосредственный пример эксплуатации данной уязвимости с прилагающимся для нее эксплоитом.

Как всегда, лентяи не хотят читать материалы на английском и разбираться в предлагаемом коде. А ведь знать и уметь все равно хочется :). Что ж, в этой статье все разжевано и на русском. Так что приготовься - мы начинаем обучение. Для начала рассмотрим работу malloc() и free() функций еще раз.

Дающий malloc

Работа malloc, как я уже это говорил в первой части статьи, представлена такой вот структурой:

struct malloc_chunk

{

INTEAL_SIZE_T prev_size;

INTEAL_SIZE_T size;

struct malloc_chunk * fd;

struct malloc_chunk * bk;

};

Т.е. заполнение heap при вызове malloc() идет предопределенным образом:

- размер предыдущего куска.

- размер текущего куска.

- struct fd.

- struct bk.

- user data (наш буфер с данными).

И следующий чанк начинается опять с размера предыдущего чанка. Итог таков: у malloc есть конкретная структура, стандартный способ аллоцирования буфера и размещения своих данных.

Освобождающий free

На самом деле, free() - это __libc_free() в GNU C library. И вот как она работает: функции просто передается указатель через аргумент ptr на память, выделенную malloc(). Т.е. free() ждет только указателя. В манах и vudu туториале все это расписано до мельчайших нюансов. Так что обязательно почитай их! Здесь же тебе необходимо запомнить, что все передается через указатель.

Забегая вперед скажу, что для написания эксплоитов под heap, достаточно базовых знаний, понимания работы malloc и free функций, а также Global Offset таблицы. Последнее мы как раз сейчас и рассмотрим, а потом уже приступим к делу.

Global Offset Table

Как ты, наверное, знаешь, существует динамическая и статическая линковка на этапе создания исполняемых файлов. Также понятно, что существует виртуальная адресация, которая совсем не фиксирована по адресам, особенно когда мы используем динамическую линковку (отсюда и название - динамическая). Для того чтобы мы могли использовать в различных позиционно-независимых кодах "меняющиеся" адреса, существуют некоторые таблицы и символы. Все друг с другом связано и замешано на ELF спецификации. Расписывать ее всю нет смысла, поэтому опишем ее вкратце.

Во всех ELF файлах есть различные секции. Каждая секция отвечает за какие-то обязанности. Вот эти секции интерпретируются ELF загрузчиком и обработчиком. Когда используется динамическая линковка (так происходит, когда мы используем C GNU функции, т.е. отключаем -static), то у нас создаются символьные, специальные и релакационные секции. Символьные секции определяют символы. Допустим, у нас есть функция free(). В символьной таблице эти символы как раз и будут записаны. Далее еще есть таблица, в которой находятся виртуальные смещения на эти символы (соответственно, и на точку входа в функцию). Вот эта вот таблица со смещениями на функции и называется глобальной таблицей смещений, или Global Offset Table (GOT). Отсюда тебе надо понять только то, что GOT помогает узнавать адреса, которые без этой таблицы узнать было бы сложно :).

Содержание  Вперед на стр. 059-074-2
ttfb: 3.3690929412842 ms