BARF. |
The BARF project includes BARF and related tools and packages. So far the project is composed of the following items:
- BARF : A multiplatform open source Binary Analysis and Reverse engineering Framework
- PyAsmJIT : A JIT for the Intel x86_64 and ARM architecture.
- Tools built upon BARF:
- BARFgadgets : Lets you search, classifiy and verify ROP gadgets inside a binary program.
- BARFcfg : Lets you recover the control-flow graph of the functions of a binary program.
- BARFcg : Lets you recover the call graph of the functions of a binary program.
For more information, see:
- BARF: A multiplatform open source Binary Analysis and Reverse engineering Framework (Whitepaper) [en]
- BARFing Gadgets (ekoparty2014 presentation)
Downloads Master.zip | Demo Install
Quickstart
This is a very simple example which shows how to open a binary file and print each instruction with its translation to the intermediate language (REIL).
from barf import BARF
# Open binary file.
barf = BARF("examples/bin/x86/branch1")
# Print assembly instruction.
for addr, asm_instr, reil_instrs in barf.translate():
print("0x{addr:08x} {instr}".format(addr=addr, instr=asm_instr))
# Print REIL translation.
for reil_instr in reil_instrs:
print("{indent:11s} {instr}".format(indent="", instr=reil_instr))
# Recover CFG.
cfg = barf.recover_cfg()
# Save CFG to a .dot file.
cfg.save("branch1_cfg")
We can check restrictions on code using a SMT solver. For instance, suppose you have the following code: 80483ed: 55 push ebp
80483ee: 89 e5 mov ebp,esp
80483f0: 83 ec 10 sub esp,0x10
80483f3: 8b 45 f8 mov eax,DWORD PTR [ebp-0x8]
80483f6: 8b 55 f4 mov edx,DWORD PTR [ebp-0xc]
80483f9: 01 d0 add eax,edx
80483fb: 83 c0 05 add eax,0x5
80483fe: 89 45 fc mov DWORD PTR [ebp-0x4],eax
8048401: 8b 45 fc mov eax,DWORD PTR [ebp-0x4]
8048404: c9 leave
8048405: c3 ret
And you want to know what values you have to assign to memory locations ebp-0x4, ebp-0x8 and ebp-0xc in order to obtain a specific value in eax register after executing the code.First, we add the instructions to the analyzer component.
from barf import BARF
# Open ELF file
barf = BARF("examples/bin/x86/constraint1")
# Add instructions to analyze.
for addr, asm_instr, reil_instrs in barf.translate(0x80483ed, 0x8048401):
for reil_instr in reil_instrs:
barf.code_analyzer.add_instruction(reil_instr)
Then, we generate expressions for each variable of interest# Get smt expression for eax and ebp registers
eap = barf.code_analyzer.get_register_expr("eax")
ebp = barf.code_analyzer.get_register_expr("ebp")
# Get smt expressions for memory locations (each one of 4 bytes)
a = barf.code_analyzer.get_memory_expr(ebp-0x8, 4)
b = barf.code_analyzer.get_memory_expr(ebp-0xc, 4)
c = barf.code_analyzer.get_memory_expr(ebp-0x4, 4)
And add the desired restrictions on them.
# Set range for variables
barf.code_analyzer.set_preconditions([a >= 2, a <= 100])
barf.code_analyzer.set_preconditions([b >= 2, b <= 100])
# Set desired value for the result
barf.code_analyzer.set_postcondition(c == 13)
Finally, we check is the restrictions we establish can be resolved.
# Check satisfiability.
if barf.code_analyzer.check() == 'sat':
print("SAT!")
# Get concrete value for expressions.
eax_val = barf.code_analyzer.get_expr_value(eax)
a_val = barf.code_analyzer.get_expr_value(a)
b_val = barf.code_analyzer.get_expr_value(b)
c_val = barf.code_analyzer.get_expr_value(c)
# Print values.
print("eax : 0x{0:%08x} ({0})".format(eax_val))
print("ebp : 0x{0:%08x} ({0})".format(ebp_val))
print(" a : 0x{0:%08x} ({0})".format(a_val))
print(" b : 0x{0:%08x} ({0})".format(b_val))
print(" c : 0x{0:%08x} ({0})".format(c_val))
else:
print("UNSAT!")
You can see these and more examples in the examples directory.