|

Shellcode своими руками
Xakep, номер #044, стр. 044-038-4
К несчастью (или к счастью?), это - далеко не выход. Ведь можно положить в стек данные таким образом, что после возврата из процедуры управление будет передано любой функции, принадлежащей основной программе, например, memcpy, и параметры ее вызова тоже будут находиться в стеке на положенных местах. В результате функция скопирует данные из стека в другую область памяти, где исполнение кода разрешено, а после возврата из нее управление будет передано в эту область памяти.
Эксплуатация переполнения "вслепую"
А что, если мы не знаем адрес возврата, длину буфера, расстояние от буфера до адреса возврата и вообще не видели уязвимую программу, а знаем лишь, что она находится на таком-то IP-адресе и таком-то порте? Возможно ли добиться выполнения шеллкода? Ответ - ДА! Некоторыми нетривиальными путями возможно добиться и этого.
Во-первых, нам нужно знать адрес буфера в памяти. Примерный адрес мы знаем - он чуть меньше, чем начальный адрес стека. Например, в linux он будет чуть меньше, чем 0xbfffffff. Насколько "чуть"? На сотню-тысячу байт. Сколько попыток нужно, чтобы угадать его? Нет, не сотня-тысяча. Нам не обязательно знать адрес шеллкода в памяти с точностью до одного байта, ничто не мешает нам разместить перед шеллкодом "посадочную зону" из большого количества NOP-ов, нам достаточно попасть адресом возврата в эту зону. Количество попыток перебора, таким образом, сведется к менее чем десяти.
Во-вторых, нам нужно знать примерную длину буфера. Ее мы подберем методом "деления на два", или "недолет-перелет". Вот псевдоисходник программы, реализующей это:
mpzone=0;slider=0x1000;
do {
mpzone+=slider;
if(!try)mpzone-=slider;
slider=slider/2;
} while(slider!=0);
Функция try - псевдофункция, определяющая, был ли "недолет" или "перелет". В случае "недолета", т.е. допустимого размера данных, удаленная программа продолжает функционировать нормально, а в случае "перелета" - подвисает, обрывает соединение или совсем выпадает. Если выпадает совсем, реализовывать эту технологию долго - надо ждать, пока админ приведет сервис в работоспособное состояние. Работа алгоритма завершится на том, что будет найден максимальный размер данных, при котором удаленный сервис работает нормально. Эту область данных я буду называть MP-зона (от лат. monopenisuale).
Для более корректного нахождения MP-зоны функция try должна проверять способность сервиса принять данные не один раз, а несколько, с различным значением данных. Такая проверка гарантирует, что внутрь MP-зоны можно помещать любые данные, и на работоспособность сервиса это не повлияет.
Что такое MP-зона с точки зрения программы? Понятно, что MP-зона не меньше места, выделенного в стеке под буфер. Но она может быть и больше, вот картинка:
Стек передаваемые данные
...
<буфер - 1024 байта> <MP-зона>
<переменная 1 - 4 байта> <MP-зона>
<адрес возврата - 4 байта> <новый адрес возврата>
...
Если значение переменной 1 не влияет на работоспособность программы, то она также попадает в MP-зону. Однако значение этой переменной может быть критично:
Назад на стр. 044-038-3 Содержание Вперед на стр. 044-038-5
|