Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #58, СЕНТЯБРЬ 2005 г.

Сокрушительная атака

Андрей Семенюченко

Спецвыпуск: Хакер, номер #058, стр. 058-010-5


/* вставляем шелл-код начиная с середины буфера */

ptr = buffer + ((BUFFERSIZE/2) - (strlen

(lunixshell)/2));

for(i=0; i<strlen(lunixshell); i++)

*(ptr++) = lunixshell[i];

/* вызываем уязвимую программу с нашем буфером в качестве аргумента*/

buffer[BUFFERSIZE-1] = 0;

execl("./simple", "simple", buffer, 0);

return 0;

}

Это довольно несложный код. Здесь мы сначала определяем размер уязвимого буфера и резервируем 100 байт под собственные нужды. В переменную linuxshell записываем один популярный шелл-код для его дальнейшего выполнение. Вообще говоря, существует огромное разнообразие шелл-кодов, многие из которых можно без труда бесплатно скачать и использовать по прямому назначению :). Далее следует функция sp(), содержащая ассемблерную вставку, которая в свою очередь копирует значение указателя стека в переменную, возвращаемую этой функцией. Как ты помнишь, это один из основных моментов.

Вот мы и добрались до функции main(), в рамках которой получаем указатель на стек и адрес возврата (в данном случае они будут идентичными при нулевом смещении), затем выделяем память для нашего буфера, заполняем буфер адресом возврата и заполняем первую половину буфера инструкцией NOP. NOP – это инструкция \x90 в шестнадцатеричном формате, которая ничего не делает, только передает управление следующей инструкции. Иногда NOP используется для создания задержек.

Небольшое отступление, чтобы понять смысл использования NOP. Проблема, с которой мы столкнулись, - выяснение адреса расположения шелл-кода, который он получит, когда строка переполнения буфера будет помещена в стек. На помощь придет то, что начальный адрес стека не меняется при запуске каждого нового приложения. Поэтому, зная, где он начинается, возможно угадать примерное расположение буфера, который планируется переполнить. Дело в том, что указатель стека указывает на начало стека, таким образом, адрес буфера нужно указать где-то поблизости к нему. Но знаем ли мы точно, куда "прыгнуть", чтобы выполнить шелл-код? Практически всегда нет. Облегчить эту задачу можно вставкой символов NOP, что мы и сделали. Тем самым мы повысили вероятность угадывания. Таким образом, в случае удачи адрес возврата укажет на одну из команд NOP и вслед за ними выполнится шелл-код.

Далее мы вставляем шелл-код в середину нашего буфера и вызываем уязвимую программу с буфером в качестве аргумента. Вуаля!

Теперь дело за малым: назовем наш эксплойт expl.c и откомпилируем его:

gcc ./expl.c –o expl

До выполнения expl зададим root в качестве владельца для программы simple, чтобы при использовании эксплойта получить рутовые привилегии.

chown 0 ./simple

chmod 4755 ./simple

Теперь зайдем в систему под любым непривилегированным пользователем и запустим эксплойт. Если все было сделано правильно, на экране должна появиться решетка, то есть значок "#", символизирующий приглашение для суперпользователя!

Примером переполнения кучи может служить уязвимость в Microsoft JPEG GDI+, описанная в бюллетене по безопасности MS04-028.

Реальные уязвимости

Назад на стр. 058-010-4  Содержание  Вперед на стр. 058-010-6