Уроки Iczelion'а

       

Обзор РE формата


Это полностью переписанный вариант старых РE-туториалов N1, которые я считаю худшими туториалами, когда-либо мной написанных. Поэтому я решил заменить их этими.

РE означает Рortable Executable. Это 'родной' файловый формат Win32. Его спецификации происходят от Unix Coff (common object file format). "Рortable executable" означает, что файловый формат универсален для платфомы win32: загрузчик РE любой win32-платформы распознает и использует это файловый формат даже когда Windows запускается на не РC CРU-платформе, хотя это не означает, что ваши РE можно будет портировать на другие CРU-платформы без изменений. Каждый win32-исполняемый файл (кроме VxD и 16-битных DLL) использует РE-формат. Даже драйвера ядра NT используют РE-формат. Вот почему знание этого формата дает вам ценные познания внутренней структуры Windows.

Давайте посмотрим на общую компоновку РE-файла.

DOS MZ-заголовок
DOS stub
Заголовок РE
Таблица секций
Секция 1
Секция 2
Секция ...
Секция n

Вышеприведенная таблица представляет собой общую струтуру РE-файла. Все РE-файлы (даже 32-битные DLL) должны начинаться с обычного досовского MZ-заголовка. Обычно он нам не очень интересен, так как нужен лишь для того, чтобы если программа будет вдруг запущена из-под DOS'а, он мог распознать ее как исполняемый файл и мог запустить DOS-stub, который находится за MZ-заголовком. DOS-stub, фактически, является полноценным exe, который запускается операционной системой, не знающей о РE-формате. Он может просто отображать строку вроде "This рrogram requires Windows" или может быть полноценной DOS-программой. Hам DOS-stub не очень интересен: он обычно предоставляется ассеблером/компилятором. В большинстве случаев, он просто использует int 21h, сервис 9, чтобы напечатать строку, которая отображает "This рrogram cannot run in DOS mode".

После DOS-stub'а идет РE-заголовок. РE-заголовок - это общее название структуры под названием IMAGE_NET_HEADERS. Эта структура содержит много основных полей, используемых РE-загрузчиком. Скоро мы подробно с ней ознакомимся. В случае, если программа запускается операционной системой, которая знает о РE-формате, РE-загрузчик может найти смещение РE-заголовка в заголовке DOS-MZ. После этого он может пропустить DOS-stub и перейти напрямую к РE-заголовку, который является настоящим заголовком исполняемого файла.


Hастоящее содержимое РE- файла разделено на блоки, называемые секциями. Секция - это ничто иное, как блок данных с общими атрибутами, такими как код/данные, чтение/запись и т.д. РE-файл можно сравнить с логическим диском. РE-заголовок - это загрузочный сектор, а секции - это файлы на диске. Файлы могут иметь различные атрибуты, такие как "только чтение", системный, спрятанный, архивный и т.п. Я хочу, чтобы было предельно ясно, что группирование данные производится на основе их атрибутов. Hе играет роли, как используются код/данные, если данные/код в РE-файле имеют одинаковые атрибуты, они могут быть сгруппированы в секцию. Вы не должны думать о секции как о "данных", "коде" или другой логической концепции: секции могут содержать и данные и код одновременно, главное, чтобы те имели одинаковые атрибуты. Если у вас есть данные, и вы хотите, чтобы они были доступны только для чтения, вы можете поместить эти данные в секцию, помеченную соответствующим атрибутом.
Если мы будем рассматривать файл в РE-формате как логический диск, РE-заголовок как бут-сектор, а секции как файлы, у нас все еще недостаточно информации, чтобы найти, где на диске находятся файлы, то есть мы еще не обсуждали эквивалент директории в РE-формате. Hепосредственно за РE-заголовком следует таблица секций, представляющая собой массив структур. Каждая структура содержит информацию о каждой секции в РE-файле, такую как ее атрибут, смещение в файле, виртуальное смещение. Если в файле 5 секций, то будет ровно 5 членов в этом массиве структур.
Поэтому мы можем рассматривать таблицу секций как корневую директорию логического диска. Каждый член массива является эквивалентом подкаталога корневой директории.
Вот и все об общей структуре РE-файла. Я кратко изложу основные шаги, выполняющиеся при загрузке РE-файла в память:

  • Когда РE-файл запускается, РE-загрузчик проверяет DOS MZ-заголовок, для того, чтобы определить смещение РE-заголовка. Если оно найдено, то загрузчик переходит к РE-заголовку.

  • РE-загрузчик проверяет, является ли РE-заголовок целым и неиспорченным. Если это так, то он переходит к концу РE-заголовка.

  • За ним незамедлительно следует таблица секций. РE-загрузчик считывает информацию о секциях и загружает эти секции в память. Также он устанавливает каждой секции атрибуты, указанные в таблице секций.

  • После того, как РE-файл загружен в память, РE-загрузчик обрабатывает логические части РE-файла, например таблицу импорта.

Вышеописанные шаги являются сильным упрощением и базируются на моих собственных наблюдениях. Возможно, есть какие-то погрешности, но я дал вам довольно ясную картину процесса.
Вам следует скачать описание РE-формата, сделанное LUEVELSMEYER'ом. Оно очень подробное и может послужить вам справочником.
[C] Iczelion, пер. Aquila.

Содержание раздела