【问题标题】:Write byte at address (hexedit/modify binary from the command line)在地址处写入字节(从命令行十六进制编辑/修改二进制文件)
【发布时间】:2011-01-24 15:21:33
【问题描述】:

有没有直接从命令行修改二进制文件的方法? 假设我知道我的二进制文件包含 1234abcd 并且我想将其更改为 12FFabcd 或 FFFFabcd 甚至可能是 FF34FFabc0(你明白了):-)

如果不使用http://stahlworks.com/dev/swiss-file-knife.html 或类似工具等任何特殊用途的工具,我如何才能实现这一目标。

如果只使用标准 linux 工具从命令行执行此操作,那就太好了。

或者甚至更好,而不是搜索我想要替换的十六进制字符串,直接在偏移量 0x10000 处写入 FF,在偏移量 0x100001 处写入 12 等等。

它应该是可编写脚本的并且可以直接从命令行运行。我正在寻找类似“binary-which-is-included-in-the-distro --write AB --at-offset 100000 --file thebinary.bin”之类的东西。我很确定使用“dd”是可能的,但我无法理解手册页。

有什么想法吗?

提前致谢!

【问题讨论】:

    标签: shell scripting hex patch edit


    【解决方案1】:
    printf '\x31\xc0\xc3' | dd of=test_blob bs=1 seek=100 count=3 conv=notrunc 
    

    dd 参数:

    • |要修补的文件
    • bs |请一次 1 个字节
    • 寻找 |转到位置 100(十进制)
    • conv=notrunc |不要在编辑后截断输出(dd 默认会这样做)

    一个乔希在寻找另一个;)

    【讨论】:

    • 美丽优雅的解决方案!是否也可以使用此命令插入字节?或者将修补后的文件输出到不同的文件名?还是让查找位置基于文件大小等变量?
    • 这是一个很好的解决方案,但遗憾的是,它不适用于 BusyBox。 BusyBox 的 dd 实现不支持 conv=notrunc(或 conv=anything,就此而言)。
    • 一定要注意seek可能不是以字节为单位的,而是以obs的大小为单位的。
    • @AdamHaun BusyBox 的 dd 确实支持一些 conv= 选项,包括 conv=notrunc,并且我已经验证了这个解决方案在默认配置中与 BusyBox 一起工作(BusyBox 是非常可配置的,这个功能可以在自定义构建)。
    • 这会覆盖数据。要将数据附加到特定位置,此答案的第二个解决方案有效:askubuntu.com/questions/1276339/…
    【解决方案2】:

    这是一个 Bash 函数replaceByte,它采用以下参数:

    • 文件名,
    • 文件中要重写的字节的偏移量,以及
    • 字节的新值(一个数字)。
    #!/bin/bash
    
    # param 1: file
    # param 2: offset
    # param 3: value
    function replaceByte() {
        printf "$(printf '\\x%02X' $3)" | dd of="$1" bs=1 seek=$2 count=1 conv=notrunc &> /dev/null
    }
    
    # Usage:
    # replaceByte 'thefile' $offset 95
    

    【讨论】:

      【解决方案3】:

      基于printf+dd 的解决方案似乎不适用于写出零。这是 python3 中的通用解决方案(包含在所有现代发行版中),它应该适用于所有字节值...

      #!/usr/bin/env python3
      #file: set-byte
      
      import sys
      
      fileName = sys.argv[1]
      offset = int(sys.argv[2], 0)
      byte = int(sys.argv[3], 0)
      
      with open(fileName, "r+b") as fh:
          fh.seek(offset)
          fh.write(bytes([byte]))
      

      用法...

      set-byte eeprom_bad.bin 0x7D00 0
      set-byte eeprom_bad.bin 1000 0xff
      

      注意:此代码可以处理十六进制(以 0x 为前缀)和十进制(无前缀)的输入数字。

      【讨论】:

      • 重要的是你在python3(不是python2)中运行它,否则你最终会写一个列表的文字字符串表示:[byte]
      • 查询的是 Shell 脚本,而不是 Python 脚本。
      • printf+dd 在写出零时起作用,因为这是使用“conv=notrunc”选项的强制性要求。
      • printf '\x00\x00\x00\x00' | dd of=blah bs=1 seek=24 count=4 conv=notrunc 工作(Linux Mint 20)
      • 对 printf 中十六进制的支持取决于 printf 的实现。 Bash 内置的 printf 支持它,GNU printf 也支持它(在许多 Linux 中发现为 /usr/bin/printf)。但是某些 sh ​​变体(如 dash)中的内置 printf 不支持它。不过,所有变体都应该支持八进制。有关 POSIX 解释,请参阅 pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html。所以另一种选择是使用其他东西,例如xxd 或 perl,用 dd 将流输出到“poke”。
      【解决方案4】:

      vim 附带的 xxd 工具(因此很可能可用)允许十六进制转储二进制文件并从修改后的十六进制转储构造新的二进制文件。

      【讨论】:

      • 但这在命令行中也行不通(请参阅我上面对 Dans 回复的评论),对吧?
      • 它应该可以工作:xxd -ps ... | sed -s "s/.../.../g/" | xxd -r ...
      • 对于您的情况:echo "010000: FF" | xxd -r - binary.x
      • 非常感谢!我会试试的! StackOverflow 真的很棒 :)
      • 我喜欢这个,因为它还允许我在不知道确切位置时对十六进制数据进行简单的搜索和替换。
      【解决方案5】:

      在同一个文件的两个不同位置用一个衬线写入同一个字节。

      printf '\x00'| tee >(dd of=filename bs=1 count=1 seek=692 conv=notrunc status=none) \
          >(dd of=filename bs=1 count=1 seek=624 conv=notrunc status=none)
      

      status=none在您不希望 dd 有任何统计信息时非常有用。

      【讨论】:

        【解决方案6】:

        如果您不需要它是可编写脚本的,您可以尝试使用“hexedit”实用程序。它在许多 Linux 发行版中都可用(如果默认未安装,通常可以在发行版的软件包存储库中找到)。

        如果你的发行版没有,你可以build and install it from source

        【讨论】:

        • 它应该是可编写脚本的并且可以直接从命令行运行。我正在寻找类似“binary-which-is-included-in-the-distro --write AB --at-offset 100000 --file thebinary.bin”之类的东西。我很确定使用“dd”是可能的,但我无法理解手册页。
        【解决方案7】:

        一些替代方案:

        【讨论】:

          【解决方案8】:

          关于乔希的回答:如果您想针对特定地址进行操作

          hexdump -C {file location}
          

          您可能尝试使用一些十六进制值添加 0x,但它会失败:

          dd: warning: ‘0x’ is a zero multiplier; use ‘00x’ if that is intended
          

          您可以通过使用 $(()) 封装它来实现这一点,终端将转换为 int 值:

          mybinary={file location}
          printf '\x31\xc0\xc3' | dd of=$mybinary bs=1 seek=$((0x100)) count=3 conv=notrunc 
          

          【讨论】:

            猜你喜欢
            • 2015-05-15
            • 2021-10-27
            • 2013-02-22
            • 1970-01-01
            • 2011-12-22
            • 1970-01-01
            • 2015-04-13
            • 2014-09-13
            • 2010-11-22
            相关资源
            最近更新 更多