Loops

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:

  1. @@ flagname-regex

For example, we want to see function information with afi command:

  1. [0x004047d6]> afi
  2. #
  3. offset: 0x004047d0
  4. name: entry0
  5. size: 42
  6. realsz: 42
  7. stackframe: 0
  8. call-convention: amd64
  9. cyclomatic-complexity: 1
  10. bits: 64
  11. type: fcn [NEW]
  12. num-bbs: 1
  13. edges: 0
  14. end-bbs: 1
  15. call-refs: 0x00402450 C
  16. data-refs: 0x004136c0 0x00413660 0x004027e0
  17. code-xrefs:
  18. data-xrefs:
  19. locals:0
  20. args: 0
  21. diff: type: new
  22. [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.):

  1. [0x004047d6]> fs functions
  2. [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:

  1. [0x004047d6]> afi @@f ~name

We can also loop over a list of offsets, using the following syntax:

  1. @@=1 2 3 ... N

For example, say we want to see the opcode information for 2 offsets: the current one, and at current + 2:

  1. [0x004047d6]> ao @@=$$ $$+2
  2. address: 0x4047d6
  3. opcode: mov rdx, rsp
  4. prefix: 0
  5. bytes: 4889e2
  6. refptr: 0
  7. size: 3
  8. type: mov
  9. esil: rsp,rdx,=
  10. stack: null
  11. family: cpu
  12. address: 0x4047d8
  13. opcode: loop 0x404822
  14. prefix: 0
  15. bytes: e248
  16. refptr: 0
  17. size: 2
  18. type: cjmp
  19. esil: 1,rcx,-=,rcx,?{,4212770,rip,=,}
  20. jump: 0x00404822
  21. fail: 0x004047da
  22. stack: null
  23. cond: al
  24. family: cpu
  25. [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.

  1. [0x004047d0]> ?v $$ > offsets.txt
  2. [0x004047d0]> ?v $$+2 >> offsets.txt
  3. [0x004047d0]> !cat offsets.txt
  4. 4047d0
  5. 4047d2
  6. [0x004047d0]> pi 1 @@.offsets.txt
  7. xor ebp, ebp
  8. 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:

  1. [0x004047d0]> pdf
  2. (fcn) entry0 42
  3. │; UNKNOWN XREF from 0x00400018 (unk)
  4. │; DATA XREF from 0x004064bf (sub.strlen_460)
  5. │; DATA XREF from 0x00406511 (sub.strlen_460)
  6. │; DATA XREF from 0x0040b080 (unk)
  7. │; DATA XREF from 0x0040b0ef (unk)
  8. 0x004047d0 xor ebp, ebp
  9. 0x004047d2 mov r9, rdx
  10. 0x004047d5 pop rsi
  11. 0x004047d6 mov rdx, rsp
  12. 0x004047d9 and rsp, 0xfffffffffffffff0
  13. 0x004047dd push rax
  14. 0x004047de push rsp
  15. 0x004047df mov r8, 0x4136c0
  16. 0x004047e6 mov rcx, 0x413660 ; "AWA..AVI..AUI..ATL.%.. "
  17. 0A..AVI..AUI.
  18. 0x004047ed mov rdi, main ; "AWAVAUATUH..S..H...." @
  19. 0
  20. 0x004047f4 call sym.imp.__libc_start_main
  21. 0x004047f9 hlt
  22. [0x004047d0]> pi 1 @@i
  23. mov r9, rdx
  24. pop rsi
  25. mov rdx, rsp
  26. and rsp, 0xfffffffffffffff0
  27. push rax
  28. push rsp
  29. mov r8, 0x4136c0
  30. mov rcx, 0x413660
  31. mov rdi, main
  32. call sym.imp.__libc_start_main
  33. 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:

  1. [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:

  1. [0x004047d6]> afi @@@ functions ~name[1]

Beware, @@@ is not compatible with JSON commands.