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

[0x00000000]> b?

Usage: b[f] [arg] # Get/Set block size

| b 33 set block size to 33

| b eip+4 numeric argument can be an expression

| b display current block size

| b+3 increase blocksize by 3

| b-16 decrease blocksize by 16

| b* display current block size in r2 command

| bf foo set block size to flag size

| bj display block size information in JSON

| bm 1M set max block size

The b command is used to change the block size:

[0x00000000]> b 0x100 # block size = 0x100

[0x00000000]> b+16 # ... = 0x110

[0x00000000]> b-32 # ... = 0xf0

The bf command is used to change the block size to value specified by a flag. For example, in symbols, the block size of the flag represents the size of the function. To make that work, you have to either run function analysis af (which is included in aa) or manually seek and define some functions e.g. via Vd.

[0x00000000]> bf sym.main # block size = sizeof(sym.main)

[0x00000000]> pD @ sym.main # disassemble sym.main

You can combine two operations in a single pdf command. Except that pdf neither uses nor affects global block size.

[0x00000000]> pdf @ sym.main # disassemble sym.main

Another way around is to use special variables $FB and $FS which denote Function's Beginning and Size at the current seek. Read more about Usable variables.

[0x00000000]> s sym.main + 0x04

[0x00001ec9]> pD @ $FB !$FS # disassemble current function

╭ 211: int main (int argc, char **argv, char **envp);

│ 0x00001ec5 55 push rbp

│ 0x00001ec6 4889e5 mov rbp, rsp

│ 0x00001ec9 4881ecc0000000 sub rsp, 0xc0

...

╰ 0x00001f97 c3 ret

Note: don't put space after ! size designator. See also Command Format.

Sections

The concept of sections is tied to the information extracted from the binary. We can display this information by using the i command.

Displaying information about sections:

[0x00005310]> iS

[Sections]

00 0x00000000 0 0x00000000 0 ----

01 0x00000238 28 0x00000238 28 -r-- .interp

02 0x00000254 32 0x00000254 32 -r-- .note.ABI_tag

03 0x00000278 176 0x00000278 176 -r-- .gnu.hash

04 0x00000328 3000 0x00000328 3000 -r-- .dynsym

05 0x00000ee0 1412 0x00000ee0 1412 -r-- .dynstr

06 0x00001464 250 0x00001464 250 -r-- .gnu.version

07 0x00001560 112 0x00001560 112 -r-- .gnu.version_r

08 0x000015d0 4944 0x000015d0 4944 -r-- .rela.dyn

09 0x00002920 2448 0x00002920 2448 -r-- .rela.plt

10 0x000032b0 23 0x000032b0 23 -r-x .init

...

As you may know, binaries have sections and maps. The sections define the contents of a portion of the file that can be mapped in memory (or not). What is mapped is defined by the segments.

Before the IO refactoring done by condret, the S command was used to manage what we now call maps. Currently the S command is deprecated because iS and om should be enough.

Firmware images, bootloaders and binary files usually place various sections of a binary at different addresses in memory. To represent this behavior, radare offers the iS. Use iS? to get the help message. To list all created sections use iS (or iSj to get the json format). The iS= will show the region bars in ascii-art.

You can create a new mapping using the om subcommand as follows:

om fd vaddr [size] [paddr] [rwx] [name]

For Example:

[0x0040100]> om 4 0x00000100 0x00400000 0x0001ae08 rwx test

You can also use om command to view information about mapped sections:

[0x00401000]> om

6 fd: 4 +0x0001ae08 0x00000100 - 0x004000ff rwx test

5 fd: 3 +0x00000000 0x00000000 - 0x0000055f r-- fmap.LOAD0

4 fd: 3 +0x00001000 0x00001000 - 0x000011e4 r-x fmap.LOAD1

3 fd: 3 +0x00002000 0x00002000 - 0x0000211f r-- fmap.LOAD2

2 fd: 3 +0x00002de8 0x00003de8 - 0x0000402f r-- fmap.LOAD3

1 fd: 4 +0x00000000 0x00004030 - 0x00004037 rw- mmap.LOAD3

Use om? to get all the possible subcommands. To list all the defined maps use om (or omj to get the json format or om* to get the r2 commands format). To get the ascii art view use om=.

It is also possible to delete the mapped section using the om-mapid command.

For Example:

[0x00401000]> om-6

Mapping Files

Radare's I/O subsystem allows you to map the contents of files into the same I/O space used to contain a loaded binary. New contents can be placed at random offsets.

The o command permits the user to open a file, this is mapped at offset 0 unless it has a known binary header and then the maps are created in virtual addresses.

Sometimes, we want to rebase a binary, or maybe we want to load or map the file in a different address.

When launching r2, the base address can be changed with the -B flag. But you must notice the difference when opening files with unknown headers, like bootloaders, so we need to map them using the -m flag (or specifying it as argument to the o command).

radare2 is able to open files and map portions of them at random places in memory specifying attributes like permissions and name. It is the perfect basic tooling to reproduce an environment like a core file, a debug session, by also loading and mapping all the libraries the binary depends on.

Opening files (and mapping them) is done using the o (open) command. Let's read the help:

[0x00000000]> o?

|Usage: o [com- ] [file] ([offset])

| o list opened files

| o-1 close file descriptor 1

| o-!* close all opened files

| o-- close all files, analysis, binfiles, flags, same as !r2 --

| o [file] open [file] file in read-only

| o+ [file] open file in read-write mode

| o [file] 0x4000 rwx map file at 0x4000

| oa[-] [A] [B] [filename] Specify arch and bits for given file

| oq list all open files

| o* list opened files in r2 commands

| o. [len] open a malloc://[len] copying the bytes from current offset

| o= list opened files (ascii-art bars)

| ob[?] [lbdos] [...] list opened binary files backed by fd

| oc [file] open core file, like relaunching r2

| of [file] open file and map it at addr 0 as read-only

| oi[-|idx] alias for o, but using index instead of fd

| oj[?] list opened files in JSON format

| oL list all IO plugins registered

| om[?] create, list, remove IO maps

| on [file] 0x4000 map raw file at 0x4000 (no r_bin involved)

| oo[?] reopen current file (kill+fork in debugger)

| oo+ reopen current file in read-write

| ood[r] [args] reopen in debugger mode (with args)

| oo[bnm] [...] see oo? for help

| op [fd] prioritize given fd (see also ob)

| ox fd fdx exchange the descs of fd and fdx and keep the mapping

Prepare a simple layout:

$ rabin2 -l /bin/ls

[Linked libraries]

libselinux.so.1

librt.so.1

libacl.so.1

libc.so.6


4 libraries

Map a file:

[0x00001190]> o /bin/zsh 0x499999

List mapped files:

[0x00000000]> o

- 6 /bin/ls @ 0x0 ; r

- 10 /lib/ld-linux.so.2 @ 0x100000000 ; r

- 14 /bin/zsh @ 0x499999 ; r

Print hexadecimal values from /bin/zsh:

[0x00000000]> px @ 0x499999

Unmap files using the o- command. Pass the required file descriptor to it as an argument:

[0x00000000]> o-14

You can also view the ascii table showing the list of the opened files:

[0x00000000]> ob=

Print Modes

One of the key features of radare2 is displaying information in many formats. The goal is to offer a selection of display choices to interpret binary data in the best possible way.

Binary data can be represented as integers, shorts, longs, floats, timestamps, hexpair strings, or more complex formats like C structures, disassembly listings, decompilation listing, be a result of an external processing...

Below is a list of available print modes listed by p?:

[0x00005310]> p?

|Usage: p[=68abcdDfiImrstuxz] [arg|len] [@addr]

| p[b|B|xb] [len] ([S]) bindump N bits skipping S bytes

| p[iI][df] [len] print N ops/bytes (f=func) (see pi? and pdi)

| p[kK] [len] print key in randomart (K is for mosaic)

| p-[?][jh] [mode] bar|json|histogram blocks (mode: e?search.in)

| p2 [len] 8x8 2bpp-tiles

| p3 [file] print stereogram (3D)

| p6[de] [len] base64 decode/encode

| p8[?][j] [len] 8bit hexpair list of bytes

| p=[?][bep] [N] [L] [b] show entropy/printable chars/chars bars

| pa[edD] [arg] pa:assemble pa[dD]:disasm or pae: esil from hex

| pA[n_ops] show n_ops address and type

| pb[?] [n] bitstream of N bits