В данной статье разберем такой тип уязвимости, как переполнение буфера в стеке, и решим 3-е задание с сайта pwnable.kr.
- PWN;
- криптография (Crypto);
- cетевые технологии (Network);
- реверс (Reverse Engineering);
- стеганография (Stegano);
- поиск и эксплуатация WEB-уязвимостей.
Вдобавок к этому я поделюсь своим опытом в компьютерной криминалистике, анализе малвари и прошивок, атаках на беспроводные сети и локальные вычислительные сети, проведении пентестов и написании эксплоитов.
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Переполнение буфера
Переполнение буфера — уязвимость в компьютерных программах, основанная на возможности записи данных за пределами выделенного в памяти буфера, возникающая, как правило, из-за неконтролируемых получения и обработки данных извне. Использование языками высоко уровня технологии стекового кадра ведет к смешиванию управляющих данных и данных программы.
В данной статье разберем только переполнение буфера в стеке. Данный вид переполнения буфера известен как Stack smashing и может эксплуатироваться следующими способами:
- перезапись локальной переменной, находящейся в памяти рядом с буфером;
- перезапись адреса возврата в стековом кадре;
- перезапись указателя на функцию или обработчик исключений;
- перезапись параметра из другого стекового кадра.
В данном задании применяется метод перезаписи локальной переменной. Рассмотрим его суть на следующем примере:
#include <stdio.h>
#include <string.h>
int main(){
char pass[9] = "p@ssw0rdx00";
char buf[9];
printf("Input password: ");
scanf("%s", buf);
if(!strcmp(pass, buf))
printf("Login ok!!!n");
else
printf("FAIL...n");
return 0;
}
Так как переменная pass определена раньше, переменная buf, то ее возможно переполнить. Если ввести в buf больше, чем 9 байт, то они перепишут данные в переменной pass. Таким образом возможно “изменить” пароль на свой, передав программе, к примеру, такую строку 11111111x0011111111x00.
Решение задания bof
Нажимаем на иконку с подписью bof, и нам предоставляют исходный код, саму программу, а также адрес и порт для TCP-соединения.
Давай просмотрим исход код.
Из кода следует, что программа принимает строку, но сравнивает уже изначально зашитый ключ с контрольным значением. Но так как ввод не контролируется, а ключ определен раньше нашего буфера, мы можем переполнить буфер и перезаписать ключ. Для этого необходимо определить взаимное расположение переменных в памяти.
Для анализа программы я буду использовать Cutter. Откроем Cutter, укажем путь к исполняемому файлу.
Cutter отправляет нас сразу в точку entry. В списке функций выбираем main.
В main видим вызов нашей функции, откроем ее, выполнив двойной клик по названию функции.
Перед кодом функции имеется комментарий, где отражаются используемые в функции переменные и их адреса относительно базы текущего кадра стека (ebp). Как можно определить, наш буфер — это переменная var_2ch, а ключ — arg_8h.
Вычислим, сколько байт нам нужно перезаписать. Для этого достаточно найти разницу между адресами.
Таким образом нам нужно послать программе 0x34 любых байта, а потом дописать эталонное значение для примера. Для удобства я использую библиотеку pwntools.
from pwn import *
conn = remote('pwnable.kr', 9000)
payload = 'A' * 0x34
payload += 'xbexbaxfexca'
conn.send(payload)
conn.interactive()
Получаем шелл и просматриваем флаг.
Как результат, получаем свои очки.
В данной статье мы рассмотрели пример эксплуатации переполнения буффера в стеке, познакомились с инструментом Cutter и библиотекой pwntools. В следующей статье поговорим об упаковке исполняемых файлов и решим четвертое задание. До встречи в следующих статьях.
Автор: RalfHacker