Структура 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), за которым следует имя. Список заканчивается нулевым элементом. Каждому элементу списка соответствует элемент списка адресов процедур (на него указывает последнее поле). В этот элемент загрузчик помещает адрес соответствующей импортируемой процедуры. Если время создания библиотеки не равно нулю, то было произведено связывание, и в последнем списке уже находятся адреса процедур. В последнем элементе таблицы импорта адрес имени библиотеки установлен в ноль.