使用hexdump查看二进制文件


有时候需要查看一些二进制文件的内容,比如二进制文件中包含的某些字符串。这个时候可以用 hexdump 进行查看。

常用参数:

hexdump -C -n length -s skip file_name

-C 定义了导出的格式;-s skip 指定了从文件头跳过多少字节,或者说是偏移量,默认是十进制,如果是0x开头,则是十六进制;-n 指定了导出多少长度。

如果是寻找文本内容,则经常在后面用管道跟上grep命令:

hexdump -C file_name | grep hellokitty

这样就可以找到相关内容的偏移量,然后hexdump -C -n length -s skip file_name 查看文本附近的内容。

参考链接http://blog.mchz.com.cn/?p=1408


用途说明

hexdump命令一般用来查看“二进制”文件的十六进制编码,但实际上它的用途不止如此,手册页上的说法是“ascii, decimal, hexadecimal, octal dump”,它能查看任何文件,而不只限于二进制文件。另外还有 xxd 和 od 也可以做类似的事情。在程序输出二进制格式的文件时,常用hexdump来检查输出是否正确。当然也可以使用Windows上的UltraEdit32之类的工具查看文件的十六进制编码,但Linux上有现成的工具,何不拿来用呢。

常用参数

如果要看到较理想的结果,推荐使用-C参数,显示结果分为三列(文件偏移量、字节的十六进制、ASCII字符)。

格式:hexdump -C binfile

一般文件都不是太小,最好用less来配合一下。

格式:hexdump -C binfile | less

示例一 比较各种参数的输出结果
[root@new55 ~]# echo /etc/passwd | hexdump
0000000 652f 6374 702f 7361 7773 0a64
000000c
[root@new55 ~]# echo /etc/passwd | od -x
0000000 652f 6374 702f 7361 7773 0a64
0000014
[root@new55 ~]# echo /etc/passwd | xxd
0000000: 2f65 7463 2f70 6173 7377 640a            /etc/passwd.
[root@new55 ~]# echo /etc/passwd | hexdump -C      <== 规范的十六进制和ASCII码显示(Canonical hex+ASCII display )
00000000  2f 65 74 63 2f 70 61 73  73 77 64 0a              |/etc/passwd.|
0000000c
[root@new55 ~]# echo /etc/passwd | hexdump -b      <== 单字节八进制显示(One-byte octal display)
0000000 057 145 164 143 057 160 141 163 163 167 144 012
000000c
[root@new55 ~]# echo /etc/passwd | hexdump -c      <== 单字节字符显示(One-byte character display)
0000000   /   e   t   c   /   p   a   s   s   w   d  \n
000000c
[root@new55 ~]# echo /etc/passwd | hexdump -d      <== 双字节十进制显示(Two-byte decimal display)
0000000   25903   25460   28719   29537   30579   02660
000000c
[root@new55 ~]# echo /etc/passwd | hexdump -o       <== 双字节八进制显示(Two-byte octal display)
0000000  062457  061564  070057  071541  073563  005144
000000c
[root@new55 ~]# echo /etc/passwd | hexdump -x       <== 双字节十六进制显示(Two-byte hexadecimal display)
0000000    652f    6374    702f    7361    7773    0a64
000000c
[root@new55 ~]# echo /etc/passwd | hexdump -v
0000000 652f 6374 702f 7361 7773 0a64
000000c

比较来比较去,还是hexdump -C选项的显示效果更好些。

示例二 确认文本文件的格式

文本文件在不同操作系统上的行结束标志是不一样的,经常会碰到由此带来的问题。比如Linux的许多命令不能很好的处理DOS格式的文本文件。Windows/DOS下的文本文件是以”\r\n”作为行结束的,而Unix/Linux下的文本文件是以”\n”作为行结束的。

[root@new55 ~]# cat test.bc
123*321
123/321
scale=4;123/321

[root@new55 ~]# hexdump -C test.bc
00000000  31 32 33 2a 33 32 31 0a   31 32 33 2f 33 32 31 0a  |123*321.123/321.|
00000010  73 63 61 6c 65 3d 34 3b  31 32 33 2f 33 32 31 0a  |scale=4;123/321.|
00000020  0a                                                |.|
00000021
[root@new55 ~]#

注:常见的ASCII字符的十六进制表示
\r  0D
\n  0A
\t  09

DOS/Windows的换行符 \r\n    即十六进制表示 0D 0A
Linux/Unix的换行符  \n      即十六进制表示 0A

参考链接http://codingstandards.iteye.com/blog/805778


hexdump / xxd / od

系统自带都有,所以在Linux下做进制转换真的是太方便了。

注:三个命令都可以像UltraEdit那样以16进制的方式查看文件。hexdump的输出格式最灵活,因为它有专门的参数指定格式;不知道od的特点在哪,od -x 和不带选项的xxd差不多;xxd还可以通过-r选项把16进制表示的反转换为正常的文件,个人感觉xxd最“正常”,因为它默认的表示方式和UltraEdit最像:以位移开头,然后每两字节一组,每行最后有相应字节的文件显示。

http://hi.baidu.com/gsxwgtvhgabbjrq/item/3d4d771ad1c66d8b88a95681


hexdump的高级用法

-e  指定格式字符串,格式字符串包含在一对单引号中,格式字符串形如:

'a/b "format1" "format2"'

每个格式字符串由三部分组成,每个由空格分隔,第一个形如a/b,b表示对每b个输入字节应用format1格式,a表示每a个字节一组一起显示,另外a可以省略,省略则a=1。format1和format2中可以使用类似printf的格式字符串,如:

  • %02d:两位十进制
  • %03x:三位十六进制
  • %02o:两位八进制
  • %c:单个字符等

还有一些特殊的用法:

  • %_ad:标记下一个输出字节的序号,用十进制表示
  • %_ax:标记下一个输出字节的序号,用十六进制表示
  • %_ao:标记下一个输出字节的序号,用八进制表示
  • %_p:对不能以常规字符显示的用.代替

同一行如果要显示多个格式字符串,则可以跟多个-e选项

参考链接:

http://www.cnblogs.com/openix/archive/2012/03/19/2406568.html

显示每个字符对应的十进制、十六进制、八进制的Bash脚本

#!/bin/bash
ASCII="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
echo $ASCII | hexdump -v -e '"%02_ad "' -e '1/1 "%1c "' -e '1/1 "hex=%02X "' -e '1/1 "dec=%3d "' -e '1/1 "oct=%03o\n"'

=EOF=

, ,

《 “使用hexdump查看二进制文件” 》 有 3 条评论

  1. 在终端中查看ASCII码表
    `$ man ascii`
    http://man7.org/linux/man-pages/man7/ascii.7.html
    若出现`No manual entry for`的报错,则表示除了需要有man之外,还需要安装man-pages
    `$ sudo yum install man man-pages`

    如何在终端中打印出所有的可打印字符?
    http://unix.stackexchange.com/questions/15139/how-to-print-all-printable-ascii-chars-in-cli
    `
    for((i=32;i<=127;i++)) do printf \$(printf '%03ot' "$i"); done;printf "n"

    awk 'BEGIN{for(i=32;i<128;i++)printf "%c",i}';echo
    `

  2. Python中如何检测字符/字符串是否可打印字符?

    Test if a python string is printable
    https://stackoverflow.com/questions/3636928/test-if-a-python-string-is-printable/50731077#50731077
    `
    >>> hello = ‘Hello World!’
    >>> bell = chr(7)
    >>> import string
    >>> all(c in string.printable for c in hello)
    True
    >>> all(c in string.printable for c in bell)
    False

    >>> printset = set(string.printable)
    >>> helloset = set(hello)
    >>> bellset = set(bell)
    >>> helloset
    set([‘!’, ‘ ‘, ‘e’, ‘d’, ‘H’, ‘l’, ‘o’, ‘r’, ‘W’])
    >>> helloset.issubset(printset)
    True
    >>> set(bell).issubset(printset)
    False

    import string
    printset = set(string.printable)
    isprintable = set(yourstring).issubset(printset)

    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注