Как мне разобрать сырой код x86?
Я хотел бы разобрать MBR (первые 512 байт) загрузочного диска x86, который у меня есть. Я скопировал MBR в файл, используя
dd if=/dev/my-device of=mbr bs=512 count=1
Любые предложения для утилиты Linux, которая может разобрать файл mbr
?
7 ответов
Вы можете использовать objdump. Согласно этой статье синтаксис:
objdump -D -b binary -mi386 -Maddr16,data16 mbr
Инструмент GNU называется objdump, например:
objdump -D -b binary -m i8086 <file>
Мне нравится ndisasm
для этого. Он поставляется с ассемблером NASM, который является бесплатным и открытым исходным кодом и входит в состав репозиториев большинства дистрибутивов Linux.
ndisasm -b16 -o7c00h -a -s7c3eh mbr
Пояснение - из справочной страницы ndisasm
-b
= Определяет 16-, 32- или 64-битный режим. По умолчанию используется 16-битный режим.-o
= Определяет условный адрес загрузки для файла. Эта опция заставляет ndisasm получить список адресов, перечисленных в левом поле, и целевые адреса ПК-относительных переходов и вызовов справа.-a
= Включает автоматический (или интеллектуальный) режим синхронизации, в котором ndisasm будет пытаться угадать, где должна быть выполнена синхронизация, путем изучения целевых адресов относительных переходов и вызывает их разборки.-s
= Вручную указывает адрес синхронизации, так что ndisasm не будет выводить никаких машинных инструкций, которые охватывают байты с обеих сторон адреса. Следовательно, инструкция, которая начинается с этого адреса, будет правильно разобрана.mbr
= Файл, который нужно разобрать.
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), а его выходной сигнал обычно может быть передан в GNU as
(ndisasm's обычно можно вводить в nasm
хотя, конечно).
Peter Cordes предполагает, что " задание Агнера Фога очень приятно. Он ставит метки на ветви целей, что значительно упрощает понимание того, что делает код. Он может быть разобран на синтаксис 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
вместо этого), что актуально для архитектур, которые существуют в любом порядке байтов.
Если вы просто хотите использовать дизассемблер, то objdump — один из вариантов. Дизассемблер, входящий в состав ассемблера nasm, называется ndisasm. Вы также можете запустить «debug.exe» в DOS Box на Linux, если у вас есть копия программы. Он также занимается разборкой, а также контролируемым исполнением; т.е. моделирование самого ЦП, что также важно, даже при разборке, по причинам, которые я собираюсь описать.
Fake86 имеет эмулятор процессора. Вы можете заставить его выполнять дизассемблирование, (а) заставив его показывать инструкцию вместо ее симуляции, (б) заставляя его не выполнять условные переходы или вызывать вызовы, а (вместо этого) складывать адрес в качестве новой точки входа в выполнить дизассемблирование (т. е., по сути, взять обе ветви и инкапсулировать подпрограммы), (c) заставить его остановить текущую дизассемблирование при безусловном переходе или возврате, (d) заставить его принять одну, две или более точек входа для начала и в идеале (e) заставить его также принимать базовые адреса для сегментов данных и (f) заставить его делать шестнадцатеричный дамп всех областей, необработанных как сегменты данных или кода (поскольку обычно это те места, где косвенные переходы или вызовы или данные с косвенным доступом сегменты приземляются.)
Это доходит до другого смысла вашего запроса: «Я хочу сделать дизассемблер ». Исходный код для ndisasm доступен, и он обрабатывает многих потомков 8086, а не только сам 8086 (что сильно загромождает его, если вам нужен только дизассемблер 8086 или даже 80386), но он не самодостаточен и имеет сильная зависимость от остальной части дистрибутива.
Его основная идея заключается в том, что он использует восьмеричные цифры для кодов операций, что лучше подходит для 80x86, как я указал в USENET в 1995 году в comp.lang.asm ... и (фактически) создание nasm было прямым ответом на что. Таким образом, это потенциально более прозрачно, и вы можете захотеть держать исходный код под рукой для проверки и сравнения, если вы делаете свой собственный дизассемблер.
Вы также можете запустить программу debug.exe на самой себе.
Вы также можете попробовать запустить ndisasm в файле debug.exe; после удаления заголовка файла .EXE размером 0x200 байт, чтобы сделать его необработанным двоичным файлом, после извлечения из него адреса точки входа CS:IP и адреса указателя стека SS:SP (стеки 80x86 растут вниз, поэтому сегмент стека номинально от СС:0 до СС:(SP-1)). EXE для debug.exe не имеет перемещений, поэтому вы можете обрабатывать код как необработанный двоичный файл.
Но ничего четко узнаваемого вы не получите, так как программа является самомодифицирующейся, точнее: самораспаковывающейся. Вы получите (едва) сжатое изображение кода (коэффициент сжатия примерно 5/6), за которым следует процедура загрузки.
Вы должны запустить эмуляцию на нем, например, запустив debug.exe на debug.exe, чтобы эмулировать его процедуру распаковки, чтобы заставить его извлекать себя, а затем вы выгружаете распакованный образ программы и дизассемблируете его. В конце процедуры загрузчика есть «таблица перемещений», поэтому в ней действительно есть перемещения — просто они применяются, когда программа распаковывает себя, а не ОС при загрузке EXE-файла .
И тогда вы только что дизассемблировали дизассемблер, который также выполняет эмуляцию процессора, как это делает Fake86, но только для 8086. подлежит повторной сборке. Как только вы это сделаете, вы можете работать с источником. Таблица кодов операций находится в открытом виде (если вы отображаете ее в виде текста)- как в упакованной, так и в неупакованной версиях debug.exe.
На GitHub также есть DosDebug. Он обрабатывает все до "80586" (или Pentium) и "80686": он помечает поколение "6" для некоторых инструкций; например, он обрабатывает условные операции "cmov", а также их плавающие "fcmov" точки. DosDebug находится в сборке 8086 и лучше всего подходит для компиляции с jwasm. Возможно, вы сможете запустить на нем nasm, я не знаю. Я никогда не пробовал.
Я мог бы перенести дизассемблер DAS на x86, так как пункты (a)-(f) уже включены в структуру DAS. До сих пор я портировал его только на 8051, 6800, 6809 и 8080/8085 (и Z80); но переход от 8085 к 8086 относительно невелик. Для этого я мог бы взломать что-нибудь из Fake86. Сейчас это в основном заброшенное ПО, так как автор заменил его на XTulator, поскольку Fake86 был написан, когда программист был относительно новичком в C. Вы также можете взломать что-то непосредственно из таблиц кодов операций DosDebug (их файлов «instr.*») .