Что такое ре файл
Для решения широкого круга программистских задач требуется знание внутренней структуры исполняемых файлов и представление о том, как они загружаются в память.
Несмотря на то, что исполняемые файлы Windows устроены достаточно просто, мне не удалось найти сколь-нибудь полного их описания. И официальные документы Microsoft, и многочисленные статьи, посвященные этой теме, грешат, во-первых, неполнотой и многочисленными неясностями, во-вторых, трудно обнаруживаемыми ошибками или неточностью описаний.
По этой причине я решил свести воедино всю известную мне информацию о строении PE-файлов с целью облегчить жизнь другим разработичкам. Все сведения, приведенные ниже, либо извлечены из доступных мне источников, либо обнаружены методом "научного тыка". В любом случае они подвергались тщательной проверке на правильность. Кроме того, изложение сопровождается примерами на языке C++, позволяющими быстро убедиться в их работоспособности.
Несмотря на то, что изложенная здесь информация прошла проверку временем (она используется во многих написанных мной утилитах, начиная с 1999 г.), гарантировать отсутствие ошибок я не берусь. Дело в том, что очень трудно различить, какая информация, содержащаяся в PE-файлах, является существенно важной для процесса загрузки и исполнения программ, а какая не используется вообще. По мере возможности я расставлял пометы "несущественно" или "загрузчиком не используется", но какие-то из этих помет могут оказаться неверными. Буду рад за указания на замеченные неточности или ошибки.
Примечание. В данную версию документа не включены описания двух каталогов данных: каталога ресурсов и каталога отладочной информации. Для понимания процесса загрузки и исполнения PE-файлов структура этих каталогов не важна, поэтому выкладываю документ в незаконченном виде. Надеюсь, что когда-нибудь я добавлю недостающие описания.
1.2. Общая структура файла
Любой PE-файл состоит из нескольких заголовков и нескольких (от 1 до 96) секций. Заголовки содержат служебную информацию, описывающую различные свойства исполняемого файла и его структуру. Секции содержат данные, которые размещаются в адресном пространстве процесса во время загрузки исполняемого файла в память.
PE-файлы являются файлами с относительной загрузкой, т. е. теоретически могут размещаться в пространстве адресов 0x00000000 - 0xFFFFFFFF с любого адреса, называемого базовым адресом. Поскольку базовый адрес заранее неизвестен, структура PE-файлов основана на понятия RVA (relative virtual address, относительный виртуальный адрес). RVA представляет собой смещение от базового адреса исполняемого файла до данного адреса. Иными словами, для получения линейного адреса в виртуальной памяти процесса нужно сложить RVA с базовым адресом.
Следует особо подчеркуть, что RVA не имеют ничего общего общего со смещениями относительно начала файла. В процессе загрузки файла каждая его секция размещается в памяти со своего RVA и при необходимости дополняется нулями до заданного размера. При этом RVA секции и ее размер в памяти, вообще говоря, никак не связаны с ее местоположением и размером в исходном файле.
Общая структура PE-файла такова:
Подробно каждая из этих структур описана в следующих разделах.
Поля NumberOfRvaAndSizes и DataDirectory
В конце необязательного заголовка располагается 32-битовое число, в котором хранится количество описателей каталогов данных. За ним следует массив самих описателей, каждый из которых имеет такой вид:
В настоящее время поле NumberOfRvaAndSizes всегда содержит число 16 (символическое имя IMAGE_NUMBEROF_DIRECTORY_ENTRIES). Соответственно массив DataDirectory состоит также из 16 описателей. Каждый описатель содержит RVA и размер для одного каталога данных. Если какого-либо каталога в файле нет, то оба поля его описателя равны нулю.
Каждый из каталогов данных содержит определенную служебную информацию. Вид этой информации определяется номером каталога в массиве описателей. Поскольку каталоги данных, как правило, располагаются внутри секций, для доступа к их содержимому нам потребуется сначала изучить структуру секций.
1.3. Проецирование файла в память
В дальнейшем мы предполагаем, что PE-файл открыт на чтение и спроецирован в память. Для открытия и закрытия файла можно использовать следующие функции:
Поле Machine
16-битовое число, которое задает архитектуру процессора, на которой может выполняться данная программа. Мне известны следующие коды процессоров (большинство из которых так никогда и не были поддержаны в Windows):
Название | Значение | Процессор |
---|---|---|
IMAGE_FILE_MACHINE_UNKNOWN | 0 | неизвестный процессор |
IMAGE_FILE_MACHINE_I386 | 0x014C | Intel 80386 или выше |
– | 0x014D | Intel 80486 или выше |
– | 0x014E | Intel Pentium или выше |
– | 0x0160 | MIPS R3000, big-endian |
IMAGE_FILE_MACHINE_R3000 | 0x0162 | MIPS R3000, little-endian |
IMAGE_FILE_MACHINE_R4000 | 0x0166 | MIPS R4000 |
IMAGE_FILE_MACHINE_R10000 | 0x0168 | MIPS R10000 |
IMAGE_FILE_MACHINE_WCEMIPSV2 | 0x0169 | MIPS WCE v2 |
IMAGE_FILE_MACHINE_ALPHA | 0x0184 | DEC/Compaq Alpha AXP |
IMAGE_FILE_MACHINE_SH3 | 0x01A2 | Hitachi SH3 |
IMAGE_FILE_MACHINE_SH3DSP | 0x01A3 | Hitachi SH3 DSP |
IMAGE_FILE_MACHINE_SH3E | 0x01A4 | Hitachi SH3E |
IMAGE_FILE_MACHINE_SH4 | 0x01A6 | Hitachi SH4 |
IMAGE_FILE_MACHINE_SH5 | 0x01A8 | Hitachi SH5 |
IMAGE_FILE_MACHINE_ARM | 0x01C0 | ARM |
IMAGE_FILE_MACHINE_THUMB | 0x01C2 | ARM Thumb |
IMAGE_FILE_MACHINE_AM33 | 0x01D3 | Panasonic AM33 |
IMAGE_FILE_MACHINE_POWERPC | 0x01F0 | IBM PowerPC |
IMAGE_FILE_MACHINE_POWERPCFP | 0x01F1 | IBM PowerPC FP |
IMAGE_FILE_MACHINE_IA64 | 0x0200 | Intel IA-64 (Itanium) |
IMAGE_FILE_MACHINE_MIPS16 | 0x0266 | MIPS16 |
– | 0x0268 | Motorola 68000 |
IMAGE_FILE_MACHINE_ALPHA64 | 0x0284 | DEC/Compaq Alpha AXP 64-bit |
– | 0x0290 | HP PA-RISC |
IMAGE_FILE_MACHINE_MIPSFPU | 0x0366 | MIPS with FPU |
IMAGE_FILE_MACHINE_MIPSFPU16 | 0x0466 | MIPS16 with FPU |
IMAGE_FILE_MACHINE_TRICORE | 0x0520 | Infineon TriCore |
IMAGE_FILE_MACHINE_CEF | 0x0CEF | . |
IMAGE_FILE_MACHINE_EBC | 0x0EBC | EFI Byte Code |
IMAGE_FILE_MACHINE_AMD64 | 0x8664 | AMD 64 (K8) |
IMAGE_FILE_MACHINE_M32R | 0x9041 | Renesas M32R |
IMAGE_FILE_MACHINE_CEE | 0xC0EE | . |
1.1. Стандарты COFF и PE
Во всех 32-разрядных ветках ОС Windows объектные (.OBJ), библиотечные (.LIB) и исполняемые (.EXE и .DLL) файлы хранятся в едином формате COFF (Common Object File Format), который используется некоторыми системами семейства Unix и ОС VMS.
На сегодняшний день существует два формата PE-файлов: PE32 и PE32+. Оба они ограничивают адресное пространство программы размеров в 4 Гб (0xFFFFFFFF), но PE32 использует 32-битовые адреса (архитектура Win32), а PE32+ – 64-битовые адреса (архитектура Win64).
Большинство описанных ниже структур и констант содержатся в стандартном заголовочном файле Windows WINNT.H. Я буду ниже использовать названия и обозначения, принятые в этом файле.
Поле DLLCharacteristics
16-битовое поле флагов, задающие дополнительные атрибуты файла. Возможные значения флагов:
Название | Значение | Описание |
---|---|---|
IMAGE_DLLCHARACTERISTICS_NO_SEH | 0x0400 | Файл не использует структурную обработку исключений. |
IMAGE_DLLCHARACTERISTICS_NO_BIND | 0x0800 | Запрещает статическое связывание этого файла. |
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER | 0x2000 | Файл является WDM-драйвером. |
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | 0x8000 | Если этот флаг не установлен, то при загрузке программы терминальным сервером будет загружена вспомогательная DLL, обеспечивающая совместимость кода. |
Поле TimeDateStamp
32-битовое число, которое содержит дату и время создания данного файла. Формат этого поля недокументирован, однако сборщики Microsoft заносят сюда время как количество секунд от полуночи 01.01.1970 в UTC (т. е. используют юниксовский формат времени, возвращаемого функцией time языка C). Между прочим, это означает, что текущее состояние формата PE действительно только до 18.01.2038 г.
Поскольку формат этого поля недокументирован, некоторые сборщики третьих фирм сохраняют его значение в других форматах. Это может оказаться важным, т. к. данное поле используется при динамическом связывании импорта из DLL.
начало работы с помощью WinPE
Поле SizeOfOptionalHeader
16-битовое число, задающее размер необязательного заголовка. Оно равно 0xE0 для файлов PE32 (IMAGE_SIZEOF_NT_OPTIONAL32_HEADER) и 0xF0 для файлов PE32+ (IMAGE_SIZEOF_NT_OPTIONAL64_HEADER).
3.3. Необязательный заголовок
Необязательный заголовок имеет два различных формата: для PE32 и для PE32+. Соответствующие структуры называются IMAGE_OPTIONAL_HEADER32 и IMAGE_OPTIONAL_HEADER64. Их поля сведены в следующей таблице:
Смещение (hex, PE32/PE32+) | Размер (PE32/PE32+) | Тип (PE32/PE32+) | Название | Описание |
---|---|---|---|---|
00 | 2 | WORD | Magic | Сигнатура заголовка. |
02 | 1 | BYTE | MajorLinkerVersion | Старшая цифра номера версии сборщика. Загрузчиком не используется. |
03 | 1 | BYTE | MinorLinkerVersion | Младшая цифра номера версии сборщика. Загрузчиком не используется. |
04 | 4 | DWORD | SizeOfCode | Сумма размеров всех секций, содержащих програмный код. |
08 | 4 | DWORD | SizeOfInitializedData | Сумма размеров всех секций, содержащих инициализированные данные. |
0C | 4 | DWORD | SizeOfUninitializedData | Сумма размеров всех секций, содержащих неинициализированные данные. |
10 | 4 | DWORD | AddressOfEntryPoint | RVA точки запуска программы. Для драйвера – это адрес DriverEntry, для DLL – адрес DllMain или нуль. |
14 | 4 | DWORD | BaseOfCode | RVA начала кода программы. |
18/– | 4/0 | DWORD | BaseOfData | RVA начала данных программы. Ненадежное поле, загрузчиком не используется. В PE32+ отсутствует! |
1С/18 | 4/8 | DWORD/ULONGLONG | ImageBase | Предпочтительный базовый адрес программы в памяти, кратный 64 Кб. По умолчанию равен 0x00400000 для EXE-файлов в Windows 9x/NT, 0x00010000 для EXE-файлов в Windows CE и 0x10000000 для DLL. Загрузка программы с этого адреса позволяет обойтись без настройки адресов. |
20 | 4 | DWORD | SectionAlignment | Выравнивание в байтах для секций при загрузке в память, большее или равное FileAlignment. По умолчанию равно размеру страницы виртуальной памяти для данного процессора. |
24 | 4 | DWORD | FileAlignment | Выравнивание в байтах для секций внутри файла. Должно быть степенью 2 от 512 до 64 Кб включительно. По умолчанию равно 512. Если SectionAlignment меньше размера страницы виртуальной памяти, то FileAlignment должно с ним совпадать. |
28 | 2 | WORD | MajorOperatingSystemVersion | Старшая цифра номера версии операционной системы. Загрузчиком не используется. |
2A | 2 | WORD | MinorOperatingSystemVersion | Младшая цифра номера версии операционной системы. Загрузчиком не используется. |
2C | 2 | WORD | MajorImageVersion | Старшая цифра номера версии данного файла. Загрузчиком не используется. |
2E | 2 | WORD | MinorImageVersion | Младшая цифра номера версии данного файла. Загрузчиком не используется. |
30 | 2 | WORD | MajorSubsystemVersion | Старшая цифра номера версии подсистемы. |
32 | 2 | WORD | MinorSubsystemVersion | Младшая цифра номера версии подсистемы. |
34 | 4 | DWORD | Win32VersionValue | Зарезервировано, всегда равно 0. |
38 | 4 | DWORD | SizeOfImage | Размер файла в памяти, включая все заголовки. Должен быть кратен SectionAlignment. |
3C | 4 | DWORD | SizeOfHeaders | Суммарный размер заголовка и заглушки DOS, заголовка PE и заголовков секций, выравненный на границу FileAlignment. Задает смещение от начала файла до данных первой секции. |
40 | 4 | DWORD | CheckSum | Контрольная сумма файла. |
44 | 2 | WORD | Subsystem | Исполняющая подсистема Windows для данного файла. |
46 | 2 | WORD | DllCharacteristics | Дополнительные атрибуты файла. |
48 | 4/8 | DWORD/ULONGLONG | SizeOfStackReserve | Размер стека стартового потока программы в байтах виртуальной памяти. При загрузке в физическую память отображается только SizeOfStackCommit байт, в дальнейшем отображается по одной странице виртуальной памяти. По умолчанию равен 1 Мб. |
4C/50 | 4/8 | DWORD/ULONGLONG | SizeOfStackCommit | Начальный размер стека программы в байтах. По умолчанию равен 4 Кб. |
50/58 | 4/8 | DWORD/ULONGLONG | SizeOfHeapReserve | Размер кучи программы в байтах. При загрузке в физическую память отображается только SizeOfHeapCommit байт, в дальнейшем отображается по одной странице виртуальной памяти. По умолчанию равен 1 Мб. Во всех 32-разрядных версиях Windows куча ограничена только размером виртуальной памяти и это поле, по-видимому, игнорируется. |
54/60 | 4/8 | DWORD/ULONGLONG | SizeOfHeapCommit | Начальный размер кучи программы в байтах. По умолчанию равен 4 Кб. |
58/68 | 4 | DWORD | LoaderFlags | Устаревшее поле, не используется. |
5C/6C | 4 | DWORD | NumberOfRvaAndSizes | Количество описателей каталогов данных. На текущий момент всегда равно 16. |
60/70 | 128 | IMAGE_DATA_DIRECTORY[16] | DataDirectory | Описатели каталогов данных. |
Поясним некоторые поля этой структуры.
Ограничения
Windows PE не является операционной системой общего назначения. Он не может использоваться ни для каких целей, кроме развертывания и восстановления. Его не следует использовать как тонкий клиент или внедренную операционную систему. Существуют и другие продукты Майкрософт, такие как Windows Embedded CE, которые могут использоваться для этих целей.
Чтобы предотвратить его использование в качестве рабочей операционной системы, Windows PE автоматически прекращает выполнение оболочки и перезапускается после 72 часов непрерывного использования. Этот период не настраивается.
При Windows перезагрузке PE все изменения теряются, в том числе изменения драйверов, букв диска и реестра Windows PE. Чтобы внести длительные изменения, см. статью WinPE: подключение и настройка.
По умолчанию Windows установке PE используется формат файлов FAT32, который создает собственные ограничения, включая максимальный размер файла размером 4 ГБ и максимальный размер диска 32 ГБ. Дополнительные сведения см. в статье WinPE: использование одного USB-ключа для WinPE и WIM-файла (WIM).
Windows PE не поддерживает следующие компоненты:
- Использование файлового сервера или сервера терминалов.
- Присоединение к сетевому домену.
- Подключение к сети IPv4 из Windows PE в сети IPv6.
- удаленный рабочий стол.
- .MSI файлы установки.
- Загрузка из пути, содержащего символы, отличные от английского.
- Запуск 64-разрядных приложений в 32-разрядной версии Windows PE.
- Добавление пакетов упакованных приложений с помощью DISM (пакеты APPXbundle).
Как правило, используйте последнюю версию WinPE для развертывания Windows. Если вы используете настроенную версию WinPE для образов Windows 10, вы можете продолжить использовать существующий образ Windows PE и запустить последнюю версию DISM из сетевого расположения. Дополнительные сведения см. в разделе "Копирование DISM на другой компьютер".
Доброго времени суток, форумчане. Сегодня, мы немного поговорим, рассмотрим и изучим под микроскопом структуру исполняемых файлов Windows ( Portable EXEcutable , или просто PE ), а в следующих статьях изучим технику модифицирования (инфицирования) PE-файлов, для того, чтобы исполнять свой собственный код после запуска чужого исполняемого файла (кстати, эта техника используется многими вирусами, для собственного "паразитического" распространения) и другие "хаки" с использованием знаний о структуре PE.
Portable Executabe файл (PE-файл) - это отдельный исполняемый модуль с расширением .exe (или .dll), получаемый в процессе сборки (компиляции и линковкии). В него включены код, ресурсы (иконки и другие данные), библиотеки, данные программы и т.д..
Давайте проведём аналогию между квартирой и PE-файлом. У каждой квартиры есть свой этаж, своя дверь, прихожая, гостинная, кладовка, свои комнаты, также у каждой квартиры есть своя схема планировки. Вся информация о квартире и сама эта квартира хранится в PE-файле. Взглянем на структуру исполняемого файла, а потом разберём основные части.
Если формально и без аналогий, то заголовки - структуры содержащие необходимые данные для загрузки программы, а секции - блоки данных с различным содержимым произвольного размера. Этим содержимым может быть код, ресурсы, виртуальные адреса функций и т.д..
- DOS заголовок
- Заглушка DOS
- PE заголовок
- Таблица секций
Как я и сказал, заголовки хранят необходимую информацию для загрузки PE-файла. Поэтому данный заголовок является обязательным для загрузки PE-файла, хоть и не несёт в себе большой смысловой информации.
Заголовок состоит из полей, как список состоит из пунктов свойств. Каждый пункт хранит в себе какое-либо значение. Естественно, в файле всё это представленно в байтовом представлении. Не все поля нужны для загрузки (запуска) PE-файла. Поэтому комментировать и рассматривать мы будем только поля, необходимые для загрузки файла в память.
Вот его структура на языке C/C++.
-
e_magic
Двухбайтовое поле e_magic хранит в себе специальную сигнатуру. Эта сигнатура нужна, чтобы указать что это действительно исполняемый файл. Вот она - "MZ". Каждый PE-файл обязан начинаться с неё. Если это не так, файл просто не запустится.
Я выделил самым большим красный прямоугольником область DOS-заголовка. Здесь мы можем увидеть байты в шестнадцатеричном представлении.
Вы можете поинтересоваться, для чего же другие поля? Дело в том, что система Windows построена на базе старой системы MS DOS (была до Windows). И на самом деле, это заголовок для DOS программы. Так вот, эти поля хранятся на случай, если кто-то попытается запустить PE-файл в DOS . В наше время никто практически ей не пользуется, но они остаются, так как если поменяют формат PE-файла, то перестанут работать программы с нынешним стандартом.
На самом деле, это не заголовок, а небольшая DOS программа . Просто для удобства я отнёс DOS-заглушку к заголовкам. Перед DOS-заголовком и PE-заголовком хранится небольшая DOS-программа, которая запустится, если вы попытаетесь запустить исполняемый файл Windows в MS DOS. Эта программка именуется DOS заглушкой или DOS стабом . По умолчанию, программа выведет "This program cannot be run in DOS" и завершит свою работу. Эта часть PE-файла не является обязательной.
Дальше у нас по списку PE-заголовок, который на самом деле, состоит из трёх частей: сигнатуры, файлового подзаголовка и дополнительного подзаголовка.
Вот его структура на языке C/C++:
Адрес начала PE-заголовка хранится в поле e_lfanew DOS-заголовка. Помните 08 01 00 00? Перевернём и получим адрес PE-заголовка. Это 00 00 01 08 или просто, 0x108. Перейдя по этому адресу в HEX-редакторе, мы встанем прямо перед началом PE-заголовка.
-
Signature
Это четырёхбайтовое поле содержит сигнатуру, а именно значение 50 45 00 00 (или "PE\x00\x00"). Эта сигнатура указывает на то, что перед нами действительно PE-файл (Ага, ещё одна проверка).
На C/C++ структура данного заголовка выглядит так:
-
Machine
Данное двухбайтовое поле содержит информацию о характеристике процессора, на котором может быть выполнена данная программа. Вот 3 основных значения, которые может принять этот заголовок:
1. IMAGE_FILE_MACHINE_I386 ( 0x014c ) - означает, что программа может выполняться на x32
2. IMAGE_FILE_MACHINE_IA64 ( 0x0200 ) - означает, что программа может выполняться на процессорах Intel Itanium (Intel x64).
3. IMAGE_FILE_MACHINE_AMD64 ( 0x8664 ) - означает, что программа может выполняться на процессорах AMD64 (x64).
Структура дополнительного заголовка представлена следующий C/C++ кодом.
-
Magic
Это двухбайтовое поле отвечает за битность программы (x32/x64). Оно может принимать следующие значения:
1. IMAGE_NT_OPTIONAL_HDR32_MAGIC ( 0x10b ) - означает, что это x32 (x86) исполняемый образ.
2. IMAGE_NT_OPTIONAL_HDR64_MAGIC ( 0x20b ) - означает, что это x64 исполняемый образ.
3. IMAGE_ROM_OPTIONAL_HDR_MAGIC ( 0x107 ) - означает, что это ROM образ.
Заголовок PE (IMAGE_NT_HEADERS) всегда выравнен на границу 8 байт и состоит из трех частей:
Как уже было сказано, заголовок PE всегда начинается с 4-байтовой сигнатуры "PE\0\0" (IMAGE_NT_SIGNATURE). За ней следуют два заголовка: заголовок файла (IMAGE_FILE_HEADER) и необязательный заголовок (IMAGE_OPTIONAL_HEADER). Несмотря на свое название, IMAGE_OPTIONAL_HEADER присутствует в PE-файле всегда (необязательным он является с точки зрения общего формата COFF, поскольку не используется в объектных и библиотечных файлах).
Поля PointerToSymbolTable и NumberOfSymbols
Согласно стандарту COFF, эти 4-байтовые поля должны обеспечивать доступ к отладочной информации в файле. Однако все известные мне сборщики заносят в них нули, а для доступа к отладочной информации используется иной способ (см. каталог отладочной информации).
1.4. Общее описание загрузки PE-файла
По мере изложения структуры PE-файлов я описываю процесс их загрузки в память во всех подробностях. Чтобы не утонуть в мелких деталях, рассмотрим основные этапы этого процесса.
Файлы… что вообще может быть проще? Мы все привыкли создавать, удалять, редактировать, перекидываться файлами.
Но можем ли мы заглянуть внутрь каждого файла и понять как он устроен? Конечно можем, поэтому сегодня мы немного покопаемся в бинарном коде и пощупаем метаданные.
Заодно узнаем, почему iPhone зависает от SMS и распотрошим PowerPoint.
Почему форматов файлов так много?
Если бы мы просто могли взглянуть на сырые данные, которые хранятся внутри жесткого диска или SSD, то мы бы не увидели никаких файлов: мы бы увидели только нолики и единички. Потому как, в любом случае, в памяти компьютера всё хранится в виде сплошного потока двоичного кода.
Но как же тогда понять, где заканчивается один файл и начинается другой?
Поначалу эту проблему человечество решало брутально. Люди записывали один файл на один жесткий диск, чтобы уж точно не ошибиться. Поэтому раньше словом файл называли не отдельную область на жестком диске, а прям целое устройство. К примеру IBM 305.
CTSS (Compatible Time-Sharing System)
Но потом, люди придумали файловые системы. Если очень упростить, это такое оглавление в котором указано имя файла, где он начинается и его длина. А также всякие метаданные, типа время создания, изменения, и можно ли его перезаписывать.
Но для того чтобы прочитать файл, знать его местоположение и границы на жестком диске недостаточно, ведь нам нужно как-то расшифровать бинарный код.
Для этого и существуют различные форматы файлов. В большинстве операционных систем форматы файлов указываются в виде расширения, которое отделяется точкой от имени файла. А если вы не видите расширения, это нормально. Потому что, по умолчанию, современные ОС их скрывают, но можно поставить галочку в настройках.
Расширение даёт подсказку операционной системе и программам, о том какой тип данных он содержит и как это всё структурировано. Например, увидев файл droider.jpg операционная система и мы, люди, сразу понимаем, что это картинка в формате JPEG.
Естественно, для типов данных и разных задач оптимальной будет разная структура файла. Поэтому и форматов файлов существует огромная масса.
Поэтому давайте разберем, как устроены наиболее популярные форматы файлов от более простых к более сложным.
Один из самый простых форматов — это TXT. Это текстовый формат. Знаменитое приложение «Блокнот» в Windows работает как раз с этим форматом.
TXT — формат незамысловатый. Он может хранить в себе только простой неформатированный текст, то есть в нем нет никаких выделений, подчеркиваний, курсивов, отступов, разных шрифтов. Только голый текст, а точнее просто символы.
Каждый символ в TXT-формате хранится в виде бинарного кода.
То что мы с вами видим как осмысленный текст, операционная система видит вот так:
01001000 01100101 01101100 01101100 01101111 00101100 00100000 01110111 01101111 01110010 01101100 01100100 00100001
Каждые 8 цифр, то есть 8 бит этого кода — это отдельный символ.
Например, 01001000 — это “H”, 01100101 — это “e”, и так далее.
Подобрав правильную кодировку остается дело техники. Система сопоставляет бинарный код с таблицей кодировки UTF-8 и готово! Но что будет если система подберет кодировку неправильно? Вариантов не много, скорее всего мы увидим крякозябры:
И такое часто случается, так как TXT-файл не содержит никакой дополнительной информации о кодировке. И это большой недостаток формата.
И вдобавок, эту таблицу нужно было загрузить в оперативную память при загрузке компьютера, а у типового ПК в начале 80-х годов редко было больше 640 килобайт оперативки. А использовать 16-битные таблицы (65536 вариантов) было просто невозможно, такая таблица просто не влезла бы в память.
Но мощность компьютеров росла и проблема ушла. К таблицам с латинскими символами добавились кириллические, которые занимали уже не по 8 бит, а по 16 бит каждый. Поэтому текст на русском занимает в два раза больше памяти, при том же количестве символов.
11010000 10011111 11010001 10000000 11010000 10111000 11010000 10110010 11010000 10110101 11010001 10000010 00101100 00100000 11010000 10111100 11010000 10111000 11010001 10000000 00100001
11010000 10011111 — П
11010001 10000000 — р
10111000 11010000 — и
11010000 10110010 — в
Старики помнят лайфхак, если писать SMS на латинице, то влезет в два раза больше текста. Всё это как раз из-за кодировки.
Так вот, чтобы у операционной системы не было проблем с пониманием как прочитать файл. Помимо самих данных, в разные форматы стали добавлять данные о данных. То есть метаданные, которые хранятся прямо внутри файла и содержат дополнительную информацию о том, как этот файл прочитать.
Это простой аудиоформат, который содержит несжатый. Всё CD диски записаны в формате WAV.
Первые 44 байта классического WAV-файла содержат заголовок, к котором указывается полезнейшая информация:
- количество аудио каналов;
- частота дискретизации;
- битовая глубина;
- и многое другое.
Открытые и проприетарные форматы
Структура WAV хорошо известна и наверное такой файл сможет прочитать практически любой плеер. Всё потому, что WAV-файл — это пример открытого формата.
Есть и другие открытые форматы, которыми вы ежедневно пользуетесь. Например:
- язык разметки web-страниц — HTML;
- картинки — PNG;
- аудио в формате — OGG;
- архива — ZIP;
- видео — MKV;
- электронной книги — EPUB;
- и другие.
Проприетарные форматы всем прекрасны, но в отдельных случаях они препятствуют конкуренции в сфере программного обеспечения, так как приводят к замыканию на поставщике. Есть даже такой термин Vendor lock-in.
Старый офис
Например, раньше такая ситуация была с форматами Microsoft Office: DOC, XLS, PPT.
Мало того, что это были проприетарные форматы компании Microsoft и работали только с фирменным ПО. Так еще Microsoft постоянно меняли свою структуру файлов от одной версии MS Office к другой. И в результате? при выходе новой версии офисного пакета? файлы из старого редактора уже не читались новым, а наоборот — и подавно.
Такая ситуация не очень нравилась Европейскому Союзу. Поэтому, ЕС взъелся на тему ограничения конкуренции. В итоге, форматы файлов опубличили, и все научились хотя бы их читать, но для записи в старые форматы, по-прежнему, нужна лицензия Microsoft. И параллельно этому начали разрабатываться открытые форматы.
ODF и OOXML
1 мая 2006 года на свет появился формат формат ODF, что буквально расшифровывается как открытый формат документов для офисных приложений. Он был разработан консорциумом OASIS и Sun Microsystems.
- ODF — Open Document Format for Office Application.
- OASIS — Organization for the Advancement of Structured Information Standards.
Microsoft тоже не спал. Под давлением Европейского суда они объединились с рядом компаний в ассоциацию ECMA и разработали свой открытый формат Office Open XML, который появился на свет чуть позже в 2006 году.
OOXML стандартизирован European Computer Manufacturers Association. Standard ECMA-376
К привычным форматом конце добавилась буква X и мы получили: DOCX, XLSX, PPTX.
OOXML — Office Open XML (DOCX, XLSX, PPTX)
OOXML, в целом, очень похож на ODF. Он также основан на XML-разметке и также представляет из себя ZIP-архив. Поэтому вы также можете заглянуть внутрь офисных файлов при помощи любого архиватора. Можно даже вытащить картинки и даже подменить их, что бывает особенно удобно при работе с презентациями или когда вам присылают текстовый документ с картинками внутри файла.
Несмотря на кажущуюся простоту, формат реально сложный. Только основная документация — это 5 тысяч страниц. И это практически без картинок.
Тем не менее, кто-то всё таки смог прочитать всю эту документацию и поэтому на свет появились классные офисные пакеты, например МойОфис, которые умеют работать и ODF форматом, и с Office Open XML, и даже с устаревшими форматами типа DOC.
Но есть важная ремарка про старые форматы. Как правило, современный софт умеет их только читать, но не записывать, потому как это действие требует приобретение лицензии Microsoft. Впрочем, в наше время это действие, мягко говоря, бессмысленно.
Итого
Что мы в итоге узнали? Файлы бывают нескольких типов:
Самые базовые — бинарные. Такие форматы любят придумывать компании, чтобы никто не понял, как их программы хранят данные.
Более открытый вариант — xml-контейнеры. К счастью, большинство популярных офисных форматов сейчас такие. Если хотите работать со всеми этими файлами хоть дома, хоть на бегу, скачивайте программы МойОфис! На этом у нас сегодня всё.
Windows PE (WinPE) — это небольшая операционная система, используемая для установки, развертывания и восстановления Windows классических выпусков, Windows Server и других операционных систем Windows. С Windows PE вы можете:
- Настройте жесткий диск перед установкой Windows.
- Установите Windows с помощью приложений или скриптов из сети или локального диска.
- Захват и применение Windows изображений.
- Измените Windows операционную систему, пока она не запущена.
- Настройте средства автоматического восстановления.
- Восстановление данных с неизменяемых устройств.
- Добавьте собственную пользовательскую оболочку или графический интерфейс для автоматизации таких задач.
Поле Characteristics
16-битовое поле флагов, содержащее COFF-атрибуты файла. Перечислим только те флаги, которые относятся к исполняемым файлам.
Поле Magic
16-битовое поле, содержащее сигнатуру заголовка. Может принимать значения:
Название | Значение | Описание |
---|---|---|
IMAGE_ROM_OPTIONAL_HDR_MAGIC | 0x0107 | Заголовок прошивки в ПЗУ ? |
IMAGE_NT_OPTIONAL_HDR32_MAGIC | 0x010B | Заголовок PE32. |
IMAGE_NT_OPTIONAL_HDR64_MAGIC | 0x020B | Заголовок PE32+. |
Поле CheckSum
32-битовая контрольная сумма файла. Проверяется только в Windows NT при загрузке драйверов ядра и нескольких системных DLL. Алгоритм вычисления контрольной суммы недокументирован, но для ее вычисления можно использовать системную функцию CheckSumMappedFile из библиотеки IMAGEHLP.DLL.
Требования к оборудованию
Windows PE имеет те же требования, что и Windows с этими исключениями:
- Жесткий диск не требуется. Вы можете полностью запустить Windows PE из памяти.
- Для базовой версии требуется только 512 МБ памяти. (При добавлении драйверов, пакетов или приложений потребуется больше памяти.)
- Чтобы загрузить Windows PE непосредственно из памяти (также известной как загрузка диска ОЗУ), должна быть доступна непрерывная часть физической памяти (ОЗУ), которая может содержать весь образ Windows PE (WIM). Чтобы оптимизировать использование памяти, производители должны убедиться, что их встроенное ПО резервирует расположения памяти в начале или в конце адресного пространства физической памяти.
- 32-разрядная версия Windows PE может загружать 32-разрядные компьютеры UEFI и BIOS, а также 64-разрядные КОМПЬЮТЕРы BIOS.
- 64-разрядная версия Windows PE может загружать 64-разрядные компьютеры UEFI и BIOS.
Поля MajorSubsystemVersion и MinorSubsystemVersion
16-битовые числа, указывающее ожидаемую версию Windows. В отличие от всех остальных полей с номерами версий это поле анализировалось при загрузке программ в NT 4.0 и 95. Если программа была графическим приложением и это поле не содержало версии 4.0, то считалось, что программа разработана для NT 3.51 и моделировалось поведение этой ОС (в частности, отсутствие трехмерных стилей диалогов и пр.). В настоящее время не используется и практически всегда равно 4.0.
Скачивание WinPE
WinPE — это надстройка для пакета средств для оценки и развертывания Windows (ADK). Вы можете скачать надстройку ADK и WinPE из скачивания и установки ADK. Установите ADK и надстройки WinPE, чтобы начать работу с WinPE.
До Windows 10, версия 1809 WinPE был включен в ADK и не был надстройкой.
3.2. Заголовок файла
Заголовок файла состоит из 0x14 байтов (определение IMAGE_SIZEOF_FILE_HEADER), размещается сразу после сигнатуры и содержит общее описание файла. Он состоит из следующих полей:
Опишем назначения полей.
Поддерживаемые функции Windows
Windows PE запускает среду командной строки Windows и поддерживает следующие Windows функции:
- Пакетные файлы и скрипты, включая поддержку узла скриптов Windows (WSH) и ActiveX объектов данных (ADO) и дополнительную поддержку PowerShell.
- Приложения, включая программные интерфейсы Win32 (API) и дополнительную поддержку html-приложений (HTA).
- Драйверы, включая универсальный набор драйверов, которые могут работать в сети, графике и запоминающих устройствах.
- Сбор и обслуживание образов, включая обслуживание образов развертывания и управление ими (DISM).
- Сеть, включая подключение к файловыми серверам с помощью TCP/IP и NetBIOS через TCP/IP через локальную сеть.
- служба хранилища, включая NTFS, DiskPart и BCDBoot.
- Средства безопасности, включая дополнительную поддержку BitLocker и доверенного платформенного модуля (TPM), безопасной загрузки и других средств.
- Hyper-V, включая VHD-файлы, интеграцию с мышью, запоминающие и сетевые драйверы, которые позволяют Windows PE выполняться в гипервизоре.
Поле Subsystem
16-битовое число, указывающее в какой подсистеме Windows API должен исполняться данный файл. Его возможные значения:
Название | Значение | Подсистема |
---|---|---|
IMAGE_SUBSYSTEM_UNKNOWN | 0 | Неизвестная подсистема. |
IMAGE_SUBSYSTEM_NATIVE | 1 | Подсистема не требуется, используется драйверами и "родными" приложениями NT. |
IMAGE_SUBSYSTEM_WINDOWS_GUI | 2 | Графическая подсистема Windows. |
IMAGE_SUBSYSTEM_WINDOWS_CUI | 3 | Консольная подсистема Windows. |
IMAGE_SUBSYSTEM_OS2_CUI | 5 | Консольная подсистема OS/2. |
IMAGE_SUBSYSTEM_POSIX_CUI | 7 | Консольная подсистема POSIX. |
IMAGE_SUBSYSTEM_NATIVE_WINDOWS | 8 | "Родной" драйвер Win 9x. |
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI | 9 | Графическая подсистема Windows CE. |
IMAGE_SUBSYSTEM_EFI_APPLICATION | 10 | Программа EFI. |
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER | 11 | Драйвер EFI, обеспечивающий загрузочный сервис. |
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER | 12 | Драйвер EFI времени выполнения. |
IMAGE_SUBSYSTEM_EFI_ROM | 13 | Прошивка ПЗУ для EFI. |
IMAGE_SUBSYSTEM_XBOX | 14 | Подсистема Xbox. |
Создание загрузочного носителя WinPE
WinPE можно загрузить с USB, CD/DVD/ISO или виртуального жесткого диска. Дополнительные сведения см. в статье "Создание загрузочного носителя WinPE ".
Читайте также: