Перехват (программирование)

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Перехват (англ. hooking) — технология, позволяющая изменить стандартное поведение тех или иных компонентов информационной системы.

Назначение технологии перехвата[править | править вики-текст]

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

  • ДО САБКЛАССИНГА:

Сообщение Windows->Окно (оконная процедура)

  • ПОСЛЕ:

Сообщение Windows->Наша оконная процедура->Окно (оконная процедура)

Например, в Уроках Iczelion’а[1] описан пример того, как сабклассинг может использоваться для организации контроля ввода в элементы управления. Технологии перехвата нужны не только в этом случае, но и, например, для предварительной обработки результатов системных функций поиска файлов FindFirst и FindNext, EnumProcess, которая перечисляет процессы в Windows и т. д. Причем в этих целях такие технологии применяют как антивирусные средства[2], так и различного рода вирусы, руткиты и прочие виды вредоносного программного обеспечения.

Очень часто перехват бывает важен для организации отладки программ и является одной из основных технологий, применяемых в отладчиках. В данном случае эта технология позволяет одной программе контролировать выполнение другой. Для этих целей предусмотрен системный вызов ptrace, который позволяет подключаться к процессам, отслеживать значения регистров у контекста отлаживаемого процесса и в том числе контролировать другие системные вызовы. Он является основой для реализации такой возможности отладчиков как точки останова. Данный системный вызов хорошо документирован и присутствует во всех главных *Nix системах: Linux, FreeBSD, Solaris.[3] Чаще всего используется совместно с системным вызовом fork, который и вызывает ptrace, указывая в параметрах вызова, что запускаемый процесс — дочерний. Microsoft Windows также предоставляет для похожих целей т. н. DebugAPI[4].

Виды перехвата системных функций[править | править вики-текст]

Основными методами перехвата являются:

  • Подмена адреса настоящей функции (модификация IAT таблиц, модификация SSDT/IDT таблиц)
  • Непосредственное изменение функции (сплайсинг, перехват в режиме ядра с модификацией тела функции)
  • Непосредственная подмена всего компонента приложения/системы (например библиотеки с целевой функцией)

Методы можно также разделить по критерию режима выполнения:

  • Пользовательские (ring3) методы: модификация IAT таблиц, сплайсинг. Их особенность в том, что невозможно что-либо изменить в поведении ядра операционной системы и его расширений.
  • Режима ядра: модификация SSDT/IDT таблиц, перехват в режиме ядра с модификацией тела функции. Позволяет модифицировать структуры данных и код любой части операционной системы и приложений.

Сплайсинг[править | править вики-текст]

Сплайсинг (от англ. splice — "сращивать или склеивать концы чего-либо") — метод перехвата API функций путём изменения кода целевой функции. Обычно изменяются первые 5 байт функции. Вместо них вставляется переход на функцию, которую определяет программист. Чтобы обеспечить корректность выполнения операции, приложение, которое перехватывает функцию, обязано дать возможность выполниться коду, который был изменен в результате сплайсинга. Для этого приложение сохраняет заменяемый участок памяти у себя, а после отработки функции перехвата восстанавливает измененный участок функции и дает полностью выполниться настоящей функции.[5]

Hot-patch point[править | править вики-текст]

Все функции стандартных dll Windows поддерживают hot-patch point. При использовании этой технологии перед началом функции располагаются пять неиспользуемых однобайтовых операций nop, сама же функция начинается с двубайтовой инструкции mov edi,edi. Места занимаемого пятью nop достаточно чтобы разместить команду перехода на функцию-перехватчик. Два байта занимаемых mov edi,edi предоставляют достаточно места для команды перехода на код размещенный на месте пяти nop. При этом, так как инструкция mov edi,edi не выполняет никаких осмысленных действий, ее затирание никак не влияет на работоспособность исходной функции. Таким образом, программист освобождается от необходимости где-либо сохранять исходное значение измененного им кода[6].

Сферы применения сплайсинга и методы обнаружения[править | править вики-текст]

Он применяется:

  • В ПО, которому необходимо осуществлять функции мониторинга системы
  • Механизмом хуков в Windows
  • Различного рода вредоносными программами. Это основная технология сокрытия для руткитов пользовательского уровня

Основной метод обнаружения факта сплайсинга — это сравнение машинного кода функции, проверяемой на сплайсинг, и кода системной функции, полученного в заведомо чистой системе. Также в обнаружении сплайсинга функции может помочь контроль адресов перехода.

Сравнение с другими технологиями[править | править вики-текст]

  • Изменение IAT таблиц процесса[7]. Данная технология не позволяет изменить поведение самой системной функции, а лишь дает возможность «обмануть» выбранное приложение, заставив его использовать вашу функцию. IAT таблица — таблица адресов функций, импортируемых процессом. Технология носит лишь локальный характер, хотя может быть применена сразу к группе приложений. Может быть довольно быстро обнаружена из-за необходимости загрузки DLL[8] в адресное пространство целевого процесса. Сплайсинг же не требует DLL и внедрения в чужой процесс, обладает возможностью глобального захвата функции. У сплайсинга есть ещё одно преимущество: не все системные функции импортируются процессом через IAT. Например, функция может быть загружена вызовом GetProcAddress. Использование же непосредственной модификации кода функции снимает подобное ограничение.
  • Перехват в режиме ядра. Позволяет перехватывать любые функции, в том числе и экспортируемые ядром. Наиболее труден для обнаружения в случае успеха, так как позволяет фальсифицировать любые данные, предоставляемые операционной системой. Требует написания специального компонента для взаимодействия с ядром драйвера. Может привести к BSOD при неправильном программировании в режиме ядра. Может быть обнаружен на фазе загрузки драйвера в ядро или при проверке активных драйверов, а также при проверке ядра на изменения[9]. Более трудный в программировании метод, чем сплайсинг, но более гибкий, так как позволяет перехватить функции самого ядра, а не только WinAPI функции, которые служат лишь посредником между ядром и программой, которая что-либо запрашивает у операционной системы.
  • Замена самой библиотеки с функцией. Весьма радикальное решение проблемы, обладающее рядом существенных недостатков:
  1. Требует замены файла на диске, что может быть запрещено и пресечено самой системой. Например, замену системных файлов Windows не позволит выполнить защита файлов Windows (WFP), хотя её можно и отключить. Такое действие может быть также обнаружено при статическом анализе системы ревизорами.
  2. Требуется полная эмуляция всех возможностей заменяемой DLL или иного компонента, что весьма трудоемко даже в случае открытости и осложняется необходимостью дизассемблирования в случае закрытости целевой программы.

Все это показывает, что это весьма нерациональный способ решения проблемы изменения поведения программы в случае возможности применения первых двух подходов или сплайсинга.

Перехват в режиме ядра[править | править вики-текст]

Он основан на модификации структур данных ядра и функций. Главными мишенями воздействия являются таблицы

  • IDT Таблица диспетчеризации прерываний. Довольно важным для перехвата является прерывание, обрабатывающее обращение к таблице служб SSDT (0x2E)[10].
  • SSDT (System Service Dispatch Table) Таблица диспетчеризации системных сервисов. Обращаясь к ней, система по номеру запрошенного сервиса может получить адрес соответствующего сервиса ядра и вызвать его. А таблица SSPT содержит общий размер параметров, передаваемых системному сервису.
  • psActiveprocess Структура ядра, хранящая список процессов в системе.
  • IRP Таблица драйвера, которая хранит указатели на функции обработки IRP-пакетов.
  • EPROCESS Структура ядра, хранящая большое количество информации о процессе, включая, например, PID (идентификатор процесса).

Такого рода руткиты называются DKOM-руткитами, то есть руткитами, основанными на непосредственной модификации объектов ядра. В руткитах для систем Windows Server 2003 и XP эта технология была модернизирована, так как в этих ОС появилась защита от записи некоторых областей памяти ядра[10]. Windows Vista и 7 получили дополнительную защиту ядра PatchGuard, однако все эти технологии были преодолены руткитописателями[11]. В то же время перехват системных функций в режиме ядра — основа проактивных систем защиты и гипервизоров.

Иные формы перехвата[править | править вики-текст]

Можно выделить и другие формы перехвата:

  • Перехват сетевых соединений и пакетов.[12]
  • Перехват паролей. Например, при помощи шпионажа за клавиатурным вводом при помощи кейлоггера.
  • Перехват обращений браузера к сайтам при помощи HTTP Proxy или расширений браузера. Позволяет проанализировать и/или подменить данные, которыми обмениваются браузер и сервер.

Здесь описана лишь часть применений данной технологии.

Примеры программ, использующих перехват[править | править вики-текст]

Примеры кода[править | править вики-текст]

См. также[править | править вики-текст]

Примечания[править | править вики-текст]

  1. Уроки Iczelion’а. Win32 API. Урок 20. Сабклассинг окна
  2. К примеру: невозможно получить доступ к процессу Kaspersky Internet Security штатными средствами Windows API, так как соответствующие функции перехвачены антивирусом.
  3. Страница из man Linux Ubuntu: man страница о вызове ptrace и русскоязычная версия: Русский перевод на OpenNET
  4. Официальное описание: The Debugging Application Programming Interface, а также примеры использования: Win32 API. Урок 28. Win32 Debug API I
  5. Цикл статей по перехвату WindowsAPI функций от Ms Rem
  6. Why do Windows functions all begin with a pointless MOV EDI, EDI instruction? – The Old New Thing (англ.).
  7. Методы доступа и модификации IAT таблицы довольно подробно описаны у Хоглунд Г., Батлер Дж. — Руткиты: внедрение в ядро Windows. Гл 4 Древнее искусство захвата
  8. Методы внедрения DLL в чужой процесс описаны довольно подробно у Дж. Рихтера Кристофера Назара Windows via C/C++. Программирование на языке Visual C++. Некоторые методы внедрения впервые документировал сам Дж. Рихтер
  9. Например, один из первых руткит-детектеров KLISTNER
  10. 1 2 Г. Хоглунд Дж. Батлер Руткиты внедрение в ядро Windows. Глава 4 Древнее искусство захвата
  11. убийство часового КРИС КАСПЕРСКИ, АКА МЫЩЪХ Спецвыпуск: Хакер, номер #072, стр. 072-072-5
  12. Например, этим занимаются снифферы. Одной из бесплатных реализаций захвата сетевых пакетов является сетевой драйвер уровня NDIS WinPCAP

Литература[править | править вики-текст]

Ссылки[править | править вики-текст]