二进制 分析工具:Radare2、r2frida、Binutils、file、string、as、nm、ldd ...

打印 上一主题 下一主题

主题 786|帖子 786|积分 2358

1、二进制 分析工具


工欲善其事,必先利其器,在二进制安全的学习中,​利用工具尤为重要。遇到一个不熟悉的文件时, 起首要确定 "这是什么类型的文件",答复这个问题的首要原则是,绝不要根据文件的扩展名来确定文件的类型。这是最根本的原则。在脑子里创建起 "文件扩展名并无实际意义" 的印象后,就可以开始考虑学习下面的实用工具。

2、r2frida ( Radare2 + Frida )


github:https://github.com/nowsecure/r2frida
Radare2 和 Frida 在一起会更好:https://github.com/nowsecure/r2frida

r2frida 简 介

r2frida 是将 Radare2 和 Frida 的功能合二为一的强盛工具,该工具本质上是一个Radare2 的自包罗插件,可以资助研究职员利用 Frida 的功能实现对目标历程的远程安全检测和通讯管理。
Radare2 项目提供了针对逆向工程分析的完整工具链,功能也比力稳定,而且还支持利用其他编程语言和工具来扩展其功能。而 Frida 则是一个动态指令工具包,可以将 JavaScript 代码注入到正在运行的目标历程举行操纵,而且还可以与脚本举行通讯。
应用场景


  • 逆向工程:通过Frida脚本直接在目标历程中运行,无需修改源码。
  • 动态调试:动态跟踪代码执行,拦截函数调用,替换实现或添加钩子。
  • 移动装备应用测试:针对iOS和Android装备举行远程调试,不局限于同一网络环境。
  • 自动化安全审计:利用 r2pipe 自动化执行 r2 和 Frida 命令,提升服从。
项目特点


  • 直观易用:与Radare2无缝集成,提供丰富的命令行操纵。
  • 多语言支持:可以在目标历程中执行C、JavaScript或TypeScript代码。
  • 跨平台兼容:覆盖多种硬件架构和操纵系统。
  • 独立安装:不需要在主机上安装Frida工具,仅需r2frida即可运行。
  • 动态扩展:支持编写插件以增强r2frida的功能,插件在署理端运行。
  • 安全性:可变动页权限、修补代码和数据,增加调试安全性。

利用 r2frida

一旦安装完成,你可以利用以下命令开始探索:$ r2 'frida://0'
  1. $ r2 'frida://?'
  2. r2 frida://[action]/[link]/[device]/[target]
  3. * action = list | apps | attach | spawn | launch
  4. * link   = local | usb | remote host:port
  5. * device = '' | host:port | device-id
  6. * target = pid | appname | process-name | program-in-path | abspath
  7. Local:
  8. * frida://?                        # 显示工具帮助信息和退出
  9. * frida://                         # 枚举本地进程
  10. * frida://0                        # 连接至frida-helper
  11. * frida:///usr/local/bin/rax2        # 生成进程的绝对路径
  12. * frida://rax2                     # 生成进程的相对路径local/bin需在PATH中设置
  13. * frida://spawn/$(program)         #在当前系统生成一个新的进程
  14. * frida://attach/(target)            # 在当前主机连接至目标PID
  15. USB:
  16. * frida://list/usb//                # 枚举第一个USB设备的进程
  17. * frida://apps/usb//               # 枚举第一个USB设备的应用程序
  18. * frida://attach/usb//12345        # 连接至第一个USB设备的给定pid
  19. * frida://spawn/usb//appname       # 在第一个USB设备中生成一个App
  20. * frida://launch/usb//appname      # 在第一个USB设备中生成+恢复一个App
  21. Remote:
  22. * frida://attach/remote/10.0.0.3:9999/558 # 连接远程frida-server的pid 558
  23.   R2FRIDA_SAFE_IO=0|1              # 解决Android/thumb上的Frida问题
  24.   R2FRIDA_DEBUG=0|1               # 用于调试参数解析行为
  25.   R2FRIDA_COMPILER_DISABLE=0|1  # 禁用新的Frida TypeScript编译器(`:. foo.ts`)
  26.   R2FRIDA_AGENT_SCRIPT=[file]      # r2frida代理文件路径
复制代码
通过r2frida,你可以列出本地历程(frida://),附加到指定历程(frida://attach/PID),或者在远程装备上启动或附加历程(frida://remote/hostname:port/PID)。
r2frida 提供了大量方便的命令,例如 :i 获取目标信息,:dm 列出内存映射,:dt 追踪函数,:.-pluginName 卸载插件等。
总的来说,r2frida 是一个强盛的开源项目,为软件安全研究职员、开发者和逆向工程师提供了深入明白应用步伐内部举动的优秀工具。无论是研究未知代码还是调试复杂问题,r2frida 都能助你一臂之力。立即实行,开启你的代码探索之旅吧!
利用样例
   $ r2 frida://0     # 与frida -p 0相同,毗连至一个本地会话
我们可以通过历程名称或pid毗连、生成或启动任意历程,下列命令将毗连到第一个名为rax2的历程:
  $ r2 frida://rax2   # 毗连至第一个名为rax2的历程
  $ r2 frida://1234  # 毗连至指定pid
利用源码的绝对路径将生成一个历程:
  $ r2 frida:///bin/ls
  [0x00000000]> :dc        # 目标应用步伐继续执行
添加其他参数运行:
  $ r2 frida://"/bin/ls -al"
下列命令可以利用USB调试iOS/Android应用步伐:
  $ r2 frida://spawn/usb/         # 枚举装备
  $ r2 frida://spawn/usb//        # 枚举iOS装备中的应用步伐
  $ r2 frida://spawn/usb//Weather # 运行Weather天气App
  1. 命令解析
  2. :i         # 获取目标详情
  3. .:i*        # 将目标进程详情导入至local r2
  4. :?         # 显示所有可用命令
  5. :dm       # 枚举映射,使用':dm|head'搜索程序基地址
  6. :iE        # 枚举当前二进制的导出
  7. :dt fread   # 跟踪'fread'函数
  8. :dt-*      # 删除所有跟踪
复制代码


3、Radare2 指南


github:https://github.com/radareorg/radare2
全功能的二进制文件分析工具 Radare2 指南:https://linux.cn/article-13074-1.html
Radare2 (也称为 r2) 是一个 类 Unix 系统上的逆向工程框架和命令行工具集,它名字中的 2 是因为这个版本从头开始重写的,使其更加模块化。
在《Linux 上分析二进制文件的 10 种方法》中,利用了 Linux 中原生工具集来分析二进制文件。但假如你想进一步探索你的二进制文件,你就需要一个为二进制分析定制的工具。假如你是二进制分析的新手,并且大多利用的是脚本语言,这篇文章《GNU binutils 里的九种武器》可以资助你开始学习编译过程和什么是二进制。
Radare2 是全功能的二进制文件分析工具,二进制文件分析神器。
Radare2 手册:https://heersin.gitbook.io/radare2/intro

为什么需要一个新工具

假如现有的 Linux 原生工具也能做类似的事变,你自然会问为什么需要另一个工具。嗯,这和你用手机做闹钟、做笔记、做相机、听音乐、上网、偶尔打电话和接电话的原因是一样的。从前,利用单独的装备和工具处置惩罚这些功能 —— 比如拍照的实体相机,记笔记的小记事本,起床的床头闹钟等等。对用户来说,有一个装备来做多件(但相干的)事变是方便的。别的,杀手锏就是独建功能之间的互操纵性
同样,纵然许多 Linux 工具都有特定的用途,但在一个工具中捆绑类似(和更好)的功能黑白常有效的。这就是为什么我认为 Radare2 应该是你需要处置惩罚二进制文件时的首选工具。
根据其 GitHub 简介,Radare2(也称为 r2)是一个“类 Unix 系统上的逆向工程框架和命令行工具集”。它名字中的 “2” 是因为这个版本从头开始重写的,使其更加模块化。

为什么选择 Radare2

有大量(非原生的)Linux 工具可用于二进制分析,为什么要选择 Radare2 呢?我的理由很简单。
起首,它是一个开源项目,有一个活跃而康健的社区。假如你正在寻找新颖的功能或提供着 bug 修复的工具,这很重要。
其次,Radare2 可以在命令行上利用,而且它有一个功能丰富的图形用户界面(GUI)环境,叫做 Cutter,适合那些对 GUI 比力熟悉的人。作为一个长期利用 Linux 的用户,我对习惯于在 shell 上输入。虽然熟悉 Radare2 的命令稍微有一点学习曲线,但我会把它比作 学习 Vim。你可以先学习根本的东西,一旦你掌握了它们,你就可以继续学习更高级的东西。很快,它就酿成了肌肉记忆。
第三,Radare2 通过插件可以很好的支持外部工具。例如,最近开源的 Ghidra 二进制分析和逆向工具reversing tool很受接待,因为它的反编译器功能是逆向软件的关键要素。你可以直接从 Radare2 控制台安装 Ghidra 反编译器并利用,这很神奇,让你两全其美。

开始利用 Radare2

要安装 Radare2,只需克隆其存储库并运行 user.sh 脚本。假如你的系统上还没有一些预备软件包,你可能需要安装它们。一旦安装完成,运行 r2 -v 命令来查看 Radare2 是否被精确安装:
  1. $ git clone https://github.com/radareorg/radare2.git
  2. $ cd radare2
  3. $ ./sys/user.sh
  4. # version
  5. $ r2 -v
  6. radare2 4.6.0-git 25266 @ linux-x86-64 git.4.4.0-930-g48047b317
  7. commit: 48047b3171e6ed0480a71a04c3693a0650d03543 build: 2020-11-17__09:31:03
  8. $
复制代码

获取二进制测试样本

现在 r2 已经安装好了,你需要一个样本二进制步伐来试用它。你可以利用任何系统二进制文件(ls、bash 等),但为了使本教程的内容简单,请编译以下 C 步伐:
cat adder.c
  1. #include <stdio.h>
  2. int adder(int num) {
  3.         return num + 1;
  4. }
  5. int main() {
  6.         int res, num1 = 100;
  7.         res = adder(num1);
  8.         printf("Number now is  : %d\n", res);
  9.         return 0;
  10. }
复制代码
$ gcc adder.c -o adder
$ file adder
adder: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=9d4366f7160e1ffb46b14466e8e0d70f10de2240, not stripped
$ ./adder
Number now is  : 101

加载二进制文件

要分析二进制文件,你必须在 Radare2 中加载它。通过提供文件名作为 r2 命令的一个命令行参数来加载它。你会进入一个独立的 Radare2 控制台,这与你的 shell 不同。要退出控制台,你可以输入 Quit 或 Exit 或按 Ctrl+D:
$ r2 ./adder
 -- Learn pancake as if you were radare!
[0x004004b0]> quit
$

分析二进制

在你探索二进制之前,你必须让 r2 为你分析它。你可以通过在 r2 控制台中运行 aaa 命令来实现:
$ r2 ./adder
 -- Sorry, radare2 has experienced an internal error.
[0x004004b0]>
[0x004004b0]>
[0x004004b0]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x004004b0]>
这意味着每次你选择一个二进制文件举行分析时,你必须在加载二进制文件后输入一个额外的命令 aaa。你可以绕过这一点,在命令后面跟上 -A 来调用 r2;这将告诉 r2 为你自动分析二进制:
$ r2 -A ./adder
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- Already up-to-date.
[0x004004b0]>

获取一些关于二进制的根本信息

在开始分析一个二进制文件之前,你需要一些背景信息。在许多环境下,这可以是二进制文件的格式(ELF、PE 等)、二进制的架构(x86、AMD、ARM 等),以及二进制是 32 位还是 64 位。方便的 r2 的 iI 命令可以提供所需的信息:
[0x004004b0]> iI
arch     x86
baddr    0x400000
binsz    14724
bintype  elf
bits     64
canary   false
class    ELF64
compiler GCC: (GNU) 8.3.1 20190507 (Red Hat 8.3.1-4)
crypto   false
endian   little
havecode true
intrp    /lib64/ld-linux-x86-64.so.2
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
relro    partial
rpath    NONE
sanitiz  false
static   false
stripped false
subsys   linux
va       true
[0x004004b0]>
[0x004004b0]>

导入和导出

通常环境下,当你知道你要处置惩罚的是什么样的文件后,你就想知道二进制步伐利用了什么样的标准库函数,或者了解步伐的潜伏功能。在本教程中的示例 C 步伐中,唯一的库函数是 printf,用来打印信息。你可以通过运行 ii 命令看到这一点,它显示了该二进制全部导入的库:
[0x004004b0]> ii
[Imports]
nth vaddr      bind   type   lib name
―――――――――――――――――――――――――――――――――――――
1   0x00000000 WEAK   NOTYPE     _ITM_deregisterTMCloneTable
2   0x004004a0 GLOBAL FUNC       printf
3   0x00000000 GLOBAL FUNC       __libc_start_main
4   0x00000000 WEAK   NOTYPE     __gmon_start__
5   0x00000000 WEAK   NOTYPE     _ITM_registerTMCloneTable
该二进制也可以有自己的符号、函数或数据。这些函数通常显示在 Exports 下。这个测试的二进制导出了两个函数:main 和 adder。别的的函数是在编译阶段,当二进制文件被构建时添加的。加载器需要这些函数来加载二进制文件(现在不消太关心它们):
[0x004004b0]>
[0x004004b0]> iE
[Exports]
nth paddr       vaddr      bind   type   size lib name
――――――――――――――――――――――――――――――――――――――――――――――――――――――
82   0x00000650 0x00400650 GLOBAL FUNC   5        __libc_csu_fini
85   ---------- 0x00601024 GLOBAL NOTYPE 0        _edata
86   0x00000658 0x00400658 GLOBAL FUNC   0        _fini
89   0x00001020 0x00601020 GLOBAL NOTYPE 0        __data_start
90   0x00000596 0x00400596 GLOBAL FUNC   15       adder
92   0x00000670 0x00400670 GLOBAL OBJ    0        __dso_handle
93   0x00000668 0x00400668 GLOBAL OBJ    4        _IO_stdin_used
94   0x000005e0 0x004005e0 GLOBAL FUNC   101      __libc_csu_init
95   ---------- 0x00601028 GLOBAL NOTYPE 0        _end
96   0x000004e0 0x004004e0 GLOBAL FUNC   5        _dl_relocate_static_pie
97   0x000004b0 0x004004b0 GLOBAL FUNC   47       _start
98   ---------- 0x00601024 GLOBAL NOTYPE 0        __bss_start
99   0x000005a5 0x004005a5 GLOBAL FUNC   55       main
100  ---------- 0x00601028 GLOBAL OBJ    0        __TMC_END__
102  0x00000468 0x00400468 GLOBAL FUNC   0        _init
[0x004004b0]>

哈希信息

如何知道两个二进制文件是否相似?你不能只是打开一个二进制文件并查看里面的源代码。在大多数环境下,二进制文件的哈希值(md5sum、sha1、sha256)是用来唯一识别它的。你可以利用 it 命令找到二进制的哈希值:
[0x004004b0]> it
md5 7e6732f2b11dec4a0c7612852cede670
sha1 d5fa848c4b53021f6570dd9b18d115595a2290ae
sha256 13dd5a492219dac1443a816ef5f91db8d149e8edbf26f24539c220861769e1c2
[0x004004b0]>

函数

代码按函数分组;要列出二进制中存在的函数,请运行 afl 命令。下面的列表显示了 main 函数和 adder 函数。通常,以 sym.imp 开头的函数是从标准库(这里是 glibc)中导入的:
[0x004004b0]> afl
0x004004b0    1 46           entry0
0x004004f0    4 41   -> 34   sym.deregister_tm_clones
0x00400520    4 57   -> 51   sym.register_tm_clones
0x00400560    3 33   -> 32   sym.__do_global_dtors_aux
0x00400590    1 6            entry.init0
0x00400650    1 5            sym.__libc_csu_fini
0x00400658    1 13           sym._fini
0x00400596    1 15           sym.adder
0x004005e0    4 101          loc..annobin_elf_init.c
0x004004e0    1 5            loc..annobin_static_reloc.c
0x004005a5    1 55           main
0x004004a0    1 6            sym.imp.printf
0x00400468    3 27           sym._init
[0x004004b0]>

交叉引用

在 C 语言中,main 函数是一个步伐开始执行的地方。理想环境下,其他函数都是从 main 函数调用的,在退出步伐时,main 函数会向操纵系统返回一个退出状态。这在源代码中是很显着的,然而,二进制步伐呢?如何判断 adder 函数的调用位置呢?
你可以利用 axt 命令,后面加上函数名,看看 adder 函数是在哪里调用的;如下图所示,它是从 main 函数中调用的。这就是所谓的交叉引用cross-referencing。但什么调用 main 函数本身呢?从下面的 axt main 可以看出,它是由 entry0 调用的(关于 entry0 的学习我就不说了,留待读者练习)。
[0x004004b0]> axt sym.adder
main 0x4005b9 [CALL] call sym.adder
[0x004004b0]>
[0x004004b0]> axt main
entry0 0x4004d1 [DATA] mov rdi, main
[0x004004b0]>

寻找定位

在处置惩罚文本文件时,你经常通过引用行号和行或列号在文件内移动;在二进制文件中,你需要利用地址。这些是以 0x 开头的十六进制数字,后面跟着一个地址。要找到你在二进制中的位置,运行 s 命令。要移动到不同的位置,利用 s 命令,后面跟上地址。
函数名就像标签一样,内部用地址表示。假如函数名在二进制中(未剥离的),可以利用函数名后面的 s 命令跳转到一个特定的函数地址。同样,假如你想跳转到二进制的开始,输入 s 0:
[0x004004b0]> s
0x4004b0
[0x004004b0]>
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> s
0x4005a5
[0x004005a5]>
[0x004005a5]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> s 0
[0x00000000]>
[0x00000000]> s
0x0
[0x00000000]>

十六进制视图

通常环境下,原始二进制没故意义。在十六进制模式下查看二进制及其等效的 ASCII 表示法会有资助:
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x004005a5  5548 89e5 4883 ec10 c745 fc64 0000 008b  UH..H....E.d....
0x004005b5  45fc 89c7 e8d8 ffff ff89 45f8 8b45 f889  E.........E..E..
0x004005c5  c6bf 7806 4000 b800 0000 00e8 cbfe ffff  ..x.@...........
0x004005d5  b800 0000 00c9 c30f 1f40 00f3 0f1e fa41  .........@.....A
0x004005e5  5749 89d7 4156 4989 f641 5541 89fd 4154  WI..AVI..AUA..AT
0x004005f5  4c8d 2504 0820 0055 488d 2d04 0820 0053  L.%.. .UH.-.. .S
0x00400605  4c29 e548 83ec 08e8 57fe ffff 48c1 fd03  L).H....W...H...
0x00400615  741f 31db 0f1f 8000 0000 004c 89fa 4c89  t.1........L..L.
0x00400625  f644 89ef 41ff 14dc 4883 c301 4839 dd75  .D..A...H...H9.u
0x00400635  ea48 83c4 085b 5d41 5c41 5d41 5e41 5fc3  .H...[]A\A]A^A_.
0x00400645  9066 2e0f 1f84 0000 0000 00f3 0f1e fac3  .f..............
0x00400655  0000 00f3 0f1e fa48 83ec 0848 83c4 08c3  .......H...H....
0x00400665  0000 0001 0002 0000 0000 0000 0000 0000  ................
0x00400675  0000 004e 756d 6265 7220 6e6f 7720 6973  ...Number now is
0x00400685  2020 3a20 2564 0a00 0000 0001 1b03 3b44    : %d........;D
0x00400695  0000 0007 0000 0000 feff ff88 0000 0020  ...............
[0x004005a5]>

反汇编

假如你利用的是编译后的二进制文件,则无法查看源代码。编译器将源代码转译成 CPU 可以明白和执行的机器语言指令;其结果就是二进制或可执行文件。然而,你可以查看汇编指令(的助记词)来明白步伐正在做什么。例如,假如你想查看 main 函数在做什么,你可以利用 s main 寻找 main 函数的地址,然后运行 pdf 命令来查看反汇编的指令。
要明白汇编指令,你需要参考体系布局手册(这里是 x86),它的应用二进制接口(ABI,或调用惯例),并对堆栈的工作原理有根本的了解:
[0x004004b0]> s main
[0x004005a5]>
[0x004005a5]> s
0x4005a5
[0x004005a5]>
[0x004005a5]> pdf
            ; DATA XREF from entry0 @ 0x4004d1
┌ 55: int main (int argc, char **argv, char **envp);
│           ; var int64_t var_8h @ rbp-0x8
│           ; var int64_t var_4h @ rbp-0x4
│           0x004005a5      55             push rbp
│           0x004005a6      4889e5         mov rbp, rsp
│           0x004005a9      4883ec10       sub rsp, 0x10
│           0x004005ad      c745fc640000.  mov dword [var_4h], 0x64    ; 'd' ; 100
│           0x004005b4      8b45fc         mov eax, dword [var_4h]
│           0x004005b7      89c7           mov edi, eax
│           0x004005b9      e8d8ffffff     call sym.adder
│           0x004005be      8945f8         mov dword [var_8h], eax
│           0x004005c1      8b45f8         mov eax, dword [var_8h]
│           0x004005c4      89c6           mov esi, eax
│           0x004005c6      bf78064000     mov edi, str.Number_now_is__:__d ; 0x400678 ; "Number now is  : %d\n" ; const char *format
│           0x004005cb      b800000000     mov eax, 0
│           0x004005d0      e8cbfeffff     call sym.imp.printf         ; int printf(const char *format)
│           0x004005d5      b800000000     mov eax, 0
│           0x004005da      c9             leave
└           0x004005db      c3             ret
[0x004005a5]>
这是 adder 函数的反汇编结果:
[0x004005a5]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> pdf
            ; CALL XREF from main @ 0x4005b9
┌ 15: sym.adder (int64_t arg1);
│           ; var int64_t var_4h @ rbp-0x4
│           ; arg int64_t arg1 @ rdi
│           0x00400596      55             push rbp
│           0x00400597      4889e5         mov rbp, rsp
│           0x0040059a      897dfc         mov dword [var_4h], edi     ; arg1
│           0x0040059d      8b45fc         mov eax, dword [var_4h]
│           0x004005a0      83c001         add eax, 1
│           0x004005a3      5d             pop rbp
└           0x004005a4      c3             ret
[0x00400596]>

字符串

查看二进制中存在哪些字符串可以作为二进制分析的起点。字符串是硬编码到二进制中的,通常会提供重要的提示,可以让你将重点转移到分析某些区域。在二进制中运行 iz 命令来列出全部的字符串。这个测试二进制中只有一个硬编码的字符串:
[0x004004b0]> iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000678 0x00400678 20  21   .rodata ascii Number now is  : %d\n
[0x004004b0]>

交叉引用字符串

和函数一样,你可以交叉引用字符串,看看它们是从哪里被打印出来的,并明白它们四周的代码:
[0x004004b0]> ps @ 0x400678
Number now is  : %d
[0x004004b0]>
[0x004004b0]> axt 0x400678
main 0x4005c6 [DATA] mov edi, str.Number_now_is__:__d
[0x004004b0]>

可视模式

当你的代码很复杂,有多个函数被调用时,很容易迷失方向。假如能以图形或可视化的方式查看哪些函数被调用,根据某些条件接纳了哪些路径等,会很有资助。在移动到感爱好的函数后,可以通过 VV 命令来探索 r2 的可视化模式。例如,对于 adder 函数:
[0x004004b0]> s sym.adder
[0x00400596]>
[0x00400596]> VV




调试器

到现在为止,你一直在做的是静态分析 —— 你只是在看二进制文件中的东西,而没有运行它,有时你需要执行二进制文件,并在运行时分析内存中的各种信息。r2 的内部调试器允许你运行二进制文件、设置断点、分析变量的值、或者转储寄存器的内容。
用 -d 标志启动调试器,并在加载二进制时添加 -A 标志举行分析。你可以通过利用 db <function-name> 命令在不同的地方设置断点,比如函数或内存地址。要查看现有的断点,利用 dbi 命令。一旦你放置了断点,利用 dc 命令开始运行二进制文件。你可以利用 dbt 命令查看堆栈,它可以显示函数调用。最后,你可以利用 drr 命令转储寄存器的内容:
$ r2 -d -A ./adder
Process with PID 17453 started...
= attach 17453 17453
bin.baddr 0x00400000
Using 0x400000
asm.bits 64
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- git checkout hamster
[0x7f77b0a28030]>
[0x7f77b0a28030]> db main
[0x7f77b0a28030]>
[0x7f77b0a28030]> db sym.adder
[0x7f77b0a28030]>
[0x7f77b0a28030]> dbi
0 0x004005a5 E:1 T:0
1 0x00400596 E:1 T:0
[0x7f77b0a28030]>
[0x7f77b0a28030]> afl | grep main
0x004005a5    1 55           main
[0x7f77b0a28030]>
[0x7f77b0a28030]> afl | grep sym.adder
0x00400596    1 15           sym.adder
[0x7f77b0a28030]>
[0x7f77b0a28030]> dc
hit breakpoint at: 0x4005a5
[0x004005a5]>
[0x004005a5]> dbt
0  0x4005a5           sp: 0x0                 0    [main]  main sym.adder+15
1  0x7f77b0687873     sp: 0x7ffe35ff6858      0    [??]  section..gnu.build.attributes-1345820597
2  0x7f77b0a36e0a     sp: 0x7ffe35ff68e8      144  [??]  map.usr_lib64_ld_2.28.so.r_x+65034
[0x004005a5]> dc
hit breakpoint at: 0x400596
[0x00400596]> dbt
0  0x400596           sp: 0x0                 0    [sym.adder]  rip entry.init0+6
1  0x4005be           sp: 0x7ffe35ff6838      0    [main]  main+25
2  0x7f77b0687873     sp: 0x7ffe35ff6858      32   [??]  section..gnu.build.attributes-1345820597
3  0x7f77b0a36e0a     sp: 0x7ffe35ff68e8      144  [??]  map.usr_lib64_ld_2.28.so.r_x+65034
[0x00400596]>
[0x00400596]>
[0x00400596]> dr
rax = 0x00000064
rbx = 0x00000000
rcx = 0x7f77b0a21738
rdx = 0x7ffe35ff6948
r8 = 0x7f77b0a22da0
r9 = 0x7f77b0a22da0
r10 = 0x0000000f
r11 = 0x00000002
r12 = 0x004004b0
r13 = 0x7ffe35ff6930
r14 = 0x00000000
r15 = 0x00000000
rsi = 0x7ffe35ff6938
rdi = 0x00000064
rsp = 0x7ffe35ff6838
rbp = 0x7ffe35ff6850
rip = 0x00400596
rflags = 0x00000202
orax = 0xffffffffffffffff
[0x00400596]>

反编译器

可以或许明白汇编是二进制分析的条件。汇编语言总是与二进制创建和预期运行的架构相干。一行源代码和汇编代码之间从来没有 1:1 的映射。通常,一行 C 源代码会产生多行汇编代码。以是,逐行读取汇编代码并不是最佳的选择。
这就是反编译器的作用。它们试图根据汇编指令重建可能的源代码。这与用于创建二进制的源代码绝不完全相同,它是基于汇编的源代码的近似表示。别的,要考虑到编译器举行的优化,它会生成不同的汇编代码以加快速度,减小二进制的巨细等,会使反编译器的工作更加困难。别的,恶意软件作者经常故意混淆代码,让恶意软件的分析职员望而却步。
Radare2 通过插件提供反编译器。你可以安装任何 Radare2 支持的反编译器。利用 r2pm -l 命令可以查看当前插件。利用 r2pm install 命令来安装一个示例的反编译器 r2dec:
$ r2pm  -l
$
$ r2pm install r2dec
Cloning into 'r2dec'...
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (97/97), done.
remote: Total 100 (delta 18), reused 27 (delta 1), pack-reused 0
Receiving objects: 100% (100/100), 1.01 MiB | 1.31 MiB/s, done.
Resolving deltas: 100% (18/18), done.
Install Done For r2dec
gmake: Entering directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
[CC] duktape/duktape.o
[CC] duktape/duk_console.o
[CC] core_pdd.o
[CC] core_pdd.so
gmake: Leaving directory '/root/.local/share/radare2/r2pm/git/r2dec/p'
$
$ r2pm  -l
r2dec
$


反编译器视图

要反编译一个二进制文件,在 r2 中加载二进制文件并自动分析它。在本例中,利用 s sym.adder 命令移动到感爱好的 adder 函数,然后利用 pdda 命令并排查看汇编和反编译后的源代码。阅读这个反编译后的源代码通常比逐行阅读汇编更容易:
$ r2 -A ./adder
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
 -- What do you want to debug today?
[0x004004b0]>
[0x004004b0]> s sym.adder
[0x00400596]>
[0x00400596]> s
0x400596
[0x00400596]>
[0x00400596]> pdda
    ; assembly                               | /* r2dec pseudo code output */
                                             | /* ./adder @ 0x400596 */
                                             | #include <stdint.h>
                                             |  
    ; (fcn) sym.adder ()                     | int32_t adder (int64_t arg1) {
                                             |     int64_t var_4h;
                                             |     rdi = arg1;
    0x00400596 push rbp                      |    
    0x00400597 mov rbp, rsp                  |    
    0x0040059a mov dword [rbp - 4], edi      |     *((rbp - 4)) = edi;
    0x0040059d mov eax, dword [rbp - 4]      |     eax = *((rbp - 4));
    0x004005a0 add eax, 1                    |     eax++;
    0x004005a3 pop rbp                       |    
    0x004005a4 ret                           |     return eax;
                                             | }
[0x00400596]>

配置设置

随着你对 Radare2 的利用越来越熟悉,你会想改变它的配置,以适应你的工作方式。你可以利用 e 命令查看 r2 的默认配置。要设置一个特定的配置,在 e 命令后面添加 config = value:
[0x004005a5]> e | wc -l
593
[0x004005a5]> e | grep syntax
asm.syntax = intel
[0x004005a5]>
[0x004005a5]> e asm.syntax = att
[0x004005a5]>
[0x004005a5]> e | grep syntax
asm.syntax = att
[0x004005a5]>
要使配置更改永久化,请将它们放在 r2 启动时读取的名为 .radare2rc 的启动文件中。这个文件通常在你的主目次下,假如没有,你可以创建一个。一些示例配置选项包括:
$ cat ~/.radare2rc
e asm.syntax = att
e scr.utf8 = true
eco solarized
e cmd.stack = true
e stack.size = 256
$

探索更多

你已经看到了充足多的 Radare2 功能,对这个工具有了一定的了解。因为 Radare2 遵循 Unix 哲学,纵然你可以从它的主控台做各种事变,它也会在下面利用一套独立的二进制来完成它的任务。
探索下面列出的独立二进制文件,看看它们是如何工作的。例如,用 iI 命令在控制台看到的二进制信息也可以用 rabin2 <binary> 命令找到:
$ cd bin/
$
$ ls
prefix  r2agent    r2pm  rabin2   radiff2  ragg2    rarun2   rasm2
r2      r2-indent  r2r   radare2  rafind2  rahash2  rasign2  rax2
$


4、Binutils 工具


GNU Binutils:http://www.gnu.org/software/binutils/
对于嵌入式系统开发,掌握相应的工具至关重要,它能使我们解决问题的服从大大提高。现在,可以说嵌入式系统的开发工具是GNU的天下,因为来自GNU的GCC编译器支持大量的目标处置惩罚器。除了GCC,还有一个非常重要的、同样来自于 GNU的工具集(toolchain) —— binutils toolchain。这一工具会合存在的一些工具,可以说是我们开发和调试不可缺少的利器。 Binutils中的工具不少和GCC相类似,也是针对特定的处置惩罚器的。
在binutils中以下的工具是我们在做嵌入式系统开发时需要掌握的:
addr2line
将步伐地址翻译成文件名和行号;给定地址和可执行文件名称,它利用其中的调试信息判断与此地址有关联的源文件和行号。
(将地址对应到文件名和行号)
ar
创建、修改和提取归档
as
一个汇编器,as工具重要用来将汇编语言编写的源步伐转换成二进制形式的目标代码。Linux平台的标准汇编器是GAS,它是Gnu GCC编译器所依靠的背景汇编工具,通常包罗在Binutils软件包中。
c++filt
被链接器用于修复 C++ 和 Java 符号,防止重载的函数相互冲突
elfedit
更新 ELF 文件的 ELF 头
gprof
显示分析数据的调用图表。gprof是Linux下一个强有力的步伐分析工具。可以或许以“日志”的形式记录步伐运行时的统计信息:步伐运行中各个函数消耗的时间和函数调用关 系,以及每个函数被调用的次数等等。从而可以资助步伐员找出浩繁函数中耗时最多的函数,也可以资助步伐员分析步伐的运行流程。相信这些功能对于分析开源代 码的步伐员来说,有着相称大的诱惑力;同时我们也可以借助gprof举行性能优化和分析。
ld
一个链接器,将几个对象和归档文件组合成一个文件,重新定位它们的数据并且捆绑符号索引。同as一样,ld也是GNU Binutils工具会合重要的工具,Linux利用ld作为标准的链接步伐,由汇编器产生的目标代码是不能直接在计算机上运行的,它必须经过链接器的处 理才气生成可执行代码,链接是创建一个可执行步伐的最后一个步骤,ld可以将多个目标文件链接成为可执行步伐,同时指定了步伐在运行时是如何执行的。
ld.bfd
到 ld 的硬链接
nm
列出给定对象文件中出现的符号(列出目标文件(.o)的符号清单)
objcopy
将一种对象文件翻译成另一种,.bin 转换成 .elf 、.elf 转换成 .bin等。
objdump
显示有关给定对象文件的内容信息,包罗指定显示信息的选项;显示的信息对编译工具开发者很有效(能实现(ar,nm)的许多功能)
最重要的作用是反汇编
ranlib
创建一个归档的内容索引并存储在归档内;索引列出其成员中可重定位的对象文件界说的全部符号。ranlib 生成索引以加快对归档文件的访问,并将结果保存到这个归档文件中,在索引中列出了归档文件各个成员所界说的可重分配目标文件。ar -s可以实现类似的功能。
readelf
显示有关 ELF 二进制文件的信息,readelf -h *.exe举行查看。是ELF文件查看利器。
size
列出给定对象文件每个部分的尺寸和总尺寸,代码段、数据段、总巨细等。
strings
对每个给定的文件输出不短于指定长度 (默认为 4) 的全部可打印字符序列;对于对象文件默认只打印初始化和加载部分的字符串,否则扫描整个文件
strip
移除对象文件中的符号,举行文件压缩,举行瘦身。即删除目标文件中的全部或者特定符号,这样可以减小可执行文件的巨细。在嵌入式应用中,可执行文件一样平常存放在flash中,空间有限,因此在产品 release的过程中接纳strip对步伐举行裁剪很有必要。
libiberty
包罗多个 GNU 步伐会利用的途径,包括 getoptobstackstrerrorstrtol 和 strtoul
libbfd
二进制文件形貌器库
libopcodes
一个库,用于处置惩罚 opcodes——处置惩罚器指令的 “可读文本” 版本;用于体例 objdump 这样的工具

file 查看文件类型

file 会设法判断文件的布局是否符合某种已知的文件格式。多数环境下,它会搜索某些文件类型所特有的标签值(通常称为幻数)。file 可以或许识别大量的文件格式,包括数种 ASCII 文本文件、各种可执行文件和数据文件。file 执行的幻数检查是由幻数文件(magicfile)所包罗的规则控制。幻数文件的默认位置因操纵系统而异,常见的位置包括 /usr/share/file/magic、/usr/share/misc/magic和/etc/magic。欲了解更多有关幻数文件的信息,请参阅 file 的文档资料。


  • file:分析任何文件的根本格式。常用参数
    -b:列出辨识结果时,不显示文件名称;
    -c:具体显示指令执行过程,便于排错或分析步伐执行的情况;常与 -m 一起利用,用来在安装幻数文件之前调试它
    -f <文件名>:指定一个或多个文件名,让file依序辨识这些文件,格式为每列一个文件名称;
    -L:直接显示符号毗连所指向的文件类别;
    -m <魔法数字文件>:指定魔法数字文件;
    -v:显示版本信息;
    -z:实行去解读压缩文件的内容。
    -i:显示MIME类别

file 及类似的工具同样也会堕落。假如一个文件碰巧包罗了某种文件格式的标志,file等工具很可能会错误地识别这个文件。你可以利用一个十六进制文件编辑器将任何文件的前4字节修改为Java的幻数序列CAFEBABE,自已证实一下上述环境。这时,file 会将这个新修改的文件错误地识别为已编译的Java类数据。同样,一个仅包罗MZ这两个字符的文本文件会被误认为是一个MS-DOS可执行文件。在逆向工程过程中,绝不要完全相信托何工具所提供的结果,除非该结果得到其他几款工具和手动分析的确认。


string 查看 字符串

strings 可以打印二进制文件中的字符串信息。参数 -a 表示搜索整个文件,参数 -t 可以显示出每一个字符串的偏移,参数-e 可以用于搜索更多的字符编码的字符串,如Unicode编码。结合grep举行搜索,用grep命令实在可以直接在二进制文件中搜索内容,但是不够直观,用strings看起来的更直观些。strings 会把任何可打印字符串都显示出来,比nm的内容更多
   -a --all:扫描整个文件而不是只扫描目标文件初始化和装载段
-f --print-file-name:在显示字符串前先显示文件名
-n --bytes=[number]:找到并且输出全部NUL终止符序列
- :设置显示的最少的字符数,默认是4个字符
-t --radix={o,d,x} :输出字符的位置,基于八进制,十进制或者十六进制
-o :类似--radix=o
-T --target= :指定二进制文件格式
-e --encoding={s,S,b,l,B,L} :选择字符巨细和排列顺序:s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit
@ :读取中选项
  查找ls中包罗libc的字符串,不区分巨细写:strings /bin/ls | grep -i libc

addr2line 将地址映射到代码行

addr2line是用来将步伐地址转换成其所对应的步伐源文件及所对应的代码行,当然,也可以得到所对应的函数。为了阐明addr2line是如何利用的,我们需要有一个练习用的步伐。先接纳编辑工具编辑一个test.c源文件,其内容如图所示。

运行如下的命令将test.c编译成可执行文件,注意:必须加 -g 这个选项 并运行之。在运行test步伐后,我们可以在其终端上看到它打印出的fun()函数的地址 —— 0x80483e4。

现在,我们可以用这一地址来看一看addr2line是如何利用的。在终端中运行如下的命令,从命令的运行结果来看,addr2line工具精确的指出了地址0x80483e4 所对于应的步伐的具体位置是在哪以及所对应的函数名是什么。

可能有人会问了:这个0x80483e4地址是我们打印出来,即然有打印,我们一样平常环境下也会打印出其具体的函数位置,而不是只打印地址,我为何要这么绕一下通过addr2line去找到地址所对应的函数呢?实在,这里打印出地址只是为了得到一个地址以便用于练习。在现实中,地址通常是在调试过程中或是当步伐崩溃时通过某种方式获得的。此外,接纳nm工具(后面会讲到)可以得到如下的函数地址信息。


as 汇编器

as 是将汇编代码汇编成目标文件

size 查看段巨细

size 是列出步伐文件中各段的巨细。在后面的章节中,我们会利用objdump查看段信息,除了这三个段还有.rdata和.idata两个段,其中.rdata段被归类到.text段中,而.idata段被归类到.data段中。下面是接纳size工具所显示出的test中的段巨细信息。


nm 查看符号

nm命令是Linux下自带的强盛的文本分析工具,是命令来源于 name 的简写。该命令用来列出指定文件中的符号(如常用的函数名、变量等,以及这些符号存储的区域)。它显示指定文件中的符号信息,文件可以是对象文件、可执行文件或对象文件库。假如文件中没有包罗符号信息,nm陈诉该环境,单不把他解释为堕落。nm缺省环境下陈诉十进制符号表示法下的数字值。
nm 列举目标文件中的符号。可查看文件中的符号,包括全局变量,全局函数等。对于一些动态库,直接nm可能查不到信息,可以通过nm -D命令查看。

参数阐明:
-A / -o / --print-file-name: 在输出时加上文件名;
-a / --debug-syms: 输出全部符号,包罗debugger-only symbols;
-B / --format=bsd: BSD码显示,兼容MIPS nm;
-C / --demangle: 将低级符号名剖析为用户级名字,可以使得C++函数名更具可读性;
-D / --dynamic: 显示动态符号。该选项只对动态目标(如特定类型的共享库)故意义;
-f format / --format=format 利用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有效。默认为bsd
-g / --extern-only: 只显示外部符号;
-l / --line-numbers: 对于每个符号,利用debug信息找到文件名和行号;
-n / -v / --numeric-sort: 按符号对应地址的顺序排序,而非按符号名字字符顺序排序;
-P /--portability: 按照POSIX2.0标准格式输出,等同于利用 -f posix;
-p / --no-sort: 按照目标文件中遇到的符号顺序显示,不排序;
-r / --reverse-sort: 反转排序;
-s / --print-armap: 当列出库成员符号时,包罗索引。索引的内容:模块和其包罗名字的映射;
-u / --undefined-only: 只显示未界说符号;
--defined-only: 只显示界说了的符号。
   常用选项:
-A    每个符号前显示文件名
-D    显示动态符号
-g    仅显示外部符号
-r    反序显示符号表
  nm用于列出步伐文件中的符号,符号是指函数或是变量名什么的。下面来看一看图 2所编译出来的步伐当中有些什么符号

      nm所列出的每一行有三部分构成:
第一列是指步伐运行时的符号所对应的地址,对于函数则地址表示的是函数的开始地址,对于变量则表示的是变量的存储地址
第二列是指相应符号是放在哪一个段的;
第三列则是指符号的名称。
在前面我们讲解addr2line时,我们提到addr2line是将步伐地址转换成这一地址所对应的具体函数是什么,而nm则是全面的列出这些信息。但是,nm不具备列出符号所在的源文件及其行号这一功能,因此,我们说每一个工具有其特定的功能,在嵌入式系统的开发过程中我们需要灵活的运用它们。  
       对于nm列出的第二列信息,非常的有效,其意义在于可以了解我们在步伐中所界说的一个符号(比如变量等等)是被放在步伐的哪一个段的,下表列出了第二列将会出现的部分字母的含义,要参看全部字母的意思,请在你的开发环境中运行“man nm”。


ldd 查看链接的库

查看文件执行所需要的 共享库/动态库。

   -v    具体信息模式,打印全部相干信息
-u    打印未利用的直接依靠
-d    执行重定位和陈诉任何丢失的对象
-r    执行数据对象和函数的重定位,并且陈诉任何丢失的对象和函数
--help    显示资助信息
  示例:ldd /bin/vim
  
strip 去除elf中的符号

strip 用于去除步伐文件中的调试信息以便减小文件的巨细。 去除符号后仍旧保持正常功能。但增加了逆向的难度,出题恶人必备。其与 objcopy 带 --strip-debug 参数时的功能是一样的。strip所具有的功能,objcopy也都有。

可以看到test小了几KB,strip在大文件中有更好的表现。

objcopy 

objcopy 用来修改可执行文件、目标文件或其他二进制文件的 格式、内容或属性。

  • 文件格式转换:将文件从一种格式转换为另一种格式。示例:objcopy -O binary  xx  xx.bin
  • 去除调试信息:从可执行文件或目标文件中移除调试符号。
  • 提取部分数据:从文件中提取某段特定的数据或段。
  • 修改符号表:重定名、删除或添加符号。
  • 创建固件镜像:用于嵌入式开发,生成特定的二进制文件或镜像。

objdump

objdump 是 GNU binutils 工具套件的一部分。objdump 依靠二进制文件形貌符库libbfd(二进制工具的一个组件)来访问目标文件,因此,它可以或许剖析libbfd支持的文件格式(ELF、PE等)。别的 readelf 工具也可用于剖析ELF文件。readelf 的大多数功能与objdump相同,它们之间的重要区别在于 readelf 并不依靠 libbfd。readelf 可查看文件的全部具体信息,包括文件的头信息,动态库信息,段信息等
objdump 将二进制代码转汇编指令。objdump是个值得深入学习的指令,不光可以还原汇编指令,还可以读取二进制中特定段的信息,更可怕的是,假如我们的步伐是以-g -o0等调试不优化的环境下,用objdump -S指令可能尽可能地还原源代码信息(没看错,是还原出源代码信息),实在也可以明白这些信息是完整的在可执行文件中的,要不然gdb调试的时候没办法单步追踪了,
objdump可以用来查看目标步伐中的段信息和调试信息,也可以用来对目标步伐举行反汇编。我们知道步伐是由多个段构成的,比如.text是用来放代码的、.data是用来放初始化好的数据的、.bss是用来放未初始化好的数据的,等等。在嵌入式系统的开发过程中,我们有时需要知道所生成的步伐中的段信息来分析问题。比如,我们需要知道其中的某个段在步伐运行时,共起始地址是什么,或者,我们需要知道正在运行的步伐中是否存在调试信息等等。 
  1. -a, --archive-headers
  2.     显示文件的头信息,展示档案每一个成员的文件格式。效果等同于命令 ar -tv
  3. -b, --target=BFDNAME
  4.     指定目标码格式。非必须。objdump 能自动识别许多格式
  5. -d, --disassemble  反汇编目标文件,将机器指令反汇编成汇编代码
  6. -D, --disassemble-all
  7.     与 -d 类似,但反汇编所有段(section)
  8. -z, --disassemble-zeroes
  9.     一般反汇编输出将省略零块,该选项使得这些零块也被反汇编
  10. -EB, -EL,--endian={big | little}
  11.     指定目标文件的字节序,在目标文件没描述字节序时很有用,例如 S-records。这个选项只影响反汇编
  12. -f, --file-headers
  13.     显示每一个目标文件的头信息
  14. -F, --file-offsets
  15.     反汇编时,打印每一个符号的偏移地址
  16. --file-start-context
  17.     显示源码/汇编代码(假设为 -S)时,将上下文扩展到文件的开头
  18. -g, --debugging
  19.     显示调试信息。企图解析保存在文件中的调试信息并以 C 语言的语法显示出来。
  20.         仅仅支持某些类型的调试信息。有些其他的格式被 readelf -w支持
  21. -e, --debugging-tags
  22.     类似 -g 选项,但是生成的信息是和ctags工具相兼容的格式
  23. -h, --section-headers, --headers
  24.     显示目标文件各个 section 的头部摘要信息
  25. -i, --info
  26.     显示对于 -b 或者 -m 选项可用的架构和目标格式列表
  27. -j, --section=NAME
  28.     仅显示指定名称的 section 的信息
  29. -l, --line-numbers
  30.     用文件名和行号标注相应的目标代码,仅仅和 -d、-D 或者 -r 一起使用
  31. -S,--source
  32.     反汇编时尽可能使用源代码表示。隐含了-d参数
  33. -m, --architecture=MACHINE
  34.     指定反汇编目标文件时使用的架构,当待反汇编文件本身没描述架构信息的时候(比如S-records)这个选项很有用。
  35.         可以用-i选项列出这里能够指定的架构
  36. -M, --disassembler-options=OPTIONS
  37.     给反汇编程序传递参数,可以指定多个,使用逗号分隔
  38. -p, --private-headers
  39.     打印目标文件格式的特定信息。打印的信息取决于目标文件格式,对于某些目标文件格式,不打印任何附加信息。
  40. -P, --private=OPTIONS
  41.     打印目标文件格式的特定信息。OPTIONS 是一个逗号分隔的列表。例如对于XCOFF,可用的
  42.         选项有 header, aout, sections, syms, relocs, lineno, loader, except, typchk, traceback and toc
  43. -r, --reloc
  44.     显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇编后的格式显示出来
  45. -R, --dynamic-reloc
  46.     显示文件的动态重定位入口,仅仅对于动态目标文件意义,比如某些共享库
  47. -s, --full-contents
  48.     显示section的完整内容。默认所有的非空section都会被显示
  49. -W[lLiaprmfFsoRt],--dwarf=
  50.     显示文件中调试段的内容,如果存在的话
  51. -G, --stabs
  52.     显示请求的任何 section 的全部内容。显示段 .stab、.stab.index 和 .stab.excl 的内容
  53. -t, --syms
  54.     显示文件的符号表入口。类似于nm -s提供的信息
  55. -T, --dynamic-syms
  56.     显示文件的动态符号表入口,仅仅对动态目标文件意义,
  57.         比如某些共享库。它显示的信息类似于 nm -D,--dynamic 显示的信息
  58. -x, --all-headers
  59.     显示所可用的头信息,包括符号表、重定位入口。-x 等价于 -a -f -h -p -r -t 同时指定
  60. -w, --wide
  61.     为具有超过80列的输出设备格式化某些行。也不要在显示符号名称时截断符号名称
  62. --start-address=ADDRESS
  63.     从指定地址开始显示数据,该选项影响 -d、-r 和 -s 选项的输出
  64. --stop-address=ADDRESS
  65.     显示数据直到指定地址为止,该项影响-d、-r和-s选项的输出
  66. --prefix-addresses
  67.     反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式
  68. --no-show-raw-insn
  69.     反汇编时,不显示汇编指令的机器码。当使用--prefix-addresses时,这是缺省选项
  70. --adjust-vma=OFFSET
  71.     当解析信息时,首先给所有的段添加偏移值offset。当段地址与符号表不符时,这个选项很有用。
  72.         比如将段放置到特殊地址,因为某个格式无法表示段地址,比如 a.out
  73. --special-syms
  74.     显示特殊符号与用户不关心的符号
  75. --prefix=PREFIX
  76.     当使用 -S 时,指定前缀添加到绝对路径中
  77. --prefix-strip=LEVEL
  78.     指定剥离绝对路径中多少个前缀目录名。此选项只有在使用了选项 --prefix=PREFIX 才有效
  79. --insn-width=WIDTH
  80.     指定反汇编后的指令输出的行宽,单位字节
  81. -V, --version
  82.     版本信息
  83. -H, --help
  84.     帮助信息
复制代码
objdump命令的利用
objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它还有其他作用,下面以ELF格式可执行文件test为例具体介绍:
  1. objdump -f test        显示test的文件头信息
  2. objdump -d test        反汇编test中的需要执行指令的那些section
  3. objdump -D test        与-d类似,但反汇编test中的所有section
  4. objdump -h test        显示test的Section Header信息
  5. objdump -x test        显示test的全部Header信息
  6. objdump -s test        除了显示test的全部Header信息,还显示他们对应的十六进制文件代码
复制代码
举例:将C源代码和反汇编出来的指令对照:
1.编译成目标文件(要加-g选项):gcc -g -o test.c
2.输出C源代码和反汇编出来的指令对照的格式:objdump -S test.o
1)-- 下面是利用objdump的--h选项来查看步伐中的段信息,练习用的步伐如前面的图,这里假设你已将其编译成了可执行文件test

2)-- 反汇编

如何对任意一个二进制文件举行反汇编?
我们可以这样做:objdump -D -b binary -m i386 a.bin
-D表示对全部文件举行反汇编,-b表示二进制,-m表示指令集架构,a.bin就是我们要反汇编的二进制文件
objdump -m可以查看更多支持的指令集架构,如i386:x86-64,i8086等
别的上面的全部objdump命令的参数同样适用于arm-linux-objdump。
同时我们也可以指定big-endian或little-endian(-EB或-EL),我们可以指定从某一个位置开始反汇编等。以是objdump命令黑白常强盛的!

readelf  读取 elf 文件

objdump 和 readelf 都可以用来查看二进制文件的一些内部信息。objdump 是借助 BFD(LIB BFD, the Binary File Descriptor Library:http://www.mssl.ucl.ac.uk/swift/om/sw/help/man/bfd.html)而更加通用一些,可以应付不同文件格式。readelf 则并不需要 BFD 而是直接读取 ELF 格式文件的信息,按 readelf 手册页上所说,得到的信息也略细致一些。
 readelf、objdump、hexdump: http://blog.csdn.net/u011118014/article/details/20869441
   假如二进制文件是ELF格式的,通过file文件可以查看文件格式.利用readelf指令可以方便分析ELF文件的布局,比如节信息,elf头文件信息,比如我们在分析文件是否为病毒文件的时候,需要读取elf文件头信息,做一些特征的判断,或作为特征参与机器学习的判断。
  示例:readelf -h xxx
  readelf 可以显示 elf 格式的可执行的文件信息。ELF格式是UNIX系统实行室作为应用步伐二进制接口开发的。ELF格式是Unix/Linux平台上应用最广泛的二进制工业标准之一。

常用的有以下几个功能选项:
  1. 1)-h或者--file-header   显示在ELF文件头里包含的所有信息
  2. 2)-l或者--program-headers或者--segments
  3.      显示程序头表信息,包扩有几个段,每个段的属性,以及每个段中包含有哪几个节(Section)
  4. 3)-S或者--section-headers或者--sections    显示节区表内的所有信息,包括每个节的属性,注意这里是用的是大写的“S”
  5. 4)-t或者--section-details    用来显示所有节的详细信息,感觉上但从信息量上来说,和前面的“-S”没有什么大的不同
  6. 5)-e或者--headers    显示所有头的信息,包括ELF文件头、程序头和节头,也就是“-h -l -S”的组合。
  7. 6)-s或者--syms或者--symbols    显示符号表的信息,包含静态符号表(.symtab)和动态符号表(.dynsym)
  8. 7)-r或者--relocs     显示所有重定位入口的信息
  9. 8)-d或者--dynamic    显示动态节区的内容
  10. 9)-x或者--hex-dump=<number|name>    显示某个节区的二进制码,具体哪个节可以用该节的编号或者名字来指定,例如“-x .text”
复制代码

C++filt

   C++filt:可以用于显示出 c++ 中复杂的重载后的函数名称。
  通常,一个目标文件中不能有两个名称相同的函数。为支持重载,编译器将形貌函数参数类型的信息合并到函数的原始名称中,从而为重载函数生成唯一的函数名称。为名称完全相同的函数生成唯一名称的过程叫做 "名称改编(name mangling)、名称改写"。
  

PE Tools、PE Sniffer

PE Tools:https://github.com/petoolse/petools
PE tools 是一组用于分析 Windows 系统中正在运行的历程和可执行文件的工具。在历程列表中,用户可以将一个历程的内存映像转储到某个文件中,也可以利用 PESniffer 实用工具确定可热行文件由何种编译器构建,或者该文件是否经过某种已知的模糊实用工具的模糊处置惩罚。Tools 菜单提供了分析磁盘文件的类似选项。别的,用户还可以利用内嵌的 PEEditor 实用工具查看 PE 文件头字段,利用该工具还可以方便地修改任何文件头的值。通常,假如想要从文件的模糊版本重建一个有效的 PE,就需要修改PE文件头。


PEiD、 Exeinfo 检测 PE文件

   PEiD 是另一款 Windows 工具,它重要用于识别构建某一特定 WindowsPE二进制文件所使
用的编译器,并确定 模糊WindowsPE所利用的二进制文件的工具。PEiD 的许多其他功能与PETools 的功能相同,包括显示PE文件头信息摘要、收集有关正在运行的历程的信息、执行根本的反汇编等。
  file、PE Tools、PE Sniffer、PEiD 一样平常用来识别文件格式,由于要对二进制举行逆向,以是需要利用更高级的工具来明白某一特定的文件格式,来提取具体的信息,并且剖析输入文件,提取输入文件包罗的具体信息。
  PEiD只支持检测32位的可执行文件,假如显示不是有效的PE文件,阐明你的可执行文件为64位,不能用 PEiD 检测。可以利用 Exeinfo PE 查看,Exeinfo 相称于 PEiD 的升级版,可查看64位的可执行文件

dumpbin (类似 objdump )

   微软 Visual Studio 套件中的一个工具。功能与 objdump 一样。可以显示大量与 Windows PE 相干的内容。
  
ltrace  跟踪函数调用

   跟踪历程调用库函数过程  ltrace ./a.out
这在查看系统调用耗时很有效。
# -T 是查看调用时间开销
ltrace -T
#-t -tt -ttt 是查看调用绝对时间,t越多越精确
ltrace -t
ltrace 查看系统调用信息  ltrace -S
  
strace 跟踪函数调用

strace 和 ltrace 的命令差不多,strace 更方向于系统调用的追踪或信号产生的环境。安装命令 yum -y install strace
   强盛地方在于可以指定系统调用的类型:
  -e trace=set 
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. 
-e trace=file 
只跟踪有关文件操纵的系统调用. 
-e trace=process 
只跟踪有关历程控制的系统调用. 
-e trace=network 
跟踪与网络有关的全部系统调用. 
-e strace=signal 
跟踪全部与系统信号有关的 系统调用 
-e trace=ipc 
跟踪全部与历程通讯有关的系统调用 
-e abbrev=set 
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all. 
-e raw=set 
将指 定的系统调用的参数以十六进制显示. 
-e signal=set 
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号. 
-e read=set 
输出从指定文件中读出 的数据.例如: 
-e read=3,5 
-e write=set 
  
xxd 查看文件的十六进制内容

   xxd 是 Linux 系统中一个非常有效的工具,用于查看文件的十六进制内容,或者将十六进制数据转换回原始格式。它常用于调试、文件分析和二进制数据操纵。
  
dd  复制块到文件

   dd 命令用指定巨细的块拷贝一个文件,并在拷贝的同时举行指定的转换。
  
otool

   MAC 下类似 objdump 的工具
  







免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

八卦阵

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表