Статья Переполнение буфера и перезапись значения переменных - разработка эксплойтов, часть 1

fuzzz

fuzzz

Red Team
03.02.2019
180
311
Все части переполнение буфера
Следующая часть Переполнение буфера и перезапись переменных к конкретному значению - разработка эксплойтов, часть 2

Доброго времени суток, посетители портала Codeby =) Решил написать цикл статей посвященный эксплуатации бинарных уязвимостей, в народе это называется чёрной магией. В сети есть куча статей и материалов на эту тему, а четкого пути так и не видно... Потому, что надо обладать огромным багажом знаний... Так как же научиться писать эксплойты? Находить 0дей уязвимости, обходить такие защиты, как DEP\ASLR ? Ответ прост нужна практика, практика и еще раз практика, чем мы с вами сейчас и займемся. Я буду вашим проводником.

В сети был такой учебный ресурс, как .

Exploit Exercises предлагает множество виртуальных машин, документацию и задачи, которые пригодятся в изучении повышения привилегий, анализа уязвимостей, разработки эксплойтов, отладки, реверс-инжиниринга и т.д.

Сейчас этот ресурс не доступен, так, как он переехал и доступен теперь по новому .

Начнем мы свой путь в профессию Exploit-Developer с решения различных ExploitMe на образе . Этот образ хорош тем, что в нем вы изучите основы, азы, переполнения буфера, уязвимости форматирования строки, переполнение кучи... А так же в нем отключены защиты подобные DEP и ASLR, чтобы мы могли сконцентрироваться именно на изучении самих уязвимостей и их эксплуатации. Обходить защиты мы будем, но чуть позже, когда наберемся опыта, а пока, что будем качать наш с вами скилл.

И так перейдем к делу, качаем и запускаем его на VirtualBox'e.

Логин и пароль "user"

Самое первое задание это .

Описание ExploitMe
Этот уровень вводит в концепцию, что доступ к памяти может осуществляться за пределами выделенной области, как размещаются переменные стека, и что изменение за пределами выделенной памяти может изменить выполнение программы.

Переходим в каталог с заданием
cd /opt/protostar/bin/


Исходный код
C:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}
Решение
Тут всё стандартно, за исключением того, что в коде присутствует ключевое слово volatile. Сказал бы я, но... Рассмотрим более подробно, что представляет из себя переполнение буфера, что это за тип уязвимости такой... Поэтому начнем с разбора исходного кода программы.

Ключевое слово volatile информирует компилятор, что значение переменной может меняться извне. Это может произойти под управлением операционной системы, аппаратных средств или другого потока. Поскольку значение может измениться, компилятор каждый раз загружает его из памяти.

Посмотрим еще раз на исходный код программы, видим, что есть буфер в 64 байта, в этот буфер будет записана строка посредством функции gets().

Посмотрим описание функции.

Функция gets считывает строку из стандартного потока ввода (stdin) и помещает ее в массив указанный аргументом. Чтение строки производится пока не будет встречен символ «переход на новую строку», или не будет достигнут конец файла.

Если чтение строки завершилось по считыванию символа «переход на новую строку», то символ «переход на новую строку» не записывается в массив, а заменяется символом «конец строки»

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

Вернемся к исходному коду и посмотрим на условие в программе. Если переменная modified не равняется нулю тогда печатается текст «you have changed the ‘modified’ variable», иначе «Try again?».

Переменная modified установлена со значением ноль, поэтому всегда будет печататься текст «Try again?».

Если мы запустим программу и передадим, ей строку типа "ААААBBBCCCC" то ничего не произойдет, а если передадим строку большего размера, чем указано в буфере "...AAAABBBBCCCCDDDD" то мы перезапишем переменную. Посмотрите на диаграмму ниже. В памяти в стеке это будет выглядеть примерно так.

27192



Исходя из того, что modified равен нулю, нам надо её изменить, что мы и сделаем. Используем буфер, функцию gets и volatile. Просто передадим в буфер строку не 64 байта, как положено, а 65, чтобы перезаписать значение переменной modified. Чтобы не вводить вручную данные, воспользуемся python’ом и перенаправим вывод в нашу программу.

python -c "print 'A' * 65" | ./stack0

Отлично, переменная перезаписана, а на экране отображается текст «you have changed the ‘modified’ variable», цель достигнута! Когда будете работать над очередным переполнением буфера, важно понимать, где и как находятся данные в стеке, поэтому вспоминайте эту диаграмму. В этом ExploitMe мы научились перезаписывать значение переменной, используя уязвимость переполнения буфера, теперь можно смело переходить на следующий уровень - .
 
InetTester

InetTester

Well-known member
21.10.2018
174
35
Очень сильно не хватает примера дизасемблерирования кода, и работы с дизасемблером.
Хоть с самым простым objdump.
 
Последнее редактирование:
  • Нравится
Реакции: Kalord, Skrillite и fuzzz
fuzzz

fuzzz

Red Team
03.02.2019
180
311
Очень сильно не хватает примера дизасемблерирования кода, и работы с дизасемблером.
Хоть с самым простым objdump.
Вы совершенно правы, но я решил пойти другим путем. На данном этапе он не нужен. Всему свое время... Это обязательно будет, objdump, gdb, ldd в следующих частях, а пока я решил огородить от этого читателей на некоторое время.
 
D

DrDerico

Скажите пожалуйста, почему хотя переменная modified и объявлена раньше буфера, на в памяти располагается после него? Или это особенность для volatile переменных?
 
  • Нравится
Реакции: ActionNum
ActionNum

ActionNum

Grey Team
27.11.2016
79
86
Скажите пожалуйста, почему хотя переменная modified и объявлена раньше буфера, на в памяти располагается после него? Или это особенность для volatile переменных?
Хороший вопрос. На мой взгляд это особенности работы компилятора или ОС. Нужно посмотреть выделение памяти в конкретной ОС. Мне тоже бы хотелось услышать ответ от автора.
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
Скажите пожалуйста, почему хотя переменная modified и объявлена раньше буфера, на в памяти располагается после него? Или это особенность для volatile переменных?
На картинке стек перевернутый просто он для простоты некоторых моментов тут так нарисован, это не особенность volatile. С начало в стек кладутся аргументы функций справа налево, потом адрес возврата. потом локальные переменные уже по порядку в том числе и буфер.

char **argv <------------ аргументы функций
int argc
ret <------ адрес возврата
modified; <------ локальные переменные в том числе и сам буфер.
... <------ дополнительное пространство несколько байт созданное компилятором для того чтобы выравнить стек
...
...
buffer[64]; <------- конец буфера
...
buffer[0]; <------- начало буфера
...
...
... <----------- верхушка стека ESP


Про стек можно почитать . + гугл.
 
Последнее редактирование:
W

wooolff

Премиум
19.02.2017
122
19
а можно подробней про установку образа.
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
а можно подробней про установку образа.
Там ничего сложного нет. Устанавливать его не надо образ собран как Live-CD.

Переходим на официальный сайт, скачиваем и устанавливаем VirtualBox.



29172


потом
Выбираем из списка нашу ВМ, заходим в меню "Настроить"

29173


Готово. Затем запускаем. Если все равно не понятно. Посмотри статьи как ставить Kali linux на VirtualBox тут на кодбае. Тоже самое и Protostar.
 
W

wooolff

Премиум
19.02.2017
122
19
я как раз его пошёл устанавливать как кали, а какой линукс, какая разрядность, скок всего выделять хз.))))
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
я как раз его пошёл устанавливать как кали, а какой линукс, какая разрядность, скок всего выделять хз.))))
кали - дебиан, а тут просто оракл 32 бит линукс указываешь. ну 1гб вполне сойдет под память. можно даже меньше. на скринах выше видно.
 
M

mr.none

Active member
08.09.2018
30
4
кали - дебиан, а тут просто оракл 32 бит линукс указываешь. ну 1гб вполне сойдет под память. можно даже меньше. на скринах выше видно.
подскажите как решить проблему открытия файла stack0?
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
подскажите как решить проблему открытия файла stack0?
Не совсем понял вопроса. Можно запустить 2 VM кали и протостар. И дальше просто подключится по ssh к протостар. как запустить ? ./stack0 или так /opt/protostar/bin/stack0
 
M

mr.none

Active member
08.09.2018
30
4
Не совсем понял вопроса. Можно запустить 2 VM кали и протостар. И дальше просто подключится по ssh к протостар. как запустить ? ./stack0 или так /opt/protostar/bin/stack0
Я имел ввиду как открыть исходник, чтобы посмотреть код. Понимаю, что он предоставлен, но хотелось бы не просто запустить ./stack0 а именно открыть его, например для редактирования.
Спасибо, что так быстро реагируете и отвечаете на вопросы)
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
Я имел ввиду как открыть исходник, чтобы посмотреть код. Понимаю, что он предоставлен, но хотелось бы не просто запустить ./stack0 а именно открыть его, например для редактирования.
Спасибо, что так быстро реагируете и отвечаете на вопросы)
Ты его не посмотришь не как. Потому что написана программа на Си т.е. на скомпилированном языке программирования. Это не скриптовой язык программирования где код посмотреть можно. К примеру ты можешь...

В директории home\user\ или директорииtmp скомпилировать - собрать свой файл.Точно такой же с небольшими изменениями как ты хочешь ))

вот ключи для компиляции кода
Код:
gcc -fno-stack-protector -z execstack -m32 -g program.c -o program
Если уж очень хочется посмотреть на код. Тогда...

Можно к примеру посмотреть код в IDA Pro, воспользовавшись декомпилятором hex-rays

И то код надо допиливать

30682


Т.е доводить его до ума

30681


Нужно это чтобы понять алгоритм работы программы так сказать...
 
S

Salivan

Active member
24.06.2019
26
8
кали - дебиан, а тут просто оракл 32 бит линукс указываешь. ну 1гб вполне сойдет под память. можно даже меньше. на скринах выше видно.
Это актуально в 2019 году? компиляторы по умолчанию собирают с защитой от переполненения, форматирования строк и прочее, нет?
 
fuzzz

fuzzz

Red Team
03.02.2019
180
311
Это актуально в 2019 году? компиляторы по умолчанию собирают с защитой от переполненения, форматирования строк и прочее, нет?
да, это задачки на которые учат ломать без защит (База эксплуатации). Потом можно порешать Fusion с защитами. Там уже mitigation ломать надо.
 
Последнее редактирование:
K

Kalord

New member
02.11.2019
1
0
Очень интересно, автору спасибо)
 
Мы в соцсетях: