96

I'd like to disassemble the MBR (first 512 bytes) of a bootable x86 disk that I have. I have copied the MBR to a file using

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

Any suggestions for a Linux utility that can disassemble the file mbr?

Peter Cordes
  • 245,674
  • 35
  • 423
  • 606
sigjuice
  • 25,352
  • 11
  • 62
  • 90

6 Answers6

113

You can use objdump. According to this article the syntax is:

objdump -D -b binary -mi386 -Maddr16,data16 mbr
hlovdal
  • 23,353
  • 10
  • 78
  • 148
  • can you explain what the options you specify do? – Hawken Nov 17 '12 at 14:18
  • 12
    or `--target` instead of `-b`. `-D` is "disassemble the contents of all sections"; `-b bfdname` or `--target=bfdname` will force reading as specified object-code format (not elf but raw binary in our case); `-m machine` will specify the architecture to use (in our file there is no header with arch info). `-M options` are options of disassembler; `addr16,data16` are used to "specify the default address size and operand size" (treat code as i8086 one in the universal x86 disasm engine) – osgx Nov 28 '12 at 16:41
31

The GNU tool is called objdump, for example:

objdump -D -b binary -m i8086 <file>
starblue
  • 51,675
  • 14
  • 88
  • 146
  • You can also set different options for the architecture and the syntax. For example, `-m i386` or `-Mintel,x86-64`. `i8086` is an old architecture and using it for modern code may yield unexpected results. Furthermore, specifying `x86-64` to `-M` might be a good idea nowadays since many machines are 64-bit. Passing `intel` to `-M` changes the syntax to Intel-style instead of the default AT&T style, which you may or may not want. – GDP2 Mar 05 '18 at 03:04
26

I like ndisasm for this purpose. It comes with the NASM assembler, which is free and open source and included in the package repositories of most linux distros.

asveikau
  • 35,672
  • 2
  • 48
  • 66
  • I like this answer better. Easier to use, and I could install nasm on OS X - objdump wasn't there, and I don't want to build it from source. –  Oct 28 '12 at 13:12
23
ndisasm -b16 -o7c00h -a -s7c3eh mbr

Explanation - from ndisasm manpage

  • -b = Specifies 16-, 32- or 64-bit mode. The default is 16-bit mode.
  • -o = Specifies 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.
  • -a = Enables automatic (or intelligent) sync mode, in which ndisasm will attempt to guess where synchronisation should be performed, by means of examining the target addresses of the relative jumps and calls it disassembles.
  • -s = Manually 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.
  • mbr = The file to be disassembled.
Drew Chapin
  • 7,031
  • 5
  • 51
  • 77
jameslin
  • 231
  • 2
  • 2
  • what does this do as opposed to simple ndisasm? Can you explain the options – Hawken Nov 17 '12 at 14:16
  • 4
    Could you explain what those options mean and do? Understanding an answering is better than just getting one. – Sled Nov 17 '12 at 17:33
  • `-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.` – Janus Troelsen May 06 '13 at 18:49
16

starblue and hlovdal both have parts of the canonical answer. If you want to disassemble raw i8086 code, you usually want Intel syntax, not AT&T syntax, too, so use:

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

If your code is ELF (or a.out (or (E)COFF)), you can use the short form:

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

For 32-bit or 64-bit code, omit the ,8086; the ELF header already includes this information.

ndisasm, as suggested by jameslin, is also a good choice, but objdump usually comes with the OS and can deal with all architectures supported by GNU binutils (superset of those supported by GCC), and its output can usually be fed into GNU as (ndisasm’s can usually be fed into nasm though, of course).

Peter Cordes suggests that “Agner Fog's objconv is very nice. It puts labels on branch targets, making a lot easier to figure out what the code does. It can disassemble into NASM, YASM, MASM, or AT&T (GNU) syntax.”

Multimedia Mike already found out about --adjust-vma; the ndisasm equivalent is the -o option.

To disassemble, say, sh4 code (I used one binary from Debian to test), use this with GNU binutils (almost all other disassemblers are limited to one platform, such as x86 with ndisasm and objconv):

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

The -m is the machine, and -EL means Little Endian (for sh4eb use -EB instead), which is relevant for architectures that exist in either endianness.

Community
  • 1
  • 1
mirabilos
  • 4,473
  • 2
  • 42
  • 65
  • 2
    [Agner Fog's objconv](http://agner.org/optimize/) is very nice. It puts labels on branch *targets*, making a lot easier to figure out what the code does. It can disassemble into NASM, YASM, MASM, or AT&T (GNU) syntax. – Peter Cordes Dec 23 '15 at 04:05
  • It built fine right out of the box on GNU/Linux, for me. But yes, it's x86 / x86-64 only, unlike GNU binutils. However, it has a lot of nice x86-specific hints that it adds as comments, like when an operand-size prefix can cause an LCP-stall in the decoders of an Intel CPU. By all means, mention it in your answer. One of the major purposes of comments is to help the poster improve their answer, not just as something that later viewers need to read, too. – Peter Cordes Dec 23 '15 at 11:11
  • 1
    @PeterCordes Yes well I have MirBSD as main OS ;) – mirabilos Dec 23 '15 at 11:35
  • @PeterCordes but it seems it can't disassemble raw binaries, can it? I had to create minimal ELF files just to be able to feed a bunch of instructions into it, but maybe I just missed some option? – Ruslan Apr 28 '17 at 12:08
  • 1
    @Ruslan: IDK, interesting question. I usually just use objdump, or if I want branch labels, `gcc -O3 -masm=intel -fverbose-asm -S -o- | less`, since I'm usually trying to tweak C source into compiling to good asm. – Peter Cordes Apr 28 '17 at 17:12
9

Try this command:

sudo dd if=/dev/sda bs=512 count=1 | ndisasm -b16 -o7c00h -
zx485
  • 24,099
  • 26
  • 45
  • 52
Jason
  • 2,221
  • 17
  • 14