Equivalent of "set-follow-fork-mode" gdb command
This can be done using 2 commands:
1. dcf - until a fork happen
2. then use dp to select what process you want to debug.
Common features
• r2 accepts FLIRT signatures
• r2 can connect to GDB, LLVM and WinDbg
• r2 can write/patch in place
• r2 have fortunes and [s]easter eggs[/s]balls of steel
• r2 can do basic loading of ELF core files from the box and MDMP (Windows minidumps)
Registers
The registers are part of a user area stored in the context structure used by the scheduler. This structure can be manipulated to get and set the values of those registers, and, for example, on Intel hosts, it is possible to directly manipulate DR0-DR7 hardware registers to set hardware breakpoints.
There are different commands to get values of registers. For the General Purpose ones use:
[0x4A13B8C0]> dr
r15 = 0x00000000
r14 = 0x00000000
r13 = 0x00000000
r12 = 0x00000000
rbp = 0x00000000
rbx = 0x00000000
r11 = 0x00000000
r10 = 0x00000000
r9 = 0x00000000
r8 = 0x00000000
rax = 0x00000000
rcx = 0x00000000
rdx = 0x00000000
rsi = 0x00000000
rdi = 0x00000000
oeax = 0x0000003b
rip = 0x7f20bf5df630
rsp = 0x7fff515923c0
[0x7f0f2dbae630]> dr rip ; get value of 'rip'
0x7f0f2dbae630
[0x4A13B8C0]> dr rip = esp ; set 'rip' as esp
Interaction between a plugin and the core is done by commands returning radare instructions. This is used, for example, to set flags in the core to set values of registers.
[0x7f0f2dbae630]> dr* ; Appending '*' will show radare commands
f r15 1 0x0
f r14 1 0x0
f r13 1 0x0
f r12 1 0x0
f rbp 1 0x0
f rbx 1 0x0
f r11 1 0x0
f r10 1 0x0
f r9 1 0x0
f r8 1 0x0
f rax 1 0x0
f rcx 1 0x0
f rdx 1 0x0
f rsi 1 0x0
f rdi 1 0x0
f oeax 1 0x3b
f rip 1 0x7fff73557940
f rflags 1 0x200
f rsp 1 0x7fff73557940
[0x4A13B8C0]> .dr* ; include common register values in flags
An old copy of registers is stored all the time to keep track of the changes done during execution of a program being analyzed. This old copy can be accessed with oregs.
[0x7f1fab84c630]> dro
r15 = 0x00000000
r14 = 0x00000000
r13 = 0x00000000
r12 = 0x00000000
rbp = 0x00000000
rbx = 0x00000000
r11 = 0x00000000
r10 = 0x00000000
r9 = 0x00000000
r8 = 0x00000000
rax = 0x00000000
rcx = 0x00000000
rdx = 0x00000000
rsi = 0x00000000
rdi = 0x00000000
oeax = 0x0000003b
rip = 0x7f1fab84c630
rflags = 0x00000200
rsp = 0x7fff386b5080
Current state of registers
[0x7f1fab84c630]> dr
r15 = 0x00000000
r14 = 0x00000000
r13 = 0x00000000
r12 = 0x00000000
rbp = 0x00000000
rbx = 0x00000000
r11 = 0x00000000
r10 = 0x00000000
r9 = 0x00000000
r8 = 0x00000000
rax = 0x00000000
rcx = 0x00000000
rdx = 0x00000000
rsi = 0x00000000
rdi = 0x7fff386b5080
oeax = 0xffffffffffffffff
rip = 0x7f1fab84c633
rflags = 0x00000202
rsp = 0x7fff386b5080
Values stored in eax, oeax and eip have changed.
To store and restore register values you can just dump the output of 'dr*' command to disk and then re-interpret it again:
[0x4A13B8C0]> dr* > regs.saved ; save registers
[0x4A13B8C0]> drp regs.saved ; restore
EFLAGS can be similarly altered. E.g., setting selected flags:
[0x4A13B8C0]> dr eflags = pst
[0x4A13B8C0]> dr eflags = azsti
You can get a string which represents latest changes of registers using drd command (diff registers):
[0x4A13B8C0]> drd
oeax = 0x0000003b was 0x00000000 delta 59
rip = 0x7f00e71282d0 was 0x00000000 delta -418217264
rflags = 0x00000200 was 0x00000000 delta 512
rsp = 0x7fffe85a09c0 was 0x00000000 delta -396752448
Memory Maps
The ability to understand and manipulate the memory maps of a debugged program is important for many different Reverse Engineering tasks. radare2 offers a rich set of commands to handle memory maps in the binary. This includes listing the memory maps of the currently debugged binary, removing memory maps, handling loaded libraries and more.
First, let's see the help message for dm, the command which is responsible for handling memory maps:
[0x55f2104cf620]>
dm?
Usage: dm # Memory maps commands
| dm List memory maps of target process
| dm address size Allocate
| dm= List memory maps of target process
(ascii-art bars)
| dm. Show map name of current address
| dm* List memmaps in radare commands
| dm- address Deallocate memory map of
| dmd[a] [file] Dump current (all) debug map region
to a file (from-to.dmp) (see Sd)
| dmh[?] Show map of heap
| dmi [addr|libname] [symname] List symbols of target lib
| dmi* [addr|libname] [symname] List symbols of target lib in radare
commands
| dmi. List closest symbol to the current
address
| dmiv Show address of given symbol for
given lib
| dmj List memmaps in JSON format
| dml
current map region
| dmm[?][j*] List modules (libraries, binaries
loaded in memory)
| dmp[?]
| dms[?]
| dms-
| dmS [addr|libname] [sectname] List sections of target lib
| dmS* [addr|libname] [sectname] List sections of target lib in radare
commands
| dmL address size Allocate
In this chapter, we'll go over some of the most useful subcommands of dm using simple examples. For the following examples, we'll use a simple helloworld program for Linux but it'll be the same for every binary.
First things first - open a program in debugging mode:
$ r2 -d helloworld
Process with PID 20304 started...
= attach 20304 20304
bin.baddr 0x56136b475000
Using 0x56136b475000
asm.bits 64
[0x7f133f022fb0]>
Note that we passed "helloworld" to radare2 without "./". radare2 will try to find this program in the current directory and then in $PATH, even if no "./" is passed. This is contradictory with UNIX systems, but makes the behaviour consistent for windows users
Let's use dm to print the memory maps of the binary we've just opened:
[0x7f133f022fb0]> dm
0x0000563a0113a000 - usr 4K s r-x /tmp/helloworld /tmp/helloworld ; map.tmp_helloworld.r_x
0x0000563a0133a000 - usr 8K s rw- /tmp/helloworld /tmp/helloworld ; map.tmp_helloworld.rw
0x00007f133f022000 * usr 148K s r-x /usr/lib/ld-2.27.so /usr/lib/ld-2.27.so ; map.usr_lib_ld_2.27.so.r_x
0x00007f133f246000 - usr 8K s rw- /usr/lib/ld-2.27.so /usr/lib/ld-2.27.so ; map.usr_lib_ld_2.27.so.rw
0x00007f133f248000 - usr 4K s rw- unk0 unk0 ; map.unk0.rw
0x00007fffd25ce000 - usr 132K s rw- [stack] [stack] ; map.stack_.rw
0x00007fffd25f6000 - usr 12K s r-- [vvar] [vvar] ; map.vvar_.r
0x00007fffd25f9000 - usr 8K s r-x [vdso] [vdso] ; map.vdso_.r_x
0xffffffffff600000 - usr 4K s r-x [vsyscall] [vsyscall] ; map.vsyscall_.r_x
For those of you who prefer a more visual way, you can use dm= to see the memory maps using an ASCII-art bars. This will be handy when you want to see how these maps are located in the memory.
If you want to know the memory-map you are currently in, use dm.: