In 10 Möglichkeiten, Binärdateien unter Linux zu analysieren, habe ich erklärt, wie man die umfangreichen nativen Tools von Linux zum Analysieren von Binärdateien verwendet. Wenn Sie Ihre Binärdatei jedoch weiter untersuchen möchten, benötigen Sie ein Tool, das speziell für die Binäranalyse entwickelt wurde. Wenn Sie neu in der Binäranalyse sind und hauptsächlich mit Skriptsprachen gearbeitet haben, 9 wesentliche GNU-Binutils-Tools hilft Ihnen beim Einstieg in den Kompilierungsprozess und was eine Binärdatei ausmacht.
Warum brauche ich ein anderes Werkzeug?
Es ist natürlich zu fragen, warum Sie noch ein weiteres Tool benötigen, wenn vorhandene Linux-native Tools ähnliche Dinge tun. Aus den gleichen Gründen verwenden Sie Ihr Mobiltelefon als Wecker, zum Aufnehmen von Notizen, als Kamera, zum Musikhören, zum Surfen im Internet und gelegentlich zum Tätigen und Empfangen von Anrufen. Zuvor wurden diese Funktionen von separaten Geräten und Tools übernommen – wie einer physischen Kamera zum Aufnehmen von Bildern, einem kleinen Notizblock zum Aufnehmen von Notizen, einem Wecker am Bett zum Aufwachen und so weiter. Ein Gerät zu haben, um mehrere (aber verwandte) Dinge zu tun, ist praktisch für den Benutzer. Außerdem ist die Killerfunktion Interoperabilität zwischen den einzelnen Funktionen.
Auch wenn viele Linux-Tools einen bestimmten Zweck haben, ist es sehr hilfreich, ähnliche (und bessere) Funktionen in einem einzigen Tool zu bündeln. Aus diesem Grund denke ich, dass Radare2 Ihr Werkzeug sein sollte, wenn Sie mit Binärdateien arbeiten müssen.
Radare2 (auch bekannt als r2) ist laut seinem GitHub-Profil ein “Unix-ähnliches Reverse-Engineering-Framework und Kommandozeilen-Toolset”. Die “2” in ihrem Namen ist, weil diese Version von Grund auf neu geschrieben wurde, um sie modularer zu machen.
Warum Radare2?
Es gibt Unmengen von (nicht nativen) Linux-Tools, die für die Binäranalyse verwendet werden, warum also sollten Sie Radare2 wählen? Meine Gründe sind einfach.
Erstens ist es ein Open-Source-Projekt mit einer aktiven und gesunden Community. Wenn Sie nach raffinierten, neuen Funktionen oder der Verfügbarkeit von Fehlerbehebungen suchen, ist dies sehr wichtig.
Zweitens kann Radare2 über die Befehlszeile verwendet werden und verfügt über eine umfangreiche grafische Benutzeroberfläche (GUI) namens Cutter für diejenigen, die mit GUIs vertrauter sind. Als langjähriger Linux-Benutzer füttere ich bequemer auf der Shell. Obwohl es eine leichte Lernkurve gibt, sich mit den Befehlen von Radare2 vertraut zu machen, würde ich es mit dem Erlernen von Vim vergleichen. Sie lernen zuerst grundlegende Dinge, und wenn Sie sie erst einmal beherrschen, gehen Sie zu fortgeschritteneren Dingen über. Im Handumdrehen wird es zur zweiten Natur.
Drittens bietet Radare2 eine gute Unterstützung für externe Tools über Plugins. Zum Beispiel ist das kürzlich als Open Source verfügbare Ghidra-Tool zur Binäranalyse und -umkehr beliebt für seine Decompiler-Funktion, die ein entscheidendes Element der Umkehrsoftware ist. Sie können den Ghidra-Decompiler direkt über die Radare2-Konsole installieren und verwenden, was erstaunlich ist und Ihnen das Beste aus beiden Welten bietet.
Erste Schritte mit Radare2
Um Radare2 zu installieren, klonen Sie einfach das Repo und führen Sie das user.sh
Skript. Möglicherweise müssen Sie einige vorausgesetzte Pakete installieren, wenn diese nicht bereits auf Ihrem System vorhanden sind. Wenn die Installation abgeschlossen ist, führen Sie die r2 -v
Befehl, um zu sehen, ob Radare2 richtig installiert wurde:
$ 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
$
Holen Sie sich eine Beispiel-Test-Binärdatei
Nachdem r2 jetzt installiert ist, benötigen Sie eine Beispiel-Binärdatei, um es auszuprobieren. Sie können eine beliebige System-Binärdatei (ls
, bash
, usw.), aber um die Dinge für dieses Tutorial einfach zu halten, kompilieren Sie das folgende C-Programm:
$ 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
$
Laden Sie die Binärdatei
Um die Binärdatei zu analysieren, müssen Sie sie in Radare2 laden. Laden Sie es, indem Sie die Datei als Befehlszeilenargument an den r2
Befehl. Sie werden in eine separate Radare2-Konsole verschoben, die sich von Ihrer Shell unterscheidet. Um die Konsole zu verlassen, können Sie Folgendes eingeben: Aufhören oder Ausgang oder schlagen Strg+D:
$ r2 ./adder
-- Learn pancake as if you were radare!
[0x004004b0]> quit
$
Analysiere die Binärdatei
Bevor Sie die Binärdatei erkunden können, müssen Sie r2 bitten, sie für Sie zu analysieren. Sie können dies tun, indem Sie die aaa
Befehl in der r2-Konsole;
$ 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]>
Dies bedeutet, dass Sie jedes Mal, wenn Sie eine Binärdatei zur Analyse auswählen, einen zusätzlichen Befehl eingeben müssen, um aaa
nach dem Laden der Binärdatei. Sie können dies umgehen, indem Sie r2 mit aufrufen -A
gefolgt vom Binärnamen; Dies weist r2 an, die Binärdatei automatisch für Sie zu analysieren:
$ 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]>
Holen Sie sich einige grundlegende Informationen über die Binärdatei
Bevor Sie mit der Analyse einer Binärdatei beginnen, benötigen Sie einen Ausgangspunkt. In vielen Fällen kann dies das Dateiformat der Binärdatei sein (ELF, PE usw.), die Architektur, für die die Binärdatei erstellt wurde (x86, AMD, ARM usw.) und ob die Binärdatei 32-Bit oder 64-Bit ist . R2 ist praktisch iI
Befehl kann die erforderlichen Informationen liefern:
[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]>
Importe und e
Wenn Sie wissen, mit welcher Art von Datei Sie es zu tun haben, möchten Sie oft wissen, welche Standardbibliotheksfunktionen die Binärdatei verwendet, oder die möglichen Funktionen des Programms kennenlernen. Im C-Beispielprogramm in diesem Tutorial ist die einzige Bibliotheksfunktion printf
um eine Nachricht zu drucken. Sie können dies sehen, indem Sie die ii
Befehl, der alle Importe der Binärdatei anzeigt:
[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
Die Binärdatei kann auch eigene Symbole, Funktionen oder Daten haben. Diese Funktionen werden normalerweise unter . angezeigt s
. Die Test-Binärdatei hat zwei Funktionen – main und adder – die iert werden. Die restlichen Funktionen werden während der Kompilierungsphase hinzugefügt, wenn die Binärdatei erstellt wird. Der Loader benötigt diese, um die Binärdatei zu laden (mach dir vorerst keine Sorgen darüber):
[0x004004b0]>
[0x004004b0]> iE
[s]
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]>
Hash-Informationen
Woher wissen Sie, ob zwei Binärdateien ähnlich sind? Sie können eine Binärdatei nicht genau öffnen und den darin enthaltenen Quellcode anzeigen. In den meisten Fällen wird der Hash einer Binärdatei – md5sum, sha1, sha256 – verwendet, um sie eindeutig zu identifizieren. Sie finden den binären Hash mit dem it
Befehl:
[0x004004b0]> it
md5 7e6732f2b11dec4a0c7612852cede670
sha1 d5fa848c4b53021f6570dd9b18d115595a2290ae
sha256 13dd5a492219dac1443a816ef5f91db8d149e8edbf26f24539c220861769e1c2
[0x004004b0]>
Funktionen
Code ist in Funktionen gruppiert; Um aufzulisten, welche Funktionen in einer Binärdatei vorhanden sind, führen Sie die afl
Befehl. Die folgende Liste zeigt die Haupt- und Addierfunktionen. Normalerweise Funktionen, die mit beginnen sym.imp
werden aus der Standardbibliothek (hier glibc) importiert:
[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]>
Querverweise
In C ist die Hauptfunktion der Punkt, an dem ein Programm seine Ausführung beginnt. Idealerweise werden andere Funktionen von main aufgerufen und beim Beenden eines Programms gibt die main-Funktion einen Exit-Status an das Betriebssystem zurück. Dies ist im Quellcode ersichtlich; Was ist jedoch mit einer Binärdatei? Wie können Sie feststellen, wo die Addiererfunktion aufgerufen wird?
Du kannst den … benutzen axt
Befehl gefolgt vom Funktionsnamen, um zu sehen, wo die Addiererfunktion aufgerufen wird; Wie Sie unten sehen können, wird es von der Hauptfunktion aufgerufen. Dies wird als Querverweis bezeichnet. Aber was ruft die main-Funktion selbst auf? Der axt main
Die folgende Funktion zeigt, dass sie aufgerufen wird von entry0
(Ich werde es verlassen, etwas darüber zu lernen entry0
als Übung für den Leser):
[0x004004b0]> axt sym.adder
main 0x4005b9 [CALL] call sym.adder
[0x004004b0]>
[0x004004b0]> axt main
entry0 0x4004d1 [DATA] mov rdi, main
[0x004004b0]>
Standorte suchen
Wenn Sie mit Textdateien arbeiten, bewegen Sie sich oft innerhalb einer Datei, indem Sie auf eine Zeilennummer gefolgt von einer Zeilen- oder Spaltennummer verweisen; in einer Binärdatei verwenden Sie Adressen. Dies sind hexadezimale Zahlen, die mit beginnen 0x
gefolgt von einer Adresse. Um herauszufinden, wo Sie sich in einer Binärdatei befinden, führen Sie die s
Befehl. Um an einen anderen Ort zu wechseln, verwenden Sie die s
Befehl gefolgt von der Adresse.
Funktionsnamen sind wie Labels, die intern durch Adressen repräsentiert werden. Wenn der Funktionsname in der Binärdatei enthalten ist (nicht entfernt), können Sie die s
Befehl gefolgt vom Funktionsnamen, um zu einer bestimmten Funktionsadresse zu springen. Wenn Sie zum Anfang der Binärdatei springen möchten, geben Sie 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]>
Hexadezimale Ansicht
Oft macht die rohe Binärdatei keinen Sinn. Es kann hilfreich sein, die Binärdatei im hexadezimalen Modus zusammen mit der entsprechenden ASCII-Darstellung anzuzeigen:
[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 [email protected]
0x004005d5 b800 0000 00c9 c30f 1f40 00f3 0f1e fa41 [email protected]
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]>
Demontage
Wenn Sie mit kompilierten Binärdateien arbeiten, können Sie keinen Quellcode anzeigen. Der Compiler übersetzt den Quellcode in Anweisungen in Maschinensprache, die die CPU verstehen und ausführen kann; Das Ergebnis ist die Binärdatei oder ausführbare Datei. Sie können jedoch Montageanweisungen (Mnemonik) anzeigen, um zu verstehen, was das Programm tut. Wenn Sie beispielsweise sehen möchten, was die Hauptfunktion macht, können Sie die Adresse der Hauptfunktion mit suchen s main
und dann führe die pdf
Befehl, um die Demontageanweisungen anzuzeigen.
Um die Assembleranweisungen zu verstehen, müssen Sie das Architekturhandbuch (in diesem Fall x86), seine binäre Anwendungsschnittstelle (seine ABI oder Aufrufkonventionen) lesen und ein grundlegendes Verständnis der Funktionsweise des Stapels haben:
[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 : %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]>
Hier ist die Demontage für die Addiererfunktion:
[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]>
Saiten
Zu sehen, welche Strings in der Binärdatei vorhanden sind, kann ein Ausgangspunkt für die Binäranalyse sein. Strings sind in eine Binärdatei hartcodiert und geben oft wichtige Hinweise, um Ihren Fokus auf die Analyse bestimmter Bereiche zu verschieben. Führen Sie die iz
Befehl innerhalb der Binärdatei, um alle Zeichenfolgen aufzulisten. Die Test-Binärdatei hat nur eine Zeichenfolge, die in der Binärdatei hartcodiert ist:
[0x004004b0]> iz
[Strings]
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x00000678 0x00400678 20 21 .rodata ascii Number now is : %dn
[0x004004b0]>
Querverweiszeichenfolgen
Wie bei Funktionen können Sie auf Strings Querverweise verweisen, um zu sehen, woher sie gedruckt werden, und um den sie umgebenden Code zu verstehen:
[0x004004b0]> ps @ 0x400678
Number now is : %d
[0x004004b0]>
[0x004004b0]> axt 0x400678
main 0x4005c6 [DATA] mov edi, str.Number_now_is__:__d
[0x004004b0]>
Visueller Modus
Wenn Ihr Code mit mehreren aufgerufenen Funktionen kompliziert ist, kann er leicht verloren gehen. Es kann hilfreich sein, eine grafische oder visuelle Ansicht darüber zu haben, welche Funktionen aufgerufen werden, welche Pfade aufgrund bestimmter Bedingungen verwendet werden usw. Sie können den visuellen Modus von r2 erkunden, indem Sie das VV
Befehl nach dem Wechsel zu einer Funktion von Interesse. Zum Beispiel für die Addiererfunktion:
[0x004004b0]> s sym.adder
[0x00400596]>
[0x00400596]> VV
radare2_visual-mode.png
(Gaurav Kamathe, CC BY-SA 4.0)
Debugger
Bisher haben Sie statische Analysen durchgeführt – Sie betrachten nur Dinge in der Binärdatei, ohne sie auszuführen. Manchmal müssen Sie die Binärdatei ausführen und verschiedene Informationen im Speicher zur Laufzeit analysieren. Mit dem internen Debugger von r2 können Sie eine Binärdatei ausführen, Haltepunkte einfügen, die Werte von Variablen analysieren oder den Inhalt von Registern ausgeben.
Starten Sie den Debugger mit der -d
Flag, und fügen Sie die -A
Flag, um eine Analyse beim Laden der Binärdatei durchzuführen. Sie können an verschiedenen Stellen, wie Funktionen oder Speicheradressen, Breakpoints setzen, indem Sie die db <function-name>
Befehl. Um vorhandene Haltepunkte anzuzeigen, verwenden Sie die dbi
Befehl. Sobald Sie Ihre Breakpoints platziert haben, starten Sie die Binärdatei mit dem dc
Befehl. Sie können den Stapel anzeigen, indem Sie dbt
Befehl, der Funktionsaufrufe anzeigt. Schließlich können Sie den Inhalt der Register mit dem drr
Befehl:
$ 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]>
Dekompilierer
Die Fähigkeit, Assemblierung zu verstehen, ist eine Voraussetzung für die Binäranalyse. Die Assemblersprache ist immer an die Architektur gebunden, auf der die Binärdatei aufbaut und auf der sie laufen soll. Es gibt nie eine 1:1-Zuordnung zwischen einer Quellcodezeile und einem Assemblercode. Häufig erzeugt eine einzelne Zeile C-Quellcode mehrere Assemblierungszeilen. Das zeilenweise Lesen von Assemblercode ist also nicht optimal.
Hier kommen Decompiler ins Spiel. Sie versuchen, den möglichen Quellcode anhand der Assembleranweisungen zu rekonstruieren. Dies ist NIEMALS genau das gleiche wie der Quellcode, der verwendet wird, um die Binärdatei zu erstellen; es ist eine genaue Darstellung der Quelle basierend auf der Montage. Berücksichtigen Sie auch, dass Compileroptimierungen, die unterschiedlichen Assemblercode generieren, um Dinge zu beschleunigen, die Größe einer Binärdatei zu reduzieren usw., die Arbeit des Decompilers erschweren. Außerdem verschleiern Malware-Autoren oft absichtlich Code, um einen Malware-Analysten abzuschrecken.
Radare2 bietet Decompiler durch Plugins. Sie können jeden Decompiler installieren, der von Radare2 unterstützt wird. Zeigen Sie aktuelle Plugins mit dem an r2pm -l
Befehl. Installieren Sie ein Beispiel r2dec
Decompiler mit dem r2pm install
Befehl:
$ 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
$
Decompiler-Ansicht
Um eine Binärdatei zu dekompilieren, laden Sie die Binärdatei in r2 und analysieren Sie sie automatisch. Wechseln Sie zu der interessierenden Funktion – in diesem Beispiel Addierer – mit dem s sym.adder
Befehl, dann verwenden Sie den pdda
Befehl, um die Assembly und den dekompilierten Quellcode nebeneinander anzuzeigen. Das Lesen dieses dekompilierten Quellcodes ist oft einfacher als das zeilenweise Lesen:
$ 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]>
Einstellungen konfigurieren
Wenn Sie mit Radare2 vertrauter werden, sollten Sie seine Konfiguration ändern, um es an Ihre Arbeitsweise anzupassen. Sie können die Standardkonfigurationen von r2 anzeigen, indem Sie das e
Befehl. Um eine bestimmte Konfiguration festzulegen, fügen Sie hinzu config = value
nach dem e
Befehl:
[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]>
Um die Konfigurationsänderungen dauerhaft zu machen, legen Sie sie in eine Startdatei namens .radare2rc
dass r2 beim Start liest. Diese Datei befindet sich normalerweise in Ihrem Home-Verzeichnis; Wenn nicht, können Sie einen erstellen. Einige Beispielkonfigurationsoptionen umfassen:
$ cat ~/.radare2rc
e asm.syntax = att
e scr.utf8 = true
eco solarized
e cmd.stack = true
e stack.size = 256
$
Erkunde mehr
Sie haben genug Radare2-Funktionen gesehen, um sich im Tool zurechtzufinden. Da Radare2 der Unix-Philosophie folgt, verwendet es, obwohl Sie verschiedene Dinge von seiner Konsole aus tun können, einen separaten Satz von Binärdateien darunter, um seine Aufgaben zu erledigen.
Sehen Sie sich die unten aufgeführten eigenständigen Binärdateien an, um zu sehen, wie sie funktionieren. Zum Beispiel die in der Konsole angezeigten binären Informationen mit dem iI
Befehl kann auch gefunden werden mit dem rabin2 <binary>
Befehl:
$ cd bin/
$
$ ls
prefix r2agent r2pm rabin2 radiff2 ragg2 rarun2 rasm2
r2 r2-indent r2r radare2 rafind2 rahash2 rasign2 rax2
$
Was halten Sie von Radare2? Teile dein Feedback in den Kommentaren.