Разработка эксплойта, часть 2: написание простого переполнения буфера

  • Автор темы Автор темы LeSh1y777
  • Дата начала Дата начала

LeSh1y777

Пользователь
Регистрация
25/9/25
Сообщения
5,682
Репутация
49
Лайки
153
Депозит
-8.95$
I. Введение

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

В этом уроке мы спроектируем и запустим простой пример переполнения буфера, чтобы продемонстрировать применение принципов, изученных в части 1. Мы будем использовать нашу систему Kali Linux для разработки нескольких простых примеров переполнения стека на языке C. Обратите внимание, что это простой пример переполнения буфера, демонстрирующий основные принципы. Это далеко не рабочий эксплойт, но я считаю, что он наглядно демонстрирует, как переполнение буфера можно использовать во вредоносных целях, не вдаваясь в подробности и не усложняя программирование. Мы оставим это для следующих уроков.

II. Откройте IDE

Поскольку в этом уроке мы будем писать простой код на языке C, вам, вероятно, понадобится IDE или интегрированная среда разработки (IDE). Конечно, можно использовать обычный текстовый редактор, но IDE, как правило, немного упрощает кодирование. Подойдёт любой удобный для вас вариант. Для этих уроков и упражнений я буду использовать IDE «MonoDevelop», встроенную в Kali. В разных версиях Kali есть разные встроенные IDE. Как правило, каждая из них будет работать. Кроме того, вы можете скачать и установить другие популярные IDE, например, Eclipse.

Его можно найти, перейдя в Приложения –>Программирование –> MonoDevelop и нажав, как показано на снимке экрана ниже.

6a4a49_5ec6e8becf5146cf9e106a489d1fdb5b~mv2.png


MonoDevelop откроет графический интерфейс, подобный показанному ниже. Теперь можно выбрать «Начать новое решение».

6a4a49_5c64af5d415d47788906430e3fcd0e82~mv2.png


Я назову своё решение « SimpleBufferOverlow », а затем создам новый файл и тоже назову его « SimpleBufferOverflow.c ». Затем нажмите на C и выберите «Пустой проект C». Нажмите «ОК».

6a4a49_183ca758f33f41f1a85994ed99fd41e7~mv2.png


Откроется новый пустой экран кодирования. Обратите внимание, что MonoDevelop создаст новый каталог с тем же именем, что и у «Solution», для хранения ваших файлов. Теперь нам нужно добавить код на языке C. Теперь вы можете использовать IDE как любой текстовый редактор.

III. Пишем переполнение буфера

Эта простая программа, которую мы собираемся создать, просто создаёт две переменные, «website» и «command» (строки 5 и 6), и выделяет им фиксированный объём памяти с помощью функции malloc языка C (выделение памяти). Затем она выводит расположение каждой из этих двух переменных в памяти (строки 11 и 12). Затем она вычисляет и выводит расстояние между двумя областями памяти (строка 14). Затем программа задаёт пользователю вопрос «где лучше всего учиться хакингу» (строка 15), и, когда пользователь отвечает, помещает эти данные в переменную «website» (строка 17). Наконец, программа выводит утверждение о лучшем месте для обучения хакингу на основе данных, полученных от пользователя (строка 19). В самой последней строке программа выполняет то, что находится в переменной «command» (строка 21), если это вообще возможно.

6a4a49_a442fcd178614e288a6367a08110358d~mv2.png


Закончив этот код, сохраните его и назовите « SimpleBufferOverflow.c ». Чтобы выполнить его, нам потребуется предоставить себе разрешение на выполнение. В Linux это можно сделать с помощью команды chmod, как показано ниже.

kali >chmod 755 SimpleBufferOverflow.c

6a4a49_813a31289b6640d783235de7f8d37fc2~mv2.png


Далее нам нужно скомпилировать код с помощью gcc. Gcc — это встроенный компилятор GNU C в Kali. Давайте воспользуемся им для компиляции нашей простой программы и сохраним её (-o) в новом файле с именем « SimpleBufferOverflow » (без расширения .c).

kali > gcc SimpleBufferOverflow.c -o SimpleBufferOverflow

6a4a49_96bf26dda9044a8ebd606f34ef22730f~mv2.png


Теперь давайте запустим эту простую программу.

6a4a49_34382dde183948ad9fcb6007a8f6c1ff~mv2.png


Цвет добавлен для акцента

Программа рассчитала объём памяти между переменной «website» и переменной «command». Как видите, он составляет 16 байт. Затем программа спрашивает пользователя:

«Где на Земле лучше всего учиться хакерству?»


Конечно, пользователь отвечает «hacker-arise.com». Вводимые пользователем данные затем сохраняются в переменной «website», и программа завершает работу, используя эти данные в переменной «website», и выводит сообщение;

«Лучшее место на Земле, где можно научиться хакерству — это hackers-arise.com».

Все прошло отлично, как и ожидалось.

IV. Переполнение переменной веб-сайта

В предыдущей программе переменные «website» и «command» имели фиксированную длину, определяемую функцией malloc. Наша простая программа вычисляла разницу между ячейками памяти, занимаемыми этими двумя переменными. Что произойдёт, если входные данные в переменную «website» превысят выделенные 16 байт и попадут в область памяти переменной «command»? Давайте попробуем и посмотрим, что произойдёт.

Мы знаем, что между двумя ячейками памяти находится 16 байт. Итак, попробуем ввести данные длиной более 16 байт/символов (символы ASCII занимают 1 байт). Например, попробуем ввести 17 случайных символов при запросе адреса нашего любимого веб-сайта (процесс отправки случайных данных в программу и её переменные называется фаззингом. Мы рассмотрим фаззинг и некоторые инструменты для его реализации на следующих уроках, чтобы попытаться обнаружить потенциальные переполнения буфера в реальном мире).

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

qwertyuiopasdfghj

6a4a49_3879725011074aacb240396bd7d79bae~mv2.png


Как видите, наш SimpleBufferOverflow работал нормально, пока не дошёл до последней строки. В этой строке кода он пытается выполнить то, что находится в переменной «command». Раньше в этой переменной ничего не было, и ничего не выполнялось, но теперь он, похоже, выполняет «j» и отвечает «not found». Это говорит нам, что команда «j» не найдена. Как видите, 17-й символ во входных данных «j» фактически переполнил область памяти переменной «command», и наша программа попыталась выполнить его. Это полезная информация, которую мы можем использовать для атаки!

Если все, что идет после 16-го символа в нашем вводе в приглашение «website», сохраняется в переменной фиксированного размера «website», а затем переполняется в переменную command, мы можем использовать эти знания против программы и, в конечном счете, против системы.

Давайте посмотрим, сможем ли мы заставить систему выполнить команду «ifconfig». Достаточно ввести 16 случайных символов, а затем «ifconfig», и, возможно, нам удастся получить информацию о сети из базовой системы. Давайте попробуем.

Входить;

qwertyuiopasdfgh ifconfig

6a4a49_fbb3f77e4bb242ebb8b853fc3f4f9681~mv2.png


Как видите, программа SimpleBufferOverflow переполнила переменную «website» и поместила всё после 16-го символа, в данном случае «ifconfig», в переменную «command», а затем выполнила её. В результате нам удалось получить информацию о сети из базовой системы!

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

Это было довольно безобидно. А что, если бы мы были более злонамеренными и захотели получить хэши паролей? Конечно, для получения хэшей паролей нашей программе потребовались бы права root, хотя бы на момент её выполнения. Это действительно так, поскольку у некоторых программ установлен бит SUID, дающий им привилегии создателя. Чтобы найти программы с установленным битом SUID для «root», попробуйте выполнить следующую команду.

kali >find / -perm +4000 -user root -type f -print

6a4a49_6b44434af6a642458c82367fb0233f6f~mv2.png


Как видите, существует множество файлов, работающих с битом SUID, установленным от имени root . Суть в том, что если бы мы могли переполнять буфер в этих программах (а это уже было!), мы могли бы выполнять команды от имени root!

Теперь посмотрим, сможем ли мы сохранить эти хеши паролей в /etc/shadow. Предположим, что у этой программы установлен бит SUID для пользователя «root». Это означает, что при запуске она выполняется с привилегиями создателя, «root». Сначала нам нужно передать переменной 16 символов любых входных данных. Затем 17-й символ переполнит переменную «website» и превратит её в «command».

Давайте попробуем;

qwertyuiopasdfghcat /etc/shadow

Обратите внимание, что символы 17–19 — это «cat», за которым следует /etc/shadow (местоположение хешей паролей в Linux). Если нам удастся выполнить эту команду, она должна вывести на экран всё содержимое файла /etc/shadow.

6a4a49_5a76f45fb692461eaf27bb5e98308aa2~mv2.png


Сработало! Теперь у нас есть все хешированные пароли. Обратите внимание, что в моей системе хешированный пароль есть только у пользователя root. У всех остальных пользователей пока нет паролей. Если бы они были, их хешированные пароли также отображались бы здесь.

Если вы хотите быть по-настоящему вредоносным, вы можете ввести при появлении запроса «лучшее место для изучения хакерства»;

qwertyuiopasdfghdd if=/dev/random of=/dev/sda

Как вы думаете, что сделает эта команда, если ее выполнить?

Заключение

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

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

В этом уроке мы спроектируем и запустим простой пример переполнения буфера, чтобы продемонстрировать применение принципов, изученных в части 1. Мы будем использовать нашу систему Kali Linux для разработки нескольких простых примеров переполнения стека на языке C. Обратите внимание, что это простой пример переполнения буфера, демонстрирующий основные принципы. Это далеко не рабочий эксплойт, но я считаю, что он наглядно демонстрирует, как переполнение буфера можно использовать во вредоносных целях, не вдаваясь в подробности и не усложняя программирование. Мы оставим это для следующих уроков.

II. Откройте IDE

Поскольку в этом уроке мы будем писать простой код на языке C, вам, вероятно, понадобится IDE или интегрированная среда разработки (IDE). Конечно, можно использовать обычный текстовый редактор, но IDE, как правило, немного упрощает кодирование. Подойдёт любой удобный для вас вариант. Для этих уроков и упражнений я буду использовать IDE «MonoDevelop», встроенную в Kali. В разных версиях Kali есть разные встроенные IDE. Как правило, каждая из них будет работать. Кроме того, вы можете скачать и установить другие популярные IDE, например, Eclipse.

Его можно найти, перейдя в Приложения –>Программирование –> MonoDevelop и нажав, как показано на снимке экрана ниже.

6a4a49_5ec6e8becf5146cf9e106a489d1fdb5b~mv2.png


MonoDevelop откроет графический интерфейс, подобный показанному ниже. Теперь можно выбрать «Начать новое решение».

6a4a49_5c64af5d415d47788906430e3fcd0e82~mv2.png


Я назову своё решение « SimpleBufferOverlow », а затем создам новый файл и тоже назову его « SimpleBufferOverflow.c ». Затем нажмите на C и выберите «Пустой проект C». Нажмите «ОК».

6a4a49_183ca758f33f41f1a85994ed99fd41e7~mv2.png


Откроется новый пустой экран кодирования. Обратите внимание, что MonoDevelop создаст новый каталог с тем же именем, что и у «Solution», для хранения ваших файлов. Теперь нам нужно добавить код на языке C. Теперь вы можете использовать IDE как любой текстовый редактор.

III. Пишем переполнение буфера

Эта простая программа, которую мы собираемся создать, просто создаёт две переменные, «website» и «command» (строки 5 и 6), и выделяет им фиксированный объём памяти с помощью функции malloc языка C (выделение памяти). Затем она выводит расположение каждой из этих двух переменных в памяти (строки 11 и 12). Затем она вычисляет и выводит расстояние между двумя областями памяти (строка 14). Затем программа задаёт пользователю вопрос «где лучше всего учиться хакингу» (строка 15), и, когда пользователь отвечает, помещает эти данные в переменную «website» (строка 17). Наконец, программа выводит утверждение о лучшем месте для обучения хакингу на основе данных, полученных от пользователя (строка 19). В самой последней строке программа выполняет то, что находится в переменной «command» (строка 21), если это вообще возможно.

6a4a49_a442fcd178614e288a6367a08110358d~mv2.png


Закончив этот код, сохраните его и назовите « SimpleBufferOverflow.c ». Чтобы выполнить его, нам потребуется предоставить себе разрешение на выполнение. В Linux это можно сделать с помощью команды chmod, как показано ниже.

kali >chmod 755 SimpleBufferOverflow.c

6a4a49_813a31289b6640d783235de7f8d37fc2~mv2.png


Далее нам нужно скомпилировать код с помощью gcc. Gcc — это встроенный компилятор GNU C в Kali. Давайте воспользуемся им для компиляции нашей простой программы и сохраним её (-o) в новом файле с именем « SimpleBufferOverflow » (без расширения .c).

kali > gcc SimpleBufferOverflow.c -o SimpleBufferOverflow

6a4a49_96bf26dda9044a8ebd606f34ef22730f~mv2.png


Теперь давайте запустим эту простую программу.

6a4a49_34382dde183948ad9fcb6007a8f6c1ff~mv2.png


Цвет добавлен для акцента

Программа рассчитала объём памяти между переменной «website» и переменной «command». Как видите, он составляет 16 байт. Затем программа спрашивает пользователя:

«Где на Земле лучше всего учиться хакерству?»


Конечно, пользователь отвечает «hacker-arise.com». Вводимые пользователем данные затем сохраняются в переменной «website», и программа завершает работу, используя эти данные в переменной «website», и выводит сообщение;

«Лучшее место на Земле, где можно научиться хакерству — это hackers-arise.com».

Все прошло отлично, как и ожидалось.

IV. Переполнение переменной веб-сайта

В предыдущей программе переменные «website» и «command» имели фиксированную длину, определяемую функцией malloc. Наша простая программа вычисляла разницу между ячейками памяти, занимаемыми этими двумя переменными. Что произойдёт, если входные данные в переменную «website» превысят выделенные 16 байт и попадут в область памяти переменной «command»? Давайте попробуем и посмотрим, что произойдёт.

Мы знаем, что между двумя ячейками памяти находится 16 байт. Итак, попробуем ввести данные длиной более 16 байт/символов (символы ASCII занимают 1 байт). Например, попробуем ввести 17 случайных символов при запросе адреса нашего любимого веб-сайта (процесс отправки случайных данных в программу и её переменные называется фаззингом. Мы рассмотрим фаззинг и некоторые инструменты для его реализации на следующих уроках, чтобы попытаться обнаружить потенциальные переполнения буфера в реальном мире).

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

qwertyuiopasdfghj

6a4a49_3879725011074aacb240396bd7d79bae~mv2.png


Как видите, наш SimpleBufferOverflow работал нормально, пока не дошёл до последней строки. В этой строке кода он пытается выполнить то, что находится в переменной «command». Раньше в этой переменной ничего не было, и ничего не выполнялось, но теперь он, похоже, выполняет «j» и отвечает «not found». Это говорит нам, что команда «j» не найдена. Как видите, 17-й символ во входных данных «j» фактически переполнил область памяти переменной «command», и наша программа попыталась выполнить его. Это полезная информация, которую мы можем использовать для атаки!

Если все, что идет после 16-го символа в нашем вводе в приглашение «website», сохраняется в переменной фиксированного размера «website», а затем переполняется в переменную command, мы можем использовать эти знания против программы и, в конечном счете, против системы.

Давайте посмотрим, сможем ли мы заставить систему выполнить команду «ifconfig». Достаточно ввести 16 случайных символов, а затем «ifconfig», и, возможно, нам удастся получить информацию о сети из базовой системы. Давайте попробуем.

Входить;

qwertyuiopasdfgh ifconfig

6a4a49_fbb3f77e4bb242ebb8b853fc3f4f9681~mv2.png


Как видите, программа SimpleBufferOverflow переполнила переменную «website» и поместила всё после 16-го символа, в данном случае «ifconfig», в переменную «command», а затем выполнила её. В результате нам удалось получить информацию о сети из базовой системы!

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

Это было довольно безобидно. А что, если бы мы были более злонамеренными и захотели получить хэши паролей? Конечно, для получения хэшей паролей нашей программе потребовались бы права root, хотя бы на момент её выполнения. Это действительно так, поскольку у некоторых программ установлен бит SUID, дающий им привилегии создателя. Чтобы найти программы с установленным битом SUID для «root», попробуйте выполнить следующую команду.

kali >find / -perm +4000 -user root -type f -print

6a4a49_6b44434af6a642458c82367fb0233f6f~mv2.png


Как видите, существует множество файлов, работающих с битом SUID, установленным от имени root . Суть в том, что если бы мы могли переполнять буфер в этих программах (а это уже было!), мы могли бы выполнять команды от имени root!

Теперь посмотрим, сможем ли мы сохранить эти хеши паролей в /etc/shadow. Предположим, что у этой программы установлен бит SUID для пользователя «root». Это означает, что при запуске она выполняется с привилегиями создателя, «root». Сначала нам нужно передать переменной 16 символов любых входных данных. Затем 17-й символ переполнит переменную «website» и превратит её в «command».

Давайте попробуем;

qwertyuiopasdfghcat /etc/shadow

Обратите внимание, что символы 17–19 — это «cat», за которым следует /etc/shadow (местоположение хешей паролей в Linux). Если нам удастся выполнить эту команду, она должна вывести на экран всё содержимое файла /etc/shadow.

6a4a49_5a76f45fb692461eaf27bb5e98308aa2~mv2.png


Сработало! Теперь у нас есть все хешированные пароли. Обратите внимание, что в моей системе хешированный пароль есть только у пользователя root. У всех остальных пользователей пока нет паролей. Если бы они были, их хешированные пароли также отображались бы здесь.

Если вы хотите быть по-настоящему вредоносным, вы можете ввести при появлении запроса «лучшее место для изучения хакерства»;

qwertyuiopasdfghdd if=/dev/random of=/dev/sda

Как вы думаете, что сделает эта команда, если ее выполнить?

Заключение

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