Как изменить бинарный файл linux

Обновлено: 06.07.2024

Оригинал: Top Hex Editors for Linux
Автор: Marin Todorov
Дата публикации: 8 февраля 2019 года
Перевод: А. Кривошей
Дата перевода: декабрь 2019 г.

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

Что такое шестнадцатеричный редактор

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

Кто использует шестнадцатеричные редакторы?

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

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

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

1. Xxd Hex Editor

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

Xxd Hex Editor

2. Hexedit Hex Editor

Hexedit - это еще один шестнадцатеричный редактор командной строки, который может быть уже предустановлен в вашей ОС. Hexedit показывает и шестнадцатеричное и ASCII представление файла одновременно.

Hexedit Hex Editor

3. Hexyl Hex Editor

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

Hexyl Hex Editor

Интерфейс Hexyl разделен на три колонки:

- столбец смещения, чтобы указать количество байтов в файле;
- столбец, содержащий шестнадцатеричное представление файла (обратите внимание, что между ними есть граница);
- текстовое представление файла.

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

4. Ghex – шестнадцатеричный редактор для GNOME

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

Ghex

5. Bless Hex Editor

Одним из наиболее продвинутых шестнадцатеричных редакторов в этой статье является Bless , похожий на Ghex, он имеет графический интерфейс, который позволяет редактировать большие файлы данных с многоуровневым механизмом отмены/восстановления. Он также имеет настраиваемые представления данных, функцию поиска-замены и многопоточные операции поиска и сохранения. Несколько файлов могут быть открыты одновременно с помощью вкладок. Функциональность также может быть расширена с помощью плагинов.

Bless

6. Okteta Editor

Okteta - еще один простой редактор для просмотра файлов необработанных данных. Некоторые из основных особенностей Okteta включают в себя:

Okteta

7. wxHexEditor

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

wxHexEditor

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

8. Hexcurse – консольный шестнадцатеричный редактор

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

Hexcurse

9. Hexer Binary Editor

Hexer - еще один бинарный редактор командной строки. Разница в этом заключается в том, что это Vi-подобный редактор. Некоторые из наиболее заметных функций - много буферов, многоуровневая отмена, редактирование командной строки с автозавершением и двоичные регулярные выражения.

HEX-редактор - это приложение, с помощью которого можно просмотреть и отредактировать файл, содержащий двоичные данные (записанные при помощи комбинаций из цифр 0 и 1), перекодировав его в 16-ричный формат.

А поскольку все без исключения файлы хранятся в памяти компьютера именно в таком виде, использование программ, позволяющих работу с HEX, открывает широкие возможности для различных манипуляций с данными (например, для восстановления поврежденных текстовых и графических документов). Некоторые HEX редакторы предназначены для анализа и редактирования данных с HDD и съемных накопителей — их называют редакторами дисков или редакторами секторов.

Рабочее окно стандартного HEX-редактора разделено на три области. Справа расположена так называемая область символов, в центральной части — область 16-ричного кода и слева — область адресов. В наше время пользователям Linux доступно множество таких программ — каждый может выбрать ту, которая окажется максимально полезной в конкретной ситуации. В этой статье мы собрали лучшие hex редакторы linux.

Лучшие HEX редакторы для Linux

Порой информация, которая хранится на каких-либо носителях, повреждается из-за ошибок в работе системы. В таком случае нет смысла изобретать велосипед и придумывать специальную программу для извлечения данных. Гораздо эффективнее будет использование HEX-редактора. Мы отобрали 20 лучших программ и подготовили их обзор.

1. Vim


Vim служит для редактирования текстовых файлов в шестнадцатеричной системе. В работе он задействует внешний инструмент «xxd», который входит в базовый набор некоторых дистрибутивов Linux. Такое «сотрудничество» иногда становится причиной ошибок в работе редактора.

Преобразование файлов происходит после применения команд:

  • :%! xxd — для конвертирования файла в 16-ричный формат;
  • %! xxd -r — для возвращения к исходному варианту.

2. Hexedit Hex Editor

Hexedit — простой и надежный HEX editor linux. Среди прочих выделяется наличием большого количества опций (быстрый поиск и/или сравнение, подсветка символов, EBCDIC, применение цветовых схем, режимы INS/OVR, закладки. отслеживание изменений.

  • Hexedit используется в работе таких функций ПК как макросы, нажатия клавиш, фоновый поиск, редактор дисков и другие.
  • Настройка подсказок, калькулятор, шаблоны. Поддержка файлов, размер которых превышает 4 Гб.
  • Наличие инструментов Auto-hide tool windows (для быстрого скрытия окон) и Docking tool windows (для закрепления окон).
  • По команде пользователя Hexedit может получать доступ к памяти компьютера, всем дискам и файлам.

3. Ghex – GNOME Hex Editor


Ghex — это бесплатный редактор, который кроме 16-ричного формата поддерживает и ASCII. Спектр использования этой программы очень широк, в частности, она позволяет обманывать систему к компьютерных играх и получать дополнительные очки либо жизни для персонажей.

  • Многошаговые команды Undo (отмена) и Redo (повтор).
  • Поиск функций в файлах и их замена.
  • Отслеживание взаимодействий между восьмеричным, двоичным, шестнадцатеричным и десятичным кодами.
  • Настраиваемый MDI.

4. Bless Hex editor


Bless — редактор с открытым исходным кодом, быстрый в работе и простой в настройке. Его интерфейс собран на GTK. Обеспечивает удобную работу с большими файлами, позволяет отменять и повторять действия.

  • Управление при помощи клавиатуры.
  • Функция поиска и замены файлов.
  • Возможность копировать и вставлять текст.
  • Блокировка устройств и редактирование большого количества файлов.

5. Okteta Editor


Изначально это приложение было разработано для программистов, однако, пригодится и обычным пользователям, у которых возникла потребность работать с файлами на уровне байтов и редактировать hex linux.

6. wxHexEditor


Мощный инструмент, поддерживающий различные типы файлов, аксессуары и тэги, размер которых может исчисляться в Эксабайтах (1 Эб = 10 18 байт). В большей степени его использование имеет смысл для программистов.

7. HexCurse


Написан на языке C на основе ncurses. Нравится пользователям из-за наличия большого числа функций. Среди прочего, он позволяет изменять сочетания клавиш, использующиеся для управления программой.

8. Hexer


Бесплатный HEX редактор Linux, который умеет только загружать весь файл целиком, что не позволяет редактировать отдельные блоки. Впрочем, есть у него и преимущества — например, функция редактирования в командной строке, многоуровневая команда отмены (Undo) и множественные буферы.

9. Dhex Hex Editor


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

10. Jeex Hex Editor


Jeex может похвастаться открытым исходным кодом, который был написан на языке Gtk + и опубликован под публичной лицензией GNU. Позволяет выполнять операции в двоичном, восьмеричном, десятичном и шестнадцатеричном форматах. На данный момент является одним из лучших HEX-редакторов.

11. Binary Ninja

Платная программа, написанная на Python и опубликованная под лицензией GPLv2. Особенность этой программы - она рассчитана в первую очередь на реверс-инжиниринг. Все желающие могут скачать демо-версию и в течение 25 минут протестировать Binary Ninja с урезанным количеством опций.

Особенности программы:

  • Графики с синопсисами, позволяющими просмотреть и проанализировать информацию о заданной в данный момент функции.
  • Благодаря подменю, выбранные плагины можно объединять в отдельные группы.
  • Улучшенная работа PE-анализатора и PE-парсера.
  • Доступ к логам осуществляется посредством нажатия на строку с адресом.
  • Binary Ninja помогает найти нужную библиотеку для выполнения той или иной бинарной функции.

12. Fileobj Hex Editor

Fileobj был написан на python и основывается на ncurses. Интерфейс этого HEX-редактора напоминает Vi, соответственно, у этих программ много одинаковых функций. Кроме того, Fileobj умеет выполнять большинство команд Vi, что удобно для пользователей.

13. Joe Hex Editor


Джо — еще один HEX-редактор на ncurses, доступный пользователям Linux. Имеет пользовательский mode-less интерфейс, который весьма прост в использовании. Доступ к справочным материалам предоставляется через специальную кнопку на экране.

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

14. VBdiff Hex Editor

Название этой программы — VBdiff — буквально обозначает «Визуально двоичный diff». Этот бесплатный редактор способен открывать два файла одновременно и может их сравнивать. Умеет работать с большими документами.

15. HexCmp

HexCmp входит в состав программного обеспечения Fairdell. Это удобное приложение для сравнения и редактирования двоичных файлов как в двоичном, так и в 16-ричном форматах.

Выводы

Упомянутые выше HEX редакторы Linux, достаточно часто используются владельцами компьютеров, работающих под этой операционной системой. Некоторые из них более популярны среди специалистов — программистов и разработчиков. Другие приходятся по вкусу тем, кто пользуется подобным ПО лишь от случая к случаю. Тем не менее, можно сказать, что все они достаточно гибкие и функциональные для того, чтобы удовлетворить потребности всех пользователей.

Нет похожих записей


Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна.

Не смотря, на то, что большинство программ в операционной системе Linux (в моем случае Ubuntu) можно установить из Центра приложений, тем самым обеспечивая совместимость с системой, иногда вам может понадобится установить новую версию программы или наоборот, старую, которой может не оказаться в списке.

Такие программы чаще всего распространяются, в формате .bin также известные как бинарные файлы. Бывает, что они запакованы в архив, а иногда как исполняемые файлы. Установка bin linux, может быть произведена через терминал либо же через графический интерфейс. Рассмотрим оба варианта.

Установка bin файлов в Linux

Консольный вариант

1. Для начала в файловом менеджере, нужно найти наш бинарник.

Загрузки_007

2. Откроем терминал, сочетанием клавиш Ctrl+Alt+T.

Терминал_009

3. Зайдем в режим суперпользователя (под рутом). Для этого введем следующую команду в терминале:

Затем нужно ввести пароль.

Терминал_011

4. Теперь, в терминале нам нужно зайти в ту директорию, где расположен наш бинарник. В моем случае это будет так:

Терминал_012

5. Дайте права на выполнение файла .bin, командой:

chmod +x thefile.bin

В моем случае это выглядит так:

chmod +x clip2net.bin

Терминал_014

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

Терминал_015

7. После этой команды, установщик программы запустился и спрашивает меня на каком языке я хотел бы установить bin файл в linux.

Language Selection_016

8. Далее устанавливаем программу как обычно это делается в ОС Windows.

Установка_017

Графический вариант

Он ненамного проще, но для новичков, которые недавно перешли с Windows будет понятнее. Первые 3 пункта из консольного варианта все же придется выполнить. Затем нужно выбрать файл, нажать правой кнопкой мыши, выбрать пункт "свойства". На вкладке права, нужно поставить галочку напротив пункта "Разрешить выполнение файла как программы".

Свойства «clip2net.bin»_018

Закрываем окно. И перетаскиваем этот файл в терминал, запущенный от суперпользователя, имя файла и путь уже впишутся автоматически, остается лишь нажать на кнопку "Enter". Далее, вы можете установить bin файл, как и в первом варианте. На этом все.

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

Я не думаю, что есть любой способ, чтобы сделать это. Форматы машинного кода очень сложны, сложнее, чем файлы сборки. На самом деле невозможно взять скомпилированный двоичный файл (скажем, в формате ELF) и создать исходную программу сборки, которая будет компилироваться в тот же (или аналогичный) двоичный файл. Чтобы получить представление о различиях, сравните результат компиляции GCC непосредственно с ассемблером ( gcc -S ) против выхода из objdump на исполняемый ( objdump -D ).

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

например, рассмотрим код C для Hello world:

это компилируется в код сборки x86:

где .LCO-именованная константа, а printf-символ в таблице символов общей библиотеки. Сравните с выходом objdump:

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

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

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

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

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

если вы заинтересованы в изменении лишь малая раздел исполняемого файла, я рекомендую гораздо более тонкий подход, чем перекомпиляция всего приложения. Используйте objdump для получения кода сборки для интересующей вас функции(функций). Преобразуйте его в" синтаксис исходной сборки " вручную (и здесь я хотел бы, чтобы был инструмент, который фактически произвел разборку в том же синтаксисе, что и вход), и измените его, как вы хотите. Когда вы закончите, перекомпилируйте только эти функции и используйте objdump, чтобы выяснить машинный код для измененной программы. Затем, используйте шестнадцатеричный редактор, чтобы вручную вставить новый машинный код поверх соответствующей части исходной программы, заботясь о том, чтобы ваш новый код был точно таким же количеством байтов, как и старый код (или все смещения были бы неправильными). Если новый код короче, вы можете заполнить его с помощью инструкций NOP. Если это дольше, вы можете быть в беде, и, возможно, придется создавать новые функции и вызывать их вместо этого.

для изменения кода внутри двоичной сборки обычно существует 3 способа сделать это.

конечно, только 2-й будет работать, если сборка выполняет какую-либо проверку целостности.

Edit: если это не очевидно, то игра с бинарными сборками-это очень высокий уровень разработчика, и вам будет трудно спросить об этом здесь, если это не действительно конкретные вещи, которые вы спрашиваете.

@mgiuca правильно рассмотрел этот ответ с технической точки зрения. На самом деле, разборка исполняемой программы в простой для перекомпиляции источник сборки не является легкой задачей.

, чтобы добавить некоторые биты к обсуждению, есть несколько методов/инструментов, которые могут быть интересны для изучения, хотя они технически сложные.

  1. статические / динамические приборы. Этот метод предполагает анализ исполняемого формата, вставьте/удалите / замените конкретные инструкции по сборке для данной цели, исправьте все ссылки на переменные / функции в исполняемом файле и испустите новый измененный исполняемый файл. Некоторые инструменты, о которых я знаю: PIN-код, удалить, PEBIL, DynamoRIO. Считайте, что настройка таких инструментов для целей, отличных от тех, для которых они были разработаны, может быть сложной и требует понимания как исполняемых форматов, так и инструкций наборы.
  2. полная исполняемая декомпиляция. Этот метод пытается восстановить полный источник сборки из исполняемого файла. Возможно, вы захотите взглянуть на Онлайн Дизассемблер, который пытается выполнить задание. Вы теряете информацию о различных исходных модулях и, возможно, функциях/именах переменных.
  3. Переназначаемая декомпиляции. Этот метод пытается извлечь дополнительную информацию из исполняемого файла, глядя на отпечатки пальцев компилятора (т. е., шаблоны кода, созданного известными компиляторами) и другие детерминированные вещи. Основная цель-восстановить исходный код более высокого уровня, например c source, из исполняемого файла. Иногда это позволяет восстановить информацию об именах функций / переменных. Считайте, что компиляция источников с -g часто обеспечивает лучший результат. Возможно, вы захотите дать Retargetable Decompiler попробовать.

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

миазм

это, по-видимому, наиболее перспективное конкретное решение. Согласно описанию проекта, Библиотека может:

  • Открытие / изменение / генерация PE / ELF 32 / 64 LE / be с помощью Elfesteem
  • сборка / разборка X86 / ARM / MIPS / SH4 / MSP430

так и должно в основном:

  • разберите эльфа на внутреннее представление (разборка)
  • изменить то, что вы хотите
  • создать новый ELF (сборка)

Я не думаю, что это создает текстовое представление разборки, вам, вероятно, придется пройти через структуры данных Python.

I думаю, эта проблема не является автоматизируемой

Я думаю, что общая проблема не полностью автоматизирована, и общее решение в основном эквивалентно "как перепроектировать" двоичный файл.

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

в формальных терминах нам нужно извлечь график потока управления двоичного файла.

еще одна вещь, которую вам может быть интересно сделать:

  • binary instrumentation-изменение существующего кода

Если интересно, проверьте: Pin, Valgrind (или проекты, делающие это: NaCl - родной клиент Google, возможно, QEmu.)

вы можете запустить исполняемый файл под контролем ptrace (другими словами, отладчика, такого как gdb) и таким образом контролировать выполнение по мере его выполнения, не изменяя фактический файл. Конечно, требует обычных навыков редактирования как найти где конкретные инструкции ты хочешь повлиять в исполняемый.

я делаю это с hexdump и текстовый редактор. Вы должны быть действительно удобный с машинным кодом и форматом файла, хранящим его, и гибкий с тем, что считается "разбирать, изменять, а затем собирать".

Если Вам сойдет с рук только "точечные изменения" (переписывание байтов, но не добавление и удаление байтов), это будет легко (относительно говоря).

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

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

Шаг 0 (подготовка)

после на самом деле правильно разобрал файл с помощью objdump -D или все, что вы обычно используете сначала, чтобы действительно понять его и найти места, которые вам нужно изменить, вам нужно будет принять к сведению следующие вещи, чтобы помочь вам найти правильные байты для изменения:

  1. "адрес" (смещение от начала файла) байт нужно менять.
  2. необработанное значение этих байтов, как в настоящее время они (the до objdump очень полезно здесь).

Шаг 1

дамп необработанное шестнадцатеричное представление двоичного файла с hexdump -Cv .

Шаг 2

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

быстрый ускоренный курс в hexdump -Cv выход:

  1. самый левый столбец-это адреса байтов (относительно начала двоичного файла сам файл, как и objdump предоставляет).
  2. самый правый столбец (в окружении | символы) - это просто "читаемое человеком" представление байтов-символ ASCII, соответствующий каждому байту, записывается там, с . standing in для всех байтов, которые не сопоставляются с печатаемым символом ASCII.
  3. важный материал находится между-каждый байт в виде двух шестнадцатеричных цифр, разделенных пробелами, 16 байт на строку.

Осторожно: В Отличие От objdump -D , который дает вам адрес каждой инструкции и показывает необработанный шестнадцатеричный код инструкции, основанный на том, как он задокументирован как закодированный, hexdump -Cv сбрасывает каждый байт точно в том порядке, в котором он появляется в файле. Это может быть немного запутанным, так как сначала на машинах, где байты инструкций находятся в противоположном порядке из-за различий endianness, которые также могут дезориентировать, когда вы ожидаете определенный байт в качестве определенного адреса.

Шаг 3

изменить байты, которые нужно изменить-Вам, очевидно, нужно выяснить кодировку команды raw machine (а не мнемонику сборки) и вручную записать в правильные байты.

Примечание:не надо менять удобочитаемый в самой правой колонке. hexdump проигнорирует его, когда вы "сбросите" его.

Шаг 4

"Un-dump" измененный файл hexdump с помощью hexdump -R .

Шаг 5 (здравомыслие проверка)

objdump ваш новый un hexdump ed файл и убедитесь, что разборка, которую вы изменили, выглядит правильно. diff против objdump оригинала.

серьезно, не пропустите этот шаг. Я делаю ошибку чаще всего при ручном редактировании машинного кода, и именно так я ловлю большинство из них.

пример

вот реальный пример работы, когда я недавно изменил двоичный файл ARMv8 (little endian). (Я знаю, вопрос помечен x86 , но у меня нет примера x86, и фундаментальные принципы одинаковы, просто инструкции разные.)

в моей ситуации мне нужно было отключить конкретную проверку" вы не должны этого делать": в моем примере binary, in objdump --show-raw-insn -d вывод строки, о которой я заботился, выглядел так (одна инструкция до и после контекста):

как вы можете видеть, наша программа "услужливо" выходит, прыгая в error функция (которая завершает программу). Неприемлемый. Поэтому мы собираемся превратить эту инструкцию в запрет. Итак, мы ищем байты 0x97fffeeb по адресу / файлу-offset 0xf44 .

здесь hexdump -Cv строка, содержащая это смещение.

обратите внимание, как соответствующие байты на самом деле перевернуты (небольшая эндианская кодировка в архитектуре применяется к машинным инструкциям, как и ко всему остальному) и как это немного неинтуитивно относится в какой байт на какой байт смещение:

во всяком случае, я знаю, глядя на другие разборки, что 0xd503201f демонтирует к nop так что это кажется хорошим кандидатом для моей инструкции no-op. Я изменяет строку в hexdump ed файл соответственно:

преобразуется обратно в двоичный файл с hexdump -R , разобран новый двоичный файл с objdump --show-raw-insn -d и проверил, что изменение было правильным:

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

изменение машинного кода успешно.

или мне это удалось? Вы заметили, что я пропустил в этом примере?

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

весь код после ветви был сгенерирован компилятором при условии, что состояние программы было как это было до условного перехода! Но, просто сделав последний прыжок в error код функции a no-op, я создал путь кода, где мы достигаем этого кода с несогласованным / неправильным состоянием программы!

в моем случае, это на самом деле казалось не вызывает никаких проблем. Так что мне повезло. очень lucky: только после того, как я уже запустил свой модифицированный двоичный файл (который, кстати, был безопасность-критические бинарные: у него была возможность setuid , setgid , и изменить контекст SELinux!) понял ли я, что забыл проследить пути кода, повлияли ли эти изменения регистра на пути кода, которые пришли позже!

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

что делать, если бы я вызывал функцию, где аргументы проливались из регистров в стек (как это очень распространено, например, на x86)? Что, если на самом деле несколько условных инструкций в наборе инструкций, предшествовавшем условному прыжку (как это обычно, например, в более старых версиях ARM)? Я был бы в еще более безрассудно непоследовательном состоянии после того, как сделал это самое простое-кажущееся изменение!

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

Итак, как мы исправим это более правильно? Читайте дальше.

Удаление Кода

до эффективно/логически "удалить" более одной инструкции, вы можете заменить первую инструкцию, которую вы хотите "удалить" с безусловным переходом к первой инструкции в конце инструкции "удалены". Для этого двоичного файла ARMv8 это выглядело так:

в принципе, вы" убиваете " код (превратите его в "мертвый код"). Sidenote: вы можете сделать что-то подобное с литеральными строками, встроенными в двоичный файл: пока вы хотите заменить его на меньшую строку, вы почти всегда можете избежать перезаписи строки (включая завершающий нулевой байт, если это "c-строка") и при необходимости перезаписать жестко закодированный размер строки в машине код, который его использует.

вы также можете заменить все нежелательные инструкции на no-ops. Другими словами, мы можем превратить нежелательный код в то, что называется "no-op sled":

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

чтобы быть ясным, ошибка проста: я испортил два (2) раз при ручном кодировании этой безусловной инструкции ветви. И это не всегда наша вина: в первый раз это было потому, что документация, которую я имел, была устаревшей/неправильной и сказала, что один бит был проигнорирован в кодировке, когда это на самом деле не было, поэтому я установил его на ноль с первой попытки.

добавить Код

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

С точки зрения машинного кода это просто: выберите одну инструкцию в том месте, где вы хотите добавить код, и преобразуйте ее в инструкцию прыжка в новый код, который вам нужно добавить (не забудьте добавить инструкции), которые вы таким образом заменили в новый код, если вам это не нужно для вашей добавленной логики, и вернуться к инструкции, к которой вы хотите вернуться в конце добавления). В принципе, вы" соединяете " новый код.

но вы должны найти место, чтобы сделать новый код, и это самое трудное.

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

по моему опыту hexdump -R игнорирует не только самый правый столбец, но и самый левый столбец, поэтому вы можете буквально просто поместить нулевые адреса для всех добавленных вручную строк, и это сработает.

Если вам повезло меньше, после добавления кода вам придется фактически настроить некоторые значения заголовка в том же файле: если загрузчик для ваша операционная система ожидает, что двоичный файл будет содержать метаданные, описывающие размер исполняемого раздела (по историческим причинам, часто называемым разделом "текст"), который вам нужно будет найти и настроить. В старые времена двоичные файлы были просто сырым машинным кодом - в настоящее время машинный код завернут в кучу метаданных (например, ELF в Linux и некоторых других).

Если вам все еще немного повезло, у вас может быть какое-то "мертвое" место в файле, которое правильно загружается как часть двоичный файл с теми же относительными смещениями, что и остальной код, который уже находится в файле (и это мертвое место может соответствовать вашему коду и правильно выровнено, если ваш процессор требует выравнивания слов для инструкций процессора). Затем вы можете перезаписать его.

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

Читайте также: