linux - 在不同架构的文件中使用 ndisasm

标签 linux assembly cpu-architecture disassembly

我想将 ndisasm 用于大量不同架构(x86x64)的文件。我不知道 -b16 是否会为我提供所有文件的正确输出,或者我是否必须为每个文件指定正确的选项,例如 -b32 -b64。我正在运行的是从命令行知道的:

for file in *; do ndisasm -b16 -07c00h -a -s7c3eh "$file" > "/my-path/$file"; done

最佳答案

我建议不要使用ndisasm,除非您确实有平面二进制文件。它将整个文件(包括元数据)视为指令。

x86 机器码是可变长度的,需要从正确的起始地址解码才能“同步”。例如如果元数据的最后几个字节解码为长指令的开始,这就是 ndisasm 解码它们的方式。这将消耗目标文件或可执行文件中本应是机器代码第一条指令的前几个字节。之后,当前位置可能在另一条指令的中间。

解码通常会很快恢复同步,并与指令的实际执行方式保持一致,但如果您要运行大批量反汇编,您不妨使用能够正确执行此操作的工具。


以下两个反汇编器都了解目标文件格式并根据文件类型选择模式。 (例如 x86-64 ELF 或 PE-COFF 对象/可执行文件的 x86-64 模式)。

  • objdump -drwC -Mintel(来自 GNU binutils)的输出非常好,但它使用类似于 MASM 的 GNU .intel_syntax noprefix。 (有关 MASM 风格与 NASM 风格的更多信息,请参阅 the intel-syntax tag wiki)。

  • Agner Fog's objconv disassembler很好,而且可以反汇编成NASM/YASM语法,或者MASM,或者AT&T。 Example of using it .输出包含所有额外信息作为注释,因此您可以将其提供给汇编程序并获得与您开始时类似的二进制文件,包括不同的部分。

    (但不保留特殊编码,例如 .plt 通常使用 push imm32 进行填充,即使是小立即数,但你会得到 push imm8 在 NASM 汇编 push 0x1 时形成,因为 objconv 不会将其反汇编为 push strict dword 0x1。)不过,它是大多数时候都很好,甚至在分支目标上贴上标签,这样您就可以轻松找到循环的顶部。


如果您的一些但不是所有二进制文件都是平面的,可以使用 file 找到不是的二进制文件并将它们提供给 objconv。对于平面二进制文件,您可能必须尝试以多种方式反汇编并使用人为判断来确定代码是否看起来“正常”。

32 位代码被反汇编为 16 的一个主要标志是 32 位立即数或寻址模式位移的末尾被解码为新指令的开始。这通常是一个add 指令(操作码00)。

对于 64 位代码和 32 位代码,一个很大的区别是 REX 前缀与单字节 dec/inc 指令。如果您在 32 位反汇编中看到奇怪的 dec/inc 指令,它可能实际上是 64 位机器代码。如果您看到奇怪的 REX 前缀(特别是当反汇编器说 rex add eax, ecx 或其他东西来告诉您有一个无用的 REX 前缀),它可能是一个单独的 inc 指令在 32 位机器代码中。

关于linux - 在不同架构的文件中使用 ndisasm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47420776/

相关文章:

linux - 跳过标题将文件中的多行合并为单行

C 内联程序集生成未处理的异常

assembly - 如何将用户输入的16位数字转换为十进制

C 从 char 指针一点一点地读取

memory-management - 什么类型的输入会减慢动态内存分配器 malloc() 和 free() 的执行时间?

java - tomcat7 100%cpu挂掉,重启tomcat没有效果。直到重新启动系统

linux - 在 Linux 中从 C/C++ 中的帧缓冲区捕获视频

linux - 在 Ubuntu 上不使用终端命令打开 Jupyter 笔记本?

c - cpu缓存访问时间分析

assembly - 为什么 SPARC 或 MIPS 的 %r0 始终为 0?