Выбрать главу

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.

   • 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)

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

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

<address> (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

<address>

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

current map region

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

loaded in memory)

| dmp[?] <address> <size> <perms> Change page at

<address> with <size>, protection <perms> (perm)

| dms[?] <id> <mapaddr> Take memory snapshot

| dms- <id> <mapaddr> 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 <size> bytes at

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