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

0x100001a23 hit1_0 90

0x10000248f hit1_1 90

0x1000027b2 hit1_2 90

0x100002b2e hit1_3 90

0x1000032b8 hit1_4 90

0x100003454 hit1_5 90

0x100003468 hit1_6 90

0x10000355b hit1_7 90

0x100003647 hit1_8 90

0x1000037ac hit1_9 90

0x10000389c hit1_10 90

0x100003c5c hit1_11 90

[0x100001200]> /bx 90

[0x100001200]> s 0x10000355b

[0x10000355b]> /bx 90

0x100003468 hit3_0 90

0x100003454 hit3_1 90

0x1000032b8 hit3_2 90

0x100002b2e hit3_3 90

0x1000027b2 hit3_4 90

0x10000248f hit3_5 90

0x100001a23 hit3_6 90

[0x10000355b]>

If you want to search for a certain assembler opcodes, you can use /a commands.

The command /ad/ jmp [esp] searches for the specified category of assembly mnemonic:

[0x00404888]> /ad/ jmp qword [rdx]

f hit_0 @ 0x0040e50d # 2: jmp qword [rdx]

f hit_1 @ 0x00418dbb # 2: jmp qword [rdx]

f hit_2 @ 0x00418fcb # 3: jmp qword [rdx]

f hit_3 @ 0x004196ab # 6: jmp qword [rdx]

f hit_4 @ 0x00419bf3 # 3: jmp qword [rdx]

f hit_5 @ 0x00419c1b # 3: jmp qword [rdx]

f hit_6 @ 0x00419c43 # 3: jmp qword [rdx]

The command /a jmp eax assembles a string to machine code, and then searches for the resulting bytes:

[0x00404888]> /a jmp eax

hits: 1

0x004048e7 hit3_0 ffe00f1f8000000000b8

Thanks to Victor Muñoz, radare2 now has support of the algorithm he developed, capable of finding expanded AES keys with /Ca command. It searches from current seek position up to the search.distance limit, or until end of file is reached. You can interrupt current search by pressing Ctrl-C. For example, to look for AES keys in physical memory of your system:

$ sudo r2 /dev/mem

[0x00000000]> /ca

0 AES keys found

If you are simply looking for plaintext AES keys in your binary, /Ca will not find them, but you might want to search with is~AES instead if the programmer left those hints for you:

[0x00000000]> /Ca

Searching 0 byte in [0x100000-0x1f0000]

hits: 0

Searching 0 byte in [0x196e4-0x1b91c]

hits: 0

Searching 0 byte in [0x194b4-0x196e4]

hits: 0

Searching 0 byte in [0x8000-0x114b4]

hits: 0

[0x00000000]> is~AES

010 0x000096d4 0x000196d4 GLOBAL OBJ 16 AES_KEY

Other than that, AES keys might show up in different ways in the binary: encrypted, hidden by another encrypting routine, so there's no absolute way other than understanding the binary being analized. For instance, p=e might give some hints if high(er) entropy sections are found trying to cover up a hardcoded secret. As an example on entropy searching, since radare 3.2.0, there's the possibility to delimit entropy sections for later use like so:

[0x00000000]> b

0x100

[0x00000000]> b 4096

[0x00000000]> /s

0x00100000 - 0x00101000 ~ 5.556094

0x014e2c88 - 0x014e3c88 ~ 0.000000

0x01434374 - 0x01435374 ~ 6.332087

0x01435374 - 0x0144c374 ~ 3.664636

0x0144c374 - 0x0144d374 ~ 1.664368

0x0144d374 - 0x0144f374 ~ 4.229199

0x0144f374 - 0x01451374 ~ 2.000000

(...)

[0x00000000]> /s*

f entropy_section_0 0x00001000 0x00100000

f entropy_section_1 0x00001000 0x014e2c88

f entropy_section_2 0x00001000 0x01434374

f entropy_section_3 0x00017000 0x01435374

f entropy_section_4 0x00001000 0x0144c374

f entropy_section_5 0x00002000 0x0144d374

f entropy_section_6 0x00002000 0x0144f374

The blocksize is increased to 4096 bytes from the default 100 bytes so that the entropy search /s can work on reasonably sized chunks for entropy analysis. The sections flags can be applied with the dot operator, ./s* and then looped through px 32 @@ entropy*.

Moreover AES keys might be referenced from strings or pointed from the imports, for instance, so the / and other search-related commands can come in handy in this regard.

Disassembling in radare is just a way to represent an array of bytes. It is handled as a special print mode within p command.

In the old times, when the radare core was smaller, the disassembler was handled by an external rsc file. That is, radare first dumped current block into a file, and then simply called objdump configured to disassemble for Intel, ARM or other supported architectures.

It was a working and unix friendly solution, but it was inefficient as it repeated the same expensive actions over and over, because there were no caches. As a result, scrolling was terribly slow.

So there was a need to create a generic disassembler library to support multiple plugins for different architectures. We can list the current loaded plugins with

$ rasm2 -L

Or from inside radare2:

> e asm.arch=??

This was many years before capstone appeared. So r2 was using udis86 and olly disassemblers, many gnu (from binutils).

Nowadays, the disassembler support is one of the basic features of radare. It now has many options, endianness, including target architecture flavor and disassembler variants, among other things.

To see the disassembly, use the pd command. It accepts a numeric argument to specify how many opcodes of current block you want to see. Most of the commands in radare consider the current block size as the default limit for data input. If you want to disassemble more bytes, set a new block size using the b command.

[0x00000000]> b 100 ; set block size to 100

[0x00000000]> pd ; disassemble 100 bytes

[0x00000000]> pd 3 ; disassemble 3 opcodes

[0x00000000]> pD 30 ; disassemble 30 bytes

The pD command works like pd but accepts the number of input bytes as its argument, instead of the number of opcodes.

The "pseudo" syntax may be somewhat easier for a human to understand than the default assembler notations. But it can become annoying if you read lots of code. To play with it:

[0x00405e1c]> e asm.pseudo = true

[0x00405e1c]> pd 3

; JMP XREF from 0x00405dfa (fcn.00404531)

0x00405e1c 488b9424a80. rdx = [rsp+0x2a8]

0x00405e24 64483314252. rdx ^= [fs:0x28]

0x00405e2d 4889d8 rax = rbx

[0x00405e1c]> e asm.syntax = intel

[0x00405e1c]> pd 3

; JMP XREF from 0x00405dfa (fcn.00404531)

0x00405e1c 488b9424a80. mov rdx, [rsp+0x2a8]

0x00405e24 64483314252. xor rdx, [fs:0x28]

0x00405e2d 4889d8 mov rax, rbx

[0x00405e1c]> e asm.syntax=att

[0x00405e1c]> pd 3

; JMP XREF from 0x00405dfa (fcn.00404531)

0x00405e1c 488b9424a80. mov 0x2a8(%rsp), %rdx

0x00405e24 64483314252. xor %fs:0x28, %rdx

0x00405e2d 4889d8 mov %rbx, %rax

The typical work involved in reversing binary files makes powerful annotation capabilities essential. Radare offers multiple ways to store and retrieve such metadata.

By following common basic UNIX principles, it is easy to write a small utility in a scripting language which uses objdump, otool or any other existing utility to obtain information from a binary and to import it into radare. For example, take a look at idc2r.py shipped with radare2ida. To use it, invoke it as idc2r.py file.idc > file.r2. It reads an IDC file exported from an IDA Pro database and produces an r2 script containing the same comments, names of functions and other data. You can import the resulting 'file.r2' by using the dot . command of radare: