1 Cheese
2 Potato
3 Butter
[0x00404800]> join foodtypes foods.txt
1 Protein Cheese
2 Carbohydrate Potato
3 Fat Butter
Similarly, sorting the content is also possible with the sort command. A typical example could be:
[0x00404800]> sort file
eleven
five
five
great
one
one
radare
The ?$? command describes several helpful variables you can use to do similar actions even more easily, like the $v "immediate value" variable, or the $m opcode memory reference variable.
One of the most common task in automation is looping through something, there are multiple ways to do this in radare2.
We can loop over flags:
@@ flagname-regex
For example, we want to see function information with afi command:
[0x004047d6]> afi
#
offset: 0x004047d0
name: entry0
size: 42
realsz: 42
stackframe: 0
call-convention: amd64
cyclomatic-complexity: 1
bits: 64
type: fcn [NEW]
num-bbs: 1
edges: 0
end-bbs: 1
call-refs: 0x00402450 C
data-refs: 0x004136c0 0x00413660 0x004027e0
code-xrefs:
data-xrefs:
locals:0
args: 0
diff: type: new
[0x004047d6]>
Now let's say, for example, that we'd like see a particular field from this output for all functions found by analysis. We can do that with a loop over all function flags (whose names begin with fcn.):
[0x004047d6]> fs functions
[0x004047d6]> afi @@ fcn.* ~name
This command will extract the name field from the afi output of every flag with a name matching the regexp fcn.*. There are also a predefined loop called @@f, which runs your command on every functions found by r2:
[0x004047d6]> afi @@f ~name
We can also loop over a list of offsets, using the following syntax:
@@=1 2 3 ... N
For example, say we want to see the opcode information for 2 offsets: the current one, and at current + 2:
[0x004047d6]> ao @@=$$ $$+2
address: 0x4047d6
opcode: mov rdx, rsp
prefix: 0
bytes: 4889e2
refptr: 0
size: 3
type: mov
esiclass="underline" rsp,rdx,=
stack: null
family: cpu
address: 0x4047d8
opcode: loop 0x404822
prefix: 0
bytes: e248
refptr: 0
size: 2
type: cjmp
esiclass="underline" 1,rcx,-=,rcx,?{,4212770,rip,=,}
jump: 0x00404822
faiclass="underline" 0x004047da
stack: null
cond: al
family: cpu
[0x004047d6]>
Note we're using the $$ variable which evaluates to the current offset. Also note that $$+2 is evaluated before looping, so we can use the simple arithmetic expressions.
A third way to loop is by having the offsets be loaded from a file. This file should contain one offset per line.
[0x004047d0]> ?v $$ > offsets.txt
[0x004047d0]> ?v $$+2 >> offsets.txt
[0x004047d0]> !cat offsets.txt
4047d0
4047d2
[0x004047d0]> pi 1 @@.offsets.txt
xor ebp, ebp
mov r9, rdx
radare2 also offers various foreach constructs for looping. One of the most useful is for looping through all the instructions of a function:
[0x004047d0]> pdf
╒ (fcn) entry0 42
│; UNKNOWN XREF from 0x00400018 (unk)
│; DATA XREF from 0x004064bf (sub.strlen_460)
│; DATA XREF from 0x00406511 (sub.strlen_460)
│; DATA XREF from 0x0040b080 (unk)
│; DATA XREF from 0x0040b0ef (unk)
│0x004047d0 xor ebp, ebp
│0x004047d2 mov r9, rdx
│0x004047d5 pop rsi
│0x004047d6 mov rdx, rsp
│0x004047d9 and rsp, 0xfffffffffffffff0
│0x004047dd push rax
│0x004047de push rsp
│0x004047df mov r8, 0x4136c0
│0x004047e6 mov rcx, 0x413660 ; "AWA..AVI..AUI..ATL.%.. "
0A..AVI..AUI.
│0x004047ed mov rdi, main ; "AWAVAUATUH..S..H...." @
0
│0x004047f4 call sym.imp.__libc_start_main
╘0x004047f9 hlt
[0x004047d0]> pi 1 @@i
mov r9, rdx
pop rsi
mov rdx, rsp
and rsp, 0xfffffffffffffff0
push rax
push rsp
mov r8, 0x4136c0
mov rcx, 0x413660
mov rdi, main
call sym.imp.__libc_start_main
hlt
In this example the command pi 1 runs over all the instructions in the current function (entry0). There are other options too (not complete list, check @@? for more information):
• @@k sdbquery - iterate over all offsets returned by that sdbquery
• @@t- iterate over on all threads (see dp)
• @@b - iterate over all basic blocks of current function (see afb)
• @@f - iterate over all functions (see aflq)
The last kind of looping lets you loop through predefined iterator types:
• symbols
• imports
• registers
• threads
• comments
• functions
• flags
This is done using the @@@ command. The previous example of listing information about functions can also be done using the @@@ command:
[0x004047d6]> afi @@@ functions ~name
This will extract name field from afi output and will output a huge list of function names. We can choose only the second column, to remove the redundant name: on every line:
[0x004047d6]> afi @@@ functions ~name[1]
Beware, @@@ is not compatible with JSON commands.
Apart from simple sequencing and looping, radare2 allows to write simple macros, using this construction:
[0x00404800]> (qwe; pd 4; ao)
This will define a macro called 'qwe' which runs sequentially first 'pd 4' then 'ao'. Calling the macro using syntax .(macro) is simple:
[0x00404800]> (qwe; pd 4; ao)
[0x00404800]> .(qwe)
0x00404800 mov eax, 0x61e627 ; "tab"
0x00404805 push rbp
0x00404806 sub rax, section_end.LOAD1
0x0040480c mov rbp, rsp
address: 0x404800
opcode: mov eax, 0x61e627
prefix: 0
bytes: b827e66100
ptr: 0x0061e627
refptr: 0
size: 5
type: mov
esiclass="underline" 6415911,rax,=
stack: null
family: cpu
[0x00404800]>
To list available macroses simply call (*:
[0x00404800]> (*
(qwe ; pd 4; ao)
And if want to remove some macro, just add '-' before the name:
[0x00404800]> (-qwe)
Macro 'qwe' removed.
[0x00404800]>
Moreover, it's possible to create a macro that takes arguments, which comes in handy in some simple scripting situations. To create a macro that takes arguments you simply add them to macro definition.
[0x00404800]
[0x004047d0]> (foo x y; pd $0; s +$1)
[0x004047d0]> .(foo 5 6)
;-- entry0:
0x004047d0 xor ebp, ebp
0x004047d2 mov r9, rdx
0x004047d5 pop rsi
0x004047d6 mov rdx, rsp
0x004047d9 and rsp, 0xfffffffffffffff0
[0x004047d6]>
As you can see, the arguments are named by index, starting from 0: $0, $1, ...
radare2 also offers aliases which might help you save time by quickly executing your most used commands. They are under $?
The general usage of the feature is: $alias=cmd
[0x00404800]> $disas=pdf
The above command will create an alias disas for pdf. The following command prints the disassembly of the main function.
[0x00404800]> $disas @ main
Apart from commands, you can also alias a text to be printed, when called.
[0x00404800]> $my_alias=$test input
[0x00404800]> $my_alias
test input
To undefine alias, use $alias=: