March 28, 2019

Разработка эксплойтов, Часть 2 - Введение в переполнение буфера.

Наш telegram канал : @Save and betray

Вступай в наши ряды

Описание ExploitMe

На этом уровне рассматривается концепция изменения переменных к конкретным значениям в программе и то, как переменные располагаются в памяти.

Этот уровень находится в / opt / protostar / bin / stack1

Переходить в каталог не нужно, так как мы сделали это в прошлый раз.

Stack1VM

Советы

  • Если вы не знакомы с отображаемым шестнадцатеричным числом, «man ascii» — ваш друг.
  • little endian

Исходный код

C:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

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

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

Решение

В этом примере у нас так же есть

буфер на 64 байта, присутствует ключевое слово

volatile, но при этом тут нет теперь функции gets(), а в место неё есть функция strcpy().

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

Функция

strcpy

(destination, source) копирует данные из строки, на которую указывает аргумент source, в строку, на которую указывает аргумент destination, пока не встретится символ конца строки (нулевой символ). Копирование производится вместе с символом конца строки. Если строки перекрываются, результат копирования будет не определен.

Посмотрим на второе условие в программе, если переменная

modified

равняется значению «

0x61626364

», тогда печатается текст «

you have correctly got the variable to the right value

» иначе «

Try again, you got 0x%08x

», плюс указывается значение переменной modified в шестнадцатеричной системе счисления. Поскольку в программе, есть еще одно условие где используется аргумент

argc.

Запустить питон код, как в прошлой программе не получится. Воспользуемся BASH для подстановки значения, чтобы использовать наш вывод, в качестве аргумента.

Последовательность команд будет следующей.

./stack1 $(python -c "print 'a' * 65")

В итоге мы получим следующий текст на экране «Try again, you got 0x00000061», как видим переменная modified приняло текущее значение. Мы писали в буфер последовательность букв из «aaaa…», из них 64 байта пошли в буфер, последним перезаписали значение переменной modified. Стало быть modified равняется ‘a’. Посмотрим чему равно ‘a’ в хексе, воспользуемся man ascii. И видим, что ‘a’ равняется значению 0x61. Теперь еще раз взглянем на значение во втором условии «0x61626364», значит остальные числа в значении это «bcd», а всё вместе «abcd». Пробуем эксплуатировать, передадим 64 байта в буфер и еще 4 байта для перезаписи значения переменной modified.

./stack1 $(python -c "print 'a' * 64 + 'abcd' ")

Получаем строку «Try again, you got 0x64636261» , хм, что-то пошло не так и строка записалась в перевёрнутом виде. Почему? Если погуглить, то можно узнать о такой вещи, как little endian, т.е. в памяти, числа перевёрнутые. Значит делаем реверс строки и эксплуатируем уязвимость переполнения буфера в функции strcpy().

./stack1 $(python -c "print 'a' * 64 + 'abcd'[::-1]")

Отлично, переменная перезаписана, а на экране отображается текст «you have correctly got the variable to the right value» цель достигнута! Если в прошлом ExploitMe нашей задачей было просто изменить значение переменной, то в этой задаче мы научились устанавливать нужное нам значение для конкретной переменной используя уязвимость переполнения буфера. Теперь переходим на следующий уровень stack2.​