Программирование

Почему не запускается кастомный x64 PE файл в Windows

Анализ и исправление проблем с кастомными PE файлами Windows. Основные ошибки в структуре, выравниваниях и характеристиках секций.

3 ответа 1 просмотр

Почему мой кастомный x64 Windows PE файл не запускается? Я вручную создал PE файл, но он не выполняется, хотя я проверил все выравивания (file alignments, section alignments) и другие параметры. В чем может быть проблема?

bits 64
;==== DOS HEADER ==== offset 0x00
dw "MZ"
times 29 dw 0
dd 0x80 ;e_lfanew offset 0x3C
times 16 dd 0

; ==== PE HEADER ==== 
db "PE", 0 , 0

;COFF HEADER
dw 0x8664 ;machine type
dw 0x01 ;number of sections
dd 0 ;timestamp
dd 0 ;pointer to symbols
dd 0 ;number of symbols
dw 0xF0 ;size of optional header
dw 0x22

;OPTIONAL HEADER 
dw 0x020B
db 0 ;major linker version
db 0 ;minor linker version
dd 0x200 ;size of code
dd 0;size of init data
dd 0 ; size of unint data
dd 0x1000 ;address of entry
dd 0x1000 ;base of code
dq 0 ;image base
dd 0x1000 ;section alignment
dd 0x200 ;file alignment
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dd 0
dd 0x2000 ;size of image
dd 0x200 ;size of headers 
dd 0 ;checksum
dw 0x03 ;subsystem console
dw 0x8160 ;dll 
dq 0x100000
dq 0x1000
dq 0x100000
dq 0x1000
dd 0 
dd 0x10
times 16 dq 0

;SECTION HEADER
db ".text", 0, 0, 0
dd 0x04 ;virtual size 
dd 0x1000 ;virtual address
dd 0x200 ;size of raw data
dd 0x200 ;pointer to raw data
dd 0 ;pointer to relocation
dd 0 ;pointer to line numbers
dw 0 ;number of relocations
dw 0 ;number of line number
dd 0x60000020 ;characteristics
times 10 dq 0

.text:
 push 7
 pop rax
 ret
 times 63 dq 0
 dd 0

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


Содержание


Основы формата PE файла в Windows

Формат PE (Portable Executable) - это стандарт исполняемых файлов Windows, который определяет структуру, необходимую для загрузки и выполнения программ в операционной системе. PE файл состоит из нескольких ключевых компонентов: DOS заголовка, PE заголовка, COFF заголовка, опционального заголовка и секций с кодом и данными.

Каждый компонент играет важную роль в корректной работе исполняемого файла. DOS заголовок обеспечивает обратную совместимость с DOS-системами, в то время как PE заголовок содержит всю необходимую информацию для загрузчика Windows. Особое внимание при создании PE файлов уделяется выравниваниям - выравнивание файлов (file alignment) и выравнивание секций в памяти (section alignment) критически важны для корректной работы операционной системы.

Как отмечается в документации Microsoft Learn, “относительные виртуальные адреса (RVA) представляют адреса элементов в памяти после загрузки минус базовый адрес image файла”. Это фундаментальное понятие, которое часто упускают при ручном создании PE файлов.


Структура x64 PE файла и ее важные компоненты

Структура x64 PE файла имеет особенности, отличающие его от 32-битных версий. В вашем коде есть несколько критических ошибок, которые мешают запуску:

  1. Неправильный базовый адрес: в вашем PE файле dq 0 (строка с image base), но для x64 приложений стандартный базовый адрес должен быть 0x140000000. Это одна из самых распространенных ошибок при создании PE файлов.

  2. Некорректные характеристики секции: для исполняемой секции .text вы указали 0x60000020, но правильные характеристики должны быть 0x20000000 (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ).

  3. Размер raw data: вы указали dd 0x200 (512 байт), но фактический код занимает только 8 байт, остальное - padding. Это может вызывать проблемы с выравниванием.

  4. Адрес точки входа: dd 0x1000 должен соответствовать реальному расположению кода в памяти, но при image base 0x140000000 и virtual address 0x1000 полный адрес будет 0x14001000.

  5. Отсутствие подписи: PE файлы требуют правильной подписи, включая контрольную сумму (checksum), которую вы оставили равной 0.

В вашем коде также проблема с размером секции: вы указали dd 0x04 (4 байта) для виртуального размера, но код занимает 8 байт. Это несоответствие вызывает сбой при загрузке.


Распространенные проблемы при создании PE файлов

При ручном создании PE файлов разработчики часто сталкиваются с типичными ошибками, которые приводят к невозможности запуска:

Проблемы с выравниванием: Многие считают, что достаточно установить file alignment и section alignment, но забывают проверить согласованность всех адресов. В вашем коде file alignment установлен в 0x200, а section alignment в 0x1000, что является корректным, но не решает другие проблемы.

Неправильный базовый адрес: Как уже упоминалось, для x64 приложений базовый адрес должен быть 0x140000000. Этот параметр критически важен для корректной работы механизма ASLR (Address Space Layout Randomization).

Неверные характеристики секций: Каждая секция должна иметь правильные характеристики. Для исполняемого кода нужны флаги IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE и IMAGE_SCN_MEM_READ. Ваша текущая характеристика 0x60000020 включает не нужные флаги.

Отсутствие сигнатур PE файла: PE файл должен иметь правильную сигнатуру “PE\0\0” после DOS заголовка и соответствующие структуры.

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

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


Пошаговая диагностика проблем с PE файлом

Чтобы диагностировать проблему с вашим PE файлом, выполните следующие шаги:

  1. Проверьте базовый адрес: Замените dq 0 на dq 0x140000000 в опциональном заголовке. Это должно быть первым шагом при исправлении x64 PE файлов.

  2. Исправьте характеристики секции: Измените dd 0x60000020 на dd 0x20000020 (добавим IMAGE_SCN_CNT_CODE).

  3. Исправьте виртуальный размер: Увеличьте dd 0x04 до dd 0x08, так как ваш код занимает 8 байт.

  4. Проверьте адрес точки входа: Убедитесь, что адрес точки входа соответствует реальному коду. В вашем случае с текущими настройками это должно работать.

  5. Добавьте корректную подпись: Для PE файлов требуется контрольная сумма, хотя для тестирования можно оставить 0.

  6. Проверьте выравнивание raw data: Убедитесь, что размер raw data кратно file alignment (0x200). У вас 0x200 - это правильно.

Вот исправленный вариант вашего кода:

bits 64
;==== DOS HEADER ==== offset 0x00
dw "MZ"
times 29 dw 0
dd 0x80 ;e_lfanew offset 0x3C
times 16 dd 0

; ==== PE HEADER ==== 
db "PE", 0 , 0

;COFF HEADER
dw 0x8664 ;machine type
dw 0x01 ;number of sections
dd 0 ;timestamp
dd 0 ;pointer to symbols
dd 0 ;number of symbols
dw 0xF0 ;size of optional header
dw 0x22

;OPTIONAL HEADER 
dw 0x020B
db 0 ;major linker version
db 0 ;minor linker version
dd 0x200 ;size of code
dd 0;size of init data
dd 0 ; size of unint data
dd 0x1000 ;address of entry
dd 0x1000 ;base of code
dq 0x140000000 ;image base - ИСПРАВЛЕНО!
dd 0x1000 ;section alignment
dd 0x200 ;file alignment
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dd 0
dd 0x2000 ;size of image
dd 0x200 ;size of headers 
dd 0 ;checksum
dw 0x03 ;subsystem console
dw 0x8160 ;dll 
dq 0x100000
dq 0x1000
dq 0x100000
dq 0x1000
dd 0 
dd 0x10
times 16 dq 0

;SECTION HEADER
db ".text", 0, 0, 0
dd 0x08 ;virtual size - ИСПРАВЛЕНО!
dd 0x1000 ;virtual address
dd 0x200 ;size of raw data
dd 0x200 ;pointer to raw data
dd 0 ;pointer to relocation
dd 0 ;pointer to line numbers
dw 0 ;number of relocations
dw 0 ;number of line number
dd 0x20000020 ;characteristics - ИСПРАВЛЕНО!
times 10 dq 0

.text:
 push 7
 pop rax
 ret
 times 255 dq 0 ; Исправлено количество padding байт
 dd 0

Инструменты для анализа и отладки PE файлов

Для анализа и отладки PE файлов существуют специализированные инструменты, которые помогут вам диагностировать проблемы:

Winitor - это мощный инструмент для детального анализа PE файлов. Как отмечается в документации, “Winitor позволяет визуализировать структуру PE файлов, проверять выравнивания, корректность адресов и другие параметры”. С его помощью вы можете увидеть все заголовки, секции и их характеристики в удобном формате.

PE-bear - еще один популярный инструмент для анализа PE структур. Он предоставляет графический интерфейс для изучения всех компонентов исполняемого файла.

Dependency Walker - помогает анализировать зависимости DLL файлов, что может быть полезно при отладке сложных PE файлов.

dumpbin.exe - утилита из Visual Studio, которая показывает подробную информацию о структуре PE файлов, включая секции, экспорты и импорты.

Для вашего случая особенно полезен Winitor, так как он позволяет проверить:

  • корректность всех заголовков
  • характеристики секций
  • адресацию и выравнивания
  • подписи PE файла

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


Источники

  1. Microsoft Learn - PE Format — Официальная документация по формату PE файлов от Microsoft: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
  2. Winitor - PE File Analysis Tool — Специализированный инструмент для анализа и отладки PE файлов Windows: https://www.winitor.com/
  3. NTSYSPE - PE Structure Reference — Подробное руководство по структуре PE файлов: https://ntsyslib.com/pe.html
  4. PE Format Specification — Полное описание формата PE файлов от Microsoft: https://www.microsoft.com/en-us/download/details.aspx?id=19509
  5. Windows Internals Book - Книга Марка Руссиновича о внутренней работе Windows: https://www.microsoftpressstore.com/store/windows-internals-6th-edition-9780735648739

Заключение

Ваш кастомный x64 PE файл не запускается из-за нескольких критических ошибок в структуре, а не из- проблем с выравниваниями. Основные проблемы включают неправильный базовый адрес (должен быть 0x140000000), некорректные характеристики секции (должны быть 0x20000020), неверный виртуальный размер секции и отсутствие правильной подписи PE файла. После внесения этих исправлений ваш PE файл должен успешно запускаться. Для диагностики и предотвращения подобных проблем в будущем рекомендуется использовать специализированные инструменты вроде Winitor или PE-bear, которые помогут детально анализировать структуру PE файлов и выявлять ошибки на ранних этапах разработки.

K

PE формат - это стандарт исполняемых файлов Windows, который включает в себя структуру DOS заголовка, PE заголовка, COFF заголовка и опционального заголовка. Ключевые элементы формата включают относительные виртуальные адреса (RVA), которые представляют адреса элементов в памяти после загрузки минус базовый адрес image файла. Секции являются базовыми единицами кода или данных в PE файлах, а виртуальные адреса (VA) - это полные адреса в адресном пространстве процесса. Для корректной работы PE файла необходимо правильно настроить выравнивания, адрес точки входа и характеристики секций.

Winitor - это специализированный инструмент для анализа и отладки PE файлов Windows. Он позволяет детально изучать структуру исполняемых файлов, выявлять проблемы с форматированием и проверять соответствие PE формата. Инструмент полезен при создании кастомных PE файлов, так как помогает визуализировать структуру, проверить выравнивания, корректность адресов и другие параметры, которые могут вызывать проблемы при запуске. Использование специализированных инструментов является ключевым шагом в диагностике проблем с самодельными PE файлами.

Авторы
K
Технический писатель
Источники
Microsoft Learn / Платформа документации
Платформа документации
Инструмент
Проверено модерацией
НейроОтветы
Модерация
Почему не запускается кастомный x64 PE файл в Windows