CLI:在地址处写入字节(来自命令行的hexedit / modify binary)

时间:2011-01-24 15:21:34

标签: shell scripting hex patch edit

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

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

仅使用标准的linux工具从命令行执行它会很棒。

或者甚至可能更好,而不是搜索十六进制字符串,我想直接替换在Offset 0x10000处写入FF,在Offset 0x100001处写入12,依此类推。

有什么想法吗?

提前致谢!

P.S。:我应该添加以下内容:

它应该是可编写脚本的,并直接从命令行运行。我正在寻找类似“二进制 - 包含在发行版 - 写入AB --at-offset 100000 --file thebinary.bin”之类的内容。我很确定使用“dd”是可能的,但是我无法绕过手册页。

8 个答案:

答案 0 :(得分:68)

printf '\x31\xc0\xc3' | dd of=test_blob bs=1 seek=100 count=3 conv=notrunc 

dd参数:

  • |文件补丁
  • bs |请一次1个字节
  • 寻求 |转到位置100(十进制)
  • conv = notrunc |编辑后不截断输出(默认为dd)

一个Josh正在寻找另一个;)

答案 1 :(得分:7)

基于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)和dec(无前缀)的输入数字。

答案 2 :(得分:6)

这是一个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 :(得分:2)

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

一些替代方案:

答案 6 :(得分:1)

使用一个衬垫在同一文件中的两个不同位置写入相同的字节。

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的任何统计数据时。

答案 7 :(得分:0)

关于Josh的答案:如果您要针对特定​​的地址

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