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

When we want to check how analysis changes affect the result in the case of big functions, we can use minimap instead, allowing to see a bigger flow graph on the same screen size. To get into the minimap mode type VV then press p twice:

This mode allows you to see the disassembly of each node separately, just navigate between them using Tab key.

Analysis hints

It is not an uncommon case that analysis results are not perfect even after you tried every single configuration option. This is where the "analysis hints" radare2 mechanism comes in. It allows to override some basic opcode or meta-information properties, or even to rewrite the whole opcode string. These commands are located under ah namespace:

Usage: ah[lba-] Analysis Hints

| ah? show this help

| ah? offset show hint of given offset

| ah list hints in human-readable format

| ah. list hints in human-readable format from current offset

| ah- remove all hints

| ah- offset [size] remove hints at given offset

| ah* offset list hints in radare commands format

| aha ppc @ 0x42 force arch ppc for all addrs >= 0x42 or until the next hint

| aha 0 @ 0x84 disable the effect of arch hints for all addrs >= 0x84 or until the next hint

| ahb 16 @ 0x42 force 16bit for all addrs >= 0x42 or until the next hint

| ahb 0 @ 0x84 disable the effect of bits hints for all addrs >= 0x84 or until the next hint

| ahc 0x804804 override call/jump address

| ahd foo a0,33 replace opcode string

| ahe 3,eax,+= set vm analysis string

| ahf 0x804840 override fallback address for call

| ahF 0x10 set stackframe size at current offset

| ahh 0x804840 highlight this address offset in disasm

| ahi[?] 10 define numeric base for immediates (2, 8, 10, 10u, 16, i, p, S, s)

| ahj list hints in JSON

| aho call change opcode type (see aho?) (deprecated, moved to "ahd")

| ahp addr set pointer hint

| ahr val set hint for return value of a function

| ahs 4 set opcode size=4

| ahS jz set asm.syntax=jz for this opcode

| aht [?] Mark immediate as a type offset (deprecated, moved to "aho")

| ahv val change opcode's val field (useful to set jmptbl sizes in jmp rax)

One of the most common cases is to set a particular numeric base for immediates:

[0x00003d54]> ahi?

Usage: ahi [2|8|10|10u|16|bodhipSs] [@ offset] Define numeric base

| ahi set numeric base (2, 8, 10, 16)

| ahi 10|d set base to signed decimal (10), sign bit should depend on receiver size

| ahi 10u|du set base to unsigned decimal (11)

| ahi b set base to binary (2)

| ahi o set base to octal (8)

| ahi h set base to hexadecimal (16)

| ahi i set base to IP address (32)

| ahi p set base to htons(port) (3)

| ahi S set base to syscall (80)

| ahi s set base to string (1)


[0x00003d54]> pd 2

0x00003d54 0583000000 add eax, 0x83

0x00003d59 3d13010000 cmp eax, 0x113

[0x00003d54]> ahi d

[0x00003d54]> pd 2

0x00003d54 0583000000 add eax, 131

0x00003d59 3d13010000 cmp eax, 0x113

[0x00003d54]> ahi b

[0x00003d54]> pd 2

0x00003d54 0583000000 add eax, 10000011b

0x00003d59 3d13010000 cmp eax, 0x113

It is notable that some analysis stages or commands add the internal analysis hints, which can be checked with ah command:

[0x00003d54]> ah

0x00003d54 - 0x00003d54 => immbase=2

[0x00003d54]> ah*

ahi 2 @ 0x3d54

Sometimes we need to override jump or call address, for example in case of tricky relocation, which is unknown for radare2, thus we can change the value manually. The current analysis information about a particular opcode can be checked with ao command. We can use ahc command for performing such a change:

[0x00003cee]> pd 2

0x00003cee e83d080100 call sub.__errno_location_530

0x00003cf3 85c0 test eax, eax

[0x00003cee]> ao

address: 0x3cee

opcode: call 0x14530

mnemonic: call

prefix: 0

id: 56

bytes: e83d080100

refptr: 0

size: 5

sign: false

type: call

cycles: 3

esil: 83248,rip,8,rsp,-=,rsp,=[],rip,=

jump: 0x00014530

direction: exec

fail: 0x00003cf3

stack: null

family: cpu

stackop: null

[0x00003cee]> ahc 0x5382

[0x00003cee]> pd 2

0x00003cee e83d080100 call sub.__errno_location_530

0x00003cf3 85c0 test eax, eax

[0x00003cee]> ao

address: 0x3cee

opcode: call 0x14530

mnemonic: call

prefix: 0

id: 56

bytes: e83d080100

refptr: 0

size: 5

sign: false

type: call

cycles: 3

esil: 83248,rip,8,rsp,-=,rsp,=[],rip,=

jump: 0x00005382

direction: exec

fail: 0x00003cf3

stack: null

family: cpu

stackop: null

[0x00003cee]> ah

0x00003cee - 0x00003cee => jump: 0x5382

As you can see, despite the unchanged disassembly view the jump address in opcode was changed (jump option).

If anything of the previously described didn't help, you can simply override shown disassembly with anything you like:

[0x00003d54]> pd 2

0x00003d54 0583000000 add eax, 10000011b

0x00003d59 3d13010000 cmp eax, 0x113

[0x00003d54]> "ahd myopcode bla, foo"

[0x00003d54]> pd 2

0x00003d54 myopcode bla, foo

0x00003d55 830000 add dword [rax], 0

Managing variables

Radare2 allows managing local variables, no matter their location, stack or registers. The variables' auto analysis is enabled by default but can be disabled with anal.vars configuration option.

The main variables commands are located in afv namespace:

Usage: afv [rbs]

| afv* output r2 command to add args/locals to flagspace

| afv-([name]) remove all or given var

| afv= list function variables and arguments with disasm refs

| afva analyze function arguments/locals

| afvb[?] manipulate bp based arguments/locals

| afvd name output r2 command for displaying the value of args/locals in the debugger

| afvf show BP relative stackframe variables

| afvn [new_name] ([old_name]) rename argument/local

| afvr[?] manipulate register based arguments

| afvR [varname] list addresses where vars are accessed (READ)

| afvs[?] manipulate sp based arguments/locals

| afvt [name] [new_type] change type for given argument/local

| afvW [varname] list addresses where vars are accessed (WRITE)

| afvx show function variable xrefs (same as afvR+afvW)

afvr, afvb and afvs commands are uniform but allow manipulation of register-based arguments and variables, BP/FP-based arguments and variables, and SP-based arguments and variables respectively. If we check the help for afvr we will get the way two others commands works too:

|Usage: afvr [reg] [type] [name]

| afvr list register based arguments

| afvr* same as afvr but in r2 commands

| afvr [reg] [name] ([type]) define register arguments

| afvrj return list of register arguments in JSON format

| afvr- [name] delete register arguments at the given index

| afvrg [reg] [addr] define argument get reference

| afvrs [reg] [addr] define argument set reference

Like many other things variables detection is performed by radare2 automatically, but results can be changed with those arguments/variables control commands. This kind of analysis relies heavily on preloaded function prototypes and the calling-convention, thus loading symbols can improve it. Moreover, after changing something we can rerun variables analysis with afva command. Quite often variables analysis is accompanied with types analysis, see afta command.

The most important aspect of reverse engineering - naming things. Of course, you can rename variable too, affecting all places it was referenced. This can be achieved with afvn for any type of argument or variable. Or you can simply remove the variable or argument with afv- command.

As mentioned before the analysis loop relies heavily on types information while performing variables analysis stages. Thus comes next very important command - afvt, which allows you to change the type of variable:

[0x00003b92]> afvs

var int local_8h @ rsp+0x8

var int local_10h @ rsp+0x10

var int local_28h @ rsp+0x28

var int local_30h @ rsp+0x30

var int local_32h @ rsp+0x32

var int local_38h @ rsp+0x38

var int local_45h @ rsp+0x45

var int local_46h @ rsp+0x46

var int local_47h @ rsp+0x47

var int local_48h @ rsp+0x48

[0x00003b92]> afvt local_10h char*

[0x00003b92]> afvs

var int local_8h @ rsp+0x8

var char* local_10h @ rsp+0x10

var int local_28h @ rsp+0x28

var int local_30h @ rsp+0x30

var int local_32h @ rsp+0x32