bin文件(bin格式手机用什么打开)

世界上有10种人。一类人懂二进制,另一类人不懂。——鲁迅大家好,我是徐良。二进制文件是我们几乎每天都需要处理的文件类型,但是很少有人知道它们是如何工作的。这里说

世界上有10种人。一类人懂二进制,另一类人不懂。——鲁迅

大家好,我是徐良。

二进制文件是我们几乎每天都需要处理的文件类型,但是很少有人知道它们是如何工作的。这里说的二进制文件是指一些可执行文件,包括你日常使用的Linux命令,也是二进制文件的一种。

Linux系统为我们提供了许多分析二进制文件的工具。无论你在Linux下做什么样的工作,了解这些工具也会让你更加了解你的系统。

在本文中,将介绍几种用于分析二进制文件的常用工具和命令。这些工具可以在大部分发行版中直接使用,如果不能直接使用也可以自己安装。

file

file命令用于分析文件类型。

如果需要分析二进制文件,可以先用file命令切入。我们知道在Linux下一切都是文件,但并不是所有的文件都是可执行的。我们还有各种文件,比如文本文件、管道文件、链接文件、套接字文件等等。

在分析一个文件之前,我们可以先使用file命令来分析它们的类型。除此之外,当然也可以看到一些其他的信息。

$ file /bin/pwd/bin/pwd: ELF 64位LSB可执行文件,x86-64,版本1 (SYSV),动态链接(使用共享库),对于GNU/Linux 2.6.32,Id[sha1]= 0d 264 bacf 2 ADC 568 f 0 e 21 bcc 9576 df 434 c 4380,可以使用strippedDDLDD命令分析可执行文件的依赖关系。

当我们使用file命令分析一个可执行文件时,有时我们可以在输出中看到动态链接的单词。这是什么意思?

大部分程序会使用第三方库,这样可以节省很多时间,不用重复造轮子。最简单的,如果我们写C程序代码,肯定会用libc或者glibc库。当然,也可以使用其他库。

那么在什么情况下我们需要分析程序的依赖库呢?有一个场景想必大家都经历过。去你同事那里复制他写的程序,在你自己的环境下运行。有时候你可能跑不起来。当然,它不能运行的原因可能有很多,但其中一个原因可能是缺少相应的依赖库。

这个时候,ldd就派上用场了。它可以分析出程序需要哪些依赖库,你只需要把对应的库放到对应的位置就可以了。

$ ldd/bin/pwd Linux-vdso . so . 1 = & gt;(0x 00007 ffeb 73 e 5000)libc . so . 6 = & gt;/lib 64/libc . so . 6(0x 00007 f 908 b 321000)/lib 64/LD-Linux-x86-64 . so . 2(0x 00007 f 908 b 6 ef 000)LTACE LTACE的作用是跟踪进程的库函数调用。

我们可以使用ldd命令来查找程序的依赖库。然而,一个库可以包含几个到几千个函数。我们怎么知道程序现在调用的是什么函数?

ltrace命令用于实现这一点。在下面的例子中,我们可以看到程序调用的函数和传入的参数,也可以看到函数调用的输出。

$ ltrace/bin/pwd _ _ libc _ start _ main(0x 401760,1,0x 7 ffff 6524 c8,0x 404 a 00 & lt;未完成的...& gtgetenv(& # 34;POSIXLY _ CORRECT & # 34)= nilstrrchr(& # 34;/bin/pwd & # 34;, '/') = "/pwd & # 34;setlocale(LC_ALL,& # 34;") = "en _ US.utf8 & # 34bindtextdomain(& # 34;coreutils & # 34, "/usr/share/locale & # 34;) = "/usr/share/locale & # 34;textdomain(& # 34;coreutils & # 34) = "coreutils & # 34__cxa_atexit(0x4022f0,0,0,0x 736 c 6974756572)= 0 get opt _ long(1,0x7ffff6524cc8,& # 34;LP & # 34,0x606d00,nil) = -1getcwd(nil,0)= & # 34;"看跌期权(& # 34;/home/阿尔文& # 34;/home/Alvin)= 12 free(0x 22 BC 030)= & lt;void & gt退出(0 & lt未完成的...& gt__fpending(0x7f3048865400,0,64,0x7f 3048865 eb0)= 0 fileno(0x7f 3048865400)= 1 _ _ f reading(0x7f 3048865400,0,64,0x7f 3048865 eb0)= 0 _ _ f reading(0x7f 3048865400,0,2052,0x7f 30488865 eb0

从上面的介绍中,我们知道ltrace命令用于跟踪函数调用。strace命令类似,但是它跟踪系统调用。什么是系统调用?简单来说,我们可以通过系统调用与内核进行交互,完成我们想要的任务。

例如,如果我们想在屏幕上打印一些字符,我们可以使用printf或puts函数,这两个函数都是libc的库函数。在较低的级别,它们都调用写系统调用。

$ strace-f/bin/pwd exec ve(& # 34;/bin/pwd & # 34;, ["/bin/pwd & # 34;],[/* 24 vars */])= 0 brk(NULL)= 0x BC 9000 mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0)= 0x7f 918 ba 69000 access(& # 34;/etc/LD . so . preload & # 34;,R_OK) = -1 ENOENT(没有这样的文件或目录)打开(& # 34;/etc/LD . so . cache & # 34;,O_RDONLY|O_CLOEXEC) = 3fstat(3,{st_mode=S_IFREG|0644,st_size=38684,...}) = 0mmap(NULL,38684,PROT_READ,MAP_PRIVATE,3,0)= 0x7f 918 ba 5f 000 close(3)= 0 open(& # 34;/lib 64/libc . so . 6 & # 34;,O_RDONLY|O_CLOEXEC) = 3read(3,& # 34;\ 177 elf \ 2 \ 1 \ 1 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 & gt;[20][20][20][20]&[20][20][20][20][20]"...,832) = 832fstat(3,{st_mode=S_IFREG|0755,st_size=2156160,...}) = 0mmap(NULL,3985888,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_DENYWRITE,3,0)= 0x7f 918 b 47 b 000 protect(0x7f 918 b 63 e 000,2097152,PROT _ NONE)= 0m MAP(0x7f 918 b 83 e 000,24576,PROT_READ|PROT_WRITE,MAP _ PRIVATE | MAP _ FIXED | MAP _ deny WRITE,3,0x1c300

一个二进制文件,如果直接用文本编辑器打开,会看到一堆乱码。此时,您可以使用hexdump命令来查看其内容。

hexdump的显示格式是:左边是字节序号,中间是文件的十六进制代码。如果是可打印字符,将显示在右侧。

通过使用这个命令,我们可以大致知道这个二进制文件里有什么,以后做什么就更方便了。

$ hex dump-C/bin/pwd | head 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 00 00。极低频............| 00000010 02 00 3e 00 01 00 00 00 17 19 40 00 00 00 00 00 00 |..& gt.......@.....| 00000020 40 00 00 00 00 00 00 00 00 50 7a 00 00 00 00 00 00 00 00 00 | @.......古生界......| 00000030 00 00 00 00 40 00 38 00 09 00 40 00 1e 00 1d 00 |....@.8...@.....|00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 |........@.......|00000050 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00 | @.@.....@.@.....| 00000060 F8 01 00 00 00 00 00 00 F8 01 00 00 00 00 00 00 00 |................|00000070 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 | ................|00000080 38 02 00 00 00 00 00 00 38 02 40 00 00 00 00 00 |8.......8.@.....| 00000090 38 02 40 00 00 00 00 00 00 1c 00 00 00 00 00 00 00 00 00 00 00 | 8。@.............| Strings Strings命令可用于打印二进制文件中的可显示字符。

什么是可显示字符?简单来说,你在显示器上看到的所有字符都是可显示字符,比如abcABC,。:.

我们知道,一个二进制文件包含许多非显示字符,所以它不能被文本处理器直接打开。在程序开发的时候,我们经常会添加一些调试信息,比如调试日志、警告日志、错误日志等等。使用strings命令可以看到这些信息。

$ strings/bin/pwd | head/lib 64/LD-Linux-x86-64 . so . 2 libc . so . 6 flush strcpy _ _ printf _ chkreaddirstertlocalembowcstr rncmpoptindreadELFreadelf一般用于查看elf格式的文件信息。

Elf(可执行和可链接格式)是一种复杂的文件格式,但它被广泛使用。当使用file命令发现一个文件是ELF文件时,可以使用readelf命令读取这个文件的信息。

$ readelf-h/bin/pwd elf Header:Magic:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 00 00 Class:elf 64 Data:2 & # 39;s补码,little endian版本:1(当前)OS/ABI: UNIX - System V ABI版本:0类型:EXEC(可执行文件)机器:Advanced Micro Devices X86-64版本:0x1入口点地址:0x401917程序头开始:64(进入文件的字节数)段头开始:31312(进入文件的字节数)标志:0x0此头的大小:64(字节)程序头的大小:56(字节)程序头的数量:9段头的大小:64(字节)段的数量

我们知道,程序开发出来后,需要进行编译,才能生成计算机可以识别的二进制文件。我们写的代码不能被计算机直接执行,需要编译成汇编程序,计算机才能依次执行。

objdump命令可以读取可执行文件,然后打印汇编指令。所以要想理解objdump的结果,需要有一定的编译基础。

2020精选阿里/腾讯等一线厂商的面试、简历、进阶电子书、私聊。我免费回复“信息”。

$ objdump-d/bin/pwd | head/bin/pwd:文件格式elf 64-x86-64部分的反汇编。init:000000000401350 & lt;。init & gt:401350: 48 83 ec 08 sub [33]x8,% RSP 401354:48 8b 05 6d 5c 20 00 mov 0x 205 c6d(% rip),% rax # 606fc8 & lt_ _ ctype _ b _ loc @ PLT+0x 205878 & gt;4135b: 48 85c0test% rax,% raxnnm命令主要是列出目标文件的符号(说白了就是一些函数和全局变量等。).

如果你编译的程序没有经过strip,那么nm命令就可以挖掘出隐藏在可执行文件中的重要秘密。它可以帮助你列出文件中的变量和函数,对于我们的逆向操作有着重要的意义。

让我们通过一个简短的程序来解释一下nm命令的用途。在编译这个程序的时候,我们添加了-g选项,可以让编译后的文件包含更多的有效信息。

$ cat hello.c # include & ltstdio.h & gtint main(){ printf(& # 34;你好世界!");返回0;} $ $ gcc-g hello . c-o hello $ $ file hello hello:ELF 64位LSB可执行文件,x86-64,版本1 (SYSV),动态链接(使用共享库),对于GNU/Linux 2.6.32,BuildID[sha1]= 3 de 46 c8 efb 98 BC E4 ad 525d 3328121568 ba 3d 8 a 5d,未剥离$ $。/你好你好世界!$ $ $ nm hello | tail 00000000000600 e20 d _ _ JCR _ END _ _ 0000000000600 e20 d _ _ JCR _ LIST _ _ 0000000004005 B0 T _ _ libc _ CSU _ fini 0000000000400540T _ _ libc _ CSU _ init U _ _ libc _ start _ m Ain @ @ glibc _ 2 . 2 . 500000000000

Gdb大家或多或少都听说过。当我们用一些ide写代码时,可以通过断点、单步、检查变量值等方式进行调试。其实这些ide的底层也是调用gdb的。

对于gdb的用法,可以写很多,我就暂时不深究了。我们先来演示一下gdb最基本的功能。

$ GD b-q ./hello从/home/flash/hello中读取符号...完成了。(gdb)在0x400521处中断main breakpoint 1:file hello . c,第4行。(gdb)info break num Type Disp Enb Address what 1断点保持y 0x 000000000400521 in main at hello . c:4(gdb)run starting程序:/home/ flash/。/hello断点1,hello . c:44 printf(& # 34;你好世界!");缺少单独的debuginfo,请使用:debug info-install glibc-2.17-260 . el7 _ 6.6 . x86 _ 64(gdb)Bt # 0 main()at hello . c:4(gdb)c继续。你好世界!【Inferior1(进程29620)正常退出】(GDB) Q $总结如果你是在Linux下开发程序,必然要处理二进制文件。熟练使用上面介绍的10个命令,对你的工作会有很大的帮助。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

作者:美站资讯,如若转载,请注明出处:https://www.meizw.com/n/176671.html

发表回复

登录后才能评论