8(495)909-90-01
8(964)644-46-00
pro@sio.su
Главная
Системы видеонаблюдения
Охранная сигнализация
Пожарная сигнализация
Система пожаротушения
Система контроля удаленного доступа
Оповещение и эвакуация
Контроль периметра
Система домофонии
Парковочные системы
Проектирование слаботочных сетей
Аварийный
контроль
Раздел: Документация

0 ... 36 37 38 39 40 41 42 ... 102

Ацкаиией указателей (см. раздел «Указатели и индексы»), индексным пе-м°ДИ,иСццеМ (см. там же) и навязыванием функции printf (и другим функци-1к"()рМатцрованного вывода) лишних спецификаторов.

модИфИКАЦИЯ СЕКРЕТНЫХ ПЕРЕМЕННЫХ

.„ясность модификации переменных дает значительно больше возможностей для атаки, позволяя:

навязывать уязвимой программе «свои» пароли, дескрпиторы файлов, TCP/ 1Р-1шентификаторы и т. д.;

•модифицировать неременные, управляющие ветвлением программы;

•манипулировать индексами и указателями, передавая управление по произвольному адресу (и адресу, содержащему код, специально подготовленный злоумышленником в том числе).

Чаще всего модификация секретных переменных реализуется посредством последовательного переполнения буфера, ио обыкновению своему порождающего целый каскад побочных эффектов. Например, если за концом переполняющегося буфера расположен указатель на некоторую переменную, в которую после переполнения что-то пишется, злоумышленник сможет затереть любую ячейку памяти на свой выбор (разумеется, за исключением ячеек, явно защищенных от модификации, например, кодовой секции или секции .rodata).

ПЕРЕДАЧА УПРАВЛЕНИЯ НА СЕКРЕТНУЮ ФУНКЦИЮ ПРОГРАММЫ

Модификация указателей на исполняемый код приводит к возможности передачи управления на любую функцию уязвимой программы (правда, с передачей аргументов имеются определенные проблемы)- Практически каждая программа содержит функции, доступные только rooty и предоставляющие те или иные управленческие возможности (например, создание новой учетной записи, открытие сессии удаленного управления, запуск файлов и т. д.). В более изощренных случаях управление передается на середину функции (или даже на середину машинной инструкции) с таким расчетом, чтобы процессор выполнил замысел злоумышленника, даже если разработчик программы не предусматривал ничего подобного.

Передача управления обеспечивается либо за счет изменения логики выполнения программы, либо за счет подмены указателей на код. И то и другое опирайся на модификацию ячеек программы, кратко рассмотренную выше.

РВДАЧА УПРАВЛЕНИЯ НА КОД, ПЕРЕДАННЫЙ ЖЕРТВЕ МИМ ЗЛОУМЫШЛЕННИКОМ

ый механизм является разновидностью механизма передачи управления кретную функцию программы, только сейчас роль этой функции выползай К"Д> Подг°товленнЬ1й злоумышленником и тем или иным способом пере-ПереЬ1Й НаУдалеиный компьютер. Для этой пели может использоваться как сам ни °Лняющиися буфер, так и любой другой буфер, доступный злоумышлен-я непосредственной модификации и в момент передачи управления на


126 Глава 4. Ошибки переполнения буфера иЗВнр и

—— .

shell-код присутствующий в адресном пространстве уязвимого npn.w (при этом он должен располагаться по более или менее предсказуемым сам, иначе передавать управление будет некому и некуда).

ЖЕРТВЫ ПЕРЕПОЛНЕНИЯ, ИЛИ ОБЪЕКТЫ АТАКИ

Переполнение может затирать ячейки памяти следующих типов: указатели лярные переменные и буферы. Объекты языка Си++ включают в себя какука затели (указывающие на таблицу виртуальных функции, если таковые в объ екте есть), так и скалярные данные-члены (если они есть). Ни те, ни другие самостоятельной сущности не образуют и вполне укладываются в приведенную выше классификацию.

УКАЗАТЕЛИ И ИНДЕКСЫ

В классическом Паскале и других «правильных» языках указатели отсутствуют, но в Си/Си++ они вездесущи. Чаще всего приходится иметь дело с указателями на данные, несколько реже встречаются указатели на исполняемый код (указатели на виртуальные функции, указатели на функции, загружаемые динамической компоновкой и т. д.). Современный Паскаль (раньше ассоциируемый с компилятором Turbo Pascal, а теперь еще и Delphi) также немыслим без указателей. Даже если в явном виде указатели и не поддерживаются, на них «держатся» динамические структуры данных (куча, разреженные массивы), используемые внутри языка.

Указатели удобны. Они делают программирование простым, наглядным, эффективным и естественным. В то же время указатели во всех отношениях категорически небезопасны. Попав в руки хакера или пищеварительный тракт червя, они превращаются в оружие опустошительной мощности — своеооразнын аналог BFG-900 или, по крайней мере, «нлазмогана». Забегая вперед, отметим что указатели обоих типов потенциально способны к передаче управления и> несанкционированный машинный код.

Вотс указателей на исполняемый код мы и начнем. Рассмотрим ситуацию,ког.ь-следом за переполняющимся буфером buff расположен указатель на функ"1*-которая инициализируется до и вызывается после переполнения буфер31 можно, вызывается не сразу, а спустя некоторое время). Тогда мы запоЛ) аналог функции call или, говоря другими словами, инструмент для neif11 управления но любому (пу или почти любому) машинному адресу, в тоМ нЫг и на сам переполняющийся буфер (тогда управление получит код, перед злоумышленником) (листинг 4.3).

Листинг 4.3. Фрагмент программы, подверженной переполнению с затиранием указателя на исполняемый код

code otrf) {

char buff[8]: void (*somo fuic) (): prir.tf("passws."): getstbuff):

Ik


sc*« func0:

e, e о выборе целевых адресов мы поговорим в другой раз, сейчас же ПоД1° тоЧцмся на поиске затираемых указателей. Первым в голову ирихо-сосрсД0 воЗВрата из функции, находящийся внизу кадра стека. Правда, что-дцтаДР лоТЯнуться, требуется пересечь весь кадр целиком, и не факт, что это удастся, к тому же его целостность контролируют многие защитные системы.

популярная мишень — указатели на объекты. В программах на Си++ бычно присутствует большое количество объектов, многие из которых созда; ются вызовом оператора new, возвращающим указатель на свежесозданный экземпляр объекта. Невиртуальные функции-члены класса вызываются точно так же как и обычные Си-функции (то есть по их фактическому смещению), но-тгому они неподвластны атаке. Виртуальные функции-члены вызываются намного более сложным образом через цепочку следующих операции: указатель на экземпляр объекта —> указатель на таблицу виртуальных функций —> указатель на конкретную виртуальную функцию. Указатели на таблицу виртуальных функций не принадлежат объекту и внедряются в каждый его экземпляр, который чаще всего сохраняется в оперативной памяти, реже — в регистровых переменных. Указатели па объекты также размещаются либо в оперативной памяти, либо в регистрах, при этом на один и тот же объект может указывать множество указателей (среди которых могут встретиться и такие, которые расположены непосредственно за концом переполняющегося буфера). Таблица виртуальных функций (далее просто виртуальная таблица) принадлежит не •жземпляру объекта, а самому объекту, то есть, упрощенно говоря, мы имеем одну виртуальную таблицу на каждый объект. «Упрощенно» потому, что в действительности виртуальная таблица помещается в каждый obj-файл. в котором встречается обращение к членам данного объекта (раздельная компиляция дает е знать). И хотя линкеры в подавляющем большинстве случаев успешно ЗТо ают лишние виртуальные таблицы, иногда они все-таки дублируются (но 1>ак/Же СЛИШКОм высокие материи для начинающих). В зависимости от «ха-тУальнь1 ВЫаннон сРеДы разработки и профессионализма программиста вир-си) либоТ3ЛИЦЫ Ра:,мсш-аются либо в секции .data (не защищенной от зани-глУЧай Всекции -codata (доступной лишь для чтения), причем последний Ъ,и - ВСТРечается значительно чаще. *<авайте лп

Всеки.ни и пР°стоты Рассмотрим приложение с виртуальными таблицами Ме,,Тов в 3 3 СЛ11 соумышленнику удастся модифицировать один из эле-ФУНкцИи ртуальной таблицы, то при вызове соответствующей виртуальной :,Тогобуде"т11,аВЛе"Ие получит не она, а совсем другой код! Однако добиться ЧаЛе сеКцииНепР°СТо- Виртуальные таблицы обычно размещаются в самом на-1(0011 авто Данных>то есть перед статическими буферами и достаточно далеко, Та"аТИческих б>(Реров (болес

конкретное расположение указать невоз-Как н,оке КаК в 3ависимости от операционной системы стек может находиться • Так и выще секции данных). Так что последовательное переполнение



0 ... 36 37 38 39 40 41 42 ... 102