Hexdump是个用十六进制、十进制、八进制数或ASCII码显示二进制文件内容的工具。它是个用于检查的工具,也可用于数据恢复、逆向工程和编程。
学习基本用法Hexdump让你毫不费力地得到输出结果,依你所查看文件的尺寸,输出结果可能会非常多。本文中我们会创建一个1x1像素的PNG文件。你可以用图像处理应用如GIMP或Mtpaint来创建该文件,或者也可以在终端内用ImageMagick创建。
用ImagiMagick生成1x1像素PNG文件的命令如下:
$convert-size1x1canvas:
你可以用file命令确认此文件是PNG格式:
$:PNGimagedata,1x1,1-bitgrayscale,non-interlaced
你可能好奇file命令是如何判断文件是什么类型。巧的是,那正是hexdump将要揭示的原理。眼下你可以用你常用的图像查看软件来看看你的单一像素图片(它看上去就像这样:.),或者你可以用hexdump查看文件内部:
$3700f96e0000020002d410041b1000b8f61fc00000300005000063205248004d7a00002600084fa000000800000e875000030ea00000005000603a00009817009c7051ba003c000000000606202474b0044dd01138a00a0000704d49074507e3081a3539a48746b0000000000800a0044495441d7086063000002000100000009021e233bc00002500457474586164657400000a0633a65727461006530323931302d2d3700000b0353232543a303735353a2b333231303a00000c0ac305dcd00c10000742558456474746100000d03a656f6d69647966320031302d39373000000e0322d54353032353a3a373335312b3a3200000f0303090dd7de5000000004549444e42ae000010082600000102
透过一个你以前可能从未用过的视角,你所见的是该示例PNG文件的内容。它和你在图像查看软件中看到的是完全一样的数据,只是用一种你或许不熟悉的方式编码。
提取熟悉的字符串尽管默认的数据输出结果看上去毫无意义,那并不意味着其中没有有价值的信息。你可以用--canonical选项将输出结果,或至少是其中可翻译的部分,翻译成更加熟悉的字符集:
$|.PNG..IHDR|0000001000000001000000010100000000376ef9|.7n.|0000002027414d410000b18f0bfc61|$.gAMAa|0000003005000000206348524d00007a26000080|.cHRM..z|00000040840000fa00000080e000ea|..u0|000000506000003a9cba513c000000|`..:.p..Q|0000006002624b47440001dd8a13a4|.|00000070494d4507e3071a08393587a4b0460000|IME..95F..|00000080000a4944415408d76360000000020001|..IDAT..c`|00000090e221bc33000000257445587464617465|.!.3%tEXtdate|000000a03a637265631392d30372d|:|000000b032355432303a35373a35332b31323a30|25T20:57:53+12:0|000000c030accd5dc10000002574455874646174|0..].%tEXtdat|000000d0653a6d6f6469667900323031392d3037|e:|000000e02d32355432303a35373a35332b31323a|-25T20:57:53+12:|000000f03030dd90e57d0000000049454e44ae42|00}.|000001006082|`.|00000102
在右侧的列中,你看到的是和左侧一样的数据,但是以ASCII码展现的。如果你仔细看,你可以从中挑选出一些有用的信息,如文件格式(PNG)以及文件创建、修改日期和时间(向文件底部寻找一下)。
file命令通过头8个字节获取文件类型。程序员会参考libpng规范来知晓需要查看什么。具体而言,那就是你能在该图像文件的头8个字节中看到的字符串PNG。这个事实显而易见,因为它揭示了file命令是如何知道要报告的文件类型。
你也可以控制hexdump显示多少字节,这在处理大于一个像素的文件时很实用:
$
hexdump不只限于查看PNG或图像文件。你也可以用hexdump查看你日常使用的二进制文件,如ls、rsync,或你想检查的任何二进制文件。
用hexdump实现cat命令阅读PNG规范的时候你可能会注意到头8个字节中的数据与hexdump提供的结果看上去不一样。实际上,那是一样的数据,但以一种不同的转换方式展现出来。所以hexdump的输出是正确的,但取决于你在寻找的信息,其输出结果对你而言不总是直接了当的。出于这个原因,hexdump有一些选项可供用于定义格式和转化其转储的原始数据。
转换选项可以很复杂,所以用无关紧要的东西练习会比较实用。下面这个简易的介绍,通过重新实现cat命令来演示如何格式化hexdump的输出。首先,对一个文本文件运行hexdump来查看其原始数据。通常你可以在硬盘上某处找到GNU通用许可证(GNUGeneralPublicLicense)(GPL)的一份拷贝,也可以用你手头的任何文本文件。你的输出结果可能不同,但下面是如何在你的系统中找到一份GPL(或至少其部分)的拷贝:
$find/usr/share/doc/-typef-name"COPYING"|tail-1/usr/share/doc/libblkid-devel/COPYING
对其运行hexdump:
$hexdump/usr/share/doc/libblkid-devel/COPYING0000000685473696c206269620730000010726665657320666f777472613b6579200000020756f63206e6697274626900000307475206574696120646e6f2f0a726f6d000004069647966692020746e75656420726876565746d722073666f7420656847200000060554e4c207365657320726547656e606c75506c6263694c0a63696e65657300000806120207375706c627369656820647962[]
如果该文件输出结果很长,用--length(或短选项-n)来控制输出长度使其易于管理。
原始数据对你而言可能没什么意义,但你已经知道如何将其转换为ASCII码:
hexdump--canonical/usr/share/doc/libblkid-devel/COPYING0000000054686973206c696272620|Thislibraryis|000000106672656520736f6674776172653b2079|freesoftware;y|000000206f752063616e20726564697374726962|oucanredistrib|0000003075746520697420616e642f6f720a6d6f|uteitand/|000000406469667920697420756e646572207468|difyitunderth|0000005065207465726d73206f66207468652047|etermsoftheG|000000604e55204c65737365722047656e657261|NULesserGenera|000000706c205075626c69630a4c6963656e7365||[]
这个输出结果有帮助但太累赘且难于阅读。要将hexdump的输出结果转换为其选项不支持的其他格式,可组合使用--format(或-e)和专门的格式代码。用来自定义格式的代码和printf命令使用的类似,所以如果你熟悉printf语句,你可能会觉得hexdump自定义格式不难学会。
在hexdump中,字符串%_p告诉hexdump用你系统的默认字符集输出字符。--format选项的所有格式符号必须以单引号包括起来:
$hexdump-e'"%_p"'/usr/share/doc/libblkid-devel/COPYINGThislibraryisfre*software;youcanredistributeitand/**SoftwareFoundation;,or(atyouroption).*Thecompletetextofthelicenseisavailableinthe..*/Documentation/licenses/.
这次的输出好些了,但依然不方便阅读。传统上UNIX文本文件假定80个字符的输出宽度(因为很久以前显示器一行只能显示80个字符)。
尽管这个输出结果未被自定义格式限制输出宽度,你可以用附加选项强制hexdump一次处理80字节。具体而言,通过80除以1这种形式,你可以告诉hexdump将80字节作为一个单元对待:
$hexdump-e'80/1"%_p"'/usr/share/doc/libblkid-devel/COPYINGThislibraryisfreesoftware;youcanredistributeitand/;,or(atyouroption)/Documentation/licenses/.
现在该文件被分割成80字节的块处理,但没有任何换行。你可以用\n字符自行添加换行,在UNIX中它代表换行:
$hexdump-e'80/1"%_p""\n"'Thislibraryisfreesoftware;youcanredistributeitand/;,or(atyouroption)/Documentation/licenses/.
现在你已经(大致上)用hexdump自定义格式实现了cat命令。
控制输出结果实际上自定义格式是让hexdump变得有用的方法。现在你已经(至少是原则上)熟悉hexdump自定义格式,你可以让hexdump-n8的输出结果跟libpng官方规范中描述的PNG文件头相匹配了。
首先,你知道你希望hexdump以8字节的块来处理PNG文件。此外,你可能通过识别这些整数从而知道PNG格式规范是以十进制数表述的,根据hexdump文档,十进制用%d来表示:
$hexdump-n8-e'8/1"%d""\n"'
你可以在每个整数后面加个空格使输出结果变得完美:
$hexdump-n8-e'8/1"%d""\n"'
现在输出结果跟PNG规范完美匹配了。
好玩又有用Hexdump是个迷人的工具,不仅让你更多地领会计算机如何处理和转换信息,而且让你了解文件格式和编译的二进制文件如何工作。日常工作时你可以随机地试着对不同文件运行hexdump。你永远不知道你会发现什么样的信息,或是什么时候具有这种洞察力会很实用。
via:
作者:SethKenlon选题:lujun9972译者:0x996校对:wxy
本文由LCTT原创编译,Linux中国荣誉推出