Что хранится в заголовке PE-файла

Заголовок PE-файла содержит служебные данные, которые Windows использует для загрузки исполняемого файла в память и подготовки его структур. В нём хранится информация об архитектуре процессора, расположении секций, точке входа, необходимых библиотеках, ресурсах, механизмах защиты и других элементах Portable Executable.

При анализе PE-файлов заголовок служит отправной точкой: по его структуре можно понять устройство программы, особенности сборки, используемые таблицы и получить сведения о файле ещё до изучения машинного кода. PE Header представляет собой не один блок данных, а набор связанных структур, каждая из которых выполняет свою функцию.

Что такое PE-файл и зачем ему нужен заголовок

PE (Portable Executable) — формат исполняемых файлов Windows. К нему относятся файлы с расширениями .exe, .dll, .sys и некоторые другие типы образов, которые операционная система может загружать в память.

Файл содержит не только машинный код программы. Windows должна знать, где находятся инструкции процессора, где размещены данные, какие библиотеки требуется загрузить, куда передать управление после загрузки и какие области памяти создать. Эту информацию содержит заголовочная часть PE-файла.

Если рассматривать PE-файл как описание будущего образа программы в памяти, то заголовки можно сравнить с картой этого образа. Они связывают расположение данных на диске с их виртуальным размещением после загрузки.

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

Общая структура PE Header

Заголовочные структуры PE-файла расположены в определённом порядке. Windows начинает обработку с начала файла и последовательно переходит к более специализированным данным.

Часть структуры Назначение
DOS Header Начальная структура совместимости, содержащая ссылку на расположение PE-заголовка.
DOS Stub Небольшой исполняемый фрагмент для старой среды DOS.
PE Signature Сигнатура, подтверждающая формат Portable Executable.
File Header (COFF Header) Общая информация о файле и его секциях.
Optional Header Данные, необходимые загрузчику Windows для создания образа в памяти.
Section Headers Описание отдельных секций файла.

Последовательность этих структур помогает загрузчику Windows определить расположение остальных частей файла. Например, количество секций берётся из File Header, а расположение специальных таблиц — из Optional Header.

DOS Header: первая структура PE-файла

Несмотря на название, DOS Header не используется современной Windows для прямого запуска программы. Это историческая часть формата, обеспечивающая совместимость с ранними исполняемыми файлами DOS.

Главное значение DOS Header при анализе PE-файла связано с полем e_lfanew. Оно содержит смещение от начала файла до PE-заголовка. Благодаря этому Windows может перейти от DOS-части к основной структуре Portable Executable.

Роль поля e_lfanew

Поле e_lfanew хранит файловое смещение, а не виртуальный адрес. Это важно при анализе: до загрузки файла в память Windows работает с расположением данных на диске.

Типичный алгоритм чтения PE-файла выглядит так:

  1. Прочитать первые байты файла и проверить DOS Header.
  2. Получить значение e_lfanew.
  3. Перейти по указанному смещению.
  4. Проверить наличие PE Signature.

Неверное понимание этого поля приводит к ошибкам при чтении всей последующей структуры.

PE Signature: начало основной структуры

После DOS Header располагается PE-сигнатура — последовательность байтов PE\0\0. Это идентификатор, который Windows использует для проверки корректности формата Portable Executable.

После сигнатуры начинается структура NT Headers, включающая два основных компонента:

  • File Header (COFF Header) — описание самого файла.
  • Optional Header — данные, необходимые загрузчику.

Если сигнатура повреждена или значение e_lfanew указывает неверное смещение, файл не будет корректно распознан как PE-образ.

File Header (COFF Header): описание файла

COFF Header содержит базовые сведения о PE-файле. Эта структура происходит из формата COFF (Common Object File Format), который также используется для объектных файлов компилятора.

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

Поле Machine

Machine определяет целевую архитектуру процессора. Оно показывает, предназначен ли файл для x86, x64 или другой поддерживаемой платформы.

При анализе это одно из первых полей, позволяющих определить тип бинарного файла. Например, PE32 и PE32+ отличаются не только разрядностью, но и размером некоторых полей Optional Header.

Поле NumberOfSections

NumberOfSections указывает количество секций в файле. После Optional Header располагается таблица Section Headers, где каждая запись описывает одну секцию.

Это поле помогает определить структуру данных программы и количество областей кода и данных в образе.

Поле TimeDateStamp

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

Поле Characteristics

Characteristics представляет набор флагов, описывающих свойства файла. С его помощью можно определить, является ли файл исполняемым образом, DLL-библиотекой и какие особенности обработки применяются.

При анализе PE эти флаги помогают понять назначение файла ещё до просмотра кода.

Optional Header: почему необязательный заголовок обязателен

Название Optional Header может вводить в заблуждение. В формате COFF объектные файлы могут обходиться без него, но для полноценного PE-образа Windows эта структура необходима.

Optional Header содержит данные, которые непосредственно используются загрузчиком при создании образа программы в памяти.

Magic: определение формата PE32 или PE32+

Поле Magic показывает вариант структуры Optional Header.

Значение Формат
0x10B PE32 для 32-битных образов.
0x20B PE32+ для 64-битных образов.

Это поле важно при ручном анализе, поскольку размеры некоторых адресных полей отличаются в 32-битных и 64-битных файлах.

AddressOfEntryPoint: точка входа программы

AddressOfEntryPoint содержит относительный виртуальный адрес (RVA) точки, с которой начинается выполнение после загрузки образа.

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

При анализе PE-файла это поле помогает найти начало исполняемого кода.

ImageBase: предпочтительный адрес загрузки

ImageBase определяет адрес, по которому образ предполагает быть размещённым в виртуальном адресном пространстве процесса.

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

SectionAlignment и FileAlignment

Эти поля показывают различие между представлением файла на диске и его расположением в памяти.

  • FileAlignment определяет выравнивание данных внутри файла.
  • SectionAlignment определяет выравнивание секций после загрузки в память.

Одна и та же секция может занимать разный объём на диске и в памяти после загрузки. Например, незаполненное пространство может существовать только в памяти и не храниться в файле.

SizeOfImage

SizeOfImage показывает общий размер образа после размещения в памяти. Значение включает заголовки и все секции с учётом выравнивания.

Загрузчик использует его для подготовки области памяти под будущий образ программы.

Subsystem

Subsystem определяет требуемую подсистему Windows. Например, файл может быть предназначен для графического интерфейса или консольного режима.

Это поле влияет на способ запуска программы операционной системой.

Data Directory: указатели на важные таблицы

В конце Optional Header находится массив Data Directory. Он содержит пары значений: RVA таблицы и её размер.

Эти записи не хранят сами данные, а указывают, где внутри файла находятся специальные структуры.

Таблица Назначение
Export Table Описание функций, которые файл предоставляет другим модулям.
Import Table Список внешних функций и библиотек, необходимых программе.
Resource Table Ресурсы: изображения, строки, диалоги и другие встроенные данные.
Exception Table Информация для обработки исключений, особенно важная в 64-битных образах.
Security Directory Данные цифровых подписей и сертификатов.
Base Relocation Table Информация для изменения адресов при загрузке не по ImageBase.
TLS Directory Данные механизма Thread Local Storage.
Load Config Дополнительная конфигурация загрузки и защитных механизмов.

Import Table

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

При анализе PE это один из самых полезных разделов: список импортов часто позволяет получить представление о возможностях программы.

Base Relocation Table

Если файл нельзя загрузить по предпочтительному адресу, Windows должна исправить адреса, зависящие от расположения образа. Для этого используется таблица релокаций.

Наличие или отсутствие этой таблицы влияет на особенности загрузки файла.

Section Headers: описание секций файла

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

Типичные имена секций:

  • .text — машинный код программы.
  • .data — изменяемые глобальные данные.
  • .rdata — данные только для чтения.
  • .rsrc — ресурсы приложения.
  • .idata — информация импорта.

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

Как загрузчик Windows использует PE-заголовок

При запуске программы Windows использует данные PE Header как описание процесса создания образа в памяти.

Упрощённо последовательность выглядит так:

  1. Проверяется формат файла и PE Signature.
  2. Определяется архитектура через File Header и Magic.
  3. Выделяется память под образ согласно SizeOfImage.
  4. Секции копируются в соответствующие области памяти.
  5. Обрабатываются импорты и загружаются необходимые библиотеки.
  6. При необходимости выполняются релокации.
  7. Управление передаётся на AddressOfEntryPoint.

Без этих данных Windows не смогла бы преобразовать набор байтов на диске в работающий процесс.

Как анализируют PE Header специалисты

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

При проверке PE-файла обращают внимание на:

  • соответствие архитектуры и заявленного назначения файла;
  • количество и характеристики секций;
  • расположение точки входа;
  • список импортируемых библиотек;
  • наличие цифровой подписи;
  • нестандартные значения размеров или адресов;
  • наличие защитных механизмов.

Заголовок не позволяет полностью определить поведение программы, но помогает сформировать первоначальное представление о структуре файла.

Типичные ошибки при чтении PE Header

  • Путать файловые смещения и адреса памяти. Поля вроде e_lfanew относятся к расположению внутри файла, а RVA используются после загрузки образа.
  • Считать имена секций обязательными. Секция с названием .text не обязана содержать только код, если файл создан нестандартным инструментом.
  • Игнорировать различия PE32 и PE32+. Размеры адресных полей отличаются.
  • Считать TimeDateStamp точной датой создания. Это служебное значение, зависящее от процесса сборки.
  • Анализировать одно поле отдельно. Полное значение появляется только при сопоставлении нескольких структур.

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

Практические рекомендации для изучения PE-структуры

Чтобы научиться уверенно читать заголовки PE-файлов, полезно двигаться от общей структуры к отдельным полям:

  1. Изучите порядок расположения структур: DOS Header, PE Signature, File Header, Optional Header и Section Headers.
  2. Научитесь различать файловые смещения, RVA и виртуальные адреса.
  3. Разберите назначение основных Data Directory.
  4. Сравните PE32 и PE32+ файлы.
  5. Используйте инструменты просмотра PE-структуры для сопоставления полей с реальным содержимым файла.

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

Вывод

Заголовок PE-файла содержит метаданные, необходимые Windows для загрузки и интерпретации исполняемого образа. В нём описываются архитектура, расположение данных, точка входа, секции, таблицы импорта, ресурсы, релокации и другие элементы, участвующие в создании процесса.

Разные структуры PE Header отвечают за отдельные этапы работы загрузчика: DOS Header помогает найти основную структуру, File Header описывает устройство файла, Optional Header передаёт параметры загрузки, а Section Headers связывают данные на диске с памятью.

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

PEFile.ru