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


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.





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.