BufferOverflow на простом примере
- Font size: Larger Smaller
- Hits: 3034
- 0 Comments
- Subscribe to this entry
- Bookmark
Большинство ИТ специалистов хоть раз слышали о такой вещи как переполнение буфера (bufferoverflow). При этом когда в какой-нибудь беседе у меня заходила речь о переполнении буфера я находил, что многие специалисты понятия не имеют, что происходит при переполнении буфера и каким это волшебным образом это позволяет получить доступ к компьютеру жертвы. Поэтому сейчас, на примере очень простого куска кода на языке С, я хочу показать что происходит, так что бы это мог понять каждый. Если вы слышали о такой вещи как bufferoverflowи хотели бы понять основы того как это происходит, то думаю данная статья будет вам полезно.
Свою лабораторную я буду проводить на машине Debian, сборке KaliLinux, хотя все то же самое можно сделать на любом компьютере, где есть компилятор языка С. Хватит болтовни, переходим к делу. Я открыл текстовый редактор (в моем случае это Leafpad) и добавил в новый документ код, как показано на рисунке 1.
Рис.1
Давайте разберем этот код подробнее, строчка за строчкой.
#include<stdio.h> // подключаем библиотеку ввода-вывода
void main() //создаем функцию main. Далее код будет располагаться внутри { }
char*name; //создаем строковую переменную name
char*command; //создаем строковую переменную command
name=(char*)malloc(10); //функция malloc возвращает указатель на первый байт области памяти (значение будет записано в переменную name), захватывая при этом блок памяти по крайней мере не меньше, чем значение указанное в скобках (10). Функция char позволяет преобразовать значение из void в char (это нужно т.к. переменная name типа char).
command=(char*)malloc(10); //аналогично, только для переменной command.
printf(“Adres peremennoi name: %d\n”,name); //выводим на экран сообщение и значение переменной name
printf(“Adres peremennoi command: %d\n”,command); //выводим на экран сообщение и значение переменной command
printf(“Raznica mezdu adresami: %d\n”,command-name); //выводим на экран разничу, между адресами nameи command, что покажет нам сколько памяти выделено для переменной name.
Printf(“Vvedite vashe ima:”); //выводим на экран сообщение с просьбой ввести имя пользователя
gets(name); // записываем данные, которые пользователь вводит с клавиатуры в переменную name
printf("Privet %s\n", name);//выводим на экран приветствие и значение переменной name
system(command); //говорим выполнить команду, содержащуюся в переменной command
Вкратце опишу общий принцип моего примера. Я создаю две переменные name и command. Далее я по очереди выделяю им область в памяти, что бы они находились друг за другом. После чего вывожу их адреса и разницу между адресами для наглядности. После этого запрашиваю пользователя ввести с клавиатуры значение. В самом конце я вывожу на экран значение, которое ввел пользователь и, при помощи функции system выполняю код, который содержится в переменной command. По умолчанию в переменной command нет никакого когда, но за счет переполнения буфера он там появится и это я вам сейчас продемонстрирую.
Давайте теперь сохраним созданный нами код. Я сохраню его в директорию /root и назову файл bufferoverflow.c
Далее откомпилируем наш код (Рис.2). Не обращайте внимания на ошибки в процессе компиляции. В результате в той же директории /root у нас появится файл bufferoverflow.
Рис.2
Теперь давайте запустим созданную нами программу (Рис.3). Когда программа запросит введем свое имя (в моем случае Александр). Как можно видеть все отработало корректно и программа сказала мне PrivetAlexander.
Рис.3
Теперь давайте снова запустим нашу программу и пока ничего не будем вводить а просто подумаем. Переменная name получила адрес в памяти 143978504, в то время как переменная command получила в памяти адрес 143978520. Не трудно понять, что эти две переменные размещены в памяти сразу друг за другом. Переменная name занимает область памяти с 143978504 до 143978519, а переменная command идет сразу за ней и аналогичным образом занимает область памяти с 143978520 до 143978535. Учитывая, что когда мы используем функцию gets(name), которая запрашивает пользователя ввести данные с клавиатуры и никак эти введенные данные не проверяем, то если пользователь введет значение превышающее 16 байт, излишек (т.е. значения, которые будут идти сразу за первыми 16 байтами) залезет на область памяти, выделенную для переменной command и перезапишет то, что там находится. В конце нашей программы я специально добавил функцию system(command), которая по сути дела постарается выполнить то, что мы перезапишем в переменную command.
Давайте продемонстрируем. Запускаем нашу программу ./bufferoverflow и когда система попросит нас “Vvedite vashe ima:” мы введем такое вот значение:
1234567890123456cat /etc/passwd
Получится, что 1234567890123456 как положено запишется в переменную name, а остаток cat /etc/passwd запишется в переменную command. Далее программа с помощь функции system(command) выполнит код (cat /etc/passwd), который находится в переменной command. На рисунке 4 можно видеть результат.
Рис.4
По сути дела мы вызвали незапланированную в коде ситуацию и выполнили код, который позволил нам прочитать файл /etc/passwd
Если мы снова запустим программу и введем допустим 1234567890123456/bin/sh, то получим доступ к shell через нашу утилиту.
Представьте если бы мы писали сетевую утилиту и использовали этот кусок кода, что бы запросить у пользователя какие-нибудь данные. Злоумышленнику достаточно было бы просто ввести непредусмотренное в коде значение и получить полный доступ к нашему компьютеру.
По сути дела мы все сделали и я надеюсь данный материал помог вам немного понять такую вещь как переполнение буфера, почему оно возникает и к каким последствиям может привести. Понятное дело, что пример выдуманный и имеет мало отношения к реальным программам, тем не менее он составлен так, что бы максимально упростить его и донести основную суть.
Надеюсь данный пост был вам интересен. Если у вас возникли какие-нибудь вопросы, буду рад ответить на них в комментариях. Так же с радостью послушаю предложения на тему о чем бы мне еще написать, что бы вам было интересно читать ;). Спасибо за внимание и потраченное время.