Среда, 23.07.2025, 09:58 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 1. Структура исполняемых модулей(1)

Часть IV. Отладка, анализ кода программ, драйверы

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

Глава 1. Структура исполняемых модулей

Исполняемым форматом в Windows является формат PE. Сокращение PE означает Portable Executable, т.е. переносимый исполняемый формат. Этот формат имеют как ЕХЕ-файлы, так и динамические библиотеки. Важно, что сейчас фирма Microsoft ввела "новый" формат и для объектных модулей - это COFF-формат (COFF - Common Object File Format), который, однако, на поверку оказался, в сущности, все тем же PE-форматом. Заметим в этой связи, что фирма Borland по-прежнему работает с объектными файлами, имеющими структуру OMF (Object Module Format). Старый NE-формат (NE - New Executable), используемый старой операционной системой Windows и рассчитанный на сегментную структуру памяти, ушел в небытие. Кроме того, есть еще формат VXD-драйверов - LE-формат (Linear Executable, т.е. линейный исполняемый). Этого формата мы коснемся, когда будем говорить о драйверах в операционной системе Windows. Таким образом, данная глава будет посвящена разбору структуры исполняемых РЕ-модулей. Поскольку в состав исполняемого РЕ-модуля входит и DOS-программа (STUB), мы начнем наше рассмотрение со структуры DOS-программ. Наше рассмотрение будет кратким, и мы воспользуемся таблицей из книги [1].

Структура ЕХЕ-программ для MS DOS

СмещениеДлинаНазваниеКомментарий
+02MZподпись, признак ЕХЕ-программы
+22PartPagдлина неполной последней страницы
+42PageCntдлина в страницах (512 б), включая заголовок и последнюю страницу
+62ReloCntчисло элементов в таблице перемещения
+82HdrSizeдлина заголовка в параграфах
+0AН2MinMemминимум требуемой памяти за концом программы
+0CH2MaxMemмаксимум требуемой памяти за концом программы
+0EН2ReloSSсегментный адрес стека
+10H2EXESpзначение регистра SP
+12Н2ChkSumконтрольная сумма
+14Н2ExeIPзначение регистра IP
+16H2ReloCSсегментный адрес кодового сегмента
+18H2TablOffсмещение в файле первого элемента таблицы перемещения
+1АН2Overlayномер оверлея, 0 для главного модуля
* Конец форматированной порции заголовка **
+1СН
** Начало таблицы перемещения (возможно с 1СН) **
+? 4*? смещ. сегмент ... смещ. сегмент

Рис. 4.1.1. Структура ЕХЕ-программы для MS DOS.

Более подробно разбор заголовка DOS-программы можно найти в [1]. Добавлю только, что сразу за таблицей перемещения начинается исполняемая часть модуля. Таблица же перемещения используется для того, чтобы при загрузке настроить адреса. Но это лишь в том случае, если в программе используются адреса сегментов. В противном случае таблица перемещения не содержит элементов, и исполняемый код начинается сразу за форматированной частью заголовка. Перейдем теперь к общей структуре РЕ-модуля.

I

Общая структура РЕ-модуля. Начало заголовка ЕХЕ-файлов в WIN32 представляет собой небольшую DOS-программу, основное предназначение которой заключается в том, чтобы при запуске в операционной системе MS DOS сделать сообщение о том, что данный модуль не предназначен для работы в MS DOS. Программа LINK.EXE (TLINK32.EXE) устанавливает свой вариант DOS-программы. Однако при желании Вы всегда можете поставить свою программу-заглушку (stub в переводе заглушка).

Рассмотрим общую структуру РЕ-заголовка.
СмещениеКомментарий
00HОбычный DOS-заголовок.
1CHЧетыре байта до выравнивания до 20Н байт, т.е. выравнивание до двух параграфов.
20HИнформация о программе, обычно отсутствующая.
3CHСмещение 32-битного РЕ-заголовка.
40HТаблица перемещения для программы-заглушки. У стандартных заглушек таблица, разумеется, пуста. Не смотря на это TablOff должен показывать именно сюда.
40H+??Здесь начинается тело самой заглушки, которая начинается за таблицей перемещения. Естественно, в стандартных заглушках нет ничего, кроме сообщения о невозможности запуска программы. Однако заглушка может иметь и весьма разрушительные свойства.
??Здесь начинается собственно PE-заголовок. Сюда показывает содержимое четырех байт по адресу 3CH. Начало должно быть выровнено по 8-байтной границе.
??Таблица описаний секций файлов (Object Table).
??Остальная информация: coff-символы, отладочная информация, таблица импорта и таблица экспорта, ресурсы и т.д. Данный раздел называется Image Pages, т.е. страницы образов.

Рис. 4.1.2. Общая структура РЕ-заголовка.

00000: 4D 5A 0A 00 02 00 00 00 | 04 00 0F 00 FF FF 00 00 MZ
00010: C0 00 00 00 00 00 00 00 | 40 00 00 00 00 00 00 00
00020: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00
00030: 00 00 00 00 00 00 00 00 | 00 00 00 00 80 00 00 00
00040: B4 09 BA 10 00 OE IF CD | 21 B8 01 4C CD 21 90 90
00050: 54 68 69 73 20 69 73 20 | 61 20 57 69 6E 33 32 20
00060: 70 72 6F 67 72 61 6D 2E | 0D OA 24 00 00 00 00 00
00070: 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00
00080: 50 45 00 00 4C 01 03 00 | 39 30 00 00 00 00 00 00 PE
00090: 00 00 00 00 E0 00 OE 03 | 0B 01 02 34 00 30 00 00
000A0: 00 10 00 00 00 60 00 00 | 30 96 00 00 00 70 00 00
000B0: 00 A0 00 00 00 00 40 00 | 00 10 00 00 00 02 00 00

Рис. 4.1.3. Фрагмент РЕ-заголовка.

На рис. 4.1.3 показан фрагмент PE-заголовка. Обратите внимание, что по смещению 3CH действительно находится адрес начала основного заголовка (символы PE).

II

В таблице, представленной ниже мы даем описание заголовка РЕ.
СмещениеДлина поляНазвание поляОписание поля
00hDWORDSignature BytesСигнатура. Первые два байта "PE" 4550Н. Еще два байта обязательно должны быть равны нулю.
04hWORDCPU TypeДанное поле указывает на процессор, который следует предпочесть при запуске программы. Вот возможное значение этого поля:
0000h - неизвестный процессор.
014Ch - i386
014Dh - i486
014Eh - i586
0162h - MIPS Mark I (R2000, R3000)
0163h - MIPS Mark II (R6000)
0166h - MIPS Mark III (R4000)
Чаще всего данное поле указывает на процессор 386.
06hWORDNum of ObjectsПоле указывает на число реальных входов в Object Table (см. таб. ниже).
08hDWORDTime/Date StampДата и время, которые устанавливаются при компоновке программы.
0ChDWORDPointer to COFF tableДополнительный указатель, определяющий местонахождение отладочной COFF-таблицы в файлах. Это поле используется только в OBJ-файлах и РЕ-файлах, содержащих отладочную COFF-информацию.
10hDWORDCOFF table sizeКоличество символов в COFF-таблице.
14hWORDNT Header SizeРазмер заголовка РЕ-файла, начиная с поля Magic - таким образом, общий размер заголовка РЕ-файла составляет NT Header Size + 18h.
16hWORDFlagsУказывает на предназначение программы. Значение флагов:
0000h - это программа;
0001h - файл не содержит перемещений и таблицы перемещаемых элементов;
0002h - образ в файле можно запускать. Если этот бит не установлен, то это обычно указывает на ошибку, обнаруженную на этапе линковки, или же на то, что код был инкрементально отлинкован (инкрементальная линковка - частичная линковка кода при изменении участка программы, а не тотальная перекомпиляция проекта);
0200h - загружать в память фиксированно. Указывает на то, что программу можно грузить только по адресу, записанному в Image Base, если это невозможно, то такой файл лучше вообще не запускать.
2000h - это библиотека.
18hWORDMagicСлово-сигнатура, определяющее состояние отображенного файла. Определены следующие значения:
107Н - отображение ПЗУ.
10BH - нормально исполняемое отображение.
1AhBYTELink MajorСтарший номер версии использовавшегося при создании модуля компоновщика. Десятичный вид.
1BhBYTELink MinorМладший номер версии использовавшегося при создании модуля компоновщика. Десятичный вид.
1ChDWORDSize of CodeРазмер именно программного кода в файле. KERNEL использует это значение для фактического отведения памяти под загружаемую программу. Установка этого значения слишком маленьким приведет к выдаче сообщения о нехватке памяти. Обычно большинство модулей имеют только одну программную секцию .text.
20hDWORDSize of Init DataРазмер секции инициализированных данных, очевидно, не используется в Windows 95, но используется в Windows NT. Назначение аналогично приведенному выше.
24hDWORDSize of UnInit DataРазмер секции неинициализированных данных. Неинициализированные данные обычно содержатся в секции .bss. Данная секция не занимает на диске никакого места, но при загрузке модуля в память загрузчик отводит под нее память.
28hDWORDEntry point RVAАдрес относительно Image Base, no которому передается управление при запуске программы или адрес инициализации/завершения библиотеки.
2ChDWORDBase of CodeАдрес секции относительно базового адреса (40000Н), содержащей программный код. Этот адрес обычно равен 1000Н для компоновщика Microsoft и 10000H для компоновщика Borland.
30hDWORDBase of DataАдрес относительно базового (40000H), с которого начинаются секции данных файла. Секции данных обычно идут последними в памяти, после заголовка РЕ и программных секций.
34hDWORDImage BaseПри создании компоновщик помещает сюда адрес, куда будет отображен исполняемый файл в памяти. Если загрузчик отобразит файл именно по этому адресу, то дополнительной настройки не потребуется.
38hDWORDObject alignВыравнивание программных секций. После отображения в память каждая секция будет обязательно начинаться с виртуального адреса, кратного данной величине.
3ChDWORDFile alignВ случае РЕ-файла исходные данные, которые входят в состав каждой секции, будут обязательно начинаться с адреса, кратного данной величине. Значение по умолчанию составляет 200Н.
40hWORDOS MajorСтарший номер версии операционной системы, необходимый для запуска программы.
42hWORDOS MinorМладший номер версии операционной системы.
44hWORDUSER MajorПользовательский номер версии, задается пользователем при линковке программы. Старшая часть.
46hWORDUSER MinorПользовательский номер версии, младшая часть.
48hWORDSubSys MajorСтарший номер версии подсистемы.
4AhWORDSubSys MinorМладший номер версии подсистемы. Типичное значение версии 4.0, что означает Windows 95.
4ChDWORDReservedЗарезервировано.
50hDWORDImage SizeПредставляет общий размер всех частей отображения, находящихся под контролем загрузчика. Эта величина равна размеру области памяти, начиная с базового адреса отображения и заканчивая адресом конца последней секции. Адрес конца секции выровнен на ближайшую верхнюю границу секции.
54hDWORDHeader SizeОбщий размер всех заголовков: DOS Stub + РЕ Header + Object Table
58hDWORDFile CheckSumКонтрольная сумма всего файла. Как и в операционной системе MS DOS, ее никто не контролирует, а программа редактирования связей устанавливает ее в 0. Предполагалось ее рассчитывать как инверсию суммы всех байтов файла.
5ChWORDSubsystemОперационная подсистема, необходимая для запуска данного файла. Вот значения этого поля:
1 - подсистема не требуется (NATIVE).
2 - запускается в подсистеме Windows GUI.
3 - запускается в подсистеме Windows character (терминальное или консольное приложение).
5 - запускается в подсистеме OS/2.
7 - запускается в подсистеме Posix.
5EhWORDDLL FlagsУказывает на специальные потребности при загрузке, начиная с операционной системы NT 3.5. Устарел и не используется.
60hDWORDStack Reserve SizeПамять, требуемая для стека приложения. Память резервируется, но выделяется только Stack Commit Size байтов. Следующая страница является охранной. Когда приложение достигает этой страницы, то она становится доступной, а следующая страница - охранной, и так до достижения нижней границы, после чего Windows 95 убивает программу.
64hDWORDStack Commit SizeОбъем памяти, отводимой для стека немедленно после загрузки.
68hDWORDHeap Reserve SizeМаксимально возможный размер локальной кучи.
6ChDWORDHeap Comit SizeОтводимый размер кучи при загрузке.
70hDWORDLoader FlagsНачиная с Windows NT 3.5 объявлено неиспользуемым, назначение неясно, но в целом связано с поддержкой отладки.
74hDWORDNum of RVA and SizesУказывает размер массива VA/Size, который следует ниже, данное поле зарезервирована под будущие расширения формата. В данный момент его значение всегда равно 10h.
78hDWORDExport Table RVAОтносительный адрес (относительно базового адреса) таблицы экспорта.
7ChDWORDExport Data SizeРазмер таблицы экспорта.
80hDWORDImport Table RVAОтносительный адрес (относительно базового адреса) таблицы импорта.
84hDWORDImport Data SizeРазмер таблицы импорта.
88hDWORDResource Table RVAОтносительный адрес (относительно базового адреса) таблицы ресурсов.
8ChDWORDResource Data SizeРазмер таблицы ресурсов.
90hDWORDException Table RVAОтносительный адрес таблицы исключений.
94hDWORDException Data SizeРазмер таблицы исключений.
98hDWORDSecurity Table RVAАдрес таблицы безопасности. По-видимому, не используется.
9ChDWORDSecurity Data SizeРазмер таблицы безопасности.
A0hDWORDFix Up's Table RVAОтносительный адрес таблицы настроек.
A4hDWORDFix Up's Data SizeРазмер таблицы настроек.
A8hDWORDDebug Table RVAОтносительный адрес таблицы отладочной информации.
AChDWORDDebug Data SizeРазмер таблицы отладочной информации.
B0hDWORDImage Description RVAОтносительный адрес строки описания модуля.
B4hDWORDDescription Data SizeРазмер строки описания модуля.
B8hDWORDMachine Specific RVAАдрес таблицы значений, специфичных для микропроцессора.
BChDWORDMachine Data SizeРазмер таблицы значений, специфичных для микропроцессора.
C0hDWORDTLS RVAУказатель на локальную область данных цепочек.
C4hDWORDTLS Data SizeРазмер области данных цепочек.
C8hDWORDLoad Config RVAПредназначение неизвестно.
CChDWORDLoad Config Data SizeПредназначение неизвестно.
D0h08hReservedЗарезервировано.
D8hDWORDIAT RVAИспользуется в NT. В Windows 95, судя по всему, нет.
DChDWORDIAT Data SizeРазмер описанного поля.
E0h08hReservedЗарезервировано.
E8h08hReservedЗарезервировано.
F0h08hReservedЗарезервировано.

Между заголовком РЕ и данными для секций расположена таблица секций. Вот элемент этой таблицы.

Элемент таблицы секций содержит полную базу данных об одной секции.

Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0