Создание заплаток на ассемблере FASM — Архив WASM.RU
Содержание
- Введение
- Бинарные файлы
- Файлы формата PE
- Заключение
Введение
Аналогичным англоязычным названием является - "patch", но использовать я буду отечественный вариант "заплатка".
Рассматривать мы будем создание заплаток для бинарных файлов и исполняемых файлов формата PE. Способ подходит как для изменения нескольких байт, так и для создания подпрограмм реализующих дополнительную функциональность.
Основной инструмент - FlatAssembler. Компилятор генерирует очень компактный код и предоставляет абсолютный контроль над размещением данных.
Дополнительная особенность - это ужаснейщий препроцессор.
Также потребуется программа, которая запищет изменения.
Принцип работы достаточно прост, все изменения описываются в исходном файле, после компиляции выходной файл и вывод препроцессора используются программой правки для внесения изменений.
Исходный файл с описанием изменений ничем не отличается от обыкновенной программы на ассемблере, единственное, блок кода/данных нужно заключать в макрокоманды __setorg/__mkdiff. Первая определяет положение в файле, по которому будет записан блок, а вторая определяет конец блока.
Бинарные файлы
При изменении бинарного файла, положение установленное макрокомандой __setorg в точности совпадает с позицией в реальном файле.
Также можно использовать ассемблер и изменять значения счетчика команд.Код (Text):
; Файл 1.asm ; Определить строку "Hello" начиная с 8-го байта include 'patchit.inc' ; Определение макрокоманд __setorg 8 ; Устанавливаем позицию в файле db 'Hello' ; Определяем данные __mkdiff ; Принять измененияНапример, нам требуется изменить *.com программу так, чтобы при запуске управление передовалось нашей подпрограмме.
Код (Text):
; Файл 2.asm ; Изменение инструкций *.com программы include 'patchit.inc' ; Изменить первую инструкцию __setorg 0 org $100 ; адрес по которому загружается программа jmp $120 ; передать управление по адресу $120 __mkdiff ; Подпрограмма выводит на консоль cтроку текста __setorg $20 ; переместить положение в файле org $120 ; установить адрес mov ah,13h mov al,1 xor bh,bh mov bl,07h xor dx,dx mov bp,msg_text mov cx,msg_size int $10 ret msg_text: dw 'Hello sailor!' msg_size = $ - msg_text __mkdiffВ дополнение можно рассказать о нескольких особенностях использования.
Изменять небольшие участки удобно макрокомандой __mkchng, она заменят набор команд __setorg/__mkdiff если требуется изменить всего одну строку.
Код (Text):
; Файл 3.asm ; Пример использования __mkchng include 'patchit.inc' __mkchng 10, <db 'Hello'> ; Заменяется на ; __setorg 10 ; db 'Hello' ; __mkdiffДля контроля выхода за пределы файла можно использовать макродирективу __maxorg, при этом необходимо указать размер файла непосредственно в байтах, либо полный или относительный путь к файлу, тогда макрос сам вычислит размер. Превышение этого значения приведет к ощибке компиляции.
Код (Text):
; Файл 4.asm ; Пресечение выхода за границу файла include 'patchit.inc' __maxorg 2 ; максимальный размер 2 байта __mkchng 0, <db 1,2,3> ; error 'выход за границу файла' ; Аналогичный способ если доступен файл __maxorg '1.asm' __mkchng 10000,<db 'ups!'> ; error 'выход за границу файла'Файлы формата PE
Правка исполняемых файлов особенно утомительный процесс, так как значение адресов и смещений запущенной программы не соответствует их положению в файле.
И для того чтобы узнать позицию инструкции в файле(RVA) по адресу памяти(VA), нужно произвести вычисление вида:
Код (Text):
RVA_секции + VA_базы - VA_инструкцииИспользуя макроопределения можно достаточно реально воспроизвести ситуацию, когда при написании кода вам необходимо знать только адрес в памяти(VA), тогда как программа, используя информацию о файле, сама вычислит действительный адрес инструкции(RVA).
Используя макроопределения ситуация упрощается, устанавливать положение маркера можно по виртуальному адресу.Все, что потребуется - это используя макродирективу __format_pe указать основные характеристики - базовый адрес загрузки и секции. Описание секции состоит из трех параметров "VA RA N". Где, VA - относительный адрес секции в памяти, RA - позиция секции в файле, N - реальный размер секции в байтах.
Узнать значения можно постмотрев заголовок файла в отладчике или специальной программомой для работы c файлами формата PE(я использовал PeID).
Код (Text):
; Файл 5.asm ; Пример изменения PE файла include 'patchit.inc' __format_pe $400000,\ ; Базовый адрес загрузки (ImageBase) $1000, $400, $200,\ ; Секция кода '.code' $2000, $600, $200 ; Секция данных '.data' ; Адреса импортируемых функци _MessageBoxA = $403044 _ExitProcess = $40303C __setorg $401000 push 0 push dword caption push dword message push 0 call dword [_MessageBoxA] push 0 call dword [_ExitProcess] __mkdiff __setorg $402000 message db 'The file was patched by unknown hacker',0 caption db 'Attention!' __mkdiffТеперь положение в файле вычисляется по виртуальному адресу. Выход за пределы секции контролируется и вызывает ошибку компиляции.
Заключение
Программа правки и примеры находятся в приложении к статье. В качестве дополнительного описания могу посоветовать только исходный код, он достаточно небольшой.
Хочется поблагодарить товарища Tomasz Grysztar за отличний ассемблер, кодеров с wasm.ru и flatassembler.net/board
Исходники к статье.
Сайт автора - www.assert.i8.com.
© Smile
Создание заплаток на ассемблере FASM
Дата публикации 21 июн 2006