Структура EXE-заголовка
В начале каждой EXE-программы идёт DOS-заголовок
Смещение | Размер | Описание |
0 | 2 | Сигнатура 'MZ' - байты 4Dh, 5Ah |
2 | 2 | Размер последней неполной страницы |
4 | 2 | Размер файла в страницах по 512 байт, включая неполную |
6 | 2 | Количество элементов в таблице настроек адресов |
8 | 2 | Размер заголовка в параграфах по 16 байт |
0Ah | 2 | Минимум дополнительно требуемой памяти в параграфах |
0Ch | 2 | Максимум дополнительно требуемой памяти в параграфах |
0Eh | 2 | Значение (относительное) регистра SS |
10h | 2 | Значение регистра SP |
12h | 2 | Контрольная сумма |
14h | 2 | Значение регистра IP |
16h | 2 | Значение (относительное) регистра CS |
18h | 2 | Смещение в файле таблицы настроек адресов |
1Ah | 2 | Номер оверлея |
1Ch | 8 | Зарезервировано |
24h | 2 | Идентификатор OEM |
26h | 2 | Информация OEM |
28h | 20 | Зарезервировано |
3Ch | 4 | Смещение в файле PE-заголовка |
За этим заголовком следуют таблица настроек адресов (нужна для запуска DOS-программ) и небольшая DOS-программа, выводящая сообщение об ошибке. Нас интересует PE-заголовок, адрес его начала записан по смещению 3Ch.
Смещение | Размер | Описание |
0 | 4 | Сигнатура 'PE' - байты 50h, 45h, 0, 0 |
4 | 2 | Тип процессора - обычно 14Ch (i386) |
6 | 2 | Число секций в таблице секций |
8 | 4 | Дата и время создания программы |
0Ch | 4 | Указатель на символьную отладочную информацию |
10h | 4 | Число этих отладочных символов |
14h | 2 | Размер PE-заголовка минус 18h (обычно E0h) |
16h | 2 | Флаги |
18h | 2 | Сигнатура 10Bh - нормальный заголовок |
1Ah | 2 | Версия использовавшегося компоновщика |
1Ch | 4 | Размер кода |
20h | 4 | Размер инициализированных данных |
24h | 4 | Размер неинициализированных данных |
28h | 4 | Относительный виртуальный адрес точки входа |
2Ch | 4 | Относительный виртуальный адрес секции кода |
30h | 4 | Относительный виртуальный адрес секции данных |
34h | 4 | Базовый адрес программы |
38h | 4 | Выравнивание секций программы в памяти |
3Ch | 4 | Выравнивание секций в файле |
40h | 4 | Номер версии операционной системы |
44h | 4 | Версия программы |
48h | 4 | Номер версии Windows (обычно 4) |
4Ch | 4 | Зарезервировано |
50h | 4 | Размер всего образа программы |
54h | 4 | Общий размер всех заголовков |
58h | 4 | Контрольная сумма |
5Ch | 2 | Подсистема: 2 - графическое приложение 3 - консольное приложение |
5Eh | 2 | Характеристики dll |
60h | 4 | Максимальный размер стека |
64h | 4 | Начальный размер стека |
68h | 4 | Максимальный размер кучи |
6Ch | 4 | Начальный размер кучи |
70h | 4 | Какие-то флаги загрузчика |
74h | 4 | Число виртуальных адресов и размеров, указанных ниже (10h) |
78h | 4 | Виртуальный адрес таблицы экспорта |
7Ch | 4 | Размер таблицы экспорта |
80h | 4 | Виртуальный адрес таблицы импорта |
84h | 4 | Размер таблицы импорта |
88h | 4 | Виртуальный адрес таблицы ресурсов |
8Ch | 4 | Размер таблицы ресурсов |
90h | 4 | Виртуальный адрес таблицы исключений |
94h | 4 | Размер таблицы исключений |
98h | 4 | Виртуальный адрес таблицы безопасности |
9Ch | 4 | Размер таблицы безопасности |
A0h | 4 | Виртуальный адрес таблицы настроек адресов |
A4h | 4 | Размер таблицы настроек адресов |
A8h | 4 | Виртуальный адрес таблицы отладочной информации |
ACh | 4 | Размер таблицы отладочной информации |
B0h | 4 | Виртуальный адрес строки с описанием программы |
B4h | 4 | Размер строки с описанием программы |
B8h | 4 | Виртуальный адрес таблицы с данными для процессора MIPS |
BCh | 4 | Размер таблицы с данными для процессора MIPS |
C0h | 4 | Виртуальный адрес области данных потоков (TLS) |
C4h | 4 | Размер области данных потоков |
C8h | 4 | Виртуальный адрес данных настройки загрузки |
CCh | 4 | Размер данных с настройками загрузки |
D0h | 4 | Виртуальный адрес таблицы привязки к библиотекам |
D4h | 4 | Размер таблицы привязки к библиотекам |
D8h | 4 | Виртуальный адрес списка импортируемых адресов |
DCh | 4 | Размер списка импортируемых адресов |
E0h | 4*2 * 3 | Зарезервировано |
Все адреса в заголовке - это относительные виртуальные адреса (RVA) - адреса в памяти относительно базового адреса (он указан по смещению 34h). Если программа загружена по базовому адресу, то действительный адрес будет равен : базовый адрес + относительный адрес.
Сразу за этим заголовком следует таблица секций. Число элементов в ней равно числу секций файла и указано в заголовке.
Смещение | Размер | Описание |
0 | 8 | Имя секции, дополненное при необходимости нулями |
8 | 4 | Виртуальный размер секции |
0Ch | 4 | Относительный виртуальный адрес начала секции |
10h | 4 | Размер секции в файле |
14h | 4 | Смещение секции от начала файла |
18h | 10h | Используется только в объектных файла |
28h | 4 | Флаги секции биты 0-3 : зарезервировано бит 5 : содержит код бит 6 : содержит инициализированные данные бит 7 : содержит неинициализированные данные бит 28 : разделяемая секция бит 29 : доступна для выполнения бит 30 : доступна для чтения бит 31 : доступна для записи |
Таблица импорта обычно содержится в секции импорта (rdata). Она содержит имена и адреса импортируемых из библиотек функций. Адрес её начала указан в PE-заголовке.
Смещение | Размер | Описание |
0 | 4 | Адрес таблицы имён процедур |
4 | 4 | Время создания библиотеки |
8 | 4 | ? |
0Ch | 4 | Адрес имени библиотеки |
10h | 4 | Адрес таблицы адресов процедур |
Одному элементу таблицы соответствует одна импортируемая библиотека. В первом её элементе указан RVA адрес списка имён всех импортируемых из библиотеки процедур. Каждый элемент (размером 4 байта) этого списка содержит либо RVA адрес имени процедуры, либо, если установлен старший бит, номер этой процедуры. Элемент указывает не прямо на имя процедуры, а на 2-байтовое число (hint), за которым следует имя. Список заканчивается нулевым элементом. Каждому элементу списка соответствует элемент списка адресов процедур (на него указывает последнее поле). В этот элемент загрузчик помещает адрес соответствующей импортируемой процедуры. Если время создания библиотеки не равно нулю, то было произведено связывание, и в последнем списке уже находятся адреса процедур. В последнем элементе таблицы импорта адрес имени библиотеки установлен в ноль.