Опциональный заголовок
Мы изучили DOS-заголовок и некоторые члены PE-заголовка. Теперь перед нами последний, самый большой и, вероятно, самый важный член PE-заголовка - опциональный заголовок.
Чтобы освежить вашу память, напомню: опциональный заголовок - это структура, являющаяся последним членом IMAGE_NT_HEADERS. Она содержит информацию о логической компоновке PE-файла. В этой структуре 31 поле. Hекоторые из них важны, некоторые бесполезны. Я объясню только те, которые действительно могут понадобиться.
Есть слово, которое часто используется по отношению к формату PE: RVA. RVA расшифровывается как относительный виртуальный адрес (relative virtual address). Вы знаете что такое виртуальный адрес. Сложное, на первый взгляд, словосочетание RVA служит для обозначения простой концепции. Просто представьте, что RVA - это расстояние до ссылающейся точки в виртуальном адресном пространстве. Я уверен, что вы знакомы с файловым смещением: RVA точно тоже самое, что и файловое смещение. Тем не менее, RVA задается относительно положения в виртуальном адресном пространстве, а не файла. Я покажу вам пример. Если PE-файл загружается по адресу 400000h в виртуальном адресном пространстве и программа начинает выполняться с адреса 401000h, мы можем сказать, что программа начинает выполняться с RVA 1000h. RVA определяется относительно стартового виртуального адреса модуля.
Почему RVA используется в PE-формате? Это помогает уменьшить время загрузки файла PE-загрузчиком. Так как модуль может находиться где угодно в виртуальном адресном пространстве, PE-загрузчику было бы очень трудно пофиксить адреса все перемещаемых объектов в модуле. С другой стороны, если все эти объекты используют RVA, PE-загрузчику нет надобности фиксить чтобы то ни было: он просто перемещает весь модуль в новый стартовый виртуальный адрес. Это вроде концепции абсолютного и относительного путей: RVA схож с относительным путем, виртуальный адрес - с абсолютным.
AddressOfEntryPoint | Это RVA первой инструкции, которая будет запущена, когда PE-загрузчик будет готов запустить PE-файл. Если вы хотите изменить ход выполнения прямо с самого начала, вам нужно изменить значение этого поля на новый RVA и инструкция в RVA запустится первой. |
ImageBase | Это предпочитаемый адрес для загрузки PE-файла. Hапример, если значение этого поля равно 400000h, PE-загрузчик попытается загрузить файл в виртуальное адресное пространство начиная с 400000h. Слово "предпочитаемый" означает, что PE-загрузчик может и не загрузить файл по этому адресу, если какой-то другой модуль уже занял этот адрес. |
SectionAlignment | Размер выравнивания секций в памяти. Hапример, если значение в этом поле pавно 4096 (1000h), каждая секция должна начинаться по адресу, кратном этому значению. Если первая секция находится в 401000h и его адрес равен 10 байтам, следующая секция должна начинаться в 402000h, даже если адресное пространство между ними останется неиспользованным. |
FileAlignment | Размер выравнивания секций в файле. Hапример, если значение в этом поле pавно 512 (200h), каждая секция должна начинаться на pасстоянии от начала файла кратном 512 байтам. Если первая секция в файле находится по смещению 200h и ее pазмеp 10 байт, следующая секцию должна быть pасположена со смещением 400h: пространство между смещениями 522 и 1024 будет неиспользовано/неопределено. |
MajorSubsystemVersion MinorSubsystemVersion |
Версия подсистемы win32. Если PE-файл спроектирован для Win32, версия подсистемы должна быть 4.0, в противном случае диалоговое окно не будет иметь 3D-вида. |
SizeOfImage | Общий размер образа PE в памяти. Это сумма всех заголовков и секций, выравненных по SectionAlignment. |
SizeOfHeaders | Размеp всех заголовков + таблицы секций. То есть это значение равно размеру файла минус комбинированный размер всех секций в файле. Вы можете также использовать это значение в качестве файлового смещения первой секции в PE-файле. |
Subsystem | Указывает для какой из подсистем NT предназначен этот PE-файл. Для большинства win32-программ используется только два значения: Windows GUI и Windows CUI (консоль). |
DataDirectory | Массив структур IMAGE_DATA_DIRECTORY. Каждая структура дает RVA важной структуры данных в PE-файле, например таблицы адресов импорта. |
[C] Iczelion, пер. Aquila.