Читаем Защита от хакеров корпоративных сетей полностью

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

Например, если библиотека kernel32.dll загружена, то можно использовать любую ее функцию, даже не используемую явно программой. Функцию можно использовать, потому что она, как и все другие компоненты библиотеки, уже загружена в память. Другими словами, при установлении связи с любой динамически подключаемой библиотекой DLL загружается гораздо больше программного кода, чем это кажется на первый взгляд.

Другой пример использования имеющегося под рукой кода относится к UNIX-системам. Речь идет о трюке, который использовался исследователями безопасности для преодоления защиты ранних патчей ядра Linux и модификаций ядра в рамках проекта PAX. Впервые этот трюк применила Solar Designer. Он заключался в записи в стек сначала параметров функции execve, а затем подмены хранимого в стеке содержимого регистра EIP на адрес функции execve. Стек оказывался настроен таким же образом, как и при вызове функции execve. По завершении функции команда ret восстанавливала подмененное содержимое регистра EIP и передавала управление на функцию execve. Следовательно, при подозрении взлома защиты выполнения программ из стека можно заблокировать выполнение программ из стека.

Загрузка новых динамически подключаемых библиотек

Наиболее современные операционные системы поддерживают концепцию совместно используемых библиотек. Они предназначены для уменьшения расхода памяти и многократного использования кода. Уже упоминалось о возможности использования в своих интересах программного кода, загруженного в память, но иногда может потребоваться то, что еще не загружено.

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

В Windows NT есть пара функций, которыми всегда может воспользоваться программа: LoadLibrary и GetProcAddress. Они позволяют загрузить любую динамически подключаемую библиотеку DLL и вызвать функцию. В системе UNIX для этих целей служат функции dlopen и dlsym.

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

Функции загрузки библиотеки LoadLibrary или dlopen загружают совместно используемую часть кода в доступную программе память. Совсем не обязательно, что загружаемый код будет выполняться, но после загрузки он доступен для использования. В основном загружаемый код впоследствии выполняется.

Функции GetProcAddress и dlsym определяют в таблице функций динамически подключаемой библиотеки адрес экспортируемой функции. Для поиска в таблице функций используются символические имена и, возможно, необязательные порядковые целые числа – индексы. Входным параметром этих функций является имя искомой функции или ее индекс, а выходным – адрес искомой функции.

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

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

Программа с жестко запрограммированными адресами функций работает быстро и безошибочно, но, как правило, непереносима с одной платформы на другую. Для Windows NT это означает ограничение работоспособности программы переполнения буфера рамками единственного служебного пакета service pack и составом операционной системы OS combo. В зависимости от используемой платформы и библиотек в UNIX она может вообще не заработать.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже