Linux中國

全功能的二進位文件分析工具 Radare2 指南

在《Linux 上分析二進位文件的 10 種方法》中,我解釋了如何使用 Linux 上豐富的原生工具集來分析二進位文件。但如果你想進一步探索你的二進位文件,你需要一個為二進位分析定製的工具。如果你是二進位分析的新手,並且大多使用的是腳本語言,這篇文章《GNU binutils 里的九種武器》可以幫助你開始學習編譯過程和什麼是二進位。

為什麼我需要另一個工具?

如果現有的 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 是否被正確安裝:

$ git clone https://github.com/radareorg/radare2.git
$ cd radare2
$ ./sys/user.sh

# version

$ r2 -v
radare2 4.6.0-git 25266 @ linux-x86-64 git.4.4.0-930-g48047b317
commit: 48047b3171e6ed0480a71a04c3693a0650d03543 build: 2020-11-17__09:31:03
$

獲取二進位測試樣本

現在 r2 已經安裝好了,你需要一個樣本二進位程序來試用它。你可以使用任何系統二進位文件(lsbash 等),但為了使本教程的內容簡單,請編譯以下 C 程序:

$ cat adder.c
#include <stdio.h>

int adder(int num) {
        return num + 1;
}

int main() {
        int res, num1 = 100;
        res = adder(num1);
        printf("Number now is  : %dn", res);
        return 0;
}
$ 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 不同。要退出控制台,你可以輸入 QuitExit 或按 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 位。方便的 r2iI 命令可以提供所需的信息:

[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 下。這個測試的二進位導出了兩個函數:mainadder。其餘的函數是在編譯階段,當二進位文件被構建時添加的。載入器需要這些函數來載入二進位文件(現在不用太關心它們):

[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...[]AA]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    ; &apos;d&apos; ; 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  : %dn" ; 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  : %dn

[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

![Radare2 Visual mode](/data/attachment/album/202102/01/112635hqi5513d1e5bx8d8.png "Radare2 Visual mode")

(Gaurav Kamathe, CC BY-SA 4.0)

調試器

到目前為止,你一直在做的是靜態分析 —— 你只是在看二進位文件中的東西,而沒有運行它,有時你需要執行二進位文件,並在運行時分析內存中的各種信息。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 &apos;r2dec&apos;...
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 &apos;/root/.local/share/radare2/r2pm/git/r2dec/p&apos;
[CC] duktape/duktape.o
[CC] duktape/duk_console.o
[CC] core_pdd.o
[CC] core_pdd.so
gmake: Leaving directory &apos;/root/.local/share/radare2/r2pm/git/r2dec/p&apos;
$
$ 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
$

你覺得 Radare2 怎麼樣?請在評論中分享你的反饋。

via: https://opensource.com/article/21/1/linux-radare2

作者:Gaurav Kamathe 選題:lujun9972 譯者:wxy 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國