Форматы исполняемых файлов. PE (Portable Executable): На странных берегах

Лекция 3. Файловая структура

Литература

o Современные операционные системы, Э. Таненбаум, 2002, СПб, Питер, 1040 стр., (в djvu 10.1Мбайт) подробнее>>

o Сетевые операционные системы Н. А. Олифер, В. Г. Олифер (в zip архиве 1.1Мбайт)

o Сетевые операционные системы Н. А. Олифер, В. Г. Олифер, 2001, СПб, Питер, 544 стр., (в djvu 6.3Мбайт)подробнее>>

Файлы

Требования к хранению информации:

o возможность хранения больших объемов данных

o информация должна сохраняться после прекращения работы процесса

o несколько процессов должны иметь одновременный доступ к информации

2.1.1Именование файлов

Длина имени файла зависит от ОС, может быть от 8 (MS-DOS) до 255 (Windows, LINUX) символов.

ОС могут различать прописные и строчные символы. Например, WINDOWS и windows для MS-DOS одно и тоже, но для UNIX это разные файлы.

Во многих ОС имя файла состоит из двух частей, разделенных точкой, например windows.exe. Часть после точки называют расширением файла . По нему система различает тип файла.

У MS-DOS расширение составляет 3 символа. По нему система различает тип файла, а также можно его исполнять или нет.

У UNIX расширение ограничено размером имени файла в 255 символов, также у UNIX может быть несколько расширений, но расширениями пользуются больше прикладные программы, а не ОС. По расширению UNIX не может определить исполняемый это файл или нет.

2.1.2Структура файла

Три основные структуры файлов:

1. Последовательность байтов - ОС не интересуется содержимым файла, она видит только байты. Основное преимущество такой системы, это гибкость использования. Используются в Windows и UNIX.

2. Последовательность записей - записей фиксированной длины (например, перфокарта), считываются последовательно. Сейчас не используются.

3. Дерево записей - каждая запись имеет ключ, записи считываются по ключу. Основное преимущество такой системы, это скорость поиска. Пока еще используется на мэйнфреймах.

Три типа структур файла.

2.1.3Типы файлов

Основные типы файлов:

o Регулярные - содержат информацию пользователя. Используются в Windows и UNIX.

o Каталоги - системные файлы, обеспечивающие поддержку структуры файловой системы. Используются в Windows и UNIX.

o Символьные - для моделирования ввода-вывода. Используются только в UNIX.

o Блочные - для моделирования дисков. Используются только в UNIX.

Основные типы регулярных файлов:

o ASCII файлы - состоят из текстовых строк. Каждая строка завершается возвратом каретки (Windows), символом перевода строки (UNIX) и используются оба варианта (MS-DOS). Поэтому если открыть текстовый файл, написанный в UNIX, в Windows, то все строки сольются в одну большую строку, но под MS-DOS они не сольются (это достаточно частая ситуация ). Основные преимущества ASCII файлов:
- могут отображаться на экране, и выводится на принтер без преобразований
- могут редактироваться почти любым редактором

o Двоичные файлы - остальные файлы (не ASCII). Как правило, имеют внутреннею структуру.

Основные типы двоичных файлов:

o Исполняемые - программы, их может обрабатывать сама операционная система, хотя они записаны в виде последовательности байт.

o Неисполняемые - все остальные.

Примеры исполняемого и не исполняемого файла

«Магическое число» - идентифицирующее файл как исполняющий.

2.1.4Доступ к файлам

Основные виды доступа к файлам:

o Последовательный - байты читаются по порядку. Использовались, когда были магнитные ленты.

2.1.5Атрибуты файла

Основные атрибуты файла:

o Защита - кто, и каким образом может получить доступ к файлу (пользователи, группы, чтение/запись). Используются в Windows и UNIX.

o Пароль - пароль к файлу

o Создатель - кто создал файл

o Владелец - текущий владелец файла

o Флаг "только чтение" - 0 - для чтения/записи, 1 - только для чтения. Используются в Windows.

o Флаг "скрытый" - 0 - виден, 1 - невиден в перечне файлов каталога (по умолчанию). Используются в Windows.

o Флаг "системный" - 0 - нормальный, 1 - системный. Используются в Windows.

o Флаг "архивный" - готов или нет для архивации (не путать сжатием). Используются в Windows.

o Флаг "сжатый" - файл сжимается (подобие zip архивов). Используются в Windows.

o Флаг "шифрованный" - используется алгоритм шифрования. Если кто-то попытается прочесть файл, не имеющий на это прав, он не сможет его прочесть. Используются в Windows.

o Флаг ASCII/двоичный - 0 - ASCII, 1 - двоичный

o Флаг произвольного доступа - 0 - только последовательный, 1 - произвольный доступ

o Флаг "временный" - 0 - нормальный, 1 - для удаления файла по окончании работы процесса

o Флаг блокировки - блокировка доступа к файлу. Если он занят для редактирования.

o Время создания - дата и время создания. Используются UNIX.

o Время последнего доступа - дата и время последнего доступа

o Время последнего изменения - дата и время последнего изменения. Используются в Windows и UNIX.

o Текущий размер - размер файла. Используются в Windows и UNIX.

2.1.6Операции с файлами

Основные системные вызовы для работы с файлами:

o Create - создание файла без данных.

o Delete - удаление файла.

o Open - открытие файла.

o Close - закрытие файла.

o Read - чтение из файла, с текущей позиции файла.

o Write - запись в файл, в текущею позицию файла.

o Append - добавление в конец файла.

o Seek - устанавливает файловый указатель в определенную позицию в файле.

o Get attributes - получение атрибутов файла.

o Set attributes - установить атрибутов файла.

o Rename - переименование файла.

Понимание файловой системы Linux, структуры каталогов, размещения конфигурационных, исполняемых и временных файлов поможет вам лучше разбираться в своей системе и стать успешным системным администратором. Файловая система Linux будет непривычна именно для новичка, только что перешедшего с Windows, ведь здесь все совсем по-другому. В отличие от Windows, программа не находится в одной папке, а, как правило, распределена по корневой файловой системе. Это распределение поддается определенным правилам. Вы когда-нибудь задавались вопросом, почему некоторые программы находятся в папке /bin, или /sbin, /usr/sbin, /usr/local/bin, в чем разница между этими каталогами?

Например, программа less, находится в каталоге /usr/bin, но почему не в /sbin или /usr/sbin. А такие программы, как ifconfig или fdisk находятся в каталоге /sbin и нигде иначе.

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

/ - корень

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

Обратите внимание, что у пользователя root домашний каталог /root, но не сам /.

/bin - (binaries) бинарные файлы пользователя

Этот каталог содержит исполняемые файлы. Здесь расположены программы, которые можно использовать в однопользовательском режиме или режиме восстановления. Одним словом, те утилиты, которые могут использоваться пока еще не подключен каталог /usr/. Это такие общие команды, как cat, ls, tail, ps и т д.

/sbin - (system binaries) системные исполняемые файлы

Так же как и /bin, содержит двоичные исполняемые файлы, которые доступны на ранних этапах загрузки, когда не примонтирован каталог /usr. Но здесь находятся программы, которые можно выполнять только с правами суперпользователя. Это разные утилиты для обслуживания системы. Например, iptables, reboot, fdisk, ifconfig,swapon и т д.

/etc - (etcetera) конфигурационные файлы

В этой папке содержатся конфигурационные файлы всех программ, установленных в системе.

Кроме конфигурационных файлов, в системе инициализации Init Scripts, здесь находятся скрипты запуска и завершения системных демонов, монтирования файловых систем и автозагрузки программ. Структура каталогов linux в этой папке может быть немного запутанной, но предназначение всех их - настройка и конфигурация.

/dev - (devices) файлы устройств

В Linux все, в том числе внешние устройства являются файлами. Таким образом, все подключенные флешки, клавиатуры, микрофоны, камеры - это просто файлы в каталоге /dev/. Этот каталог содержит не совсем обычную файловую систему. Структура файловой системы Linux и содержащиеся в папке /dev файлы инициализируются при загрузке системы, сервисом udev. Выполняется сканирование всех подключенных устройств и создание для них специальных файлов. Это такие устройства, как: /dev/sda, /dev/sr0, /dev/tty1, /dev/usbmon0 и т д.

/proc - (proccess) информация о процессах

Это тоже необычная файловая система, а подсистема, динамически создаваемая ядром. Здесь содержится вся информация о запущенных процессах в реальном времени. По сути, это псевдофайловая система, содержащая подробную информацию о каждом процессе, его Pid, имя исполняемого файла, параметры запуска, доступ к оперативной памяти и так далее. Также здесь можно найти информацию об использовании системных ресурсов, например, /proc/cpuinfo, /proc/meminfo или /proc/uptime. Кроме файлов в этом каталоге есть большая структура папок linux, из которых можно узнать достаточно много информации о системе.

/var (variable) - Переменные файлы

Название каталога /var говорит само за себя, он должен содержать файлы, которые часто изменяются. Размер этих файлов постоянно увеличивается. Здесь содержатся файлы системных журналов, различные кеши, базы данных и так далее. Дальше рассмотрим назначение каталогов Linux в папке /var/.

/var/log - Файлы логов

/var/lib - базы данных

Еще один тип изменяемых файлов - это файлы баз данных, пакеты, сохраненные пакетным менеджером и т д.

/var/mail - почта

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

/var/spool - принтер

Изначально, эта папка отвечала за очереди печати на принтере и работу набора программ cpus.

/var/lock - файлы блокировок

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

/var/run - PID процессов

Содержит файлы с PID процессов, которые могут быть использованы, для взаимодействия между программами. В отличие от каталога /run данные сохраняются после перезагрузки.

/tmp (temp) - Временные файлы

В этом каталоге содержатся временные файлы, созданные системой, любыми программами или пользователями. Все пользователи имеют право записи в эту директорию.

Файлы удаляются при каждой перезагрузке. Аналогом Windows является папка Windows\Temp, здесь тоже хранятся все временные файлы.

/usr - (user applications) Программы пользователя

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

/usr/bin/ - Исполняемые файлы

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

/usr/sbin/

Содержит двоичные файлы программ для системного администрирования, которые нужно выполнять с правами суперпользователя. Например, таких как Gparted, sshd, useradd, userdel и т д.

/usr/lib/ - Библиотеки

Содержит библиотеки для программ из /usr/bin или /usr/sbin.

/usr/local - Файлы пользователя

Содержит файлы программ, библиотек, и настроек созданные пользователем. Например, здесь могут храниться программы собранные и установленные из исходников и скрипты, написанные вручную.

/home - Домашняя папка

В этой папке хранятся домашние каталоги всех пользователей. В них они могут хранить свои личные файлы, настройки программ и т д. Например, /home/sergiy и т д. Если сравнивать с Windows, то это ваша папка пользователя на диске C, но в отличии от WIndows, home как правило размещается на отдельном разделе, поэтому при переустановке системы все ваши данные и настройки программ сохранятся.

/boot - Файлы загрузчика

Содержит все файлы, связанные с загрузчиком системы. Это ядро vmlinuz, образ initrd, а также файлы загрузчика, находящие в каталоге /boot/grub.

/lib (library) - Системные библиотеки

Содержит файлы системных библиотек, которые используются исполняемыми файлами в каталогах /bin и /sbin.

Библиотеки имеют имена файлов с расширением *.so и начинаются с префикса lib*. Например, libncurses.so.5.7. Папка /lib64 в 64 битных системах содержит 64 битные версии библиотек из /lib. Эту папку можно сравнить с WIndows\system32, там тоже сгружены все библиотеки системы, только там они лежат смешанные с исполняемыми файлами, а здесь все отдельно.

/opt (Optional applications) - Дополнительные программы

В эту папку устанавливаются проприетарные программы, игры или драйвера. Это программы созданные в виде отдельных исполняемых файлов самими производителями. Такие программы устанавливаются в под-каталоги /opt/, они очень похожи на программы Windows, все исполняемые файлы, библиотеки и файлы конфигурации находятся в одной папке.

/mnt (mount) - Монтирование

В этот каталог системные администраторы могут монтировать внешние или дополнительные файловые системы.

/media - Съемные носители

В этот каталог система монтирует все подключаемые внешние накопители - USB флешки, оптические диски и другие носители информации.

/srv (server) - Сервер

В этом каталоге содержатся файлы серверов и сервисов. Например, могут содержаться файлы веб-сервера apache.

/run - процессы

Еще один каталог, содержащий PID файлы процессов, похожий на /var/run, но в отличие от него, он размещен в TMPFS, а поэтому после перезагрузки все файлы теряются.

/sys (system) - Информация о системе

Назначение каталогов Linux из этой папки - получение информации о системе непосредственно от ядра. Это еще одна файловая система организуемая ядром и позволяющая просматривать и изменить многие параметры работы системы, например, работу swap, контролировать вентиляторы и многое другое.

Обфускаторы

Отладчики

Отладчик или дебаггер (англ. debugger) является модулем среды разработки или отдельным приложением, предназначенным для поиска ошибок в программе. Отладчик позволяет выполнять пошаговую трассировку, отслеживать, устанавливать или изменять значения переменных в процессе выполнения программы, устанавливать и удалять контрольные точки или условия остановки и т. д.

Обфускация (от лат. obfuscare - затенять, затемнять; и англ. obfuscate - делать неочевидным, запутанным, сбивать с толку) или запутывание кода - приведение исходного текста или исполняемого кода программы к виду, сохраняющему ее функциональность, но затрудняющему анализ, понимание алгоритмов работы и модификацию при декомпиляции.

«Запутывание » кода может осуществляться на уровне алгоритма, исходного текста и/или ассемблерного текста. Для создания запутанного ассемблерного текста могут использоваться специализированные компиляторы, использующие неочевидные или недокументированные возможности среды исполнения программы. Существуют также специальные программы, производящие обфускацию, называемые обфускаторами (англ. Obfuscator).

Исполнимый (исполняемый) модуль, исполнимый файл (англ. executable file) - файл, содержащий программу в виде, в котором она может быть (после загрузки в память и настройки по месту) исполнена компьютером.

Чаще всего он содержит двоичное представление машинных инструкций для определённого процессора (по этой причине на программистском сленге в отношении него используют слово бинарник - кальку с английского binary), но может содержать и инструкции на интерпретируемом языке программирования, для исполнения которых требуется интерпретатор. В отношении последних часто используется термин «скрипт».

Исполнением бинарных файлов занимаются аппаратно- и программно-реализованные машины. К первым относятся процессоры - например, семейств x86 или SPARC. Ко вторым - виртуальные машины, например, виртуальная машина Java или.NET Framework. Формат бинарного файла определяется архитектурой исполняющей его машины. Известны машины, реализованные как аппаратно, так и программно, например, процессоры семейства x86 и виртуальная машина VMware.

Статус исполнимости файла чаще всего определяется принятыми соглашениями. Так, в одних операционных системах исполнимые файлы распознаются благодаря соглашению об именовании файлов (например, путём указания в имени расширения файла - .exe или.bin ), тогда как в других исполнимые файлы обладают специфичными метаданными (например, битом разрешения execute в UNIX-подобных операционных системах).

В современных компьютерных архитектурах исполнимые файлы содержат большие объемы данных, не являющихся компьютерной программой: описание программного окружения, в котором программа может быть выполнена, данные для отладки программы, используемые константы, данные, которые могут потребоваться операционной системе для запуска процесса (например, рекомендуемый размер кучи), и даже описания структур окон графической подсистемы, используемых программой.



Зачастую исполнимые файлы содержат вызовы библиотечных функций, например, вызовы функций операционной системы. Таким образом, наряду с процессорозависимостью (машинозависимым является любой бинарный исполнимый файл, содержащий машинный код) исполнимым файлам может быть свойственна зависимость от версии операционной системы и её компонент.

Структура PE файла

Общее описание PE файла

Для решения широкого круга программистских задач требуется знание внутренней структуры исполняемых файлов и представление о том, как они загружаются в память.

Во всех 32-разрядных ветках ОС Windows объектные (.OBJ), библиотечные (.LIB) и исполняемые (.EXE и.DLL) файлы хранятся в едином формате COFF (Common Object File Format), который используется некоторыми системами семейства Unix и ОС VMS.

Формат PE (Portable Executable) является специализацией COFF для хранения исполняемых модулей. Он был стандартизован Tool Interface Standard Committee (Microsoft, Intel, IBM, Borland, Watcom и др.) в 1993 г., а затем понемногу обновлялся (последнее известное мне обновление было проведено в феврале 1999 г., но оно не учитывает поддержки метаданных для.NET, добавленной в 2000 г.). Название Portable Executable связано с тем, что данный формат не зависит от архитектуры процессора, для которого построен исполняемый файл.

На сегодняшний день существует два формата PE-файлов: PE32 и PE32+. Оба они ограничивают адресное пространство программы размеров в 4 Гб (0xFFFFFFFF), но PE32 использует 32-битовые адреса (архитектура Win32), а PE32+ - 64-битовые адреса (архитектура Win64).

Большинство описанных ниже структур и констант содержатся в стандартном заголовочном файле Windows WINNT.H.

Любой PE-файл состоит из нескольких заголовков и нескольких (от 1 до 96) секций. Заголовки содержат служебную информацию, описывающую различные свойства исполняемого файла и его структуру. Секции содержат данные, которые размещаются в адресном пространстве процесса во время загрузки исполняемого файла в память.

PE-файлы являются файлами с относительной загрузкой, т.е. теоретически могут размещаться в пространстве адресов 0x00000000 - 0xFFFFFFFF с любого адреса, называемого базовым адресом. Поскольку базовый адрес заранее неизвестен, структура PE-файлов основана на понятия RVA (relative virtual address, относительный виртуальный адрес). RVA представляет собой смещение от базового адреса исполняемого файла до данного адреса. Иными словами, для получения линейного адреса в виртуальной памяти процесса нужно сложить RVA с базовым адресом.

Следует особо подчеркуть, что RVA не имеют ничего общего общего со смещениями относительно начала файла. В процессе загрузки файла каждая его секция размещается в памяти со своего RVA и при необходимости дополняется нулями до заданного размера. При этом RVA секции и ее размер в памяти, вообще говоря, никак не связаны с ее местоположением и размером в исходном файле.

Общая структура PE-файла представлена в таблице 2.1:

Таблица 2.1 - Структура ре файла

Подробно каждая из этих структур описана ниже.

Общее описание заголовка и заглушки DOS

Поскольку и приложения DOS, и приложения Windows имеют расширение.EXE, все исполняемые файлы Windows используют схему двойной загрузки. Она состоит в том, что файл начинается с заголовка DOS, за которым следует заглушка (stub), т.е. небольшой EXE-файл формата DOS. При попытке загрузить файл из DOS"а исполняется заглушка, а при загрузке файла из Windows загрузчик анализирует заголовок DOS и извлекает из него смещение до настоящего заголовка исполняемого файла.

ь Структура заголовка DOS называется IMAGE_DOS_HEADER. Я не буду полностью описывать заголовок DOS, т.к. нас интересуют в нем только два поля, а именно:

ь 2-байтовая (WORD) сигнатура, находящаяся по смещению 0 (e_magic) и равная «MZ» (IMAGE_DOS_SIGNATURE);

ь 4-байтовое (DWORD) смещение от начала файла до заголовка PE, находяшееся по смещению 0x3C (e_lfanew).

При загрузке PE-файла сначала нужно проверить сигнатуру DOS, затем найти смещение до заголовка PE, а затем проверить сигнатуру PE, расположенную в начале его заголовка. Эта сигнатура состоит из 4 байтов и равна «PE» (обозначение IMAGE_NT_SIGNATURE).

Такую же схему двойной загрузки используют и другие файлы (исполняемые файлы Win16 и OS/2 и VxD-драйверы Windows 9x), поэтому проверка правильности сигнатуры PE обязательна.

Обычно заглушка DOS выводит на экран сообщение типа «Эта программа требует Microsoft Windows» и заканчивает работу. Однако при сборке программы мы можем указать в командной строке сборщика любой EXE-файл DOS в качестве заглушки. Это позволяет создавать «дуальные» программы, работающие и в DOS, и в Windows.

Сруктура DOS заголовка

typedef struct _IMAGE_DOS_HEADER { // DOS.EXE заголовок

USHORT e_magic; // Магическое число

USHORT e_cblp; // Количество байт на последней странице файла

USHORT e_cp; // Количество страниц в файле

USHORT e_crlc; // Relocations

USHORT e_cparhdr; // Размер заголовка в параграфах

USHORT e_minalloc; // Minimum extra paragraphs needed

USHORT e_maxalloc; // Maximum extra paragraphs needed

USHORT e_ss; // Начальное (относительное) значение регистра SS

USHORT e_sp; // Начальное значение регистра SP

USHORT e_csum; // Контрольная сумма

USHORT e_ip; // Начальное значение регистра IP

USHORT e_cs; // Начальное (относительное) значение регистра CS

USHORT e_lfarlc; // Адрес в файле на таблицу переадресации

USHORT e_ovno; // Количество оверлеев

USHORT e_res; // Зарезервировано

USHORT e_oemid; // OEM identifier (for e_oeminfo)

USHORT e_oeminfo; // OEM information; e_oemid specific

USHORT e_res2 ; // Зарезервировано

LONG e_lfanew; // Адрес в файле нового.exe-заголовка

} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

Самым важным здесь является поле e_lfanew, которое содержит 4-байтовое смещение от начала файла до PE-заголовка. Первое поле структуры e_magic содержит сигнатуру исполняемого файла. Все MS-DOS-совместимые исполняемые файлы имеют сигнатуру 0x54AD, которая в ASCII-символах представлена двумя символами MZ. По этой причине заголовок DOS часто называют MZ-заголовком.

Структура PE заголовка

Заголовок PE (IMAGE_NT_HEADERS) состоит из трех частей (см. Таблицу 2.2):

Таблица 2.2 - Структура заголовка

struct IMAGE_NT_HEADERS {

DWORD Signature;

IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER OptionalHeader;

Заголовок PE всегда начинается с 4-байтовой сигнатуры «PE» (IMAGE_NT_SIGNATURE). За ней следуют два заголовка: заголовок файла (IMAGE_FILE_HEADER) и необязательный заголовок (IMAGE_OPTIONAL_HEADER). Несмотря на свое название, IMAGE_OPTIONAL_HEADER присутствует в PE-файле всегда (необязательным он является с точки зрения общего формата COFF, поскольку не используется в объектных и библиотечных файлах).

Заголовок файла

Заголовок файла состоит из 0x14 байтов (определение IMAGE_SIZEOF_FILE_HEADER), размещается сразу после сигнатуры и содержит общее описание файла. Он состоит из следующих полей:

Таблица 2.3 - Структура заголовка файла

Описание назначения полей.

Поле Machine

16-битовое число, которое задает архитектуру процессора, на которой может выполняться данная программа.

Поле TimeDateStamp

32-битовое число, которое содержит дату и время создания данного файла. Формат этого поля недокументирован, однако сборщики Microsoft заносят сюда время как количество секунд от полуночи 01.01.1970 в UTC (т.е. используют юниксовский формат времени, возвращаемого функцией time языка C). Между прочим, это означает, что текущее состояние формата PE действительно только до 18.01.2038 г.

Поскольку формат этого поля недокументирован, некоторые сборщики третьих фирм сохраняют его значение в других форматах. Это может оказаться важным, т.к. данное поле используется при динамическом связывании импорта из DLL.

Поля PointerToSymbolTable и NumberOfSymbols

Согласно стандарту COFF, эти 4-байтовые поля должны обеспечивать доступ к отладочной информации в файле. Однако все известные мне сборщики заносят в них нули, а для доступа к отладочной информации используется иной способ (см. каталог отладочной информации).

Поле SizeOfOptionalHeader

16-битовое число, задающее размер необязательного заголовка. Оно равно 0xE0 для файлов PE32 (IMAGE_SIZEOF_NT_OPTIONAL32_HEADER) и 0xF0 для файлов PE32+ (IMAGE_SIZEOF_NT_OPTIONAL64_HEADER).

Поле Characteristics

16-битовое поле флагов, содержащее COFF-атрибуты файла.

Необязательный заголовок

Необязательный заголовок имеет два различных формата: для PE32 и для PE32+. Соответствующие структуры называются IMAGE_OPTIONAL_HEADER32 и IMAGE_OPTIONAL_HEADER64. Их поля сведены в Таблице 2.4:

Таблица 2.4 - Структура необязательного заголовка

Смещение (hex, PE32/PE32+)

Размер (PE32/PE32+)

Тип (PE32/PE32+)

Название

Описание

Сигнатура заголовка.

MajorLinkerVersion

Старшая цифра номера версии сборщика. Загрузчиком не используется.

MinorLinkerVersion

Младшая цифра номера версии сборщика. Загрузчиком не используется.

Сумма размеров всех секций, содержащих програмный код.

SizeOfInitializedData

Сумма размеров всех секций, содержащих инициализированные данные.

SizeOfUninitializedData

Сумма размеров всех секций, содержащих неинициализированные данные.

AddressOfEntryPoint

RVA точки запуска программы. Для драйвера - это адрес DriverEntry, для DLL - адрес DllMain или нуль.

RVA начала кода программы.

RVA начала данных программы. Ненадежное поле, загрузчиком не используется. В PE32+ отсутствует!

Предпочтительный базовый адрес программы в памяти, кратный 64 Кб. По умолчанию равен 0x00400000 для EXE-файлов в Windows 9x/NT, 0x00010000 для EXE-файлов в Windows CE и 0x10000000 для DLL. Загрузка программы с этого адреса позволяет обойтись без настройки адресов.

SectionAlignment

Выравнивание в байтах для секций при загрузке в память, большее или равное FileAlignment. По умолчанию равно размеру страницы виртуальной памяти для данного процессора.

Выравнивание в байтах для секций внутри файла. Должно быть степенью 2 от 512 до 64 Кб включительно. По умолчанию равно 512. Если SectionAlignment меньше размера страницы виртуальной памяти, то FileAlignment должно с ним совпадать.

MajorOperatingSystemVersion

Старшая цифра номера версии операционной системы. Загрузчиком не используется.

MinorOperatingSystemVersion

Младшая цифра номера версии операционной системы. Загрузчиком не используется.

MajorImageVersion

Старшая цифра номера версии данного файла. Загрузчиком не используется.

MinorImageVersion

Младшая цифра номера версии данного файла. Загрузчиком не используется.

MajorSubsystemVersion

Старшая цифра номера версии подсистемы.

MinorSubsystemVersion

Младшая цифра номера версии подсистемы.

Win32VersionValue

Зарезервировано, всегда равно 0.

Размер файла в памяти, включая все заголовки. Должен быть кратен SectionAlignment.

Суммарный размер заголовка и заглушки DOS, заголовка PE и заголовков секций, выравненный на границу FileAlignment. Задает смещение от начала файла до данных первой секции.

Контрольная сумма файла.

Исполняющая подсистема Windows для данного файла.

DllCharacteristics

Дополнительные атрибуты файла.

SizeOfStackReserve

Размер стека стартового потока программы в байтах виртуальной памяти. При загрузке в физическую память отображается только SizeOfStackCommit байт, в дальнейшем отображается по одной странице виртуальной памяти. По умолчанию равен 1 Мб.

SizeOfStackCommit

Начальный размер стека программы в байтах. По умолчанию равен 4 Кб.

SizeOfHeapReserve

Размер кучи программы в байтах. При загрузке в физическую память отображается только SizeOfHeapCommit байт, в дальнейшем отображается по одной странице виртуальной памяти. По умолчанию равен 1 Мб. Во всех 32-разрядных версиях Windows куча ограничена только размером виртуальной памяти и это поле, по-видимому, игнорируется.

SizeOfHeapCommit

Начальный размер кучи программы в байтах. По умолчанию равен 4 Кб.

Устаревшее поле, не используется.

NumberOfRvaAndSizes

Количество описателей каталогов данных. На текущий момент всегда равно 16.

IMAGE_DATA_DIRECTORY

Описатели каталогов данных.

16-битовое поле, содержащее сигнатуру заголовка. Может принимать значения (см. Таблицу 2.4):

Таблица 2.4 - Допустимые значения поля Magic

Поля MajorSubsystemVersion и MinorSubsystemVersion

16-битовые числа, указывающее ожидаемую версию Windows. В отличие от всех остальных полей с номерами версий это поле анализировалось при загрузке программ в NT 4.0 и 95. Если программа была графическим приложением и это поле не содержало версии 4.0, то считалось, что программа разработана для NT 3.51 и моделировалось поведение этой ОС (в частности, отсутствие трехмерных стилей диалогов и пр.). В настоящее время не используется и практически всегда равно 4.0.

Поле CheckSum

32-битовая контрольная сумма файла. Проверяется только в Windows NT при загрузке драйверов ядра и нескольких системных DLL. Алгоритм вычисления контрольной суммы недокументирован, но для ее вычисления можно использовать системную функцию CheckSumMappedFile из библиотеки IMAGEHLP.DLL.

Поле Subsystem

16-битовое число, указывающее в какой подсистеме Windows API должен исполняться данный файл. Его возможные значения представлены в таблице 2.5:

Таблица 2.5 - Допустимые значения поля Subsystem

Название

Значение

Подсистема

IMAGE_SUBSYSTEM_UNKNOWN

Неизвестная подсистема.

IMAGE_SUBSYSTEM_NATIVE

Подсистема не требуется, используется драйверами и «родными» приложениями NT.

IMAGE_SUBSYSTEM_WINDOWS_GUI

Графическая подсистема Windows.

IMAGE_SUBSYSTEM_WINDOWS_CUI

Консольная подсистема Windows.

IMAGE_SUBSYSTEM_OS2_CUI

Консольная подсистема OS/2.

IMAGE_SUBSYSTEM_POSIX_CUI

Консольная подсистема POSIX.

IMAGE_SUBSYSTEM_NATIVE_WINDOWS

«Родной» драйвер Win 9x.

IMAGE_SUBSYSTEM_WINDOWS_CE_GUI

Графическая подсистема Windows CE.

IMAGE_SUBSYSTEM_EFI_APPLICATION

Программа EFI.

IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER

Драйвер EFI, обеспечивающий загрузочный сервис.

IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER

Драйвер EFI времени выполнения.

IMAGE_SUBSYSTEM_EFI_ROM

Прошивка ПЗУ для EFI.

IMAGE_SUBSYSTEM_XBOX

Подсистема Xbox.

Поле DLLCharacteristics

16-битовое поле флагов, задающие дополнительные атрибуты файла. Возможные значения флагов представлены в таблице 2.6.

Таблица 2.6 - Возможные значения флагов поля DLLCharacteristics

Поля NumberOfRvaAndSizes и DataDirectory

В конце необязательного заголовка располагается 32-битовое число, в котором хранится количество описателей каталогов данных. За ним следует массив самих описателей, каждый из которых имеет такой вид:

struct IMAGE_DATA_DIRECTORY {

DWORD VirtualAddress;

В настоящее время поле NumberOfRvaAndSizes всегда содержит число 16 (символическое имя IMAGE_NUMBEROF_DIRECTORY_ENTRIES). Соответственно массив DataDirectory состоит также из 16 описателей. Каждый описатель содержит RVA и размер для одного каталога данных. Если какого-либо каталога в файле нет, то оба поля его описателя равны нулю.

Каждый из каталогов данных содержит определенную служебную информацию. Вид этой информации определяется номером каталога в массиве описателей. Поскольку каталоги данных, как правило, располагаются внутри секций, для доступа к их содержимому нам потребуется сначала изучить структуру секций.

Заголовки секций

Сразу после заголовка PE в файле располагается массив заголовков секций. Его размер задается полем NumberOfSections заголовка файла. Каждый заголовок секции состоит из 0x28 байт и имеет следующую структуру (см. Таблицу 2.7):

Таблица 2.7 - Струкура заголовка секции

Смещение (hex)

Название

Описание

Название секции.

Misc. VirtualSize

Размер секции в памяти. Если это значение больше SizeOfRawData, то секция дополняется в памяти нулевыми байтами.

RVA секции в памяти.

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

PointerToRawData

Смещение в файле до начала данных секций. Всегда кратно FileAlignment из необязательного заголовка. Если секция содержит только неинициализированные данные, то это поле равно нулю.

PointerToRelocations

PointerToLinenumbers

В исполняемых файлах это поле всегда равно нулю.

NumberOfRelocations

В исполняемых файлах это поле всегда равно нулю.

NumberOfLinenumbers

В исполняемых файлах это поле всегда равно нулю.

Characteristics

Атрибуты секции.

Название секции

Название секции содержит от 0 до 8 ASCII-символов. Вместо константы 8 можно использовать определение IMAGE_SIZEOF_SHORT_NAME. Если длина названия меньше 8 символов, то оно дополняется нулевыми байтами. Если оно состоит ровно из 8 символов, то завершающего нулевого байта нет. Важно отметить, что название секции, вообще говоря, никак не соотносится с ее содержимым. Каждый компилятор использует свое собственное соглашение о именовании секций, поэтому полагаться на название секции при ее анализе нельзя. Единственно надежным способом определить, что содержит данная секция, является анализ ее атрибутов и содержащихся в ней каталогов данных.

Атрибуты секции

32-битовое поле Characteristics содержит набор флагов, описывающих содержимое данной секции. Секции исполняемого файла могут иметь следующие атрибуты (см. Таблицу 2.8):

Таблица 2.8 - Атрибуты секции

Название

Значение

Описание

IMAGE_SCN_CNT_CODE

Секция содержит исполняемый код.

IMAGE_SCN_CNT_INITIALIZED_DATA

Секция содержит инициализированные данные.

IMAGE_SCN_CNT_UNINITIALIZED_DATA

Секция содержит неинициализированные данные.

IMAGE_SCN_MEM_DISCARDABLE

Секция может быть удалена из памяти после создания процесса.

IMAGE_SCN_MEM_NOT_CACHED

Секция не может кэшироваться.

IMAGE_SCN_MEM_NOT_PAGED

Секция не может выгружаться в файл подкачки.

IMAGE_SCN_MEM_SHARED

Все копии данного файла могут иметь один общий экземпляр этой секции. По-видимому, используется только для секций данных динамических библиотек.

IMAGE_SCN_MEM_EXECUTE

Секцию можно исполнять как программный код.

IMAGE_SCN_MEM_READ

IMAGE_SCN_MEM_WRITE

В секцию можно писать.

Сами секции располагаются в файле после всех заголовков секций. Каждая секция выравнена на границу FileAlignment из необязательного заголовка.

При анализе содержимого секций следует учитывать, что это содержимое может быть разнородным. Например, одна секция может содержать и исполняемый код, и таблицу импорта.

2.1 Файлы

Требования к хранению информации:

    возможность хранения больших объемов данных

    информация должна сохраняться после прекращения работы процесса

    несколько процессов должны иметь одновременный доступ к информации

2.1.1 Именование файлов

Длина имени файла зависит от ОС, может быть от 8 (MS-DOS) до 255 (Windows, LINUX) символов.

ОС могут различать прописные и строчные символы. Например, WINDOWS и windows для MS-DOS одно и тоже, но для UNIX это разные файлы.

Во многих ОС имя файла состоит из двух частей, разделенных точкой, например windows.exe. Часть после точки называют расширением файла . По нему система различает тип файла.

У MS-DOS расширение составляет 3 символа. По нему система различает тип файла, а также можно его исполнять или нет.

У UNIX расширение ограничено размером имени файла в 255 символов, также у UNIX может быть несколько расширений, но расширениями пользуются больше прикладные программы, а не ОС. По расширению UNIX не может определить исполняемый это файл или нет.

2.1.2 Структура файла

Три основные структуры файлов:

    Последовательность байтов - ОС не интересуется содержимым файла, она видит только байты. Основное преимущество такой системы, это гибкость использования. Используются в Windows и UNIX.

    Последовательность записей - записей фиксированной длины (например, перфокарта), считываются последовательно. Сейчас не используются.

    Дерево записей - каждая запись имеет ключ, записи считываются по ключу. Основное преимущество такой системы, это скорость поиска. Пока еще используется на мэйнфреймах.

Три типа структур файла.

2.1.3 Типы файлов

Основные типы файлов:

    Регулярные - содержат информацию пользователя. Используются в Windows и UNIX.

    Каталоги - системные файлы, обеспечивающие поддержку структуры файловой системы. Используются в Windows и UNIX.

    Символьные - для моделирования ввода-вывода. Используются только в UNIX.

    Блочные - для моделирования дисков. Используются только в UNIX.

Основные типы регулярных файлов:

    ASCII файлы - состоят из текстовых строк. Каждая строка завершается возвратом каретки (Windows), символом перевода строки (UNIX) и используются оба варианта (MS-DOS). Поэтому если открыть текстовый файл, написанный в UNIX, в Windows, то все строки сольются в одну большую строку, но под MS-DOS они не сольются (это достаточно частая ситуация ). Основные преимущества ASCII файлов:
    - могут отображаться на экране, и выводится на принтер без преобразований
    - могут редактироваться почти любым редактором

    Двоичные файлы - остальные файлы (не ASCII). Как правило, имеют внутреннею структуру.

Основные типы двоичных файлов:

    Исполняемые - программы, их может обрабатывать сама операционная система, хотя они записаны в виде последовательности байт.

    Неисполняемые - все остальные.

Примеры исполняемого и не исполняемого файла

«Магическое число» - идентифицирующее файл как исполняющий.

2.1.4 Доступ к файлам

Основные виды доступа к файлам:

    Последовательный - байты читаются по порядку. Использовались, когда были магнитные ленты.

2.1.5 Атрибуты файла

Основные атрибуты файла:

    Защита - кто, и каким образом может получить доступ к файлу (пользователи, группы, чтение/запись). Используются в Windows и UNIX.

    Пароль - пароль к файлу

    Создатель - кто создал файл

    Владелец - текущий владелец файла

    Флаг "только чтение" - 0 - для чтения/записи, 1 - только для чтения. Используются в Windows.

    Флаг "скрытый" - 0 - виден, 1 - невиден в перечне файлов каталога (по умолчанию). Используются в Windows.

    Флаг "системный" - 0 - нормальный, 1 - системный. Используются в Windows.

    Флаг "архивный" - готов или нет для архивации (не путать сжатием). Используются в Windows.

    Флаг "сжатый" - файл сжимается (подобие zip архивов). Используются в Windows.

    Флаг "шифрованный" - используется алгоритм шифрования. Если кто-то попытается прочесть файл, не имеющий на это прав, он не сможет его прочесть. Используются в Windows.

    Флаг ASCII/двоичный - 0 - ASCII, 1 - двоичный

    Флаг произвольного доступа - 0 - только последовательный, 1 - произвольный доступ

    Флаг "временный" - 0 - нормальный, 1 - для удаления файла по окончании работы процесса

    Флаг блокировки - блокировка доступа к файлу. Если он занят для редактирования.

    Время создания - дата и время создания. Используются UNIX.

    Время последнего доступа - дата и время последнего доступа

    Время последнего изменения - дата и время последнего изменения. Используются в Windows и UNIX.

    Текущий размер - размер файла. Используются в Windows и UNIX.

2.1.6 Операции с файлами

Основные системные вызовы для работы с файлами:

    Create - создание файла без данных.

    Delete - удаление файла.

    Open - открытие файла.

    Close - закрытие файла.

    Read - чтение из файла, с текущей позиции файла.

    Write - запись в файл, в текущею позицию файла.

    Append - добавление в конец файла.

    Seek - устанавливает файловый указатель в определенную позицию в файле.

    Get attributes - получение атрибутов файла.

    Set attributes - установить атрибутов файла.

    Rename - переименование файла.

2.1.7 Файлы, отображаемые на адресное пространство памяти

Иногда удобно файл отобразить в памяти (не надо использовать системные вызовы ввода-вывода для работы с файлом), и работать с памятью, а потом записать измененный файл на диск.

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

При использовании сегментной организации памяти, файл загружают в отдельный сегмент.

Пример копирования файла через отображение в памяти.

Алгоритм:

    Создается сегмент для файла 1

    Файл отображается в памяти

    Создается сегмент для файла 2

    Сегмент 1 копируется в сегмент 2

    Сегмент 2 сохраняется на диске

Недостатки этого метода:

    Тяжело определить длину выходного файла

    Если один процесс отобразил файл в памяти и изменил его, но файл еще не сохранен, второй процесс откроет это же файл, и будет работать с устаревшим файлом.

    Файл может оказаться большим, больше сегмента или виртуального пространства.

2.2 Каталоги

2.2.1 Одноуровневые каталоговые системы

В этой системе все файлы содержатся в одном каталоге.

Однокаталоговая система, содержащая четыре файла, файлов А два, но разных владельцев

Преимущества системы:

    Простота

    Возможность быстро найти файл, не надо лазить по каталогам

Недостатки системы:

    Различные пользователи могут создать файлы с одинаковыми именами.

2.2.2 Двухуровневые каталоговые системы

Для каждого пользователя создается свой собственный каталог.

Двухуровневая каталоговая система

Пользователь, при входе в систему, попадает в свой каталог и работает только с ним. Это делает проблематичным использование системных файлов.

Эту проблему можно решить созданием системного каталога, с общим доступом.

Если у одного пользователя много файлов, то у него тоже может возникнуть необходимость в файлах с одинаковыми именами.

2.2.3 Иерархические каталоговые системы

Каждый пользователь может создавать столько каталогов, сколько ему нужно.

Иерархическая каталоговая система

Почти все современные универсальные ОС, организованы таким образом. Специализированным ОС это может быть не нужным.

2.2.4 Имя пути

Для организации дерева каталогов нужен некоторый способ указания файла.

Два основных метода указания файла:

    абсолютное имя пути - указывает путь от корневого каталога, например:
    - для Windows \usr\ast\mailbox
    - для UNIX /usr/ast/mailbox
    - для MULTICS >usr>ast>mailbox

    относительное имя пути - путь указывается от текущего каталога (рабочего каталога), например:
    - если текущий каталог /usr/, то абсолютный путь /usr/ast/mailbox перепишется в ast/mailbox
    - если текущий каталог /usr/ast/, то абсолютный путь /usr/ast/mailbox перепишется в mailbox
    - если текущий каталог /var/log/, то абсолютный путь /usr/ast/mailbox перепишется в../../usr/ast/mailbox

./ - означает текущий каталог

../ - означает родительский каталог

2.2.5 Операции с каталогами

Основные системные вызовы для работы с каталогами:

    Create - создать каталог

    Delete - удалить каталог

    OpenDir - закрыть каталог

    CloseDir - закрыть каталог

    Rename - переименование каталога