1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Создание заплаток на ассемблере FASM

Дата публикации 21 июн 2006

Создание заплаток на ассемблере FASM — Архив WASM.RU

Содержание

  • Введение
  • Бинарные файлы
  • Файлы формата PE
  • Заключение

Введение

Аналогичным англоязычным названием является - "patch", но использовать я буду отечественный вариант "заплатка".

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

Основной инструмент - FlatAssembler. Компилятор генерирует очень компактный код и предоставляет абсолютный контроль над размещением данных.

Дополнительная особенность - это ужаснейщий препроцессор.

Также потребуется программа, которая запищет изменения.

Принцип работы достаточно прост, все изменения описываются в исходном файле, после компиляции выходной файл и вывод препроцессора используются программой правки для внесения изменений.

Исходный файл с описанием изменений ничем не отличается от обыкновенной программы на ассемблере, единственное, блок кода/данных нужно заключать в макрокоманды __setorg/__mkdiff. Первая определяет положение в файле, по которому будет записан блок, а вторая определяет конец блока.

Бинарные файлы

При изменении бинарного файла, положение установленное макрокомандой __setorg в точности совпадает с позицией в реальном файле.

Код (Text):
  1.  
  2.     ; Файл 1.asm
  3.     ; Определить строку "Hello" начиная с 8-го байта
  4.  
  5.     include 'patchit.inc'   ; Определение макрокоманд
  6.  
  7.     __setorg 8              ; Устанавливаем позицию в файле
  8.     db 'Hello'      ; Определяем данные
  9.     __mkdiff                ; Принять изменения
Также можно использовать ассемблер и изменять значения счетчика команд.

Например, нам требуется изменить *.com программу так, чтобы при запуске управление передовалось нашей подпрограмме.

Код (Text):
  1.  
  2.     ; Файл 2.asm
  3.     ; Изменение инструкций *.com программы
  4.  
  5.     include 'patchit.inc'
  6.  
  7.     ; Изменить первую инструкцию
  8.     __setorg 0
  9.     org $100        ; адрес по которому загружается программа
  10.     jmp $120        ; передать управление по адресу $120
  11.     __mkdiff
  12.  
  13.     ; Подпрограмма выводит на консоль cтроку текста
  14.     __setorg $20        ; переместить положение в файле
  15.     org $120        ; установить адрес
  16.     mov ah,13h
  17.     mov al,1
  18.     xor bh,bh
  19.     mov bl,07h
  20.     xor dx,dx
  21.     mov bp,msg_text
  22.     mov cx,msg_size
  23.     int $10
  24.     ret
  25.     msg_text: dw 'Hello sailor!'
  26.     msg_size = $ - msg_text
  27.     __mkdiff

В дополнение можно рассказать о нескольких особенностях использования.

Изменять небольшие участки удобно макрокомандой __mkchng, она заменят набор команд __setorg/__mkdiff если требуется изменить всего одну строку.

Код (Text):
  1.  
  2.     ; Файл 3.asm
  3.     ; Пример использования __mkchng
  4.  
  5.     include 'patchit.inc'
  6.  
  7.     __mkchng 10, <db 'Hello'>
  8.     ; Заменяется на
  9.     ; __setorg 10
  10.     ; db 'Hello'
  11.     ; __mkdiff

Для контроля выхода за пределы файла можно использовать макродирективу __maxorg, при этом необходимо указать размер файла непосредственно в байтах, либо полный или относительный путь к файлу, тогда макрос сам вычислит размер. Превышение этого значения приведет к ощибке компиляции.

Код (Text):
  1.  
  2.     ; Файл 4.asm
  3.     ; Пресечение выхода за границу файла
  4.  
  5.     include 'patchit.inc'
  6.     __maxorg 2      ; максимальный размер 2 байта
  7.     __mkchng 0, <db 1,2,3>    ; error 'выход за границу файла'
  8.  
  9.     ; Аналогичный способ если доступен файл
  10.     __maxorg '1.asm'
  11.     __mkchng 10000,<db 'ups!'> ; error 'выход за границу файла'

Файлы формата PE

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

И для того чтобы узнать позицию инструкции в файле(RVA) по адресу памяти(VA), нужно произвести вычисление вида:

Код (Text):
  1.  
  2.     RVA_секции + VA_базы - VA_инструкции

Используя макроопределения можно достаточно реально воспроизвести ситуацию, когда при написании кода вам необходимо знать только адрес в памяти(VA), тогда как программа, используя информацию о файле, сама вычислит действительный адрес инструкции(RVA).

Используя макроопределения ситуация упрощается, устанавливать положение маркера можно по виртуальному адресу.

Все, что потребуется - это используя макродирективу __format_pe указать основные характеристики - базовый адрес загрузки и секции. Описание секции состоит из трех параметров "VA RA N". Где, VA - относительный адрес секции в памяти, RA - позиция секции в файле, N - реальный размер секции в байтах.

Узнать значения можно постмотрев заголовок файла в отладчике или специальной программомой для работы c файлами формата PE(я использовал PeID).

Код (Text):
  1.  
  2.         ; Файл 5.asm
  3.         ; Пример изменения PE файла
  4.  
  5.         include 'patchit.inc'
  6.  
  7.         __format_pe $400000,\           ; Базовый адрес загрузки (ImageBase)
  8.                 $1000, $400, $200,\     ; Секция кода '.code'
  9.                 $2000, $600, $200       ; Секция данных '.data'
  10.  
  11.         ; Адреса импортируемых функци
  12.         _MessageBoxA = $403044
  13.         _ExitProcess = $40303C
  14.  
  15.         __setorg $401000
  16.         push 0
  17.         push dword caption
  18.         push dword message
  19.         push 0
  20.         call dword [_MessageBoxA]
  21.         push 0
  22.         call dword [_ExitProcess]
  23.         __mkdiff
  24.  
  25.  
  26.         __setorg $402000
  27.          message db 'The file was patched by unknown hacker',0
  28.          caption db 'Attention!'
  29.         __mkdiff

Теперь положение в файле вычисляется по виртуальному адресу. Выход за пределы секции контролируется и вызывает ошибку компиляции.

Заключение

Программа правки и примеры находятся в приложении к статье. В качестве дополнительного описания могу посоветовать только исходный код, он достаточно небольшой.

Хочется поблагодарить товарища Tomasz Grysztar за отличний ассемблер, кодеров с wasm.ru и flatassembler.net/board

Исходники к статье.

Сайт автора - www.assert.i8.com.

© Smile

0 852
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532