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

Тема в разделе "FASM", создана пользователем Mikl___, 9 дек 2016.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.308
    Создание заплаток на ассемблере FASM — Архив WASM.RU

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

    Вложения:

    • patchbyfasm.zip
      Размер файла:
      22,3 КБ
      Просмотров:
      803
    Последнее редактирование: 9 дек 2016
    Demon13 и rococo795 нравится это.