Как разобрать необработанный 16-битный машинный код x86?

91

Я хотел бы разобрать MBR (первые 512 байт) загрузочного диска x86, который у меня есть. Я скопировал MBR в файл, используя

dd if=/dev/my-device of=mbr bs=512 count=1

Есть ли предложения по утилите Linux, которая может дизассемблировать файл mbr?

sigjuice
источник

Ответы:

109

Вы можете использовать objdump. Согласно этой статье синтаксис:

objdump -D -b binary -mi386 -Maddr16,data16 mbr
Hlovdal
источник
не могли бы вы объяснить, что делают указанные вами параметры?
Hawken
11
или --targetвместо -b. -Dэто «разобрать содержимое всех разделов»; -b bfdnameили --target=bfdnameзаставит читать как указанный формат объектного кода (в нашем случае не elf, а raw binary); -m machineукажет используемую архитектуру (в нашем файле нет заголовка с информацией об арке). -M optionsварианты дизассемблера; addr16,data16используются для «указания размера адреса по умолчанию и размера операнда» (трактуйте код как i8086 в универсальном движке дизасмации x86)
osgx
30

Инструмент GNU называется objdump , например:

objdump -D -b binary -m i8086 <file>
звездно-голубой
источник
Вы также можете установить различные параметры для архитектуры и синтаксиса. Например, -m i386или -Mintel,x86-64. i8086- это старая архитектура, и ее использование для современного кода может привести к неожиданным результатам. Кроме того, x86-64в настоящее время -Mможет быть хорошей идеей указать to, поскольку многие машины 64-битные. Переход intelк -Mизменяет синтаксис на стиль Intel вместо стиля AT&T по умолчанию, который может вам понадобиться, а может и нет.
GDP2 05
24

Мне ndisasmдля этого нравится . Он поставляется с ассемблером NASM, который является бесплатным с открытым исходным кодом и включен в репозитории пакетов большинства дистрибутивов Linux.

Асвейкау
источник
Мне этот ответ больше нравится. Проще использовать, и я мог бы установить nasm в OS X - objdump там не было, и я не хочу собирать его из исходников.
23
ndisasm -b16 -o7c00h -a -s7c3eh mbr

Объяснение - из справочной страницы ndisasm

  • -b= Задает 16-, 32- или 64-разрядный режим. По умолчанию используется 16-битный режим.
  • -o= Задает условный адрес загрузки файла. Эта опция заставляет ndisasm получать адреса, которые он перечисляет, внизу слева, а целевые адреса переходов и вызовов, относящихся к ПК, справа.
  • -a = Включает автоматический (или интеллектуальный) режим синхронизации, в котором ndisasm будет пытаться угадать, где должна быть выполнена синхронизация, путем проверки целевых адресов относительных переходов и вызывает его дизассемблирование.
  • -s= Указывает адрес синхронизации вручную, так что ndisasm не будет выводить машинные инструкции, содержащие байты с обеих сторон адреса. Следовательно, инструкция, которая начинается с этого адреса, будет правильно разобрана.
  • mbr = Файл, который нужно разобрать.
Джеймслин
источник
что это делает в отличие от простого ndisasm? Можете ли вы объяснить варианты?
Hawken
4
Не могли бы вы объяснить, что означают и делают эти варианты? Лучше понять ответ, чем просто его получить.
Sled
-b specifies 16-, 32- or 64-bit mode. The default is 16-bit mode. -o is the notional load address for the file. This option causes ndisasm to get the addresses it lists down the left hand margin, and the target addresses of PC-relative jumps and calls, right. -s specifies a synchronisation address, such that ndisasm will not output any machine instruction which encompasses bytes on both sides of the address. Hence the instruction which starts at that address will be correctly disassembled.
Янус Троелсен
15

У starblue и hlovdal есть части канонического ответа. Если вы хотите дизассемблировать необработанный код i8086, вам обычно нужен синтаксис Intel, а не синтаксис AT&T, поэтому используйте:

objdump -D -Mintel,i8086 -b binary -m i386 mbr.bin
objdump -D -Mintel,i386 -b binary -m i386 foo.bin    # for 32-bit code
objdump -D -Mintel,x86-64 -b binary -m i386 foo.bin  # for 64-bit code

Если ваш код - ELF (или a.out (или (E) COFF)), вы можете использовать короткую форму:

objdump -D -Mintel,i8086 a.out  # disassembles the entire file
objdump -d -Mintel,i8086 a.out  # disassembles only code sections

Для 32-битного или 64-битного кода опустите ,8086; заголовок ELF уже включает эту информацию.

ndisasm, как было предложено jameslin , также является хорошим выбором, но objdumpобычно поставляется с ОС и может работать со всеми архитектурами, поддерживаемыми GNU binutils (надмножеством тех, которые поддерживаются GCC), и его вывод обычно может быть asпередан в GNU (ndisasm обычно может подаваться в nasmхотя, конечно).

Питер Кордес предполагает, что « objconv Агнера Фога очень хорош. Он помещает метки на цели ветки, что значительно упрощает понимание того, что делает код. Его можно разобрать на синтаксис NASM, YASM, MASM или AT&T (GNU) ».

Мультимедиа Майк уже узнал --adjust-vma; ndisasmэквивалент является -oвариантом.

Чтобы дизассемблировать, скажем, sh4код (я использовал один двоичный файл из Debian для тестирования), используйте его с GNU binutils (почти все другие дизассемблеры ограничены одной платформой, например x86 с ndisasmи objconv):

objdump -D -b binary -m sh -EL x

Это -mмашина и -ELозначает Little Endian (для sh4ebиспользования -EBвместо этого), что актуально для архитектур, которые существуют в любом порядке.

Mirabilos
источник
2
Objconv Агнера Фога очень хорош. Он помещает метки на цели веток , что значительно упрощает понимание того, что делает код. Его можно разобрать на синтаксис NASM, YASM, MASM или AT&T (GNU).
Питер Кордес
На мой взгляд, он отлично построен прямо из коробки на GNU / Linux. Но да, это только x86 / x86-64, в отличие от GNU binutils. Однако у него есть много хороших подсказок, специфичных для x86, которые он добавляет в качестве комментариев, например, когда префикс размера операнда может вызвать остановку LCP в декодерах процессора Intel. Обязательно укажите это в своем ответе. Одна из основных целей комментариев - помочь постеру улучшить свой ответ, а не только как что-то, что позже нужно прочитать зрителям.
Питер Кордес
1
@PeterCordes Да ну у меня MirBSD в качестве основной ОС;)
mirabilos
@PeterCordes, но кажется, что он не может дизассемблировать необработанные двоичные файлы, не так ли? Мне пришлось создать минимальные файлы ELF, чтобы иметь возможность ввести в него кучу инструкций, но, может быть, я просто пропустил какой-то вариант?
Руслан
1
@Ruslan: IDK, интересный вопрос. Обычно я просто использую objdump или, если мне нужны метки веток gcc -O3 -masm=intel -fverbose-asm -S -o- | less, так как я обычно пытаюсь настроить исходный код C для компиляции в хороший asm.
Питер Кордес
9

Попробуйте эту команду:

sudo dd if=/dev/sda bs=512 count=1 | ndisasm -b16 -o7c00h -
Джейсон
источник