网易首页 > 网易号 > 正文 申请入驻

在 Linux 上分析二进制文件的 10 种方法 | Linux 中国

0
分享至

这些简单的命令和工具可以帮助你轻松完成分析二进制文件的任务。

https://linux.cn/article-12187-1.html
作者:Gaurav Kamathe
译者:Xingyu.Wang

“这个世界上有 10 种人:懂二进制的人和不懂二进制的人。”

我们每天都在与二进制文件打交道,但我们对二进制文件却知之甚少。我所说的二进制,是指你每天运行的可执行文件,从命令行工具到成熟的应用程序都是。

Linux 提供了一套丰富的工具,让分析二进制文件变得轻而易举。无论你的工作角色是什么,如果你在 Linux 上工作,了解这些工具的基本知识将帮助你更好地理解你的系统。

在这篇文章中,我们将介绍其中一些最流行的 Linux 工具和命令,其中大部分都是 Linux 发行版的一部分。如果没有找到,你可以随时使用你的软件包管理器来安装和探索它们。请记住:学习在正确的场合使用正确的工具需要大量的耐心和练习。

file

它的作用:帮助确定文件类型。

这将是你进行二进制分析的起点。我们每天都在与文件打交道,并非所有的文件都是可执行类型,除此之外还有各种各样的文件类型。在你开始之前,你需要了解要分析的文件类型。是二进制文件、库文件、ASCII 文本文件、视频文件、图片文件、PDF、数据文件等文件吗?

命令将帮助你确定你所处理的文件类型。

  1. $ file /bin/ls

  2. /bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=94943a89d17e9d373b2794dcb1f7e38c95b66c86, stripped

  3. $

  4. $ file /etc/passwd

  5. /etc/passwd: ASCII text

  6. $

ldd

它的作用:打印共享对象依赖关系。

如果你已经在一个可执行的二进制文件上使用了上面的 命令,你肯定会看到输出中的“动态链接(dynamically linked)”信息。它是什么意思呢?

在开发软件的时候,我们尽量不要重造轮子。有一组常见的任务是大多数软件程序需要的,比如打印输出或从标准输入/打开的文件中读取等。所有这些常见的任务都被抽象成一组通用的函数,然后每个人都可以使用,而不是写出自己的变体。这些常用的函数被放在一个叫 libcglibc的库中。

如何找到可执行程序所依赖的库?这就是 命令的作用了。对动态链接的二进制文件运行该命令会显示出所有依赖库和它们的路径。

  1. $ ldd /bin/ls

  2. linux-vdso.so.1 => (0x00007ffef5ba1000)

  3. libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fea9f854000)

  4. libcap.so.2 => /lib64/libcap.so.2 (0x00007fea9f64f000)

  5. libacl.so.1 => /lib64/libacl.so.1 (0x00007fea9f446000)

  6. libc.so.6 => /lib64/libc.so.6 (0x00007fea9f079000)

  7. libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fea9ee17000)

  8. libdl.so.2 => /lib64/libdl.so.2 (0x00007fea9ec13000)

  9. /lib64/ld-linux-x86-64.so.2 (0x00007fea9fa7b000)

  10. libattr.so.1 => /lib64/libattr.so.1 (0x00007fea9ea0e000)

  11. libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fea9e7f2000)

  12. $

ltrace

它的作用:库调用跟踪器。

我们现在知道如何使用 命令找到一个可执行程序所依赖的库。然而,一个库可以包含数百个函数。在这几百个函数中,哪些是我们的二进制程序正在使用的实际函数?

命令可以显示运行时从库中调用的所有函数。在下面的例子中,你可以看到被调用的函数名称,以及传递给该函数的参数。你也可以在输出的最右边看到这些函数返回的内容。

  1. $ ltrace ls

  2. __libc_start_main(0x4028c0, 1, 0x7ffd94023b88, 0x412950

  3. strrchr("ls", '/') = nil

  4. setlocale(LC_ALL, "") = "en_US.UTF-8"

  5. bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"

  6. textdomain("coreutils") = "coreutils"

  7. __cxa_atexit(0x40a930, 0, 0, 0x736c6974756572) = 0

  8. isatty(1) = 1

  9. getenv("QUOTING_STYLE") = nil

  10. getenv("COLUMNS") = nil

  11. ioctl(1, 21523, 0x7ffd94023a50) = 0

  12. << snip >>

  13. fflush(0x7ff7baae61c0) = 0

  14. fclose(0x7ff7baae61c0) = 0

  15. +++ exited (status 0) +++

  16. $

hexdump

它的作用:以 ASCII、十进制、十六进制或八进制显示文件内容。

通常情况下,当你用一个应用程序打开一个文件,而它不知道如何处理该文件时,就会出现这种情况。尝试用 打开一个可执行文件或视频文件,你屏幕上会看到的只是抛出的乱码。

在 中打开未知文件,可以帮助你看到文件的具体内容。你也可以选择使用一些命令行选项来查看用 ASCII 表示的文件数据。这可能会帮助你了解到它是什么类型的文件。

  1. $ hexdump -C /bin/ls | head

  2. 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|

  3. 00000010 02 00 3e 00 01 00 00 00 d4 42 40 00 00 00 00 00 |..>......B@.....|

  4. 00000020 40 00 00 00 00 00 00 00 f0 c3 01 00 00 00 00 00 |@...............|

  5. 00000030 00 00 00 00 40 00 38 00 09 00 40 00 1f 00 1e 00 |....@.8...@.....|

  6. 00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 |........@.......|

  7. 00000050 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00 |@.@.....@.@.....|

  8. 00000060 f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00 |................|

  9. 00000070 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 |................|

  10. 00000080 38 02 00 00 00 00 00 00 38 02 40 00 00 00 00 00 |8.......8.@.....|

  11. 00000090 38 02 40 00 00 00 00 00 1c 00 00 00 00 00 00 00 |8.@.............|

  12. $

strings

它的作用:打印文件中的可打印字符的字符串。

如果你只是在二进制中寻找可打印的字符,那么 对于你的使用场景来说似乎有点矫枉过正,你可以使用 命令。

在开发软件的时候,各种文本/ASCII 信息会被添加到其中,比如打印信息、调试信息、帮助信息、错误等。只要这些信息都存在于二进制文件中,就可以用 命令将其转储到屏幕上。

  1. $ strings /bin/ls

readelf

它的作用:显示有关 ELF 文件的信息。

ELF(可执行和可链接文件格式(Executable and Linkable File Format))是可执行文件或二进制文件的主流格式,不仅是 Linux 系统,也是各种 UNIX 系统的主流文件格式。如果你已经使用了像 命令这样的工具,它告诉你文件是 ELF 格式,那么下一步就是使用 命令和它的各种选项来进一步分析文件。

在使用 命令时,有一份实际的 ELF 规范的参考是非常有用的。你可以在找到该规范。

  1. $ readelf -h /bin/ls

  2. ELF Header:

  3. Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

  4. Class: ELF64

  5. Data: 2's complement, little endian

  6. Version: 1 (current)

  7. OS/ABI: UNIX - System V

  8. ABI Version: 0

  9. Type: EXEC (Executable file)

  10. Machine: Advanced Micro Devices X86-64

  11. Version: 0x1

  12. Entry point address: 0x4042d4

  13. Start of program headers: 64 (bytes into file)

  14. Start of section headers: 115696 (bytes into file)

  15. Flags: 0x0

  16. Size of this header: 64 (bytes)

  17. Size of program headers: 56 (bytes)

  18. Number of program headers: 9

  19. Size of section headers: 64 (bytes)

  20. Number of section headers: 31

  21. Section header string table index: 30

  22. $

objdump

它的作用:从对象文件中显示信息。

二进制文件是通过你编写的源码创建的,这些源码会通过一个叫做编译器的工具进行编译。这个编译器会生成相对于源代码的机器语言指令,然后由 CPU 执行特定的任务。这些机器语言代码可以通过被称为汇编语言的助记词来解读。汇编语言是一组指令,它可以帮助你理解由程序所进行并最终在 CPU 上执行的操作。

实用程序读取二进制或可执行文件,并将汇编语言指令转储到屏幕上。汇编语言知识对于理解 命令的输出至关重要。

请记住:汇编语言是特定于体系结构的。

  1. $ objdump -d /bin/ls | head

  2. /bin/ls: file format elf64-x86-64

  3. Disassembly of section .init:

  4. 0000000000402150 <_init@@Base>:

  5. 402150: 48 83 ec 08 sub $0x8,%rsp

  6. 402154: 48 8b 05 6d 8e 21 00 mov 0x218e6d(%rip),%rax # 61afc8 <__gmon_start__>

  7. 40215b: 48 85 c0 test %rax,%rax

  8. $

strace

它的作用:跟踪系统调用和信号。

如果你用过前面提到的 ,那就把 想成是类似的。唯一的区别是, 工具不是追踪调用的库,而是追踪系统调用。系统调用是你与内核对接来完成工作的。

举个例子,如果你想把一些东西打印到屏幕上,你会使用标准库 libc 中的 printfputs 函数;但是,在底层,最终会有一个名为 write 的系统调用来实际把东西打印到屏幕上。

  1. $ strace -f /bin/ls

  2. execve("/bin/ls", ["/bin/ls"], [/* 17 vars */]) = 0

  3. brk(NULL) = 0x686000

  4. mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f967956a000

  5. access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

  6. open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

  7. fstat(3, {st_mode=S_IFREG|0644, st_size=40661, ...}) = 0

  8. mmap(NULL, 40661, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9679560000

  9. close(3) = 0

  10. << snip >>

  11. fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0

  12. mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9679569000

  13. write(1, "R2 RH\n", 7R2 RH

  14. ) = 7

  15. close(1) = 0

  16. munmap(0x7f9679569000, 4096) = 0

  17. close(2) = 0

  18. exit_group(0) = ?

  19. +++ exited with 0 +++

  20. $

nm

它的作用:列出对象文件中的符号。

如果你所使用的二进制文件没有被剥离, 命令将为你提供在编译过程中嵌入到二进制文件中的有价值的信息。 可以帮助你从二进制文件中识别变量和函数。你可以想象一下,如果你无法访问二进制文件的源代码时,这将是多么有用。

为了展示 ,我们快速编写了一个小程序,用 -g 选项编译,我们会看到这个二进制文件没有被剥离。

  1. $ cat hello.c

  2. #include

  3. int main() {

  4. printf("Hello world!");

  5. return 0;

  6. }

  7. $

  8. $ gcc -g hello.c -o hello

  9. $

  10. $ file hello

  11. hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=3de46c8efb98bce4ad525d3328121568ba3d8a5d, not stripped

  12. $

  13. $ ./hello

  14. Hello world!$

  15. $

  16. $ nm hello | tail

  17. 0000000000600e20 d __JCR_END__

  18. 0000000000600e20 d __JCR_LIST__

  19. 00000000004005b0 T __libc_csu_fini

  20. 0000000000400540 T __libc_csu_init

  21. U __libc_start_main@@GLIBC_2.2.5

  22. 000000000040051d T main

  23. U printf@@GLIBC_2.2.5

  24. 0000000000400490 t register_tm_clones

  25. 0000000000400430 T _start

  26. 0000000000601030 D __TMC_END__

  27. $

gdb

它的作用:GNU 调试器。

好吧,不是所有的二进制文件中的东西都可以进行静态分析。我们确实执行了一些运行二进制文件(进行分析)的命令,比如 和 ;然而,软件由各种条件组成,这些条件可能会导致执行不同的替代路径。

分析这些路径的唯一方法是在运行时环境,在任何给定的位置停止或暂停程序,并能够分析信息,然后再往下执行。

这就是调试器的作用,在 Linux 上, 就是调试器的事实标准。它可以帮助你加载程序,在特定的地方设置断点,分析内存和 CPU 的寄存器,以及更多的功能。它是对上面提到的其他工具的补充,可以让你做更多的运行时分析。

有一点需要注意的是,一旦你使用 加载一个程序,你会看到它自己的 (gdb) 提示符。所有进一步的命令都将在这个 命令提示符中运行,直到你退出。

我们将使用我们之前编译的 hello 程序,使用 来看看它的工作原理。

  1. $ gdb -q ./hello

  2. Reading symbols from /home/flash/hello...done.

  3. (gdb) break main

  4. Breakpoint 1 at 0x400521: file hello.c, line 4.

  5. (gdb) info break

  6. Num Type Disp Enb Address What

  7. 1 breakpoint keep y 0x0000000000400521 in main at hello.c:4

  8. (gdb) run

  9. Starting program: /home/flash/./hello

  10. Breakpoint 1, main () at hello.c:4

  11. 4 printf("Hello world!");

  12. Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7_6.6.x86_64

  13. (gdb) bt

  14. #0 main () at hello.c:4

  15. (gdb) c

  16. Continuing.

  17. Hello world![Inferior 1 (process 29620) exited normally]

  18. (gdb) q

  19. $

结语

一旦你习惯了使用这些原生的 Linux 二进制分析工具,并理解了它们提供的输出,你就可以转向更高级和专业的开源二进制分析工具,比如 。

via:

作者: 选题: 译者: 校对:

本文由 原创编译, 荣誉推出

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
陈思诚没想到,广西水灾3天后,前妻佟丽娅因一举动实现口碑暴涨

陈思诚没想到,广西水灾3天后,前妻佟丽娅因一举动实现口碑暴涨

陈意小可爱
2026-07-11 07:50:08
如果英格兰队赢得世界杯,英足总将给球员和工作人员1.7亿元奖金,FIFA将奖励冠军5000万美元

如果英格兰队赢得世界杯,英足总将给球员和工作人员1.7亿元奖金,FIFA将奖励冠军5000万美元

红星新闻
2026-07-11 09:00:21
美国咬定一条逻辑:只要坚持不降息,中国必将率先“爆雷”!

美国咬定一条逻辑:只要坚持不降息,中国必将率先“爆雷”!

混沌录
2026-07-10 22:39:14
空调连开多久必须停?国家标准给出答案,别再傻傻浪费电了

空调连开多久必须停?国家标准给出答案,别再傻傻浪费电了

另子维爱读史
2026-07-09 22:14:41
一个贪财一个好色?41岁嫁78岁恩师,被骂图钱的她终究骗了所有人

一个贪财一个好色?41岁嫁78岁恩师,被骂图钱的她终究骗了所有人

鲸探所长
2026-07-09 11:34:47
教育部任命:浙江大学党委副书记黄翔峰任上海财经大学党委书记

教育部任命:浙江大学党委副书记黄翔峰任上海财经大学党委书记

双一流高校
2026-07-11 03:44:17
直面广西水患的个体,这才是媒体该有的担当!

直面广西水患的个体,这才是媒体该有的担当!

胖胖说他不胖
2026-07-09 09:55:12
别吹梅里诺了!西班牙隐形真神!世界杯独扛全队挺进四强

别吹梅里诺了!西班牙隐形真神!世界杯独扛全队挺进四强

澜归序
2026-07-11 06:54:13
重磅:曝乌克兰将把火烈鸟导弹射程提升至4500公里!

重磅:曝乌克兰将把火烈鸟导弹射程提升至4500公里!

项鹏飞
2026-07-10 21:41:17
体内有癌,双腿先知?提醒:腿上若有5个迹象,癌细胞或已苏醒

体内有癌,双腿先知?提醒:腿上若有5个迹象,癌细胞或已苏醒

熊猫医学社
2026-07-11 11:30:03
87岁老人8周力量暴涨174%!科学证实:肌肉生长没有年龄上限

87岁老人8周力量暴涨174%!科学证实:肌肉生长没有年龄上限

荷兰豆爱健康
2026-07-09 06:51:45
3D动画还原福建晋江鞋厂大火:28人遇难,5层厂房为何成为“火场牢笼”?

3D动画还原福建晋江鞋厂大火:28人遇难,5层厂房为何成为“火场牢笼”?

每日经济新闻
2026-07-10 19:51:31
影院经理押宝周星驰功夫女足,隔15分钟就有一场,18亿不是梦?

影院经理押宝周星驰功夫女足,隔15分钟就有一场,18亿不是梦?

新金牌娱乐观察家
2026-07-10 09:34:24
浦东新区里比仁济东院还牛的医院,在上海浦东悄悄出现了

浦东新区里比仁济东院还牛的医院,在上海浦东悄悄出现了

王二哥老搞笑
2026-07-11 09:13:24
交通运输部:坚决拥护党中央决定

交通运输部:坚决拥护党中央决定

新京报
2026-07-10 19:49:40
人性铁律:一个男人的生理需求被满足之后,他脑子里想的从来不是感恩,想让他离不开你,关键在于这两个心理陷阱

人性铁律:一个男人的生理需求被满足之后,他脑子里想的从来不是感恩,想让他离不开你,关键在于这两个心理陷阱

心理观察局
2026-07-11 06:29:08
决赛将是西法胜者?罗梅罗回应库尔图瓦:不听其他球员的想法

决赛将是西法胜者?罗梅罗回应库尔图瓦:不听其他球员的想法

懂球帝
2026-07-11 08:43:09
比利时球迷意难平!不止因为1-2惜败西班牙,更多在于以下五点!

比利时球迷意难平!不止因为1-2惜败西班牙,更多在于以下五点!

田先生篮球
2026-07-11 06:54:47
1595年,穆罕默德三世在登基当天,下令将19个弟弟全部绞死,这种为争夺王位而骨肉相残的传统延续了六百年,几乎把皇室逼到血脉断绝的地步

1595年,穆罕默德三世在登基当天,下令将19个弟弟全部绞死,这种为争夺王位而骨肉相残的传统延续了六百年,几乎把皇室逼到血脉断绝的地步

人生录
2026-07-08 19:04:20
郑州一厨师离职时被老板要求交出菜品配方,“步骤都写清楚,不然不结工资”;厨师:工作是工作,配方是配方;监管部门:于法无据

郑州一厨师离职时被老板要求交出菜品配方,“步骤都写清楚,不然不结工资”;厨师:工作是工作,配方是配方;监管部门:于法无据

深圳晚报
2026-07-11 01:20:17
2026-07-11 12:04:49
Linux
Linux
Linux 中国开源社区
8018文章数 73111关注度
往期回顾 全部

科技要闻

苹果起诉OpenAI系统性窃密,挖超400前员工

头条要闻

中国工程院产生新一届院领导班子 张玉卓任院长

头条要闻

中国工程院产生新一届院领导班子 张玉卓任院长

体育要闻

燃尽的比利时黄金一代,逃不过厄运诅咒

娱乐要闻

IU被曝分手双方回应 年初互动早有预兆

财经要闻

一封举报信 引发小红书IPO合规考验

汽车要闻

行驶清爽智驾聪慧 奇瑞风云A9有颜更有趣

态度原创

健康
艺术
旅游
手机
教育

肝病、肾病患者注意!吃粘食要谨慎

艺术要闻

当实景美成画,谁还舍得只当个观众?

旅游要闻

入境游“主角”不止北上广深:外国游客飞赴中国160城 成都稳居前五、稻城首次上榜

手机要闻

曝三星Galaxy S27/S27+手机将配第三方显示驱动芯片

教育要闻

一个实验带你看懂“潭清疑水浅”,暑假来临,提醒孩子远离危险水域!(来源:快看智界)

无障碍浏览 进入关怀版