The Official Radare2 Book — страница 38 из 64

frame.frameParameters/LocalsDisplay parametersN/AafvN/Ainfo argsdv /t /i /VDisplay parametersN/AafvN/Ainfo localsdv /t /i /VDisplay parameters/locals in jsonN/AafvjN/Ainfo localsdv /t /i /Vlist addresses where vars are accessed(R/W)N/AafvR/afvWN/A??Project Relatedopen projectPo [file]?save projectautomaticPs [file]?show project informationsPi [file]?MiscellaneousDump byte char arrayN/Apc? (json, C, char, etc.)Vppppx/bcdboptionsoption menue?esearchsearch menu/?Select the zone with the cursor c then /s

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 bytes at

(anywhere if address is -1) in child process

| 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 Load contents of file into the

current map region

| dmm[?][j*] List modules (libraries, binaries

loaded in memory)

| dmp[?]

Change page at

with , protection (perm)

| dms[?] Take memory snapshot

| dms- Restore memory snapshot

| 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 bytes at

and promote to huge page

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