多进制数据查看工具-xxd


xxd 是一个 Linux 下的命令行工具,用于将文件或数据转换为十六进制格式显示,类似于十六进制查看器;也可以将十六进制数据重新转换为二进制文件。通常用于调试、文件内容分析和数据转换。
语法格式:xxd [参数] 文件名
xxd [options] [infile [outfile]]
xxd -r[evert] [options] [infile [outfile]]
inputfile:输入文件。如果未指定,则读取标准输入。
outputfile:输出文件。如果未指定,则输出到标准输出。
如果没有给定输入文件,标准输入就作为输入文件infile;如果infile是一个'-'字符,也从标准输入读入。如果没有给定outfile (或者它的文件名是一个'-'字符),结果将输出至标准输出。
为什么需要xxd
当调试网络协议、分析文件结构或处理加密数据时,常常会遇到这样的困境:
这个文件为什么无法用cat查看?
这个加密结果为什么是乱码?
如何确认这个二进制文件的实际内容?
OpenSSL怎样得到和其它编程语言一致的加密结果?
xxd就是为解决这些问题而生:能在二进制和可读文本之间架起一座桥梁,让不可见的二进制世界变得可见。与hexdump共同撑起多进制的内容。
常用选项简介:
-a 自动跳过空白内容。
-b
转到比特(二进制数字)模式,而不是十六进制模式。在这种模式下,每个字符被表示成8个 0/1 的数字,而不是一般的十六进制形式。每一行都以一个用十六进制形式表示的行号,后面是ascii (或者 ebcdic) 形式开头。命令行选项 -r, -p 在这个模式下不起作用。
-c 设置每行显示多少字节内容,默认为 16。
-g 设置以几个字节为一块。即每组显示多少字节,默认为 2。
-h 显示帮助信息后退出。
-i 显示为C语言的包含文件形式。即以 C 语言的数组格式输出。
-l N 只输出 N 个字符还只显示指定长度的字节。
-p 以连续纯十六进制形式(不带偏移地址和 ASCII)转储输出,这也叫做纯十六进制转储。
-r 逆向操作:把xxd的十六进制输出内容转换回原文件的二进制内容。
-seek offset 用在 -r 之后: 会在当前文件的偏移量上增加 <offset>。
-s [+][-]seek
从infile的绝对或者相对偏移量开始。'+'表示相对于标输入当前的位置(如果不标准输入就没有意义了)。'-'表示从档桉末尾(如果和 + 连用:从标准输入当前位置)向前数一些字符,从那个地方开始。如果没有 -s 选项,xxd 从当前位置开始。支持负数表示从文件末尾开始。
-u 十六进制输出时使用大写字母,默认是小写字母。
-v | -version 显示版本字符串。
详细选项介绍:
-a | -autoskip
打开/关闭 autoskip: 用一个单独的 '*' 来代替空行。默认关闭。
-b | -bits
转到比特(二进制数字)模式,而不是十六进制模式。在这种模式下,每个字符被表示成八个0/1的数字, 而不是一般的十六进制形式。每一行都以一个用十六进制形式表示的行号,后面是 ascii (或ebcdic)形式开头。命令行选项-r, -p, -i在这个模式下不起作用。
-c cols | -cols cols
cols每行表示<cols>个字符。 默认 16 (-i: 12, -ps: 30, -b: 6)。最多256。
-g bytes | -groupsize bytes
每<bytes>个字符(每两个十六进制字符或者八个二进制数字)之间用一个空格隔开。用 -g 0禁止分组。在普通模式中<Bytes>默认是2,在二进制模式中是1。分组并不适用于postscript 或者include style 选项。
-h | -help
显示可用命令概述并且退出。不做其它任何事情。
-i | -include
输出为C语言的包含文件形式。除非xxd从标准输入读入,不然会输出一个完整的静态数组定义(与输入文件同名)。
-l len | -len len
输出<len>个字符后停止。
-p | -ps | -postscript | -plain
以postscript的连续十六进制转储输出。这也叫做纯十六进制转储。
-r | -revert
逆向操作:把十六进制转储转换(或者打补丁)成二进制形式。如果不输出到标准输出,xxd并不把输出文件截断,而是直接写到输出文件。用 -r -p 来从一个没有行号没有某种列格式的纯十六进制转储读入。附加的空格和换行可以出现在任何地方。
-seek offset
用在-r之后:会在当前文件的偏移量上增加 <offset>。
-s [+][-]seek
从infile的绝对或者相对偏移量<seek>开始。'+'表示相对于标准输入当前的位置(如果不是标准输入就没有意义了)。'-'表示从文件末尾(如果和+连用:从标准输入当前位置)向前数一些字符,从那个地方开始。如果没有-s选项,xxd从当前位置开始。
-u
用大写字母。默认的是小写字母。
-v | -version
显示版本字符串。
常见用法
将文件以十六进制格式输出:
xxd filename
该命令会将 filename 文件以十六进制的方式显示。
将标准输入转换为十六进制:
echo "Hello World" | xxd
这会把字符串 "Hello World" 转换为十六进制并输出。
指定每行输出的字节数:默认情况下,xxd 每行输出 16 字节的数据。可以使用 -c 参数修改:
xxd -c 8 filename
上述命令将每行显示 8 个字节的数据。
转换回原始数据:xxd 也可以将十六进制格式转换回原始的二进制数据,使用 -r 参数:
xxd -r hexfile
该命令将 hexfile 中的十六进制数据还原为二进制文件。
仅显示十六进制(不显示 ASCII):使用 -p 选项只显示纯十六进制,不显示对应的 ASCII 字符:
xxd -p filename
控制输出的范围:使用 -s 参数可以指定从文件的某个偏移处开始输出,使用 -l 指定输出的字节长度:
xxd -s 0x10 -l 0x20 filename
该命令从偏移量 0x10 开始,输出 0x20 字节的数据。
xxd -s 100 -l 16 file # 从100字节处读取16字节
echo "48656c6c6f" | xxd -r -p | xxd -u -p # 小写转大写
核心功能:二进制与十六进制的双向转换
1. 文件内容可视化(hexdump)
xxd image.png | head -n 5
输出:
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 02bc 0000 01e0 0806 0000 00a0 9c0e ................
00000020: 1a00 0000 0173 5247 4200 aece 1ce9 0000 .....sRGB.......
00000030: 0004 6741 4d41 0000 b18f 0bfc 6105 0000 ..gAMA......a...
00000040: 0009 7048 5973 0000 1625 0000 1625 0149 ..pHYs...%...%.I
格式解读:
左侧:偏移地址(文件位置)
中间:十六进制数据(每2字符=1字节)
右侧:ASCII字符(不可显示字符显示为.)
2. 简洁十六进制输出(无干扰查看)
echo -n "Hello" | xxd -p -u
输出:48656c6c6f
参数说明:
-p:输出纯十六进制字符串(无地址/ASCII干扰)
-u:输出大写十六进制(默认小写)
注意:-p 与 -u 选项不能合并为 -pu 使用,否则只有第一个选项生效。这与大多数 Linux 命令(如 sort)允许合并多个无参数选项的惯例不同。
3. 反向转换:十六进制转为二进制
echo "48656c6c6f" | xxd -r -p
输出:Hello
参数说明:
-r:反向模式(十六进制→二进制)
-p:识别连续十六进制输入(无空格/换行)
使用'-i'参数生成 C语言中的数组格式,bcc工具也提供此功能。
xxd -i filename.txt
此命令会将文件内容以 C语言数组的形式输出并附上其内容长度。输出示例:
unsigned char filename_txt[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x0a
};
unsigned int filename_txt_len = 6;
此处的文件内容为:Hello.
注意:0x0a表示换行符LF,即'\n'。
显示 file 除了前三行 (十六进制的 0×30) 的所有内容
xxd -s 0×30 file
显示 120 个字符, 每行 20 个 字符,并连续显示
xxd -l 120 -ps -c 20 file
以十六进制形式查看文件,自动跳过空白,从0x200位置开始显示内容
xdd -a -s +0x200 file
以十六进制形式查看文件,每行显示12字节,从0x200位置开始显示内容
xxd -c 12 -s +0x200 file
以十六进制形式查看文件,1个字节一块,总共显示512字节内容
xxd -g 1 -l 512 -s +0x200 file
密钥转换(加密必备)
# 文本密钥转十六进制(用于OpenSSL)
echo -n "mySecretKey" | xxd -p
# 输出:6d795365637265744b6579
# 十六进制密钥转文本(验证密钥)
echo "6d795365637265744b6579" | xxd -r -p
AES加密实战(输出十六进制密文)
# 加密示例:明文"Hello",密钥"123456"
echo -n "Hello" | openssl enc -aes-128-ecb \
-K $(echo -n "123456" | xxd -p | awk '{printf "%032s", $0}' | tr ' ' '0') \
-nosalt | xxd -p | tr -d '\n'
# 输出:504dbf479a69343d62542624e9333555
xxd -p:将文本密钥转为十六进制
awk '{printf "%032s", $0}':补全到32字符(16字节)
tr ' ' '0':将空格替换为0(补位处理)
最终xxd -p:将二进制密文转为十六进制
需要注意的是密钥长度的处理:AES 算法支持的密钥长度分为 16 字节、24 字节和 32 字节三种规格。在使用 OpenSSL 命令行操作时,需分别通过 awk 将密钥的十六进制表示补足至 32 字符、48 字符和 64 字符,分别对应 aes-128-ecb、aes-192-ecb 和 aes-256-ecb 三种加密模式。
文件头分析(文件类型识别)
xxd -l 8 unknown_file
# JPEG文件:ffd8ffe0
# PNG文件: 89504e47
# PDF文件:25504446 (%PDF)
网络调试(抓包数据分析)
tcpdump -w packet.pcap
xxd packet.pcap | grep "HTTP" -B 2 -A 5
二进制补丁(直接修改文件)
# 将文件前4字节改为"ABCD"
echo "41424344" | xxd -r -p | dd of=targetfile bs=1 seek=0 count=4 conv=notrunc
语法格式:xxd [参数] 文件名
xxd [options] [infile [outfile]]
xxd -r[evert] [options] [infile [outfile]]
inputfile:输入文件。如果未指定,则读取标准输入。
outputfile:输出文件。如果未指定,则输出到标准输出。
如果没有给定输入文件,标准输入就作为输入文件infile;如果infile是一个'-'字符,也从标准输入读入。如果没有给定outfile (或者它的文件名是一个'-'字符),结果将输出至标准输出。
为什么需要xxd
当调试网络协议、分析文件结构或处理加密数据时,常常会遇到这样的困境:
这个文件为什么无法用cat查看?
这个加密结果为什么是乱码?
如何确认这个二进制文件的实际内容?
OpenSSL怎样得到和其它编程语言一致的加密结果?
xxd就是为解决这些问题而生:能在二进制和可读文本之间架起一座桥梁,让不可见的二进制世界变得可见。与hexdump共同撑起多进制的内容。
常用选项简介:
-a 自动跳过空白内容。
-b
转到比特(二进制数字)模式,而不是十六进制模式。在这种模式下,每个字符被表示成8个 0/1 的数字,而不是一般的十六进制形式。每一行都以一个用十六进制形式表示的行号,后面是ascii (或者 ebcdic) 形式开头。命令行选项 -r, -p 在这个模式下不起作用。
-c 设置每行显示多少字节内容,默认为 16。
-g 设置以几个字节为一块。即每组显示多少字节,默认为 2。
-h 显示帮助信息后退出。
-i 显示为C语言的包含文件形式。即以 C 语言的数组格式输出。
-l N 只输出 N 个字符还只显示指定长度的字节。
-p 以连续纯十六进制形式(不带偏移地址和 ASCII)转储输出,这也叫做纯十六进制转储。
-r 逆向操作:把xxd的十六进制输出内容转换回原文件的二进制内容。
-seek offset 用在 -r 之后: 会在当前文件的偏移量上增加 <offset>。
-s [+][-]seek
从infile的绝对或者相对偏移量开始。'+'表示相对于标输入当前的位置(如果不标准输入就没有意义了)。'-'表示从档桉末尾(如果和 + 连用:从标准输入当前位置)向前数一些字符,从那个地方开始。如果没有 -s 选项,xxd 从当前位置开始。支持负数表示从文件末尾开始。
-u 十六进制输出时使用大写字母,默认是小写字母。
-v | -version 显示版本字符串。
详细选项介绍:
-a | -autoskip
打开/关闭 autoskip: 用一个单独的 '*' 来代替空行。默认关闭。
-b | -bits
转到比特(二进制数字)模式,而不是十六进制模式。在这种模式下,每个字符被表示成八个0/1的数字, 而不是一般的十六进制形式。每一行都以一个用十六进制形式表示的行号,后面是 ascii (或ebcdic)形式开头。命令行选项-r, -p, -i在这个模式下不起作用。
-c cols | -cols cols
cols每行表示<cols>个字符。 默认 16 (-i: 12, -ps: 30, -b: 6)。最多256。
-g bytes | -groupsize bytes
每<bytes>个字符(每两个十六进制字符或者八个二进制数字)之间用一个空格隔开。用 -g 0禁止分组。在普通模式中<Bytes>默认是2,在二进制模式中是1。分组并不适用于postscript 或者include style 选项。
-h | -help
显示可用命令概述并且退出。不做其它任何事情。
-i | -include
输出为C语言的包含文件形式。除非xxd从标准输入读入,不然会输出一个完整的静态数组定义(与输入文件同名)。
-l len | -len len
输出<len>个字符后停止。
-p | -ps | -postscript | -plain
以postscript的连续十六进制转储输出。这也叫做纯十六进制转储。
-r | -revert
逆向操作:把十六进制转储转换(或者打补丁)成二进制形式。如果不输出到标准输出,xxd并不把输出文件截断,而是直接写到输出文件。用 -r -p 来从一个没有行号没有某种列格式的纯十六进制转储读入。附加的空格和换行可以出现在任何地方。
-seek offset
用在-r之后:会在当前文件的偏移量上增加 <offset>。
-s [+][-]seek
从infile的绝对或者相对偏移量<seek>开始。'+'表示相对于标准输入当前的位置(如果不是标准输入就没有意义了)。'-'表示从文件末尾(如果和+连用:从标准输入当前位置)向前数一些字符,从那个地方开始。如果没有-s选项,xxd从当前位置开始。
-u
用大写字母。默认的是小写字母。
-v | -version
显示版本字符串。
常见用法
将文件以十六进制格式输出:
xxd filename
该命令会将 filename 文件以十六进制的方式显示。
将标准输入转换为十六进制:
echo "Hello World" | xxd
这会把字符串 "Hello World" 转换为十六进制并输出。
指定每行输出的字节数:默认情况下,xxd 每行输出 16 字节的数据。可以使用 -c 参数修改:
xxd -c 8 filename
上述命令将每行显示 8 个字节的数据。
转换回原始数据:xxd 也可以将十六进制格式转换回原始的二进制数据,使用 -r 参数:
xxd -r hexfile
该命令将 hexfile 中的十六进制数据还原为二进制文件。
仅显示十六进制(不显示 ASCII):使用 -p 选项只显示纯十六进制,不显示对应的 ASCII 字符:
xxd -p filename
控制输出的范围:使用 -s 参数可以指定从文件的某个偏移处开始输出,使用 -l 指定输出的字节长度:
xxd -s 0x10 -l 0x20 filename
该命令从偏移量 0x10 开始,输出 0x20 字节的数据。
xxd -s 100 -l 16 file # 从100字节处读取16字节
echo "48656c6c6f" | xxd -r -p | xxd -u -p # 小写转大写
核心功能:二进制与十六进制的双向转换
1. 文件内容可视化(hexdump)
xxd image.png | head -n 5
输出:
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 02bc 0000 01e0 0806 0000 00a0 9c0e ................
00000020: 1a00 0000 0173 5247 4200 aece 1ce9 0000 .....sRGB.......
00000030: 0004 6741 4d41 0000 b18f 0bfc 6105 0000 ..gAMA......a...
00000040: 0009 7048 5973 0000 1625 0000 1625 0149 ..pHYs...%...%.I
格式解读:
左侧:偏移地址(文件位置)
中间:十六进制数据(每2字符=1字节)
右侧:ASCII字符(不可显示字符显示为.)
2. 简洁十六进制输出(无干扰查看)
echo -n "Hello" | xxd -p -u
输出:48656c6c6f
参数说明:
-p:输出纯十六进制字符串(无地址/ASCII干扰)
-u:输出大写十六进制(默认小写)
注意:-p 与 -u 选项不能合并为 -pu 使用,否则只有第一个选项生效。这与大多数 Linux 命令(如 sort)允许合并多个无参数选项的惯例不同。
3. 反向转换:十六进制转为二进制
echo "48656c6c6f" | xxd -r -p
输出:Hello
参数说明:
-r:反向模式(十六进制→二进制)
-p:识别连续十六进制输入(无空格/换行)
使用'-i'参数生成 C语言中的数组格式,bcc工具也提供此功能。
xxd -i filename.txt
此命令会将文件内容以 C语言数组的形式输出并附上其内容长度。输出示例:
unsigned char filename_txt[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x0a
};
unsigned int filename_txt_len = 6;
此处的文件内容为:Hello.
注意:0x0a表示换行符LF,即'\n'。
显示 file 除了前三行 (十六进制的 0×30) 的所有内容
xxd -s 0×30 file
显示 120 个字符, 每行 20 个 字符,并连续显示
xxd -l 120 -ps -c 20 file
以十六进制形式查看文件,自动跳过空白,从0x200位置开始显示内容
xdd -a -s +0x200 file
以十六进制形式查看文件,每行显示12字节,从0x200位置开始显示内容
xxd -c 12 -s +0x200 file
以十六进制形式查看文件,1个字节一块,总共显示512字节内容
xxd -g 1 -l 512 -s +0x200 file
密钥转换(加密必备)
# 文本密钥转十六进制(用于OpenSSL)
echo -n "mySecretKey" | xxd -p
# 输出:6d795365637265744b6579
# 十六进制密钥转文本(验证密钥)
echo "6d795365637265744b6579" | xxd -r -p
AES加密实战(输出十六进制密文)
# 加密示例:明文"Hello",密钥"123456"
echo -n "Hello" | openssl enc -aes-128-ecb \
-K $(echo -n "123456" | xxd -p | awk '{printf "%032s", $0}' | tr ' ' '0') \
-nosalt | xxd -p | tr -d '\n'
# 输出:504dbf479a69343d62542624e9333555
xxd -p:将文本密钥转为十六进制
awk '{printf "%032s", $0}':补全到32字符(16字节)
tr ' ' '0':将空格替换为0(补位处理)
最终xxd -p:将二进制密文转为十六进制
需要注意的是密钥长度的处理:AES 算法支持的密钥长度分为 16 字节、24 字节和 32 字节三种规格。在使用 OpenSSL 命令行操作时,需分别通过 awk 将密钥的十六进制表示补足至 32 字符、48 字符和 64 字符,分别对应 aes-128-ecb、aes-192-ecb 和 aes-256-ecb 三种加密模式。
文件头分析(文件类型识别)
xxd -l 8 unknown_file
# JPEG文件:ffd8ffe0
# PNG文件: 89504e47
# PDF文件:25504446 (%PDF)
网络调试(抓包数据分析)
tcpdump -w packet.pcap
xxd packet.pcap | grep "HTTP" -B 2 -A 5
二进制补丁(直接修改文件)
# 将文件前4字节改为"ABCD"
echo "41424344" | xxd -r -p | dd of=targetfile bs=1 seek=0 count=4 conv=notrunc