Introduction

Reverse engineering is the art of understanding how software works without access to its source code. Modern reverse engineering tools provide disassembly, decompilation, debugging, and scripting capabilities. This article compares four major platforms: Ghidra, IDA Free, radare2, and Binary Ninja.

Reverse Engineering Tools: Ghidra, IDA Free, radare2, Binary Ninja

Ghidra

NSA's open-source reverse engineering framework:

// Ghidra scripting API

import ghidra.app.script.GhidraScript;

import ghidra.program.model.listing.*;

import ghidra.program.model.symbol.*;

public class AnalyzeFunction extends GhidraScript {

@Override

public void run() throws Exception {

// Get the current program

Program program = getCurrentProgram();

Listing listing = program.getListing();

// Iterate over all functions

FunctionIterator functions = listing.getFunctions(true);

for (Function function : functions) {

println("Function: " + function.getName());

println(" Address: " + function.getEntryPoint());

println(" Body size: " + function.getBody().getNumAddresses());

// Check for imported functions

SymbolTable symTable = program.getSymbolTable();

ReferenceIterator refs = program.getReferenceManager()

.getReferencesTo(function.getEntryPoint());

while (refs.hasNext()) {

Reference ref = refs.next();

println(" Referenced by: " + ref.getFromAddress());

}

}

}

}

Key features :

  • Decompiler (produces C-like pseudocode from assembly)

  • Program tree and listing views

  • Cross-reference analysis (XREFs)

  • Version tracking (collaborative analysis)

  • Scripting in Java and Python (Jython)

  • Processor support: x86, x64, ARM, AARCH64, MIPS, PowerPC, RISC-V, 6502, 8051, and 50+ more

Ghidra Python script

from ghidra.program.model.symbol import SourceType

def find_string_refs(target_string):

for address in currentProgram.getListing().getDefinedData(True):

data = getDataAt(address)

if data and data.isString():

string_value = str(data.getDefaultValueRepresentation())

if target_string in string_value:

print(f"Found '{string_value}' at {address}")

refs = getReferencesTo(address)

for ref in refs:

print(f" Referenced from: {ref.getFromAddress()}")

Key strengths : Free and open-source, excellent decompiler, collaborative features, extensive processor support, active development.

IDA Free

Hex-Rays' industry-standard disassembler (free edition):

IDAPython scripting

import idautils

import ida_funcs

import ida_xref

def analyze_critical_functions():

for func_addr in idautils.Functions():

func = ida_funcs.get_func(func_addr)

name = ida_funcs.get_func_name(func_addr)

Identify functions with many cross-references

xref_count = len(list(idautils.CodeRefsTo(func_addr, 0)))

if xref_count > 20:

print(f"Hot function: {name} at {hex(func_addr)} ({xref_count} refs)")

Check if function references suspicious strings

for ref in idautils.XrefsFrom(func_addr):

if is_string(ref.to):

string_val = get_strlit_contents(ref.to)

if string_val and b"password" in string_val.lower():

print(f"Password reference in {name} at {hex(func_addr)}")

Rename subroutines based on string references

for addr, name in idautils.Names():

if name.startswith("sub_"):

refs = list(idautils.DataRefsTo(addr))

for ref in refs[:3]:

string_ref = get_strlit_contents(ref)

if string_ref:

idaapi.set_name(addr, f"sub_{string_ref[:16].decode('utf-8', errors='replace')}")

break

Key features : Industry-standard disassembly, cross-references (the best XREF system), IDAPython scripting, mature plugin ecosystem, compact database format.

Limitations of Free edition : No decompiler (Hex-Rays decompiler is paid), x86/x64 only, no collaborative features.

radare2

The most powerful command-line reverse engineering framework:

Open a binary

r2 ./binary

r2 -d ./binary # Debug mode

r2 -A ./binary # Analyze automatically

Common commands

aaaa # Full analysis

afl # List functions

afl ~main # Find main function

s main # Seek to main

pdf # Print disassembly of function

V # Visual mode (arrow keys to navigate)

VV # Graph view (control flow graph)

Searching

/ \x00\x00\x00 # Search for bytes

/v 42 # Search for value

/! popen # Search for string

wx 9090 # Write bytes (patch)

Analysis

afvn new_name var_4 # Rename local variable

afn new_name 0x401000 # Rename function

axt 0x401000 # Find XREFs to address

axf 0x401000 # Find XREFs from address

Output formats

pdf > output.asm # Save disassembly

pdr # Decompiled pseudocode (experimental)

Scripting (r2pipe)

r2 -q -c 'aaa; afl~main' ./binary

Binary Ninja

Modern reverse engineering platform with Python scripting:

import binaryninja as bn

Open binary

bv = bn.BinaryViewType.get_view_of_file("./binary")

bv.update_analysis()

Analyze functions

for func in bv.functions:

print(f"Function: {func.name} @ {hex(func.start)}")

print(f" Basic blocks: {len(func.basic_blocks)}")

print(f" Callers: {len(func.callers)}")

High-level IL

for block in func.high_level_il:

for instr in block:

print(f" HLIL: {instr}")

Medium-level IL (more detailed)

for block in func.medium_level_il:

for instr in block:

if "call" in str(instr).lower():

print(f" Call: {instr}")

Find all calls to a specific function

target = bv.get_function_at(bv.symbols["strcpy"][0].address)

for ref in target.callers:

caller = ref.function

print(f"strcpy called from: {caller.name} @ {hex(ref.address)}")

Data flow analysis

var = func.mlil.ssa_form[42].dest

uses = func.mlil.ssa_form.get_ssa_uses(var)

for use in uses:

print(f" Used at: {use.address}")

Comparison

| Feature | Ghidra | IDA Free | radare2 | Binary Ninja |

|---------|--------|----------|---------|--------------|

| Price | Free | Free | Free | $299-$999 |

| Decompiler | Excellent | None (paid) | Basic | Good |

| UI | GUI + Headless | GUI | CLI + Web GUI | GUI + CLI |

| Scripting | Java, Python | Python | Python, JS, Lua | Python, C++ |

| Processor support | 50+ | x86/x64 | 50+ | 20+ |

| Learning curve | High | High | Very high | Medium |

Recommendations

  • Starting reverse engineering : Ghidra provides the best free experience with its decompiler and user-friendly interface.

  • Quick analysis : IDA Free for rapid disassembly if you are already familiar with the IDA workflow.

  • Automation/scripting : Binary Ninja's clean Python API makes it ideal for automated analysis pipelines.

  • Power users : radare2 for the deepest control and command-line workflows.

  • Malware analysis : Ghidra with its decompiler and extensive processor support.

All four tools are capable of serious reverse engineering work. Ghidra offers the best free decompiler and the broadest platform support. Binary Ninja has the cleanest API for scripting. radare2 is unbeatable for command-line automation.