RawrXD PE Writer - Полная реализация
Обзор
Это полный PE32+ писатель и эмиттер машинного кода, реализованный на чистом ассемблере x64 MASM без зависимостей и без использования CRT. Он генерирует исполняемые Windows-файлы с нуля.
Архитектура
PE-писатель следует подходу бэкенд-дизайна, предоставляя чистый API для:
- Создания контекстов PE-исполняемых файлов
- Добавления импортов с правильными структурами IAT/INT
- Эмиссии машинного кода с управлением секциями
- Записи полных PE-файлов со всеми необходимыми заголовками
Основные компоненты
1. Определенные структуры
- IMAGE_DOS_HEADER: Стандартный DOS-заголовок с указателем e_lfanew
- IMAGE_NT_HEADERS64: NT-заголовки с файловым заголовком и дополнительным заголовком
- IMAGE_SECTION_HEADER: Заголовки секций для .text, .rdata, .idata
- IMAGE_IMPORT_DESCRIPTOR: Дескрипторы таблицы импорта
- PE_CONTEXT: Внутренняя структура контекста для создания PE-файлов
2. Ключевые функции
PEWriter_CreateExecutable
- Вход: RCX = базовый адрес образа (0 = по умолчанию), RDX = RVA точки входа
- Выход: RAX = дескриптор контекста PE (0 = ошибка)
- Назначение: Выделяет и инициализирует полную структуру контекста PE
Детали реализации:
- Выделяет память для DOS-заголовка, NT-заголовков, заголовков секций
- Инициализирует DOS-заголовок с правильной сигнатурой и e_lfanew
- Настраивает NT-заголовки с типом машины AMD64 и магией PE32+
- Настраивает дополнительный заголовок с базовым адресом образа, выравниванием секций/файлов
- Выделяет буфер кода и таблицы импорта
- Устанавливает виртуальные адреса и смещения файлов по умолчанию
PEWriter_AddImport
- Вход: RCX = контекст PE, RDX = имя DLL, R8 = имя функции
- Выход: RAX = 1 успех, 0 ошибка
- Назначение: Создает таблицу импорта с правильными структурами IAT/INT
Детали реализации:
- Управляет дескрипторами импорта для нескольких DLL
- Создает записи таблицы поиска импорта (INT)
- Настраивает записи таблицы адресов импорта (IAT)
- Обрабатывает структуры импорта по имени
- Отслеживает количество импортов и проверяет ограничения
PEWriter_AddCode
- Вход: RCX = контекст PE, RDX = буфер кода, R8 = размер кода
- Выход: RAX = RVA кода (0 = ошибка)
- Назначение: Обрабатывает эмиссию машинного кода с правильным управлением секциями
Детали реализации:
- Копирует машинный код во внутренний буфер
- Проверяет размер кода на соответствие максимальным ограничениям
- Вычисляет и возвращает RVA для кода
- Обновляет внутренний учет размера кода
- Управляет содержимым секции .text
PEWriter_WriteFile
- Вход: RCX = контекст PE, RDX = имя файла
- Выход: RAX = 1 успех, 0 ошибка
- Назначение: Полная запись файла со всеми заголовками, секциями и таблицей импорта
Детали реализации:
- Создает выходной файл с помощью соответствующих вызовов Win32 API
- Записывает DOS-заголовок и DOS-заглушку
- Вычисляет и обновляет финальные значения NT-заголовка
- Записывает заголовки секций для .text, .rdata, .idata
- Реализует правильное заполнение и выравнивание файла
- Записывает данные секций с таблицей импорта
- Обрабатывает все вычисления RVA и смещения файлов
Управление памятью
Реализация использует Windows heap API:
- GetProcessHeap(): Получает кучу текущего процесса
- HeapAlloc(): Выделяет память, инициализированную нулями
- HeapFree(): Освобождает выделенную память при очистке
Все выделения памяти включают правильную обработку ошибок и очистку.
Структура файла
DOS Header (64 bytes)
DOS Stub (variable size, padded to 0x80)
NT Headers (248 bytes for PE32+)
Section Headers (40 bytes * 3 sections)
Padding to file alignment (0x400)
.text Section (code)
- Machine code
- Padded to file alignment
.rdata Section (read-only data)
- String constants, resources
- Padded to file alignment
.idata Section (import data)
- Import descriptors
- Import lookup table
- Import address table
- Import by name structures
- Padded to file alignment
Расположение виртуальных адресов
0x1000: .text section (SECTION_ALIGNMENT)
0x2000: .rdata section
0x3000: .idata section
0x4000: Next available virtual address
Константы и значения по умолчанию
- Базовый адрес образа: 0x140000000 (по умолчанию для x64)
- Выравнивание секций: 0x1000 (4 КБ)
- Выравнивание файла: 0x200 (512 байт)
- Точка входа: Настраиваемый RVA
- Подсистема: Консольное приложение (IMAGE_SUBSYSTEM_WINDOWS_CUI)
Пример использования
; Create PE context
mov rcx, 0 ; Default image base
mov rdx, 1000h ; Entry point RVA
call PEWriter_CreateExecutable
mov rbx, rax ; Save context
; Add kernel32.dll imports
mov rcx, rbx
mov rdx, offset dll_kernel32
mov r8, offset func_GetStdHandle
call PEWriter_AddImport
; Add machine code
mov rcx, rbx
mov rdx, offset code_buffer
mov r8, code_size
call PEWriter_AddCode
; Write executable file
mov rcx, rbx
mov rdx, offset filename
call PEWriter_WriteFile
Инструкции по сборке
- Убедитесь, что MASM64 и Windows SDK установлены
- Запустите
build.bat для компиляции PE-писателя и примера
- Выполните
PE_Writer_Example.exe для генерации hello.exe
- Протестируйте сгенерированный исполняемый файл
Обработка ошибок
Все функции возвращают 0 при ошибке и ненулевое значение при успехе. Реализация включает:
- Проверки сбоев выделения памяти
- Обработка ошибок ввода-вывода файлов
- Проверка входных данных
- Правильная очистка ресурсов
- Проверка границ буферов
Ограничения
- Максимум 99 импортов (MAX_IMPORTS - 1)
- Максимальный размер кода 64 КБ (MAX_CODE_SIZE)
- Три фиксированные секции (.text, .rdata, .idata)
- Только консольная подсистема
- Нет поддержки перемещений
- Нет цифровых подписей
Расширенные возможности
Реализация предоставляет прочную основу для:
- Создания пользовательских секций
- Сложного связывания импортов
- Встраивания ресурсов
- Цифровой подписи
- Поддержки перемещений
- Таблиц обработки исключений
Технические примечания
- Чистый ассемблер x64 MASM - без зависимостей CRT
- Использует кучу Windows для управления памятью
- Генерирует формат PE32+ для x64
- Совместим с Windows Vista и более поздними версиями
- Следует спецификации PE от Microsoft
- Нулевые зависимости от внешних библиотек, кроме kernel32.dll
Эта реализация предоставляет полный, готовый к использованию PE32+ писатель, подходящий для бэкендов генерации кода, пользовательских компиляторов и упаковщиков исполняемых файлов.