二进制代码的阅0130406.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
二进制代码的阅0130406

Linux下二进制代码的阅读 大多数时候,我们研究的是如何阅读源代码。但在一些情况下,比如源代码不公开或得到源代码的代价很高的情况下,我们又不得不需要了解程序的行为,这 时阅读二进制文件就非常重要。假设现在有一个二进制可执行文件,我们木有源代码,但要了解它的实现,这里仅简单列出一些常用的工具。 阅读方式可分为两个方面:静态阅读和动态阅读。 静态阅读 首先,file命令可以查看可执行文件的大体信息。比如是哪种格式的,哪个体系结构的,有没有调试信息等。这些决定了需要用哪个版本的工具进行进一 步查看。比如如果是arm体系的可执行文件就可用arm toolchain里的工具,如arm-eabi-objdump,arm-eabi-gdb等。 众所周知,GNU Binutils提供了一系列解析和操作二进制文件的工具,最常用的如objdump,其最主要的功能之一是反汇编: objdump -d libxxx.so 其它常用选项包括: -x 打印所有头信息 -s 打印所有段的内容 -S 将反汇编和源代码一起打印 -r 打印重定位表 -R 打印动态重定位表 -D 打印所有段,即不止代码段 -t 打印符号表,和nm的功能类似,但格式不一样 -T 只打印动态链接的符号表项 等等。 readelf命令主要用于查看elf文件的元信息(如段信息等)。如查看可执行文件的头信息: readelf -h libxxx.so 其它常用选项包括: -s 打印符号表 -r 打印重定位表 -l 打印装载属性 -S 打印段表 等等。 除了以上两个用得最多的,其它一些辅助工具有时也必不可少: nm 打印符号表 c++filt 把c++符号unmangle strip 把调试信息删除 strings 看文件中的字符串 ldd: 查看依赖关系 等等 动态阅读 要了解可程序的行为,最可靠的还是看二进制文件跑起来时的样子。很多时候,由于运行环境复杂,特别是多线程情况下,动态阅读能发现很多静态阅读所不可能发现的东西。 首先,在/proc/pid(pid为进程号)下记录了二进制文件跑起来后的很多信息,如通过/proc/pid/maps可以知道该程序链接了哪些库, 分别被加载在了什么地方(这样,知道了错误地址,理论上就可以找到相应库的对应反汇编代码。),/proc/pid/mem是进程所用的内存镜像, /proc/pid/stat则记录了中断统计信息等。/proc/pid/cmdline则记录了启动程序的命令行。 其次,通过trace(strace,lstrace)可以看程序有哪些系统调用。strace用于跟踪系统调用,ltrace用于跟踪动态库调用。 如对于在/proc/pid/maps中看到的一些匿名内存映射,想要看它们是在什么时候或是在哪被创建可以用: strace -f -p 3742 -e trace=mmap2,open,mprotect |tee tmp.trace 其中3742为进程ID。这里只过滤出关于内存映射的函数。 最后,指令级动态阅读的神器还属gdb。 在gdb中查看寄存器信息可用: (gdb) i r 在调试过程中打印出反汇编代码可用 (gdb) disass addr 或者 (gdb) x/10i addr 然后就可以和objdump出来的反汇编结合着看了。如GOT表之类的信息在静态阅读时是无意义的,只有这时才能看。 各种break point能让我们迅速定位到我们关注的地方: watch point 在指定数据被访问时程序停止。 break point 在指定代码被执行时程序停止。 因为很多时候库不带symbol,所以得直接设在地址上 break *addr。 catch point 在指定事件发生时程序停止,如进程创建,动态链接库加载及异常。 条件断点有时很有用:break ... if condition,但这玩意一旦设上不是一般的慢啊。。。 gdb中的bt和info frame命令常用来看堆栈信息和函数调用关系。但有时因为bug栈被写坏了,但如果不是被写得很坏,查看栈的内容常通常能找到一些线索: (gdb) x/40x $sp 该命令是查看$sp指向区域的40个byte的内存内容。该命令也可用来查看任意指定地址的内存内容。 关于gdb常用的功能:/%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F 其它的一些gdb使用备忘:/ariesjzj/article/details/6913671 一些相关资料 /articles/understanding-elf-using-readelf-and-objdump_125.html /thread-1972423-1-1.html el

文档评论(0)

vbk530 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档