Under this bunny-arabic-like name, radare hides a powerful tool to handle binary files, to get information on imports, sections, headers and other data. Rabin2 can present it in several formats accepted by other tools, including radare2 itself. Rabin2 understands many file formats: Java CLASS, ELF, PE, Mach-O or any format supported by plugins, and it is able to obtain symbol import/exports, library dependencies, strings of data sections, xrefs, entrypoint address, sections, architecture type.
$ rabin2 -h
Usage: rabin2 [-AcdeEghHiIjlLMqrRsSvVxzZ] [-@ at] [-a arch] [-b bits] [-B addr]
[-C F:C:D] [-f str] [-m addr] [-n str] [-N m:M] [-P[-P] pdb]
[-o str] [-O str] [-k query] [-D lang symname] | file
-@ [addr] show section, symbol or import at addr
-A list sub-binaries and their arch-bits pairs
-a [arch] set arch (x86, arm, .. or
-b [bits] set bits (32, 64 ...)
-B [addr] override base address (pie bins)
-c list classes
-C [fmt:C:D] create [elf,mach0,pe] with Code and Data hexpairs (see -a)
-d show debug/dwarf information
-D lang name demangle symbol name (-D all for bin.demangle=true)
-e entrypoint
-E globally exportable symbols
-f [str] select sub-bin named str
-F [binfmt] force to use that bin plugin (ignore header check)
-g same as -SMZIHVResizcld (show all info)
-G [addr] load address . offset to header
-h this help message
-H header fields
-i imports (symbols imported from libraries)
-I binary info
-j output in json
-k [sdb-query] run sdb query. for example: '*'
-K [algo] calculate checksums (md5, sha1, ..)
-l linked libraries
-L [plugin] list supported bin plugins or plugin details
-m [addr] show source line at addr
-M main (show address of main symbol)
-n [str] show section, symbol or import named str
-N [min:max] force min:max number of chars per string (see -z and -zz)
-o [str] output file/folder for write operations (out by default)
-O [str] write/extract operations (-O help)
-p show physical addresses
-P show debug/pdb information
-PP download pdb file for binary
-q be quiet, just show fewer data
-qq show less info (no offset/size for -z for ex.)
-Q show load address used by dlopen (non-aslr libs)
-r radare output
-R relocations
-s symbols
-S sections
-u unfiltered (no rename duplicated symbols/sections)
-v display version and quit
-V Show binary version information
-x extract bins contained in file
-X [fmt] [f] .. package in fat or zip the given files and bins contained in file
-z strings (from data section)
-zz strings (from raw bins [e bin.rawstr=1])
-zzz dump raw strings to stdout (for huge files)
-Z guess size of binary program
......
File type identification is done using -I. With this option, rabin2 prints information on a binary type, like its encoding, endianness, class, operating system:
$ rabin2 -I /bin/ls
arch x86
binsz 128456
bintype elf
bits 64
canary true
class ELF64
crypto false
endian little
havecode true
intrp /lib64/ld-linux-x86-64.so.2
lang c
linenum false
lsyms false
machine AMD x86-64 architecture
maxopsz 16
minopsz 1
nx true
os linux
pcalign 0
pic true
relocs false
relro partial
rpath NONE
static false
stripped true
subsys linux
va true
To make rabin2 output information in format that the main program, radare2, can understand, pass -Ir option to it:
$ rabin2 -Ir /bin/ls
e cfg.bigendian=false
e asm.bits=64
e asm.dwarf=true
e bin.lang=c
e file.type=elf
e asm.os=linux
e asm.arch=x86
e asm.pcalign=0
The -e option passed to rabin2 will show entrypoints for given binary. Two examples:
$ rabin2 -e /bin/ls
[Entrypoints]
vaddr=0x00005310 paddr=0x00005310 baddr=0x00000000 laddr=0x00000000 haddr=0x00000018 type=program
1 entrypoints
$ rabin2 -er /bin/ls
fs symbols
f entry0 1 @ 0x00005310
f entry0_haddr 1 @ 0x00000018
s entry0
Rabin2 is able to find imported objects by an executable, as well as their offsets in its PLT. This information is useful, for example, to understand what external function is invoked by call instruction. Pass -i flag to rabin2 to get a list of imports. An example:
$ rabin2 -i /bin/ls
[Imports]
nth vaddr bind type lib name
―――――――――――――――――――――――――――――――――――――
1 0x000032e0 GLOBAL FUNC __ctype_toupper_loc
2 0x000032f0 GLOBAL FUNC getenv
3 0x00003300 GLOBAL FUNC sigprocmask
4 0x00003310 GLOBAL FUNC __snprintf_chk
5 0x00003320 GLOBAL FUNC raise
6 0x00000000 GLOBAL FUNC free
7 0x00003330 GLOBAL FUNC abort
8 0x00003340 GLOBAL FUNC __errno_location
9 0x00003350 GLOBAL FUNC strncmp
10 0x00000000 WEAK NOTYPE _ITM_deregisterTMCloneTable
11 0x00003360 GLOBAL FUNC localtime_r
12 0x00003370 GLOBAL FUNC _exit
13 0x00003380 GLOBAL FUNC strcpy
14 0x00003390 GLOBAL FUNC __fpending
15 0x000033a0 GLOBAL FUNC isatty
16 0x000033b0 GLOBAL FUNC sigaction
17 0x000033c0 GLOBAL FUNC iswcntrl
18 0x000033d0 GLOBAL FUNC wcswidth
19 0x000033e0 GLOBAL FUNC localeconv
20 0x000033f0 GLOBAL FUNC mbstowcs
21 0x00003400 GLOBAL FUNC readlink
...
Rabin2 is able to find exports. For example:
$ rabin2 -E /usr/lib/libr_bin.so | head
[Exports]
nth paddr vaddr bind type size lib name
―――――――――――――――――――――――――――――――――――――――――――――――――――――
210 0x000ae1f0 0x000ae1f0 GLOBAL FUNC 200 r_bin_java_print_exceptions_attr_summary
211 0x000afc90 0x000afc90 GLOBAL FUNC 135 r_bin_java_get_args
212 0x000b18e0 0x000b18e0 GLOBAL FUNC 35 r_bin_java_get_item_desc_from_bin_cp_list
213 0x00022d90 0x00022d90 GLOBAL FUNC 204 r_bin_class_add_method
214 0x000ae600 0x000ae600 GLOBAL FUNC 175 r_bin_java_print_fieldref_cp_summary
215 0x000ad880 0x000ad880 GLOBAL FUNC 144 r_bin_java_print_constant_value_attr_summary
216 0x000b7330 0x000b7330 GLOBAL FUNC 679 r_bin_java_print_element_value_summary
217 0x000af170 0x000af170 GLOBAL FUNC 65 r_bin_java_create_method_fq_str
218 0x00079b00 0x00079b00 GLOBAL FUNC 15 LZ4_createStreamDecode
With rabin2, the generated symbols list format is similar to the imports list. Use the -s option to get it:
rabin2 -s /bin/ls | head
[Symbols]
nth paddr vaddr bind type size lib name
――――――――――――――――――――――――――――――――――――――――――――――――――――――
110 0x000150a0 0x000150a0 GLOBAL FUNC 56 _obstack_allocated_p
111 0x0001f600 0x0021f600 GLOBAL OBJ 8 program_name
112 0x0001f620 0x0021f620 GLOBAL OBJ 8 stderr
113 0x00014f90 0x00014f90 GLOBAL FUNC 21 _obstack_begin_1
114 0x0001f600 0x0021f600 WEAK OBJ 8 program_invocation_name
115 0x0001f5c0 0x0021f5c0 GLOBAL OBJ 8 alloc_failed_handler
116 0x0001f5f8 0x0021f5f8 GLOBAL OBJ 8 optarg
117 0x0001f5e8 0x0021f5e8 GLOBAL OBJ 8 stdout
118 0x0001f5e0 0x0021f5e0 GLOBAL OBJ 8 program_short_name
With the -sr option rabin2 produces a radare2 script instead. It can later be passed to the core to automatically flag all symbols and to define corresponding byte ranges as functions and data blocks.
$ rabin2 -sr /bin/ls | head
fs symbols
f sym.obstack_allocated_p 56 0x000150a0
f sym.program_invocation_name 8 0x0021f600
f sym.stderr 8 0x0021f620
f sym.obstack_begin_1 21 0x00014f90
f sym.program_invocation_name 8 0x0021f600
f sym.obstack_alloc_failed_handler 8 0x0021f5c0
f sym.optarg 8 0x0021f5f8
f sym.stdout 8 0x0021f5e8
f sym.program_invocation_short_name 8 0x0021f5e0
Rabin2 can list libraries used by a binary with the -l option:
$ rabin2 -l `which r2`
[Linked libraries]
libr_core.so
libr_parse.so
libr_search.so
libr_cons.so
libr_config.so
libr_bin.so
libr_debug.so
libr_anal.so
libr_reg.so
libr_bp.so
libr_io.so
libr_fs.so
libr_asm.so
libr_syscall.so
libr_hash.so
libr_magic.so
libr_flag.so
libr_egg.so
libr_crypto.so
libr_util.so
libpthread.so.0
libc.so.6
22 libraries
Lets check the output with ldd command:
$ ldd `which r2`
linux-vdso.so.1 (0x00007fffba38e000)
libr_core.so => /usr/lib64/libr_core.so (0x00007f94b4678000)
libr_parse.so => /usr/lib64/libr_parse.so (0x00007f94b4425000)
libr_search.so => /usr/lib64/libr_search.so (0x00007f94b421f000)
libr_cons.so => /usr/lib64/libr_cons.so (0x00007f94b4000000)
libr_config.so => /usr/lib64/libr_config.so (0x00007f94b3dfa000)
libr_bin.so => /usr/lib64/libr_bin.so (0x00007f94b3afd000)
libr_debug.so => /usr/lib64/libr_debug.so (0x00007f94b38d2000)
libr_anal.so => /usr/lib64/libr_anal.so (0x00007f94b2fbd000)
libr_reg.so => /usr/lib64/libr_reg.so (0x00007f94b2db4000)
libr_bp.so => /usr/lib64/libr_bp.so (0x00007f94b2baf000)
libr_io.so => /usr/lib64/libr_io.so (0x00007f94b2944000)
libr_fs.so => /usr/lib64/libr_fs.so (0x00007f94b270e000)
libr_asm.so => /usr/lib64/libr_asm.so (0x00007f94b1c69000)
libr_syscall.so => /usr/lib64/libr_syscall.so (0x00007f94b1a63000)
libr_hash.so => /usr/lib64/libr_hash.so (0x00007f94b185a000)
libr_magic.so => /usr/lib64/libr_magic.so (0x00007f94b164d000)
libr_flag.so => /usr/lib64/libr_flag.so (0x00007f94b1446000)
libr_egg.so => /usr/lib64/libr_egg.so (0x00007f94b1236000)
libr_crypto.so => /usr/lib64/libr_crypto.so (0x00007f94b1016000)
libr_util.so => /usr/lib64/libr_util.so (0x00007f94b0d35000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f94b0b15000)
libc.so.6 => /lib64/libc.so.6 (0x00007f94b074d000)
libr_lang.so => /usr/lib64/libr_lang.so (0x00007f94b0546000)
libr_socket.so => /usr/lib64/libr_socket.so (0x00007f94b0339000)
libm.so.6 => /lib64/libm.so.6 (0x00007f94affaf000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f94afdab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f94b4c79000)
libssl.so.1.0.0 => /usr/lib64/libssl.so.1.0.0 (0x00007f94afb3c000)
libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0 (0x00007f94af702000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007f94af4ff000)
libz.so.1 => /lib64/libz.so.1 (0x00007f94af2e8000)
If you compare the outputs of rabin2 -l and ldd, you will notice that rabin2 lists fewer libraries than ldd. The reason is that rabin2 does not follow and does not show dependencies of libraries. Only direct binary dependencies are shown.
The -z option is used to list readable strings found in the .rodata section of ELF binaries, or the .text section of PE files. Example:
$ rabin2 -z /bin/ls | head
[Strings]
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
000 0x000160f8 0x000160f8 11 12 (.rodata) ascii dev_ino_pop
001 0x00016188 0x00016188 10 11 (.rodata) ascii sort_files
002 0x00016193 0x00016193 6 7 (.rodata) ascii posix-
003 0x0001619a 0x0001619a 4 5 (.rodata) ascii main
004 0x00016250 0x00016250 10 11 (.rodata) ascii ?pcdb-lswd
005 0x00016260 0x00016260 65 66 (.rodata) ascii # Configuration file for dircolors, a utility to help you set the
006 0x000162a2 0x000162a2 72 73 (.rodata) ascii # LS_COLORS environment variable used by GNU ls with the --color option.
007 0x000162eb 0x000162eb 56 57 (.rodata) ascii # Copyright (C) 1996-2018 Free Software Foundation, Inc.
008 0x00016324 0x00016324 70 71 (.rodata) ascii # Copying and distribution of this file, with or without modification,
009 0x0001636b 0x0001636b 76 77 (.rodata) ascii # are permitted provided the copyright notice and this notice are preserved.
With the -zr option, this information is represented as a radare2 commands list. It can be used in a radare2 session to automatically create a flag space called "strings" pre-populated with flags for all strings found by rabin2. Furthermore, this script will mark corresponding byte ranges as strings instead of code.
$ rabin2 -zr /bin/ls | head
fs stringsf str.dev_ino_pop 12 @ 0x000160f8
Cs 12 @ 0x000160f8
f str.sort_files 11 @ 0x00016188
Cs 11 @ 0x00016188
f str.posix 7 @ 0x00016193
Cs 7 @ 0x00016193
f str.main 5 @ 0x0001619a
Cs 5 @ 0x0001619a
f str.pcdb_lswd 11 @ 0x00016250
Cs 11 @ 0x00016250
Rabin2 called with the -S option gives complete information about the sections of an executable. For each section the index, offset, size, alignment, type and permissions, are shown. The next example demonstrates this:
$ rabin2 -S /bin/ls
[Sections]
nth paddr size vaddr vsize perm name
―――――――――――――――――――――――――――――――――――――――――――――――――――――
00 0x00000000 0 0x00000000 0 ----
01 0x00000238 28 0x00000238 28 -r-- .interp
02 0x00000254 32 0x00000254 32 -r-- .note.ABI_tag
03 0x00000278 176 0x00000278 176 -r-- .gnu.hash
04 0x00000328 3000 0x00000328 3000 -r-- .dynsym
05 0x00000ee0 1412 0x00000ee0 1412 -r-- .dynstr
06 0x00001464 250 0x00001464 250 -r-- .gnu.version
07 0x00001560 112 0x00001560 112 -r-- .gnu.version_r
08 0x000015d0 4944 0x000015d0 4944 -r-- .rela.dyn
09 0x00002920 2448 0x00002920 2448 -r-- .rela.plt
10 0x000032b0 23 0x000032b0 23 -r-x .init
11 0x000032d0 1648 0x000032d0 1648 -r-x .plt
12 0x00003940 24 0x00003940 24 -r-x .plt.got
13 0x00003960 73931 0x00003960 73931 -r-x .text
14 0x00015a2c 9 0x00015a2c 9 -r-x .fini
15 0x00015a40 20201 0x00015a40 20201 -r-- .rodata
16 0x0001a92c 2164 0x0001a92c 2164 -r-- .eh_frame_hdr
17 0x0001b1a0 11384 0x0001b1a0 11384 -r-- .eh_frame
18 0x0001e390 8 0x0021e390 8 -rw- .init_array
19 0x0001e398 8 0x0021e398 8 -rw- .fini_array
20 0x0001e3a0 2616 0x0021e3a0 2616 -rw- .data.rel.ro
21 0x0001edd8 480 0x0021edd8 480 -rw- .dynamic
22 0x0001efb8 56 0x0021efb8 56 -rw- .got
23 0x0001f000 840 0x0021f000 840 -rw- .got.plt
24 0x0001f360 616 0x0021f360 616 -rw- .data
25 0x0001f5c8 0 0x0021f5e0 4824 -rw- .bss
26 0x0001f5c8 232 0x00000000 232 ---- .shstrtab
With the -Sr option, rabin2 will flag the start/end of every section, and will pass the rest of information as a comment.
$ rabin2 -Sr /bin/ls | head
fs sections
"f section. 1 0x00000000"
"f section..interp 1 0x000002a8"
"f section..note.gnu.build_id 1 0x000002c4"
"f section..note.ABI_tag 1 0x000002e8"
"f section..gnu.hash 1 0x00000308"
"f section..dynsym 1 0x000003b8"
"f section..dynstr 1 0x00000fb8"
"f section..gnu.version 1 0x00001574"
"f section..gnu.version_r 1 0x00001678"