Ethical Hacking #radare2#reverse-engineering#binary-analysis

Radare2: Binary Analysis and Reverse Engineering

Learn Radare2 for binary analysis, disassembly, function analysis, comparison with Ghidra, and automation with r2pipe Python scripting.

7 min read

Reverse engineering is at the heart of malware analysis, vulnerability research, and CTF challenges. Radare2 (r2) is a free, open-source framework that handles binary analysis, disassembly, debugging, and patching across a wide range of architectures. It has a steep learning curve, but once you internalize its command language, it becomes one of the fastest tools available for deep binary work.

Installation

# Linux — recommended: install from source for latest version
git clone https://github.com/radareorg/radare2
cd radare2
sys/install.sh

# macOS
brew install radare2

# Kali Linux
sudo apt install radare2

# Verify
r2 -version

Opening a Binary

r2 /path/to/binary

By default, r2 opens the binary in read-only mode. To open for writing (patching):

r2 -w /path/to/binary

To open with auto-analysis:

r2 -A /path/to/binary

The -A flag runs aaa (analyze all) automatically — essential for understanding function boundaries and cross-references.

The r2 command language uses short prefixes that group related commands. The most important:

CommandAction
s <addr>Seek (navigate) to address
s mainSeek to main function
s sym.functionnameSeek to named function
pdfPrint disassembly of function
px 64Print 64 bytes as hex dump
pxw 32Print 32 bytes as hex words
psPrint string at current address
?Help for any command prefix

After analysis, list all functions:

[0x00401000]> afl

This shows every detected function with its address, size, and name. Grep through them:

[0x00401000]> afl~check

The ~ character is r2’s internal grep.

Analyzing Functions

Navigate to a function and disassemble it:

[0x00401000]> s main
[0x00401234]> pdf

pdf (print disassembly function) shows the full function with comments, labels, and cross-references. To see the function in a graph view:

[0x00401234]> VV

This opens an interactive graph where you can navigate basic blocks with arrow keys. Press q to exit.

To rename a function (helps when reversing stripped binaries):

[0x00401234]> afn my_decrypt_routine

To add a comment:

[0x00401234]> CCa 0x401240 "This checks the license key"

Cross-References (xrefs)

Understanding where functions are called from and what data they reference is critical:

# List all calls to the current function
[0x00401234]> axt

# List all data xrefs from a function
[0x00401234]> axf

Strings and Imports

# Find all strings in the binary
iz

# Find strings with "password" 
iz~password

# List imports
ii

# List exports
iE

# File info (architecture, bits, OS, etc.)
iI

Debugging with r2

r2 includes a built-in debugger:

r2 -d /path/to/binary arg1 arg2

Common debug commands:

dc          # continue execution
db 0x401234 # set breakpoint at address
db sym.main # set breakpoint at main
dbt         # print backtrace
dr          # print all registers
dr rax      # print specific register
dm          # show memory maps
dso         # step over
dsi         # step into

Radare2 vs. Ghidra

Both tools are free and powerful, but they serve different workflows:

FeatureRadare2Ghidra
InterfaceTerminal (+ Cutter GUI)Full Java GUI
Decompilerr2ghidra pluginBuilt-in
SpeedFaster on large binariesSlower startup
Scriptingr2pipe (Python, JS, Go)Python/Java API
CollaborationFile-basedProject sharing
Learning curveSteepModerate
Architecture supportExtensiveExtensive

Many reverse engineers use both: Ghidra for the decompiler view and r2 for fast CLI work and scripting. The r2ghidra plugin brings Ghidra’s decompiler into r2:

r2pm -ci r2ghidra
# Then use:
pdg  # decompile current function

r2pipe: Python Scripting

r2pipe lets you control a radare2 session from Python, enabling automation of repetitive analysis tasks.

pip install r2pipe

Example: Extract all strings and function names

import r2pipe
import json

r2 = r2pipe.open("/path/to/binary")
r2.cmd("aaa")  # analyze

# Get all functions as JSON
functions = json.loads(r2.cmd("aflj"))
for f in functions:
    print(f"Function: {f['name']} at {hex(f['offset'])} ({f['size']} bytes)")

# Get all strings
strings = json.loads(r2.cmd("izj"))
for s in strings:
    print(f"String at {hex(s['vaddr'])}: {s['string']}")

r2.quit()

Example: Automated vulnerability pattern detection

import r2pipe
import json

r2 = r2pipe.open("/path/to/binary")
r2.cmd("aaa")

# Find calls to dangerous functions
dangerous = ["strcpy", "sprintf", "gets", "strcat"]
for func in dangerous:
    result = r2.cmd(f"axt sym.imp.{func}")
    if result.strip():
        print(f"[!] Calls to {func} found:")
        print(result)

r2.quit()

Practical CTF Workflow

  1. Open with analysis: r2 -A ./challenge
  2. Check file type: iI
  3. List strings for hints: iz~flag
  4. Find main: s main; pdf
  5. Identify key decision points in graph view: VV
  6. Set breakpoints around comparisons, debug interactively
  7. Rename functions as you understand them: afn
  8. Use r2pipe to automate any repetitive analysis

Radare2 rewards investment. The first hour is frustrating; the tenth hour reveals why so many security researchers rely on it daily.

#disassembly #r2pipe #binary-analysis #reverse-engineering #radare2