Angr & Pwn
by malweisse
vulnerability detection using symbolic execution
About me
Andrea Fioraldi [ @andreafioraldi, @malweisse on IRC ]
22 years old, student of Engineering in Computer Science.
Interested in binary analysis (symbolic execution, reversing and other pretty stuffs) and binary exploitation (do u know what is double free?).
Capturing flags with TheRomanXpl0it and mHACKeroni.
Not so much skilled trumpeter, mountain bike and trekking lover, Dragon Ball fanboy, homebrewer.
Symbolic execution
Angr crash course
Angr and the bugs
Concrete execution
Symbolic execution
Symbolic execution
Storage: c = 77
Storage: c = 77
Target: line 12
Symbolic execution
The interesting paths are 1.1 and 2.1 because they reached our target
Symbolic execution
solve(X + Y = 42 ∧ 77 − Y = 38)
X = 3, Y = 39
Symbolic execution (what about?)
Symbolic execution
Angr crash course
Angr and the bugs
Angr WTF
Angr is a binary analysis framework.
Binary loader, emulator, symbolic executor.
python3 -m pip install angr
Angr modules
Loading a binary
import angr�# load the example�project = angr.Project("./foo")� |
Simulation
# start a new SimulationManager�simgr = project.factory.simulation_manager()�# step�simgr.step()�# step until it branches�simgr.run(until=lambda sm: len(sm.active) != 1)�# check the states that are still active�print (simgr.active) |
States
state = simgr.active[0]��# a state has plugins, representing registers, memory, etc�print (state.regs.rax)�print (state.memory.load(state.regs.rsp, 8))�# one of the plugins represents the system state�print (state.posix.fd)�# files are backed by a memory region�print (state.posix.fd[0].read_data(8)) #return (value, size)�� |
Solver
state = simgr.active[0]��# SMT solver�print (state.solver)�addr = state.regs.rsp + 0x100 # each value in angr is represented as an expression tree�v = state.memory.load(addr, 8) + 0x10 print (v) print (v.op) # __add__ print (v.args) # (other bitvector, 0x10)�# add state constraints�state.add_constraints(v < 0x2a)�state.add_constraints(v > 0x1a)�# concretize a value�print (hex(state.solver.eval(v))) |
Simulation 2
# create a state starting on foo()�initial_state = project.factory.blank_state()�initial_state.regs.rip = 0x4005c7 # foo address # create symbolic args�a = initial_state.solver.BVS("sym_a", 64)�b = initial_state.solver.BVS("sym_b", 64)�initial_state.regs.rdi = a�initial_state.regs.rsi = b�# start a new SimulationManager based on initial_state�simgr = project.factory.simulation_manager(initial_state)�# explore using conditions�simgr.explore(find=0x400600, avoid=0x40060e) # well done, try again �print (simgr, simgr.found) # found stash�# conretize found inputs�print (a.args[0], "=", simgr.found[0].solver.eval(a))�print (b.args[0], "=", simgr.found[0].solver.eval(b)) |
Default Stashes
Symbolic execution
Angr crash course
Angr and the bugs
Stack Buffer Overflow
What is the purpose of a stack buffer overflow?
Control the program counter value overwriting the return address on the stack
Stack Buffer Overflow
DEMO
Thank you!
QUESTIONS?
References
USEFUL PAPERS:
BRIEF SUMMARY (the chapter 1 of my thesis):
MORE ABOUT ANGR