The most useful feature in r2 for working with data structures is pf
commands, which prints formatted data.
You can use this command to print data in certain address according to a defined format, and moreover - define specific formats, for repeating structure.
The command is used as pf [types] [member1] [member2] [...]
. To see all the type code, pf??
, and pf???
for some usage examples. To define a type, use pf.[type] [..]
.
Example:
[0x08048e26]> pf.node ii*? value index (node)next
[0x08048e26]> pf.node @@ obj.node*
value : 0x0804b230 = 432
index : 0x0804b234 = 6
next : (*0x0) NULL
value : 0x0804b254 = 301
index : 0x0804b258 = 3
next : (*0x804b248)
struct<node>
value : 0x0804b248 = 997
index : 0x0804b24c = 4
next : (*0x804b23c)
<snip>
You can also parse a header file with radare to add the structure to the saved types, and then generate a pf
command for it.
to [file]
is used to load and parse a file, and ts
is used to print all loaded tructures.
You can make the following header file:
typedef struct Node {
int value;
int index;
struct Node *next;
} node;
and load it using to
. You can then use t Node
to generate automatically a pf
command for the structure. The command in this example is pf ddp value index next
:
[0x0804b260]> pf ddp value index next
value : 0x0804b260 = 725
index : 0x0804b264 = 2
next : 0x0804b268 = 0x0804b254
As you can see, it is less accurate than defining pf yourself, but can be quicker if you've alreay got a header file / need it for sthg else / more comfortable with the syntax.
ts* Node
can be used to generate a pf command to define this type (for futurepf
s)- You can also define a struct inline and not in a file using
td
(td struct foo {char* a; int b;}
) tl
can be used to to permenantly link an address with a chosen type.tas [offset]
&ta [struct.member]
can be used to convert an offset in assembly to an offset inside a struct:[0x000052f0]> pd 1 0x000052f0 mov rax, qword [rsi + 8] ; [0x8:8]=0 [0x000052f0]> "td struct ms { char b[8]; int member1; int member2; };" [0x000052f0]> "td struct ms1 { uint64_t a; int member1; };" [0x000052f0]> "td struct ms2 { uint16_t a; int64_t b; int member1; };" [0x000052f0]> tas 8 ms.member1 ms1.member1 [0x000052f0]> ta ms1.member1 [0x000052f0]> pd 1 0x000052f0 488b4608 mov rax, qword [rsi + ms1.member1] ; [0x8:8]=0