Аналог objdump для windows

Обновлено: 07.07.2024

Список программ для работы с двоичными файлами в операционной системе Linux .

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

Objdump

Objdump из GNU binutils . Дамп объекта ( objdump ) - простое и понятное решение для быстрого дизассемблирования программного кода. Objdump отлично подходит для дизассемблирования простых и неповреждённых двоичных файлов, но все его ограничения сразу выплывут на поверхность при попытке использовать objdump для любого, действительно сложного реверса, особенно в ситуациях, использования данной программы против вредоносного ПО. Основная слабость objdump заключается в том, что он, в своей работе, полностью полагается на заголовки раздела ELF и не выполняет необходимый анализ нижнего уровня управления . Оба эти ограничения значительно снижают надёжность программы , что приводит к невозможности правильно дизассемблировать код внутри двоичного файла, а возможно, что даже к возникновению ошибок при простой попытке открыть двоичный файл, не имеющий в своей структуре заголовков разделов. Однако, для многих простых и обычных задач, он идеально подходит . Например, при дизассемблировании обычных двоичных файлов , которые не расширяются , не удаляются , не используют обфускацию . Он может читать все распространенные типы двоичных ELF файлов. Вот несколько примеров использования программы objdump :

• Просмотрите все данные / код в каждом разделе файла ELF:

objdump -D <elf_object>

• Просмотр только программного кода в файле ELF:

objdump -d <elf_object>

• Просмотреть все символы:

objdump -tT <elf_object>

Objcopy

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

Пример использования objcopy :

Для копирования секции .data из объекта ELF в файл , используйте следующую команду:

objcopy –only-section=.data <infile> <outfile>

Strace

Трассировка системного вызова ( strace ) - это инструмент, основанный на системном вызове ptrace (2) , он

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

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

Команда strace , используемая для трассировки базовой программы :

strace / bin / ls -o ls.out

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

strace -p <pid> -o daemon.out

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

SYS_read (2, buf, sizeof (buf));

Если вы хотите увидеть все данные, которые считывались в дескриптор файла 2 , вы можете выполнить следующую команду:

strace -e read = 2 / bin / ls

Вы также можете использовать параметр -e write = fd для просмотра записанных данных . Программа strace - отличный инструмент, и у вас, несомненно, будет целый ряд причин, чтобы его использовать.

ltrace

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

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

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

Пример использования ltrace :

ltrace <program> -o program.out

ftrace

Функция трассировки ( ftrace ) - это инструмент, очень похожий на ltrace , он

показывает вызовы функций внутри самого двоичного файла .

Readelf

Программа readelf - это пожалуй, один из самых полезных инструментов для анализа двоичных файлов формата ELF. Readelf анализирует каждый бит данных, используемый в формате ELF и позволяет получить большое количество информации об объекте ещё до его реверс инжиниринга . Readelf используется для сбора информации о символах , сегментах , разделах , записях релокации , динамическом связывании данных и ещё много другой полезной информации. Команда readelf - это

Швейцарский армейский нож для файлов формата ELF .

Примеры некоторых из наиболее часто используемых функций readelf:

readelf -S <object>

readelf -l <object>

readelf -s <object>

  • Получение данных заголовка файла формата ELF:

readelf -e <object>

readelf -r <object>

readelf -d <object>

Послесловие

А какие программы для анализа бинарных файлов в операционной системе Linux знаете и используете Вы? Поделитесь своим личным опытом и расскажите об этом в комментариях !

image

На русском языке довольно мало информации про то, как работать с ELF-файлами (Executable and Linkable Format — основной формат исполняемых файлов Linux и многих Unix-систем). Не претендуем на полное покрытие всех возможных сценариев работы с эльфами, но надеемся, что информация будет полезна в виде справочника и сборника рецептов для программистов и реверс-инженеров.

Подразумевается, что читатель на базовом уровне знаком с форматом ELF (в противном случае рекомендуем цикл статей Executable and Linkable Format 101).

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

— Я тоже эльф… Синий в красный… Эльфы очень терпеливы… Синий в красный… А мы эльфы. Синий в красный… От магии одни беды…
(с) Маленькое королевство Бена и Холли

В большинстве случаев примеры можно выполнить как на Linux, так и на Windows.

В рецептах мы будем использовать следующие инструменты:

  • утилиты из набора binutils (objcopy, objdump, readelf, strip);
  • фреймворк radare2;
  • hex-редактор с поддержкой шаблонов файлов (в примерах показан 010Editor, но можно использовать, например, свободный Veles);
  • Python и библиотеку LIEF;
  • другие утилиты (ссылки указаны в рецепте).

В качестве «подопытного» будем использовать ELF-файл simple из таска nutcake's PieIsMyFav на crackmes.one, но подойдёт любой представитель «эльфийского» семейства. Если готовый файл с требуемыми характеристиками не был найден в свободном доступе, то будет приведён способ создания такого эльфа.

«Свободных» эльфов можно также найти по ссылкам:

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

Тип файла, заголовок, секции

В зависимости от задачи интерес могут представлять:

  • тип файла (DYN — библиотека, EXEC — исполняемый, RELOC — линкуемый);
  • целевая архитектура (E_MACHINE — x86_64, x86, ARM и т.д.);
  • точка входа в приложение (Entry Point);
  • информация о секциях.

010Editor

HEX-редактор 010Editor предоставляет систему шаблонов. Для ELF-файлов шаблон называется, как ни странно, ELF.bt и находится в категории Executable (меню Templates — Executable).
Интерес может представлять, например, точка входа в исполняемый файл (entry point) (записана в заголовке файла).

image

readelf

Утилиту readelf можно считать стандартом де-факто для получения сведений об ELF-файле.

Для удобства чтения адреса приведены к 32-битному формату:

Для удобства чтения адреса приведены к 32-битному формату:

Вывод сокращён для удобства чтения:

Опция -W нужна для увеличения ширины консольного вывода (по умолчанию, 80 символов).

Прочитать заголовок и информацию о секциях можно с использованием кода на Python и библиотеки LIEF (предоставляет API не только для Python):

Информация о компиляторе

objdump

readelf

Я вычислю тебя по… RPATH

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

Для этого используется запись в секции .dynamic с типом DT_RPATH или DT_RUNPATH (см. главу Directories Searched by the Runtime Linker в документации).

И будь осторожен, юный разработчик, не «спали» свою директорию проекта!

Как появляется RPATH?

Основная причина появления RPATH-записи в эльфе — опция -rpath линковщика для поиска динамической библиотеки. Примерно так:

Такая команда создаст в секции .dynamic RPATH-запись со значением /run/media/pablo/disk1/projects/cheat_sheets/ELF/lib/ .

readelf

Посмотреть элементы из секции .dynamic (среди которых есть и RPATH) можно так:

Для удобства чтения результат команды сокращён:

С помощью библиотеки LIEF также можно прочитать RPATH-запись в эльфе:

Проверка эльфа на безопасность

Скрипт проверки безопасности checksec.sh от исследователя Tobias Klein (автора книги A Bug Hunter's Diary) не обновлялся с 2011 года. Данный скрипт для ELF-файлов выполняет проверку наличия опций RelRO (Read Only Relocations), NX (Non-Executable Stack), Stack Canaries, PIE (Position Independent Executables) и для своей работы использует утилиту readelf.

Можно сделать свой аналог на коленке Python и LIEF (чуть короче прародителя и с дополнительной проверкой опции separate-code):

Radare2

Спасибо dukebarman за дополнение по использованию Radare2 для вывода информации аналогично checksec:

«Сырой код» из эльфа (binary from ELF)

Бывают ситуации, когда «эльфийские одёжи» в виде ELF-структуры не нужны, а нужен только «голый» исполняемый код приложения.

objcopy

Использование objcopy вероятно знакомо тем, кто пишет прошивки:

  • -S — для удаления символьной информации;
  • -g — для удаления отладочной информации.

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

Mangled — demangled имена функций

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

Для представления имён в удобочитаемом виде можно использовать утилиту nm из набора binutils:

Вывод имён символов в деманглированном виде с использованием библиотеки LIEF:

Эльф без метаинформации

После того как приложение отлажено и выпускается в дикий мир, имеет смысл удалить метаинформацию:

  • отладочные секции — бесполезны в большинстве случаев;
  • имена переменных и функций — совершенно ни на что не влияют для конечного пользователя (чуть усложняет реверс);
  • таблица секций — совершенно не нужна для запуска приложения (её отсутсвие чуть усложнит реверс).

Удаление символьной информации

Символьная информация — это имена объектов и функций. Без неё реверс приложения немного усложняется.

strip

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

  • для исполняемого файла:
  • для динамической библиотеки:

sstrip

Для тщательного удаления символьной информации (в том числе ненужных нулевых байтов в конце файла) можно воспользоваться утилитой sstrip из набора ELFkickers. Для удаления всей символьной информации достаточно выполнить команду:

C использованием библиотеки LIEF также можно сделать быстрый strip (удаляется таблица символов — секция .symtab ):

Удаление таблицы секций

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

Изменение и удаление RPATH

chrpath, PatchELF

Для изменения RPATH под Linux можно воспользоваться утилитами chrpath (доступна в большинстве дистрибутивов) или PatchELF.

Во время трансляции objcopy создает временный файл, который после работы уничтожается. objcopy использует BFD на протяжении всей трансляции; это позволяет получить доступ ко всем форматам описанным в BFD и распозновать многие форматы без явного их указания. Смотри раздел BFD в 'Использование LD'.

objcopy может быть использован для создания S-записей используя вывод результата в 'srec' (используя '-O srec').

objcopy может быть использован для создания двоичных файлов используя вывод результата в 'binary' (используя '-O binary'). Когда objcopy создает двоичный файл, он на самом деле делает дамп памяти исходного объектного файла. Все символы и информация размещения могут быть удалены. Дамп памяти начиная с виртуального адреса первого раздела копируется в выходной файл.

Во время создания S-записи или двоичного файла, разделы содержащие отладочную информацию могут быть удалены с помощъю опции '-S'. Опция '-R' может быть полезна для удаления разделов содержащих информацию не нужную в двоичном файле. INFILE

Задают входной и выходной файлы, соответственно. Если Вы не указываете INFILE, objcopy создает временный файл и переименовывает результат в INFILE.

Принять формат исходного объектного файла за формат BFDNAME. Подробнее см. раздел 12.1 [Выбор целевой ОС], стр. 37.

Принять формат результирующего объектного файла за формат BFDNAME. Подробнее см. раздел 12.1 [Выбор целевой ОС], стр. 37.

Использовать BFDNAME как формат входного и выходного объектных файлов; т.е. просто перереписывает INFILE в OUTFILE без трансляции. Подробнее см. раздел 12.1 [Выбор целевой ОС], стр. 37.

Удаляет любые разделы с названием SECTIONNAME из выходного файла. Опция может задаваться неоднократно. ВНИМАНИЕ неосторожное применение этой опции может привести к порче выходного файла.

Не копировать информацию о распределении и символы из входного файла.

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

Убрать все сивыолы ненужные для процесса загрузки.

Копировать из входного файла только символ SYMBOLNAME. Опция может задаваться неоднократно.

Не копировать из входного файла символ SYMBOLNAME. Опция может задаваться неоднократно, и может комбинироваться с любыми '--strip-' - опциями также как и '-K'.

Не копировать не глобальные символы из входного файла.

Не копировать локальные символы, генерируемые компилятором (они обычно начинаются с 'L' имя '.' ).

Оставить только каждый BYTE-выи байт фходного файла (данные заголовка остаются без изменений). BYTE может быть в диапазоне от 0 до INTERLEAVE-1, где INTERLEAVE задается опцией -i или --interleave, и по умолчанию равен 4. Эта опция помогает создавать файлы для записи в ПЗУ. Обычно она используется с выводом в 'srec'.

Копировать только каждый INTERLIV-ный байт. Выберите копируемый байт используя опцию '-b' или '--byte'.

Заполняет промежутки в разделах значением VAL. Увеличивает размер раздела с нижних адресов и заполняет лишние пробелы значением VAL.

Расширяет выходной фай до виртуального адреса ADDRESS. Это достигается увеличением размера последнего раздела. Заполняет промежутки в разделах значением указанным в опци '--gap-fill' (по умолчанию 0).

Установить алрес нового файла в значение VAL. Не все форматы объектных файлов поддерживают установку начального адреса.

Выронять стартовый адрес посредством добавления INCR. Не все форматы объектных файлов поддерживают установку начального адреса.

Выравнивание адресов всех разделов, как и стартового адреса, прибавлением INCR. Некоторые форматы объектных файлов не позволяют произвольно изменять адрес секции. Обратите внимание на то что расположение разделов остается без изменения; если программа ожидает згрузки раздела по определенному адресу, и эта опция использовалась изменения адреса загрузки раздела, то программа может работать неправильно.

Установить или варовнять адрес раздела с названием SECTION. При использовании '=' адрес раздела устанавливается в VAL. Иначе VAL добавляется или вычитается из адреса раздела. См. выше комментарии к '--adjust-vma'. Если SECTION не существует во входном файле, будет выдано предупреждение, если не использована опция '--no-adjust-warnings'.

Если использована опция '--adjust-section-vma', и раздел не существует, выдается предупреждение. Опция используется по умолчанию.

Если использована опция '--adjust-section-vma', и раздел не существует, предупреждение не выдается.

Устанавливает флаги для указаного раздела. Аргумент FLAGS - является строкой имен флагов, разделенных точками. Возможны имены флагов: 'aloc', 'load', 'readonly', 'code', 'data' и 'rom'. не все флаги могут применяться для всех форматов объектного файла.

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

Выводит номер версии objcopy.

Выводит имена всех измененных объектных файлов. В применении к архивам, 'objcopy -v' выводит имена всех членов архива.

Выводит краткий список всех опций.

objdump [-a | --archive-headers] [-b BFDNAME | --target=BFDNAME] [-d | --disassemble] [-D | --disassemble-all] [-f | --file-headers] [-h | --section-headers | --headers] [-i | --info] [-j SECTION | --section=SECTION] [-l | --line-numbers] [-S | --source] [-m MACHINE | --architecture=MACHINE] [-r | --reloc] [-R | --dynamic-reloc] [-s | --full-contens] [--stabs] [-t | --syms] [-T | --dynamic-syms] [-x | --all-headers] [-w | --wide] [--tart-address=ADDRESS] [--stop-address=ADDRESS] [--version] [--help] OBJFILE .

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

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

Длинные и короткие формы опций, приведенные в качестве альтернативных, эквивалентны. В конце каждой опции, кроме того, должно быть задано '-l'.

Для любого OBJFILE являющегося архивом, показывает информацию из заголовка (в формате аналогичном 'ls -l'). Кроме того, с 'ar tv', 'objdump -a' показывает формат объектного файла каждого члена архива.

Интерпретирует формат объектного кода в объектном фацле как BFDNAME. Опция не является обязательной, т.к. objdump может автоматически распознавать множесво форматов. Например:

objdump -b oasys -m vax -h fu.o

выдает краткую информацию по секции заголовка ('-h') для ''fu.o, которая явно определена ('-m') как VAX-овский объектный файл в формате представляемом компиляторами Oasys. Вы можете записать доступные форматы с опцией '-i'. Подробнее см. раздел 12.1 [Выбор целевой ОС], стр. 37.

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

Аналогична опции '-d', но дезассемблирует содержимое всех секций, независимо от наличия в них машинного кода.

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

Показывает краткую информацию для секции заголовка объектного файла. Сегменты в файле могут быть размещены по нестандартным адресам, например как при использовании '-Ttext', '-Tdata' или '-Tbss' в опции 'ld'. Тем не менее, в форматы некоторых объектных файлов, таких как 'a.out', не содержат информацию о начальных адресах сегментов. В таких случаях, несмотря на корректное перемещение секций 'ld', использование 'objdump -h' приводит к выдаче неправильных адресов из секции заголовка. Вместо этого отображаются обычные адреса, которые неявно подразумеваются.

Показывает краткий список опций objdump.

Показывает список с указанием доступных архитектур и форматов объектных файлов. Используется с '-b' или '-m'.

Показывает информацию только для раздела с именем NAME.

Выводит информацию (используя отладочную информацию) с именем файла и номерами строк соответствующих показываемому объектному коду. Используется только с '-d' или '-D'.

Показывает что объектный файл OBJFILE сделан для архитектура MACHINE. Вы можете получить список доступных архитектур используя опцию '-i'ю

Печатает таблицу связей файла. Если использована с '-d' или '-D' связи будут напечатаны вперемежку с дизассемблируемым кодом.

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

Выводит полное содержимое любой запрошенной секции.

Выводит исходнай код вперемежку с дисассемблируемым (если возможно). Требует опцию '-d'.

Выводит полное содержимое запрошенной секции. Выводит содержимое секций: .stab .index, .stab .excl из ELF файлов. Это доступно только на системах (типа SOLARIS 2.0) в которых отладочная информация помещена в ELF раздел. Во многих других форматах файлов отладочная информация перемешана с другими символами и может быть просмотрена с помощью '--sims'.

Начать вывод данных с указанного адреса, не применяется с опциями '-d', '-r'.

Зкончить вывод данных с указанного адреса, не применяется с опциями '-d', '-r'.

Напечатать таблицу символов для файла. Аналогично результату от программы nm.

Напечатать информацию о динамических символах файла. Опция действительна только для динамических объектов, таких как некоторые типы разделяемых библиотек. Аналогично программе nm с опцией '-D' (--dynamic).

Печатает номер версии objdump и завершается.

Распечатывает всю доступную информацию из заголовка, включая таблицы символов и таблицы связей загрузки. Использование '-x' эквивалентно '-a -f -h -r -t'.

Форматировать некоторые строки для вывода на устройство имеющее более 80 колонок.

команда objdumpЭто инструмент gcc для просмотра состава целевых файлов или исполняемых целевых файлов.

Параметры

Пример

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



Просмотрите номер версии используемого в настоящее время objdump:



Отобразите список доступных архитектур и целевых структур:



Отобразите содержимое текстового сегмента в файле mytest:



Обратите внимание: -j или -section нельзя использовать отдельно, например objdump --section=.text mytest Он не будет работать успешно.

Разберите содержимое текстового раздела в mytest и максимально выразите его в виде исходного кода:



Обратите внимание: -j или -section нельзя использовать отдельно, например objdump -j .text mytest Он не будет работать успешно. Кроме того, команда -S имеет лучший эффект отображения для целевых файлов, содержащих отладочную информацию.Если параметр -g не указан при компиляции, целевой файл не содержит отладочной информации, и эффект отображения намного хуже.

Дизассемблируйте исходный код mytest.o:



Здесь, особенно когда параметр отладки -g указан при компиляции, эффект дизассемблирования более очевиден. Подразумевается параметр -d.

Отобразите запись файла в таблице символов:



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


Разберите определенный сегмент машинного кода объектного файла:



Здесь дизассемблировано содержимое текстового раздела.

Разберите определенный раздел и сопоставьте имя файла и номер строки, соответствующие коду сборки:



Здесь элемент «-d» дизассемблирует часть машинного кода этих конкретных инструкций из файла obj и использует «-l» для указания соответствующего объектного кода с именем файла и номером строки, только и Используйте вместе -d, -D или -r. Разница между использованием -ld и -d не очень велика. Это полезно для отладки на уровне исходного кода. При компиляции необходимо использовать параметры компиляции отладки, такие как -g.

Отобразите сводную информацию заголовка каждого сегмента целевого файла:



Для получения дополнительных сведений см. этот параметр в man objdump.

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