ChatGPT解决这个技术问题 Extra ChatGPT

如何反汇编原始 16 位 x86 机器代码?

我想反汇编我拥有的可引导 x86 磁盘的 MBR(前 512 个字节)。我已使用将 MBR 复制到文件中

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

对于可以反汇编文件 mbr 的 Linux 实用程序有什么建议吗?


h
hlovdal

您可以使用 objdump。根据 this article,语法为:

objdump -D -b binary -mi386 -Maddr16,data16 mbr

你能解释一下你指定的选项是做什么的吗?
--target 而不是 -b-D 是“反汇编所有部分的内容”; -b bfdname--target=bfdname 将强制读取为指定的目标代码格式(在我们的例子中不是 elf,而是原始二进制文件); -m machine 将指定要使用的体系结构(在我们的文件中没有包含拱信息的标题)。 -M options 是反汇编程序的选项; addr16,data16 用于“指定默认地址大小和操作数大小”(在通用 x86 disasm 引擎中将代码视为 i8086 之一)
s
starblue

GNU 工具称为 objdump,例如:

objdump -D -b binary -m i8086 <file>

您还可以为体系结构和语法设置不同的选项。例如,-m i386-Mintel,x86-64i8086 是一种旧架构,将其用于现代代码可能会产生意想不到的结果。此外,现在将 x86-64 指定为 -M 可能是一个好主意,因为许多机器都是 64 位的。将 intel 传递给 -M 会将语法更改为 Intel 样式,而不是您可能想要也可能不想要的默认 AT&T 样式。
a
asveikau

为此,我喜欢 ndisasm。它带有 NASM 汇编器,它是免费和开源的,并包含在大多数 linux 发行版的软件包存储库中。


我更喜欢这个答案。更容易使用,我可以在 OS X 上安装 nasm - objdump 不存在,我不想从源代码构建它。
D
Drew Chapin
ndisasm -b16 -o7c00h -a -s7c3eh mbr

说明 - 来自 ndisasm 手册页

-b = 指定 16、32 或 64 位模式。默认为 16 位模式。

-o = 指定文件的名义加载地址。此选项使 ndisasm 获取它在左边距下列出的地址,以及与 PC 相关的跳转和调用的目标地址,右边。

-a = 启用自动(或智能)同步模式,在这种模式下,ndisasm 将尝试通过检查相对跳转的目标地址来猜测应该在哪里执行同步,并将其称为反汇编。

-s = 手动指定同步地址,这样 ndisasm 将不会输出包含地址两侧字节的任何机器指令。因此,从该地址开始的指令将被正确反汇编。

mbr = 要反汇编的文件。


与简单的 ndisasm 相比,这有什么作用?你能解释一下选项吗
你能解释一下这些选项的含义和作用吗?理解答案总比得到答案要好。
-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.
C
Community

starbluehlovdal 都有部分规范答案。如果你想反汇编原始 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 标头已包含此信息。

jameslin 建议的 ndisasm 也是一个不错的选择,但 objdump 通常是操作系统自带的,可以处理 GNU binutils 支持的所有架构(GCC 支持的超集),它的输出通常可以输入到 GNU as 中(当然,ndisasm 通常可以输入到 nasm 中)。

Peter Cordes 表示“Agner Fog's objconv 非常好。它将标签放在分支目标上,从而更容易弄清楚代码的作用。它可以反汇编成 NASM、YASM、MASM 或 AT&T (GNU) 语法。”

Multimedia Mike 已经发现了 --adjust-vmandisasm 等效项是 -o 选项。

例如,要反汇编 sh4 代码(我使用 Debian 的一个二进制文件进行测试),请将其与 GNU binutils 一起使用(几乎所有其他反汇编程序都仅限于一个平台,例如带有 ndisasmobjconv 的 x86):

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

-m 是机器,-EL 表示 Little Endian(sh4eb 使用 -EB 代替),这与存在于任一字节序的架构相关。


Agner Fog's objconv 非常好。它将标签放在分支 targets 上,从而更容易弄清楚代码的作用。它可以反汇编成 NASM、YASM、MASM 或 AT&T (GNU) 语法。
对我来说,它在 GNU/Linux 上开箱即用。但是,是的,它只是 x86 / x86-64,不像 GNU binutils。但是,它有很多很好的 x86 特定提示,它作为注释添加,例如当操作数大小的前缀可能导致 Intel CPU 的解码器中的 LCP 停止时。无论如何,请在您的答案中提及它。评论的主要目的之一是帮助发布者改进他们的答案,而不仅仅是后来观众需要阅读的东西。
@PeterCordes 是的,我将 MirBSD 作为主要操作系统;)
@PeterCordes,但它似乎无法反汇编原始二进制文件,可以吗?我必须创建最小的 ELF 文件才能向其中输入一堆指令,但也许我只是错过了一些选项?
@Ruslan:IDK,有趣的问题。我通常只使用 objdump,或者如果我想要分支标签,gcc -O3 -masm=intel -fverbose-asm -S -o- | less,因为我通常会尝试将 C 源代码调整为编译为好的 asm。
z
zx485

试试这个命令:

sudo dd if=/dev/sda bs=512 count=1 | ndisasm -b16 -o7c00h -