Таблица экспорта PE-файлов¶
Таблица экспорта PE-файлов — это структура данных в формате исполняемых файлов Windows (Portable Executable, PE), которая содержит информацию о функциях и переменных, экспортируемых из модуля (DLL или EXE) для использования другими программами. Таблица экспорта является частью каталога данных PE-заголовка (Data Directory) и описывает точку входа в динамически подключаемые библиотеки, обеспечивая связывание и разрешение символов во время загрузки.
¶Назначение и роль
Таблица экспорта позволяет операционной системе и приложениям находить адреса функций, предоставляемых библиотекой. Когда программа импортирует функцию из DLL, загрузчик Windows обращается к таблице экспорта этой DLL, чтобы получить фактический адрес функции в памяти. Без этой структуры динамическое связывание и совместное использование кода между модулями было бы невозможным.
Для исполняемых файлов (EXE) таблица экспорта обычно отсутствует, однако она может присутствовать в случае, если EXE используется в качестве библиотеки (например, в плагинах или модулях ядра). Для DLL наличие таблицы экспорта является обязательным условием их функционирования.
¶Структура таблицы экспорта
Таблица экспорта описывается структурой IMAGE_EXPORT_DIRECTORY, которая содержит следующие ключевые поля:
- Characteristics — флаги, зарезервированные для будущего использования (в текущих версиях Windows значение равно нулю).
- TimeDateStamp — время создания таблицы экспорта (обычно совпадает со временем сборки файла).
- MajorVersion / MinorVersion — версия таблицы экспорта (в большинстве случаев нулевая).
- Name — относительный виртуальный адрес (RVA) строки, содержащей имя модуля (например,
kernel32.dll). - Base — базовое порядковое число, с которого начинается нумерация экспортируемых функций.
- NumberOfFunctions — общее количество экспортируемых функций и переменных.
- NumberOfNames — количество функций, имеющих символьные имена (всегда меньше или равно
NumberOfFunctions). - AddressOfFunctions — RVA массива адресов экспортируемых функций (каждый элемент — 4 байта).
- AddressOfNames — RVA массива указателей на строки с именами функций.
- AddressOfNameOrdinals — RVA массива порядковых номеров, связывающих имена с адресами.
¶Механизм разрешения экспорта
Таблица экспорта поддерживает два способа доступа к функциям:
- По имени — приложение указывает строковое имя функции. Загрузчик ищет имя в массиве
AddressOfNames, получает индекс, затем по индексу обращается к массивуAddressOfNameOrdinals, который содержит порядковый номер, и наконец по номеру получает адрес из массиваAddressOfFunctions. - По порядковому номеру — приложение указывает число, равное
Base + ordinal. В этом случае загрузчик напрямую обращается к элементу массиваAddressOfFunctionsс индексом, равным порядковому номеру.
¶Виды экспортируемых элементов
Экспортироваться могут не только функции, но и данные (переменные). Для данных в таблице экспорта указывается адрес переменной, а не код. Определить тип экспортируемого элемента по самой таблице невозможно — это зависит от контекста использования.
Экспорт может быть организован тремя способами:
- Экспорт по имени — наиболее распространённый способ, при котором каждая функция имеет символьное имя.
- Экспорт по порядковому номеру — используется для оптимизации и уменьшения размера таблицы, однако затрудняет использование библиотеки сторонними разработчиками.
- Смешанный экспорт — часть функций экспортируется по имени, часть только по порядковому номеру.
¶Расположение в файле
Таблица экспорта находится в разделе .edata (export data), который обычно присутствует в DLL-файлах. В PE-заголовке (структура IMAGE_OPTIONAL_HEADER) в поле DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] хранится RVA и размер таблицы экспорта. При загрузке файла в память система отображает таблицу по этому адресу и использует её для построения внутренней базы экспортируемых символов.
¶Инструменты для анализа
Для просмотра таблицы экспорта используются следующие инструменты:
- Dumpbin (утилита из Visual Studio) — команда
/exportsвыводит список экспортируемых функций с их порядковыми номерами и RVA. - PE Explorer — графическая утилита для просмотра структуры PE-файлов.
- CFF Explorer — бесплатный инструмент, позволяющий просматривать и редактировать таблицу экспорта.
- Python-библиотека pefile — предоставляет программный доступ к структурам PE, включая таблицу экспорта.
¶Практическое значение
Таблица экспорта важна для:
- Обратной разработки — анализ экспортируемых функций позволяет понять функциональность DLL без доступа к исходному коду.
- Разработки плагинов — модули расширения должны экспортировать определённые функции, которые вызывает основное приложение.
- Восстановления импорта — при повреждении таблицы импорта знание структуры экспорта помогает восстановить связи между модулями.
- Обнаружения вредоносного ПО — анализ экспортируемых функций часто используется для идентификации подозрительных библиотек и их поведения.
¶Особенности и ограничения
- Таблица экспорта не является обязательной для EXE-файлов, но может присутствовать в драйверах и системных модулях.
- Максимальное количество экспортируемых функций ограничено размером раздела
.edataи обычно не превышает нескольких тысяч. - Порядковые номера в таблице экспорта не обязаны быть непрерывными — пропуски допустимы, но загрузчик обрабатывает их как несуществующие функции.
- В 64-битных PE-файлах структура таблицы экспорта идентична 32-битной, однако адреса функций занимают 8 байт, что увеличивает размер массива
AddressOfFunctions.