十六进制转储反转命令

23

Hexdump 命令可以将任何文件转换为十六进制值。

但是如果我已经有了十六进制值并且想要反向这个过程,这可能吗?

8个回答

28

有一个类似的工具叫做xxd。如果你只用文件名运行xxd,它会以相当标准的十六进制转储格式转储数据:

# xxd bdata
0000000: 0001 0203 0405
......

如果您使用-r选项将输出作为管道传递回 xxd,并将其重定向到新文件,则可以将十六进制转储转换回二进制:

# xxd bdata | xxd -r >bdata2
# cmp bdata bdata2
# xxd bdata2
0000000: 0001 0203 0405

方便地说,xxd -r 还可以接受 hexdump 输出作为输入。 - tripleee
2
如果我有一个文件,它没有像冒号、空格和换行符这样的格式,并且只是一个流匹配 [0-9A-F]* 直到文件结束,那我该怎么办? - Aaron Franke

6

我写了一个简短的 AWK 脚本,可以将 hexdump -C 输出的结果反向转换为原始数据。使用方法如下:

reverse-hexdump.sh hex.txt > data

处理'*'重复标记,即使是二进制数据也能生成原始数据。hexdump -Creverse-hexdump.sh可以构成一个数据往返对。具体可以在以下地址获取:


@Zibri 是的,我的脚本确实可以处理hexdump -C在没有-v选项的情况下产生的*重复标记。自述文件中的示例显示了它的工作原理。有5个单元测试用例证实了这一点。如果您真的遇到了无法正常工作的情况,请在GitHub存储库中提出问题。 - Mike Fleetwood
我的错。干得好。我发现五分钟后,却忘记移除注释了。 - Zibri

5

恢复文件,仅提供hexdump file的输出

如果您只有hexdump file的输出并且想要恢复原始文件,请首先注意hexdump默认输出取决于运行hexdump的系统的数据字节序(endian)

如果您可以访问创建转储的系统,则可以使用下面的命令确定其字节序:

[[ "$(printf '\01\03' | hexdump)" == *0103* ]] && echo big || echo little

反转小端十六进制转储

这是最常见的情况。所有的x86/x64系统都是小端模式。如果你不知道运行hexdump file的系统的字节序,可以尝试以下方法。

sed 's/ \(..\)\(..\)/ \2\1/g;$d' dump | xxd -r

sed部分将hexdump的格式转换为xxd的格式,至少目前为止,xxd -r可以正常工作。

反转大端模式的hexdump

sed '$d' dump | xxd -r

已知的问题(请参见评论部分)

  • 如果原始文件的长度是奇数(例如1、3、5、7、...字节长),则会添加一个尾随的空字节。
  • 如果使用*进行hexdump,则无法正确恢复原始文件的重复部分。

您可以通过运行以下命令检查上述问题:

grep -qE '^\*|^[0-9a-f]*[13579bdf] *$' dump && echo bug || echo ok

更好的十六进制转储创建替代方案

除了非posix(因此不太可移植)的xxd之外,还有od八进制 转储),它应该在所有类unix系统上都可用,因为它是由posix指定的:

od -tx1 -An -v

将以十六进制转储方式打印,将数字按单个字节分组(-tx1),不带地址前缀 (-An,类似于xxd -p),不缩写重复部分为 * (-v)。您可以使用 xxd -r -p 反转此类转储。


这对我来说不是必要的(MacOS Mojave) - tripleee
1
如果你使用hexdump命令的-v选项运行它,就可以避免*错误。 - David Knipe
或者您可以指定十六进制转储格式,这样您就可以只使用 xxd -p -r mydumphexdump -ve '1/1 "%.2x"' mybinaryfile > mydump - dagelf
1
对我来说,这个问题的重点是反转一个十六进制转储,而你没有二进制文件。在这种情况下,无法以另一种格式进行转储。无论如何,我都必须更新这个答案,因为有些人声称 xdd -r 可以单独处理 hexdump 的默认输出。 - Socowi
请记住,那些只有二进制文件,但没有其他传输方式,只能通过telnet或串行访问控制台来获取该文件的人也会遇到这个问题和答案:因此无需更新。此外,Google已经将其索引用于有关反转十六进制转储的搜索中 :-0 - dagelf
显示剩余2条评论

3
作为一个对bash不擅长的人,我无法理解已经发布的示例。 以下是我最初搜索时会有用的内容:
取出你的文本文件“AYE.TXT”,并将其转换为名为“BEE.TXT”的十六进制转储。
xxd -p "AYE.TXT" > "BEE.TXT"

将十六进制转储文件(“BEE.TXT”)转换回 ASCII 文件“CEE.TXT”。
xxd -r -p "BEE.TXT" > "CEE.TXT"

现在你有一些简单的可工作代码,可以在命令行上检查 "xxd -help" 以了解所有这些标志的含义。 (这部分很容易,难的是bash语法的具体细节)

从man xxd:使用组合-r -p来读取没有行号信息和特定列布局的纯十六进制转储。谢谢@KANJICODER,这是一个快速有效的答案! - undefined

1

如果您没有xxd,可以使用hexdumpodperlpython

以下所有方法都会产生相同的输出:

# If you only have hexdump
hexdump -ve '1/1 "%.2x"' mybinaryfile > mydump

# This gives exactly the same output as:
xxd -p mybinaryfile > mydump

# Or, much slower:
od -v -t x1 -An < mybinaryfile | tr -d "\n " > mydump 

# Or, the fastest:
perl -pe 'BEGIN{$/=\1e6} $_=unpack "H*"' < mybinaryfile > mydump

# Or, if you somehow have Python, and not Perl:
python -c "print(open('mybinaryfile','rb').read().hex())" > mydump

然后您可以复制粘贴或使用管道输出,并使用以下命令进行转换:

xxd -r -p mydump mybinaryfileagain

# Or
xxd -r -p < mydump > mybinaryfileagain

hexdump命令几乎可以在任何地方使用,并且通常是默认的busybox的一部分 - 如果没有链接,您可以尝试运行busybox hexdumpbusybox xxd

如果xxd不可用于反转数据,则可以尝试使用awk。

旧时代:Zmodem

在旧时代,我们曾经使用X/Y/Zmodem,它包含在lrzsz软件包中,可以容忍有损通信 - 但它是双向协议,因此二进制文件需要同时运行,并且需要双向通信:

# Demo on local machine, using FIFOs
mkfifo /tmp/fifo-in
mkfifo /tmp/fifo-out
sz -b mybinaryfile > /tmp/fifo-out < /tmp/fifo-in
mkdir out; cd out
rz -b < /tmp/fifo-out > /tmp/fifo-in

幸运的是,screen支持接收Zmodem,因此如果你在一个screen会话中:
screen
telnet somehost

然后输入Ctrl+A,然后:,然后zmodem catchEnter。然后在远程主机的屏幕内,输入:

# sz -b mybinaryfile

当你看到以 "!!!" 开头的字符串时,请按 Enter 键。

当你看到 "Transfer Complete" 时,如果想要正常继续终端会话,可以运行 reset 命令。


0

0

有很多更优雅的方法来完成这个任务,但是在重新生成由hexdump -C some_file.bin生成的十六进制转储文件时,我已经快速地把一些东西拼凑在一起,对我很有效(商标):

sed 's/\(.\{8\}\)  \(..\) \(..\) \(..\) \(..\) \(..\) \(..\) \(..\) \(..\)/\1: \2\3 \4\5 \6\7 \8\9/g' some_file.hexdump | sed 's/\(.*\)  \(..\) \(..\) \(..\) \(..\) \(..\) \(..\) \(..\) \(..\)  |/\1 \2\3 \4\5 \6\7 \8\9  /g' | sed 's/.$//g' | xxd -r > some_file.restored

基本上,使用2个sed进程,每个进程处理每行的一部分。虽然不太美观,但某些人可能会发现它有用。


0
我找到了更简单的解决方法:
bin2hex
echo -n "abc" | hexdump -ve '1/1 "%02x"'
hex2bin
echo -n "616263" | grep -Eo ".{2}" | sed 's/\(.*\)/\\x\1/' | tr -d '\n' | xargs -0 echo -ne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接