尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Linux hexdump命令详解:从二进制文件分析到调试实战

Linux hexdump命令详解:从二进制文件分析到调试实战 1. 从“乱码”到“真相”为什么我们需要hexdump在Linux世界里我们每天都在和各种文件打交道。文本文件用cat、less一目了然二进制文件呢比如一个编译好的可执行程序、一张图片的原始数据、一段网络抓来的数据包或者系统里某个神秘的日志文件你用文本编辑器打开很可能看到的是一堆乱码或者干脆被编辑器拒绝。这时候一种“透视”能力就变得至关重要——直接查看文件最原始的字节形态。hexdump命令就是Linux系统赋予我们的这样一双“十六进制的眼睛”。我第一次深刻体会到它的价值是在排查一个诡异的服务崩溃问题时。日志文件里只留下一行“Segmentation fault (core dumped)”再无其他线索。用cat看core文件满屏的不可打印字符。直到用了hexdump配合objdump和addr2line我才从那一串串十六进制数字中定位到了一个函数指针在释放后被错误地再次使用。那一刻这些看似冰冷的数字仿佛在说话它们精确地记录了程序崩溃前内存的最后一幕。从此hexdump就成了我调试工具箱里的常客无论是分析网络协议、逆向工程小工具还是检查磁盘镜像的特定扇区它都是不可或缺的第一道工序。简单说hexdump是一个将文件内容以十六进制也可选八进制、十进制、ASCII格式转储dump到标准输出的工具。它不关心文件的格式或内容含义只是忠实地将每一个字节转换为可读的数值。这对于程序员、系统管理员、安全研究员乃至嵌入式开发者来说是一项基础且强大的技能。接下来我将带你从入门到精通不仅学会怎么用更要明白为何这么用以及如何避开我踩过的那些坑。2. hexdump命令的核心语法与模式解析刚接触hexdump你可能会被它众多的选项吓到。别担心我们化繁为简它的核心语法其实就一条hexdump [选项] [文件...]如果不指定文件或者文件名为-它会从标准输入读取数据。这意味着你可以用管道将其他命令的输出直接交给hexdump分析非常灵活。hexdump的强大之处在于其格式控制选项-C和-e。这形成了它的两种主要使用模式经典布局模式和自定义格式化模式。理解这两种模式你就掌握了八成以上的使用场景。2.1 经典布局模式-C 选项这是最常用、最直观的模式。-C选项告诉hexdump使用一种“标准”的、信息密度很高的格式输出很多人也称之为“Canonical”规范模式。hexdump -C filename.bin执行后你会看到类似这样的输出00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 3e 00 01 00 00 00 c0 55 40 00 00 00 00 00 |........U.....| 00000020 40 00 00 00 00 00 00 00 e0 1d 02 00 00 00 00 00 |...............| 00000030 00 00 00 00 40 00 38 00 09 00 40 00 1c 00 1b 00 |.....8........|这个布局分为三列地址偏移量Offset最左边的8位十六进制数例如00000000表示当前行第一个字节在文件中的起始位置。这对于定位特定数据块至关重要。十六进制字节区Hex Bytes中间部分每行显示16个字节这是默认值可通过-s和-n控制范围。每两个十六进制数表示一个字节例如7f字节之间用空格分隔。为了便于阅读每8个字节后会插入一个额外的空格。这是文件的“原始真相”。ASCII表示区ASCII Representation最右边在竖线|之间。这里将中间的16个字节尝试解释为ASCII字符。如果是可打印字符如字母、数字、标点就显示出来如果是控制字符或不可打印字符则显示为一个点.。这一列让你能快速瞥见文件中可能存在的文本信息。比如上面例子开头的.ELF就明确告诉我们这是一个ELF格式的可执行文件。注意-C模式是许多人的首选因为它一次性提供了地址、十六进制和ASCII三种视角信息全面且排版整齐。在大多数不需要复杂格式化的场景下直接用-C准没错。2.2 自定义格式化模式-e 选项当你需要更精细地控制输出格式或者要解析具有特定结构的数据时-eformat string选项就是你的瑞士军刀。这个模式功能强大但语法也稍复杂。其基本格式是hexdump -e ‘格式字符串1’ -e ‘格式字符串2’ ... 文件名格式字符串由一系列“转换单元conversion units”组成放在单引号内。每个转换单元告诉hexdump如何解释和显示一定数量的输入字节。最常见的转换说明符有%_p 用默认的字符集显示字符类似-C的ASCII列。%_c 同样显示字符。%_u 显示US-ASCII字符控制字符显示为缩写。%x、%d、%o 分别以十六进制、十进制、八进制整数形式解释并显示数据。%_ad 以十进制显示当前偏移地址。%_ax 以十六进制显示当前偏移地址。你可以在说明符前加数字表示重复次数或字节数。例如%16x 将接下来的16个字节每1个字节作为一个十六进制数输出输出16个数字。8/2 “%04x ” “8/2”表示重复8次每次处理2个字节。“%04x”表示将2个字节16位作为一个十六进制整数输出宽度为4位不足补零。这常用于查看16位的短整型数据。一个简单的例子如果我们只想看十六进制不要ASCII列并且每行显示8个字节hexdump -e ‘8/1 “%02x ” “\n”’ data.bin这个命令中8/1表示将接下来的8个字节每个字节1 byte按“%02x ”格式输出两位十六进制后跟空格。处理完8个字节后输出一个换行符“\n”。实操心得自定义格式初学有点绕建议从模仿开始。可以先用手头的文件用-C模式看一遍然后思考“如果我只想要其中某一部分信息该怎么写格式字符串”。多试几次就能逐渐掌握。对于分析网络协议头如IP、TCP头固定格式或自定义二进制文件结构这个功能无可替代。3. 常用参数详解与实战场景组合除了核心的-C和-ehexdump还有其他一系列参数用于处理不同的查看需求。下面我结合具体场景讲解最常用的几个。3.1 限制查看范围-sskip与 -nlength你有一个几百MB的大日志文件但只想看文件开头100个字节或者跳过文件头直接看中间某部分。这时候-s和-n就是你的剪刀。-s offset 跳过文件开头offset字节后再开始显示。offset可以带后缀如-s 10k跳过10KB-s 2M跳过2MB。-n length 仅显示length字节长度的数据。场景一查看文件开头部分如文件头、魔数hexdump -C -n 128 myfile.zip这命令查看myfile.zip的前128个字节。对于ZIP文件开头通常会有PK魔数你可以快速验证文件是否完整或格式是否正确。场景二跳过文件头查看特定数据结构假设你知道一个自定义数据文件的前512字节是文件头你想查看紧接着的文件体内容。hexdump -C -s 512 -n 256 data.bin这命令跳过前512字节然后显示接下来的256字节。场景三结合使用精确定位这在分析崩溃的core文件时特别有用。你从日志或调试器得到一个内存地址需要查看该地址附近的内容。hexdump -C -s 0x7ffc01a4b320 -n 64 core.1234这里我直接使用了十六进制的偏移量0x7ffc01a4b320。hexdump的-s参数接受十进制和以0x开头的十六进制数非常方便。3.2 控制输出长度-vverbose选项默认情况下hexdump为了节省输出空间如果连续多行的内容完全相同它会用一颗星号*来表示这些行被省略了。00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200 48 65 6c 6c 6f 20 57 6f 72 6c 64 0a 00 00 00 00 |Hello World.....|中间从0x00000110到0x000001f0的内容都是0被压缩显示为*。这在查看大部分是空值如新格式化的磁盘片段的文件时很清晰。但如果你在排查问题需要确认某一段区域是否真的全是某个值而不是因为其他原因被省略这个“智能”压缩就很危险。-v选项强制hexdump显示所有输入数据一行都不省略。hexdump -C -v large_zeros.bin在需要绝对精确、进行二进制数据比对或调试时务必加上-v选项。这是我早期踩过的一个坑我以为一段数据全是0结果因为没加-v错过了中间一个非0的异常字节导致排查方向错误浪费了好几个小时。3.3 其他实用参数-b 单字节八进制显示。这是最“古老”的格式之一现在用得少了但在一些旧的协议或文档中可能遇到。-x 双字节十六进制显示。它把每2个字节16位作为一个单元以十六进制输出。注意它受系统字节序Endianness影响。在x86/x86_64小端序系统上文件中的字节序列01 02会被解释为0x0201然后输出。如果不清楚字节序使用-C更稳妥。-d 双字节十进制显示。同样受字节序影响。4. 高级技巧与组合拳应用掌握了基础命令我们可以玩一些更高级的操作将hexdump与其他命令组合解决实际问题。4.1 动态分析结合管道|与tail -f当你想实时监控一个不断增长的文件比如应用日志的原始字节流时可以这样tail -f application.log | hexdump -C或者你只想看日志中新增的、包含特定错误的行假设错误码0xdeadbeef以二进制形式写入tail -f application.log | hexdump -C | grep -A2 -B2 “dead beef”这里grep搜索十六进制输出中的模式。注意在-C模式下十六进制部分和ASCII部分是分开的grep会搜索整行。4.2 数据提取结合dd和xxd有时你需要从一个大文件中精确截取一小块数据进行分析或保存。dd是块数据拷贝的利器。# 从文件disk.img的偏移量1024KB处截取4KB数据并用hexdump查看 dd ifdisk.img bs1k skip1024 count4 2/dev/null | hexdump -C | head -20dd的参数if是输入文件bs是块大小skip是跳过多少块这里块大小是1KB所以跳过1024块即1024KBcount是拷贝多少块4块即4KB。2/dev/null是为了隐藏dd的统计信息。然后通过管道交给hexdump查看前20行。另一个强大的工具是xxd它和hexdump功能类似但有一个独门绝技它可以将十六进制输出反向转换回二进制文件。# 1. 用xxd生成一个文件的十六进制转储带地址 xxd original.bin hexdump.txt # 2. 你可以编辑这个hexdump.txt文件比如修改某些字节的值 # 3. 用xxd将编辑后的十六进制文件还原为二进制 xxd -r hexdump.txt modified.bin这个“编辑-回写”的功能在手动修补二进制文件、修改固件特定字节等场景下非常有用。而hexdump本身不具备反向转换功能。4.3 自定义格式解析复杂结构假设你有一个简单的二进制数据文件data.bin其结构定义为前4字节是一个32位整数小端序表示ID接着2字节是一个16位整数小端序表示长度接着是可变长度的数据。 你可以用hexdump的自定义格式来清晰地查看hexdump -e ‘1/4 “ID: %08x ” 1/2 “Len: %04x ” “\n”’ -e ‘”Data: ” 1/1 “%02x ” “\n\n”’ data.bin这个命令比较复杂它用了两个格式字符串。第一个-e处理ID和长度1/4表示处理1次每次4字节按32位十六进制输出1/2同理。第二个-e处理数据部分。实际上对于变长数据更好的方法是先用-s和-n定位或者写一个小脚本配合hexdump解析。5. 常见问题排查与避坑指南即使掌握了命令在实际使用中还是会遇到各种问题。下面是我总结的一些典型场景和解决方案。5.1 问题输出看起来是乱的字节顺序不对现象你用-x或-d查看一个已知数据的文件发现输出的多字节整数如0x1234显示成了0x3412。原因与解决你遇到了字节序Endianness问题。-x和-d选项默认按你当前系统的字节序来解释数据。x86/x86_64架构是小端序Little-Endian即低位字节在前。如果你的数据文件是按大端序Big-Endian网络字节序常见存储的解释就会出错。解决方案1优先使用-C模式。它按单字节显示不涉及多字节解释没有字节序困扰你可以自己手动组合字节。解决方案2如果你必须用-x查看大端序数据并且知道文件格式可以事后在脑子里或通过脚本进行字节反转。更专业的做法是使用像od八进制转储命令它提供了-I使用本地字节序的4字节整数等更多显式控制选项。5.2 问题想搜索文件中的特定十六进制序列现象你知道文件中某处存在字节序列CA FE BA BEJava class文件的魔数想快速找到它的位置。解决hexdump本身没有搜索功能但我们可以用管道组合grep。hexdump -C file.bin | grep -n “ca fe ba be”但这里有个大坑-C模式输出中十六进制部分每两个字符之间是有空格的而ASCII部分也可能包含这些字符的文本表示。上面的命令可能会匹配到ASCII栏里恰好是“ca fe ba be”的文本行而不是十六进制值。 更可靠的方法是使用xxd或odxxd -p file.bin | grep -o ‘cafebabe’ | head -1xxd -p输出纯连续的十六进制字符串无空格无地址然后我们用grep -o只输出匹配的部分。再结合xxd -p的偏移量计算就能定位。或者直接用grep的二进制模式但不太直观grep -obUaP “\xca\xfe\xba\xbe” file.bin5.3 问题查看大文件时输出刷屏太快现象对一个几GB的文件直接运行hexdump -C终端会疯狂输出直到文件结束。解决一定要养成先限制范围的习惯。除非你明确需要全部内容否则总是结合-n查看前N字节或head命令。# 只看前1KB hexdump -C -n 1024 hugefile.bin # 或者用管道交给less分页查看 hexdump -C hugefile.bin | less # 结合tail查看文件末尾比如看文件尾部的索引或摘要信息 tail -c 512 hugefile.bin | hexdump -C在管道中使用less可以上下翻页、搜索是查看长输出的标准做法。5.4 问题如何比较两个二进制文件的差异现象两个文件看起来应该一样但行为不同你想找出它们第一个不同的字节在哪里。解决hexdump本身不直接做比较但我们可以用它的输出作为diff的输入。不过更专业高效的工具是cmp和vbindiff。# 使用cmp快速定位第一个不同点 cmp -l file1.bin file2.bin | head -5cmp -l会以十进制格式列出所有不同的字节位置、file1的字节值、file2的字节值。找到位置后再用hexdump去查看该位置附近的上下文。# 假设cmp报告第一个不同在偏移量1234十进制 hexdump -C -s 1220 -n 40 file1.bin # 查看file1从1220开始的40字节 hexdump -C -s 1220 -n 40 file2.bin # 对比查看file2对于图形化界面vbindiffVisual Binary Diff工具可以并排高亮显示两个二进制文件的差异非常直观。5.5 一个容易忽略的细节关于“字节”与“字符”这是概念上的一个坑。hexdump处理的是字节Byte即8位数据。而我们在终端或文本编辑器中看到的“字符”可能对应一个字节ASCII也可能对应多个字节UTF-8编码的中文等。-C模式右边的ASCII栏只是简单地将每个字节的值映射到ASCII字符集0-127对于大于127的字节它统一显示为点.这不意味着该字节是无效的它可能只是UTF-8编码的一部分。例如一个UTF-8编码的中文字“你”其十六进制是E4 BD A0三个字节。用hexdump -C查看ASCII栏会显示三个点...。不要误以为这是乱码或损坏这只是因为hexdump没有进行UTF-8解码。要查看正确的文本应该使用文本查看命令如cat、less并确保终端编码正确。最后分享一个我个人的习惯在编写脚本或文档时如果需要展示一小段二进制数据我常常会用hexdump -C生成输出然后复制粘贴。比起用文字描述“偏移量0x10处是0x7f接着是0x45, 0x4c, 0x46...”直接贴上一段hexdump的输出清晰又准确能让读者一目了然。这个命令看似简单却是深入计算机底层世界的一把钥匙用得越熟练你对自己所处理的数据的理解就越透彻。
返回列表