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

considered as a union (all fields at offset 0)

| pf.plop ? (troll)mystruct Use structure troll

previously defined

| pfj.plop @ 0x14 Apply format object at

the given offset

| pf 10xiz pointer length string Print a size 10 array of

the xiz struct with its field names

| pf 5sqw string quad word Print an array with sqw

struct along with its field names

| pf {integer}? (bifc) Print integer times the

following format (bifc)

| pf [4]w[7]i Print an array of 4 words

and then an array of 7 integers

| pf ic...?i foo bar "(pf xw yo foo)troll" yo Print nested anonymous

structures

| pf ;..x Print value located 6

bytes from current offset

| pf [10]z[3]i[10]Zb Print an fixed size str,

widechar, and var

| pfj +F @ 0x14 Print the content at

given offset with flag

| pf n2 print signed short (2

bytes) value. Use N instead of n for printing unsigned values

| pf [2]? (plop)structname @ 0 Prints an array of

structs

| pf eqew bigWord beef Swap endianness and print

with given labels

| pf.foo rr (eax)reg1 (eip)reg2 Create object referencing

to register values

| pf tt troll plop print time stamps with

labels troll and plop

Some examples are below:

[0x4A13B8C0]> pf i

0x00404888 = 837634441

[0x4A13B8C0]> pf

0x00404888 = 837634432.000000

Valid print code formats for human-readable languages are:

   • pc C

   • pc* print 'wx' r2 commands

   • pch C half-words (2 byte)

   • pcw C words (4 byte)

   • pcd C dwords (8 byte)

   • pci C array of bytes with instructions

   • pca GAS .byte blob

   • pcA .bytes with instructions in comments

   • pcs string

   • pcS shellscript that reconstructs the bin

   • pcj json

   • pcJ javascript

   • pco Objective-C

   • pcp python

   • pck kotlin

   • pcr rust

   • pcv JaVa

   • pcV V (vlang.io)

   • pcy yara

   • pcz Swift

If we need to create a .c file containing a binary blob, use the pc command, that creates this output. The default size is like in many other commands: the block size, which can be changed with the b command.

We can also just temporarily override this block size by expressing it as an argument.

[0xB7F8E810]>

pc 32

#define _BUFFER_SIZE 32

unsigned char buffer[_BUFFER_SIZE] = {

0x89, 0xe0, 0xe8, 0x49, 0x02, 0x00, 0x00, 0x89, 0xc7, 0xe8, 0xe2, 0xff,

0xff, 0xff, 0x81, 0xc3, 0xd6, 0xa7, 0x01, 0x00, 0x8b, 0x83, 0x00, 0xff,

0xff, 0xff, 0x5a, 0x8d, 0x24, 0x84, 0x29, 0xc2 };

That cstring can be used in many programming languages, not just C.

[0x7fcd6a891630]>

pcs

"\x48\x89\xe7\xe8\x68\x39\x00\x00\x49\x89\xc4\x8b\x05\xef\x16\x22\x00\x5a\x48\x8d\x24\xc4\x29\xc2\x52\x48\x89\xd6\x49\x89\xe5\x48\x83\xe4\xf0\x48\x8b\x3d\x06\x1a

Strings are probably one of the most important entry points when starting to reverse engineer a program because they usually reference information about functions' actions (asserts, debug or info messages...). Therefore, radare supports various string formats:

[0x00000000]> ps?

|Usage: ps[bijqpsuwWxz+] [N] Print String

| ps print string

| ps+[j] print libc++ std::string (same-endian, ascii, zero-terminated)

| psb print strings in current block

| psi print string inside curseek

| psj print string in JSON format

| psp[j] print pascal string

| psq alias for pqs

| pss print string in screen (wrap width)

| psu[zj] print utf16 unicode (json)

| psw[j] print 16bit wide string

| psW[j] print 32bit wide string

| psx show string with escaped chars

| psz[j] print zero-terminated string

Most strings are zero-terminated. Below there is an example using the debugger to continue the execution of a program until it executes the 'open' syscall. When we recover the control over the process, we get the arguments passed to the syscall, pointed by %ebx. In the case of the 'open' call, it is a zero terminated string which we can inspect using psz.

[0x4A13B8C0]> dcs open

0x4a14fc24 syscall(5) open ( 0x4a151c91 0x00000000 0x00000000 ) = 0xffffffda

[0x4A13B8C0]> dr

eax 0xffffffda esi 0xffffffff eip 0x4a14fc24

ebx 0x4a151c91 edi 0x4a151be1 oeax 0x00000005

ecx 0x00000000 esp 0xbfbedb1c eflags 0x200246

edx 0x00000000 ebp 0xbfbedbb0 cPaZstIdor0 (PZI)

[0x4A13B8C0]>

[0x4A13B8C0]> psz @ 0x4a151c91

/etc/ld.so.cache

It is also possible to print various packed data types using the pf command:

[0xB7F08810]> pf xxS @ rsp

0x7fff0d29da30 = 0x00000001

0x7fff0d29da34 = 0x00000000

0x7fff0d29da38 = 0x7fff0d29da38 -> 0x0d29f7ee /bin/ls

This can be used to look at the arguments passed to a function. To achieve this, simply pass a 'format memory string' as an argument to pf, and temporally change the current seek position/offset using @. It is also possible to define arrays of structures with pf. To do this, prefix the format string with a numeric value. You can also define a name for each field of the structure by appending them as a space-separated arguments list.

[0x4A13B8C0]> pf 2*xw pointer type @ esp

0x00404888 [0] {

pointer :

(*0xffffffff8949ed31) type : 0x00404888 = 0x8949ed31

0x00404890 = 0x48e2

}

0x00404892 [1] {

(*0x50f0e483) pointer : 0x00404892 = 0x50f0e483

type : 0x0040489a = 0x2440

}

A practical example for using pf on a binary of a GStreamer plugin:

$ radare2 /usr/lib/gstreamer-1.0/libgstflv.so

[0x00006020]> aa; pdf @ sym.gst_plugin_flv_get_desc

[x] Analyze all flags starting with sym. and entry0 (aa)

sym.gst_plugin_flv_get_desc ();

[...]

0x00013830 488d0549db0000 lea rax, section..data.rel.ro ; 0x21380

0x00013837 c3 ret

[0x00006020]> s section..data.rel.ro

[0x00021380]> pf ii*z*zp*z*z*z*z*z*z major minor name desc init version license source package origin release_datetime

major : 0x00021380 = 1

minor : 0x00021384 = 18

name : (*0x19cf2)0x00021388 = "flv"

desc : (*0x1b358)0x00021390 = "FLV muxing and demuxing plugin"

init : 0x00021398 = (qword)0x0000000000013460

version : (*0x19cae)0x000213a0 = "1.18.2"

license : (*0x19ce1)0x000213a8 = "LGPL"

source : (*0x19cd0)0x000213b0 = "gst-plugins-good"

package : (*0x1b378)0x000213b8 = "GStreamer Good Plugins (Arch Linux)"

origin : (*0x19cb5)0x000213c0 = "https://www.archlinux.org/"

release_datetime : (*0x19cf6)0x000213c8 = "2020-12-06"

The pd command is used to disassemble code. It accepts a numeric value to specify how many instructions should be disassembled. The pD command is similar but instead of a number of instructions, it decompiles a given number of bytes.