- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
ТЕХНИКА СЕТЕВЫХ АТАК - Крис Касперский
Шрифт:
Интервал:
Закладка:
– Смещение от кадра стека Содержимое ячеек
– 0 A
– 1 buf[0]
– 2 buf[1]
– 3 buf[2]
– 4 buf[3]
– 5 buf[4]
– 6 B
– 7 Адрес возврата
– 8… Стек функции, вызвавшей myfunt
Попытка записи в ячейку buff[6] приведет к искажению адреса возврата, и после завершения работы функции myfunct() произойдет передача управления на совершенно незапланированный разработчиком участок кода и, скорее всего, дело кончится повисанием. Все было бы иначе, если бы компилятор располагал локальные переменные ниже ячейки, хранящей адрес возврата, но, эта область стека уже занята, - она принадлежит функции, вызвавшей myfunct. Так уж устроен стек, - он растет снизу вверх, но не наоборот.
Пример, приведенный ниже, служит наглядной иллюстрацией ошибки программиста, известной под названием «срыва стека» (на диске, прилагаемом к книге, он расположен в файле “/SRC/buff.demo.c.”)
· #include «stdio.h»· #include «string.h»·· root()· {· printf("Hello, Root!n");·}·· auth()· {· char user[10];· char pass[10];· printf("Login:"); gets( amp;user[0]);· printf("Passw:"); gets( amp;pass[0]);· if (!strcmp( amp;pass[0],"guest"))· return 1;· return 0;·}·· main()· {· printf("Buffer Overflows Demon");· if (auth())· printf("Password okn");· else· printf("Invalid passwordn");·}
На первый взгляд, программа как будто бы должна работать нормально. Но функция gets(), читающая строку с клавиатуры, не имеет никаких представлений о размере выделенного под нее буфера, и принимает данные до тех пор, пока не встретит символ возврата каретки. Если пользователь введет в качестве своего имени строку, превышающую десять символов [307], ее «хвост» затрет адрес возврата функции и дальнейшее выполнение программы окажется невозможным.
Например, если запустить этот пример под управлением Windows 2000, и в качестве имени пользователя ввести строку “1234567890qwerty” операционная система выдаст следующее сообщение, предлагая либо завершить работу приложения, либо запустить отладчик (если он установлен) для выяснения причин сбоя: «Исключение unknown software exception (0xc000001) в приложении по адресу 0x0012ffc0».
Рисунок 72 Реакция системы на переполнение буфераДопустим, в программе присутствует некая функция (условно названная “root”), которая выполняет действия, необходимые злоумышленнику. Может ли он специально подобранной строкой изменить адрес возврата таким образом, чтобы вместо сообщения о неправильно набранном пароле, управление передавалось на эту функцию?
Для ответа на такой вопрос необходимо знать по какому адресу расположена интересующая злоумышленника функция, и какой именно байт из введенной строки затирает адрес возврата. Выяснить это можно с помощью дизассемблирования кода программы.
Дизассемблирование - процесс сложный и требующий от исследователя хороших знаний ассемблера, архитектуры операционной системы и техники компиляции кода. Без этого разобраться с алгоритмом работы программы практически невозможно. К сожалению, практически не существует литературы, посвященной дизассемблированию, поэтому, в большинстве случаев приходится осваивать эту тему самостоятельно [308].
Все, сказанное ниже, рассчитано на читателя средней квалификации, как минимум знающего назначение наиболее употребляемых команд микропроцессора Intel 80x86. В качестве дизассемблера выбрана IDA PRO четвертой версии [309], однако, можно воспользоваться и другими инструментами, такими как SOURCER, W32Dasm или на худой конец DumpBin, который поставляется с любым Windows-компилятором.
Результат дизассемблирования buff.demo.exe показан ниже (на диске, прилагаемом к книге, он расположен в файле “/LOG/buff.demo.lst”). Исследователь должен изучить «устройство» функции Auth, (как ее найти во много килобайтовом листинге - тема отдельного разговора). Для облегчения понимания, листинг снабжен подробными комментариями.
·.text:00401000; Segment type: Pure code
·.text:00401000 _text segment para public 'CODE' use32
·.text:00401000 assume cs:_text
·.text:00401000;org 401000h
·.text:00401000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
·.text:00401000 Root proc near
·.text:00401000; Функции root расположена по адресу 0x401000
·.text:00401000 push ebp
·.text:00401000 ;… назначение процедуры root значение не имеет
·.text:00401000 ;… для ее вызова достаточно знать по какому адресу она расположена в памяти
·.text:00401000;… а расположена она по адресу 0x401000
·.text:00401001 mov ebp, esp
·.text:00401003 push offset aHelloRoot; "Hello, Root!n"
·.text:00401008 call _printf
·.text:0040100D add esp, 4
·.text:00401010 pop ebp
·.text:00401011 retn
·.text:00401011 Root endp
·.text:00401012
·.text:00401012; --------------- S U B R O U T I N E ---------------------------------------
·.text:00401012
·.text:00401012; Attributes: bp-based frame
·.text:00401012
·.text:00401012 auth proc near; CODE XREF: main+10p
·.text:00401012
·.text:00401012 var_18 = byte ptr -18h
·.text:00401012 var_C = byte ptr -0Ch
·.text:00401012; Так IDA обозначает локальные переменные, а цифры указывают относительное
·.text:00401012; расположение от конца кадра стека.
·.text:00401012; В Момент вызова функции указатель стека указывает на адрес возврата
·.text:00401012 push ebp
·.text:00401012; В стек заносится регистр ebp, значение указателя стека уменьшается на 4
·.text:00401013 mov ebp, esp
·.text:00401013; Открывается кадр стека:
·.text:00401013; В регистр ebp заносится значение регистра указателя стека esp.
·.text:00401013; Регистр ebp будет использоваться для адресации локальных переменных относительно конца кадра стека
·.text:00401015 sub esp, 18h
·.text:00401015; Резервируется 0x18 (24 в десятичной нотации) байт под локальные переменные
·.text:00401015; Но размер двух буферов равен 10+10=20 байтам! Откуда взялись четрые лишние байта?
·.text:00401015 ; Для ускорения доступа к данным компилятор размещает начала каждого из буферов по адресам, кратным
·.text:00401015; четырем байтам, так называемое выравнивание.
·.text:00401015; Таким образом на данный момент стек выглядит так:
·.text:00401015;
·.text:00401015; Относительный адрес Содержимое ячейки
·.text:00401015; - 0x18 буфер var_18[0]
·.text:00401015; - 0x17 буфер var_18[1]
·.text:00401015; - 0x16 буфер var_18[2]
·.text:00401015; - 0x15 буфер var_18[3]
·.text:00401015; - 0x14 буфер var_18[4]
·.text:00401015; - 0x13 буфер var_18[5]
·.text:00401015; - 0x12 буфер var_18[6]
·.text:00401015; - 0x11 буфер var_18[7]
·.text:00401015; - 0x10 буфер var_18[8]
·.text:00401015; - 0x0F буфер var_18[9]
·.text:00401015; - 0x0E дырка для выравнивания
·.text:00401015; - 0x0D дырка для выравнивания
·.text:00401015; - 0x0С буфер var_С[0] 01
·.text:00401015; - 0x0B буфер var_С[1] 02
·.text:00401015; - 0x0A буфер var_С[2] 03
·.text:00401015; - 0x09 буфер var_С[3] 04
·.text:00401015; - 0x08 буфер var_С[4] 05
·.text:00401015; - 0x07 буфер var_С[5] 06
·.text:00401015; - 0x06 буфер var_С[6] 07
·.text:00401015; - 0x05 буфер var_С[7] 08
·.text:00401015; - 0x04 буфер var_С[8] 09
·.text:00401015; - 0x03 буфер var_С[9] 10
·.text:00401015; - 0x02 дырка для выравнивания 11
·.text:00401015; - 0x01 дырка для выравнивания 12
·.text:00401015; 0x00 значение регистра ebp[0] 13
·.text:00401015; + 0x01 значение регистра ebp[1] 14
·.text:00401015; + 0x02 значение регистра ebp[2] 15
·.text:00401015; + 0x03 значение регистра ebp[3] 16
·.text:00401015; + 0x04 значение регистра eip[0] (адрес возврата) 17
·.text:00401015; + 0x05 значение регистра eip[1] (адрес возврата) 18
·.text:00401015; + 0x06 значение регистра eip[2] (адрес возврата) 19
·.text:00401015; + 0x07 значение регистра eip[3] (адрес возврата) 20
·.text:00401015; Таким образом, байты с 17 до 20 (не считая нуля завершающего строку) из буфера var_c затирают
·.text:00401015: адрес возврата сохраненный в стеке. Следовательно, строка из шестнадцати символов, включая
·.text:00401015; завершающий ноль вызовет модификацию младшего байта адреса возврата.
·.text:00401015; Остается отождествить буфер var_c - что он собой представляет имя пользователя или пароль?
·.text:00401018 push offset aLogin; "Login:"
·.text:00401018; В стек заносится смещение строки “Login”, значение указателя стека уменьшается на 4
·.text:00401018; Это первый (и единственный) аргумент функции printf
·.text:0040101D call _printf
·.text:0040101D; Вывод на экран приглашения “Login:”
·.text:00401022 add esp, 4
·.text:00401022; Значение указателя стека увеличивается на четыре, чтобы избавится от занесенного в стек смещения
·.text:00401025; строки “Login”. Си-функции не очищают стек после своего завершения
·.text:00401025 lea eax, [ebp+var_C]
·.text:00401025; В регистр eax заносится смещение буфера var_c, для последующей передачи его функции gets, читающей
·.text:00401025; строку с клавиатуры.
·.text:00401025; Следовательно, буфер var_c содержит имя пользователя
·.text:00401028 push eax
·.text:00401028; Значение eax заносится в стек
·.text:00401029 call _gets
·.text:00401029; Вызов функции _gets
·.text:0040102E add esp, 4
·.text:0040102E; Удаление двойного слова из стека (для очистки аргумента функции gets)
·.text:00401031 push offset aPassw; "Passw:"
·.text:00401031; Занесение в стек строки «Passw»
·.text:00401036 call _printf
·.text:00401036; Вывод строки “Passw” на экран с помощью функции printf

