01.07.2011

Разработка эксплоитов для Linux. Часть III - переполнение буфера с помощью ret2libc

В данном руководстве будет продемонстрирована эксплуатация переполнения буфера с помощью ret2libc.

Автор: sickn3ss
http://sickness.tor.hu
Перевод: SecurityLab.ru

ПРИМЕЧАНИЕ: Перед чтением данного руководства рекомендуем вам просмотреть:

Во второй части данного руководства, при компиляции уязвимого приложения, мы использовали флаг -z execstack для gcc. Таким образом, был получен исполняемый стек. Но проблема в том, что большинство современных операционных систем по умолчанию использует неисполняемый стек.

В предыдущих частях данного руководства эксплоиты разрабатывались на Backtrack 4 R2. В данном руководстве эксплоит будет создан на Debian Squeeze.

Необходимые навыки:

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

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

Неисполняемый стек

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

Более подробно о неисполняемом стеке можно прочитать здесь: http://en.wikipedia.org/wiki/NX_bit

Для того чтобы обойти это ограничение, мы воспользуемся техникой “ret2libc” (возвращение к libc).

Эксплоиты, продемонстрированные в предыдущих статьях данной серии, имеют такую структуру:

##############################
мусорные данные + NOP + шеллкод + EIP (переписанный с помощью инструкции JMP/CALL в регистр, указывающий в область мусорных данных и NOP)
##############################

В случае с неисполняемым стеком, данная техника работать не будет. Выполнение инструкции jmp для стека приведет к ошибке сегментации. Вот здесь нам и пригодиться библиотека libc. Вместо перезаписи EIP с помощью инструкции, мы производим перезапись EIP с помощью функций, которые содержаться в библиотеке libc, после которых укажем аргументы функций.

ПРИМЕЧАНИЕ: Можно сделать так, чтобы код возвращался в любое место, которое вам необходимо. Но в этих целях чаще всего используется libc, так как она всегда используется в приложениях и предоставляет полезные вызовы.

Мы разобрались с тем, для чего нужно использовать libc. Теперь давайте перейдем к практическому применению техники вызова переполнения буфера.

Мы располагаем уязвимым приложением:

##############################
#include <stdio.h>
#include <string.h>
 
void evil(char* input)
{
        char buffer[500];
        strcpy(buffer, input); // Vulnerable function!
        printf("Buffer stored!\n");
        printf("Buffer is: %s\n\n",input);
}
 
int main(int argc, char** argv)
{
        evil(argv[1]);
        return 0;
}
##############################

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


Рис. 1

Присоединяем уязвимую программу к gdb и устанавливаем точки остановки на “call evil” и “ret” из функции “evil” для вычисления смещения, в которое будут переданы нужные данные.


Рис 2

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


Рис. 4

Рис. 5
Как было показано, для перезаписи нам дополнительно требуется 8 байтов, что в итоге даст 516 байт (Это означает, что объем мусорных данных должен составлять 512 байтов).
Теперь, давайте проверим, можно ли использовать libc для отправки нижеуказанной команды в GDB.
###########################
maint info sections ALLOBJ
###########################

Рис. 6

Мы не получили никаких нулевых данных, следовательно libc нам подходит.

Требуемое нам смещение равно 516. В начале данного руководства, было сказано о том, что EIP будет переписано с помощью инструкции JMP/CALL, так как это приведет к ошибке сегментации. Вместо этого, мы попытаемся перезаписать EIP с помощью одной из функций libc, а затем продолжим вызывать различные функции и передавать требуемые аргументы.

Мы будем работать с такими функциями:

  • system(): Данная функция выполняет команду или программу, указанную в аргументе.
  • exit(): Функция для выхода из программы.

Нам необходимо отыскать адреса функций system() и exit(), а также адрес “/bin/bash”, который необходимо указать как аргумент для system().
Структура нашего эксплоита, будет выглядеть таким образом:

##############################
мусорные данные * 512 + system() + exit() + адрес /bin/bash
##############################

Давайте найдем все необходимые адреса для формирования работоспособного эксплоита.


Рис. 7

Адрес system(), по всей видимости, действительный.


Рис. 8

Данный адрес хранит нулевой байт, поэтому использовать его нельзя. Функция exit() для наших целей не обязательна, эксплоит будет работать и без нее, но давайте все же попытаемся ее отыскать. Если мы окажемся в ситуации, в которой, например, выходная функция будет содержать нулевой байт, нам удастся быстро найти ей замену, равную значению exit+смещение.

По адресу 0xb7ebc304 можно найти функцию <exit+4>, которая нам подходит.


Рис. 9
Теперь найдем /bin/bash.


Рис. 10

Давайте проследим за /bin/bash.


Рис. 11

Теперь нам необходимо изменить адрес таким образом, чтобы заменить только “/bin/bash” для получения действительных аргументов для system().


Рис. 12

Все необходимые адреса найдены, перейдем к эксплуатации:

##############################
мусорные данные * 512 + “\x80\x61\xec\xb7” + “\x04\xc3\xeb\xb7” + “\x73\xf7\xff\xbf”
##############################

Посмотрим, что у нас получиться:


Рис. 13

Эксплуатация прошла успешно.

или введите имя

CAPTCHA
02-07-2011 03:42:09
всё как бы прекрасно, но сейчас модно собирать с -fstack-protector, а не с отключенным прополисом.
0 |
Задолбал
03-07-2011 18:02:17
Задолбали мои коменты затирать! Так то эксплоиты из под Рута запускать, это все равно что вирусы под виндой с учетки админа запускать. Модно нынче так
0 |
03-07-2011 23:11:33
Бан за тупость и ослиное упрямство. На месяц. От "задолбавшего". Алаверды - задолбал чушь всякую писать.
0 |
fObject
04-07-2011 12:42:44
Сорри,за повтор. А я давно уже предлагаю: 1) инженерам Intel & AMD: измените направление роста стека (ну достало уже - ведь это сохранившийся атавизм времен 4-битных процессоров; тогда рост стека сверху вниз был оправдан небольшим объемом памяти; сейчас в таком подходе нет необходимости, зато изменение направления роста сделает невозможным эксплуатацию большинства таких ошибок - EIP адрес просто так в стеке не перезатрешь; хотя кривые руки разработчиков софта и здесь не помогут smile;-) ). 2) разработчикам всяких ОС: запретите под страхом расстрела выполнение кода в стеке (и вообще данных как кода, а кода как данных), без всяких исключений, которые можно изменять программно (типа вызов системной функции уровня ядра в Windows отключает DEP - нафиг она такая нужна? а еще ее и через реестр можно отключить - вообще пипец; кстати жестко реализованный DEP обламает по полной все современные полиморфные и самошифрующиеся вирусы; и между прочим такая защита была внедрена в процессоры еще со времен IAx86 - ни кто, кроме некоторых версий ядер OpenBSD ее не задействует - а зачем? и правда. антивирусы то нужны...). И вообще в настоящей защите не должно быть никаких компромисов. Иначе это не защита - а создание видимости.
0 |
95268
06-07-2011 01:35:58
да и неплохо бы поменять форматы исполнительных файлов...
0 |
/dev/null
06-07-2011 11:20:38
да и неплохо бы поменять форматы исполнительных файлов... Лучше голову поменять. Тогда, возможно, в ней не будут зарождаться идиотские мысли. Про "исполнительные" файлы.
0 |
сапосаосаоса
07-07-2011 19:54:55
шгвчтпшгвчтшпвчошргчтвшрчвщшртщчвштрщчвшорщчвшорщчвшорщчвшорщчвшощршчовщршочвщшровчщшорщчвшорщчвшощршчвощшрочвщшорвчщслртьчдлтрдсчлтрдлчстрдлчстрдлчстрдлчстдрлчстдлртсчдлртдсчлтрдлчстрдлчстдрлчстдрлчстдлртчсдлртдчлсрт
0 |