Перейти до вмісту

Portable Executable

Матеріал з Вікіпедії — вільної енциклопедії.
Portable Executable
Розширення:.exe, .dll, .sys, .scr, .drv, .efi, .acm, .ax, .mui або .tsp Редагувати інформацію у Вікіданих
MIME-тип:application/vnd.microsoft.portable-executable[1] і application/efi[2] Редагувати інформацію у Вікіданих

Формат Portable Executable ( PE ) — це формат файлів для виконуваних файлів, об’єктного коду, бібліотек динамічного компонування (DLL) і двійкових файлів, які використовуються в 32-розрядних і 64-розрядних операційних системах Windows, а також у середовищах UEFI . [3] Це стандартний формат для бінарних програмних файлів у системах на базі Windows NT: виконуваних програм (.exe), динамічних бібліотек (.dll), системних драйверів (.sys), .mui . За своєю суттю формат PE є структурованим контейнером даних, який надає завантажувачу операційної системи Windows усе необхідне для належного керування виконуваним кодом, який він містить. Контейнер може містити посилання для динамічно пов’язаних бібліотек, таблиці для імпорту та експорту API, дані керування ресурсами та інформації про локальне сховище потоків (TLS).

Відповідно до специфікації Unified Extensible Firmware Interface (UEFI), формат PE також є прийнятним стандартом для виконуваних файлів у середовищах EFI. [4] У системах Windows NT він підтримує набори інструкцій IA-32, x86-64 (AMD64/Intel 64), IA-64, ARM і ARM64. Старіші версії Windows NT, що могли працювати на архітерктурах MIPS, DEC Alpha і PowerPC, також використовували формат PE. Крім того, завдяки використанню в Windows CE PE зберіг сумісність із декількома варіантами MIPS, ARM (включно з ARM Thumb) і SuperH.[5]

Функціонально формат PE подібний до інших форматів виконуваних файлів для певної платформи, таких як формат ELF, який використовується в Linux і більшості Unix-подібних систем, а також формат Mach-O, який існує в macOS і iOS .

Історія

[ред. | ред. код]

Корпорація Microsoft вперше представила формат PE у Windows NT 3.1, замінивши старий 16-розрядний формат New Executable (NE). Незабаром після цього Windows 95, 98, ME та розширення Win32s для Windows 3.1x прийняли структуру PE. Кожен PE-файл містить заголовок виконуваного файлу DOS, який зазвичай відображає повідомлення « Цю програму неможливо запустити в режимі DOS ». Однак цей розділ DOS можна замінити повнофункціональною програмою DOS, як показано в інсталяторі Windows 98 SE. Розробники можуть додати таку програму за допомогою параметра /STUB із компонувальником Microsoft, фактично створюючи так званий «жирний двійковий файл» (англ. fat binary).[6]

З часом формат PE розширився разом із платформою Windows. Відомими розширеннями є .NET PE для керованого коду, PE32+ для підтримки 64-розрядного адресного простору та спеціалізована версія для Windows CE .

Щоб визначити, чи PE-файл призначений для 32-розрядної чи 64-розрядної архітектури, можна перевірити поле Machine в IMAGE_FILE_HEADER. Загальними машинними значеннями є 0x014c для 32-розрядних процесорів Intel і 0x8664 для процесорів x86_64. Крім того, поле Magic в IMAGE_OPTIONAL_HEADER показує, чи є адреси 32-бітними чи 64-бітними. Значення 0x10B вказує на 32-розрядний (PE32) файл, тоді як 0x20B вказує на 64-розрядний (PE32+) файл.

Технічні деталі

[ред. | ред. код]

Макет

[ред. | ред. код]

Файл PE складається з кількох заголовків і розділів, які вказують динамічному компонувальнику, як відобразити файл у пам’яті. Виконуваний образ складається з кількох різних областей, кожна з яких потребує різних атрибутів захисту пам’яті. Щоб забезпечити правильне вирівнювання, початок кожного розділу має бути вирівняно за межею сторінки. [7] Наприклад, розділ .text, який містить програмний код, зазвичай відображається як виконання/лише читання. І навпаки, розділ .data, який містить глобальні змінні, відображається як заборонений на виконання/читання і запис. Однак для економії місця розділи не вирівнюються на диску таким чином. Динамічний компонувальник відображає кожен розділ у пам’яті окремо та призначає правильні дозволи на основі інформації в заголовках. [8]

Таблиця імпортів

[ред. | ред. код]

Таблиця адрес імпорту (IAT) використовується як таблиця пошуку, коли програма викликає функцію в іншому модулі. Імпорт можна вказати за порядковим номером або за назвою. Оскільки скомпільована програма не може заздалегідь знати розташування залежних від неї бібліотек, для викликів API необхідний непрямий перехід. Оскільки динамічний компонувальник утримує модулі та вирішує залежності, він заповнює слоти IAT фактичними адресами відповідних функцій бібліотеки. Незважаючи на те, що це додає додаткову інструкцію jmp, спричиняючи погіршення продуктивності порівняно з міжмодульними викликами, це мінімізує кількість сторінок пам’яті, для яких потрібні зміни копіювання під час запису, таким чином зберігаючи пам’ять і зменшуючи обсяг дискового вводу-виводу. Якщо заздалегідь відомо, що виклик є міжмодульним (якщо це вказано атрибутом dllimport ), компілятор може створити оптимізований код за допомогою простого коду операції непрямого виклику. [8]

Рандомізація розташування адресного простору (ASLR)

[ред. | ред. код]

Файли PE за замовчуванням не залежать від позиції ; вони скомпільовані для роботи за певною фіксованою адресою пам’яті. Сучасні операційні системи використовують рандомізацію адресного простору (ASLR), щоб зловмисникам було важче використовувати вразливості, пов’язані з пам’яттю. ASLR працює шляхом випадкової зміни адреси пам’яті важливих частин програми кожного разу, коли вона завантажується. Це включає базову адресу самої програми, спільні бібліотеки (DLL) і області пам’яті, такі як купа та стек. ASLR змінює позиції в адресному просторі ключових областей даних процесу, включаючи базу виконуваного файлу та позиції стека, купи та бібліотек . Шляхом рандомізації цих адрес пам’яті кожного разу, коли процес завантажується програма, ASLR не дозволяє зловмисникам надійно передбачити розташування пам’яті.

.NET, метадані та формат PE

[ред. | ред. код]

У .NET, розділ коду PE містить заглушку, яка викликає запис запуску віртуальної машини CLR, _CorExeMain або _CorDllMain у mscoree.dll, подібно до того, як це було у виконуваних файлах Visual Basic . Тоді віртуальна машина використовує наявні метадані .NET, на корінь яких (IMAGE_COR20_HEADER , також званий «заголовок CLR») вказує запис IMAGE_DIRECTORY_ENTRY_COMHEADER (раніше використовувався для метаданих COM+ у програмах COM+, звідки й назва[джерело?] ) у каталозі даних заголовка PE. IMAGE_COR20_HEADER дуже нагадує додатковий заголовок PE, по суті, відіграючи його роль для завантажувача CLR.[9]

Дані, пов’язані з CLR, включно з власне кореневою структурою, зазвичай містяться в розділі загального коду .text. Він складається з кількох каталогів: метаданих, вбудованих ресурсів, сильних імен і кількох для взаємодії з рідним кодом. Каталог метаданих — це набір таблиць із переліком усіх окремих сутностей .NET у збірці (англ. assembly, включаючи типи, методи, поля, константи, події, а також посилання між ними та на інші збірки.

Використання в інших операційних системах

[ред. | ред. код]

Формат PE також використовується ReactOS, операційною системою з відкритим початковим кодом, створеною для бінарної сумісності з Windows. Історично він також використовувався іншими операційними системами, такими як SkyOS і BeOS R3. Однак і SkyOS, і BeOS з часом перейшли на ELF.[джерело?]

Платформа розробки Mono, яка прагне бути бінарно сумісною з Microsoft .NET Framework використовує той самий формат PE, що й реалізація Microsoft. Те саме стосується власної кросплатформеності Microsoft .NET Core .

У x86 (-64) Unix-подібних операційних системах двійкові файли Windows (у форматі PE) можна виконати за допомогою Wine . HX DOS Extender також використовує формат PE для власних 32-розрядних двійкових файлів DOS і може виконувати деякі двійкові файли Windows у DOS, таким чином діючи як еквівалент Wine для DOS.

Mac OS X 10.5 має можливість завантажувати та аналізувати файли PE, хоча вона не підтримує бінарну сумісність із Windows. [10]

Мікропрограмне забезпечення UEFI та EFI використовує PE-файли, а також угоду про виклик Windows ABI x64 для програм. PE використовується навіть на платформах, для яких Windows не існує (наприклад, RISC-V).

Див. також

[ред. | ред. код]

Примітки

[ред. | ред. код]
  1. Внутрішній формат архівів ar, як правило, або COFF, або BSD

Джерела

[ред. | ред. код]
  1. https://www.iana.org/assignments/media-types/application/vnd.microsoft.portable-executable
  2. https://www.iana.org/assignments/media-types/application/efi
  3. Portable executable (PE) - Definition - Trend Micro IN. www.trendmicro.com. Процитовано 10 листопада 2022.
  4. UEFI Specification, version 2.8B (PDF).
  5. PE Format (Windows) (англ.). 20 лютого 2025. Процитовано 4 березня 2025.
  6. /STUB (MS-DOS Stub File Name). 3 серпня 2021.
  7. The Portable Executable File From Top to Bottom. Процитовано 21 жовтня 2017.
  8. а б Peering Inside the PE: A Tour of the Win32 Portable Executable File. 30 червня 2010. Процитовано 21 жовтня 2017.
  9. PE Format (Windows). Процитовано 21 жовтня 2017.
  10. Chartier, David (30 листопада 2007). Uncovered: Evidence that Mac OS X could run Windows apps soon. Ars Technica. Процитовано 3 грудня 2007. ... Steven Edwards describes the discovery that Leopard apparently contains an undocumented loader for Portable Executables, a type of file used in 32-bit and 64-bit versions of Windows. More poking around revealed that Leopard's own loader tries to find Windows DLL files when attempting to load a Windows binary.

Зовнішні посилання

[ред. | ред. код]