def test_files(): s = angr.SimState(arch='AMD64') s.posix.write(0, "HELLO", 5) s.posix.write(0, "WORLD", 5) assert s.posix.dumps(0) == "HELLOWORLD" s = angr.SimState(arch='AMD64') s.posix.write(0, "A" * 0x1000, 0x1000) assert s.posix.dumps(0) == "A" * 0x1000
def test_files(): s = angr.SimState(arch='AMD64') s.posix.get_fd(1).write_data(b"HELLO") s.posix.get_fd(1).write_data(b"WORLD") assert s.posix.dumps(1) == b"HELLOWORLD" assert s.posix.stdout.concretize() == [b"HELLO", b"WORLD"] s = angr.SimState(arch='AMD64') s.posix.get_fd(1).write_data(b"A" * 0x1000, 0x800) assert s.posix.dumps(1) == b"A" * 0x800
def test_concretization_strategies(): initial_memory = {0: b'A', 1: b'B', 2: b'C', 3: b'D'} s = angr.SimState(arch='AMD64', dict_memory_backer=initial_memory) # sanity check nose.tools.assert_equal( s.solver.eval_upto(s.memory.load(3, size=1), 2, cast_to=bytes), [b'D']) x = s.solver.BVS('x', s.arch.bits) s.add_constraints(x >= 1) s.add_constraints(x <= 3) ss = s.copy() nose.tools.assert_equal( tuple( sorted(ss.solver.eval_upto(ss.memory.load(x, 1), 10, cast_to=bytes))), (b'B', b'C', b'D')) ss = s.copy() x = s.solver.BVS('x', s.arch.bits) s.add_constraints(x >= 1) ss.options.add(angr.options.CONSERVATIVE_READ_STRATEGY) ss.memory._create_default_read_strategies() nose.tools.assert_true( 'symbolic' in next(iter(ss.memory.load(x, 1).variables)))
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState(project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory) # Execute each block state = blank_state for b in blocks: irsb = self.project.factory.default_engine.process(state, b, force_addr=next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr ) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) callfunc = cc.arg(state, 2) retaddr = state.memory.load(state.regs.sp, self.arch.bytes) all_exits = [ {'address': callfunc, 'jumpkind': 'Ijk_Call', 'namehint': 'thread_entry'}, {'address': retaddr, 'jumpkind': 'Ijk_Ret', 'namehint': None}, ] return all_exits
def dynamic_returns(self, blocks, **kwargs) -> bool: # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState( project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory, add_options={ angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY, angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS }) # Execute each block state = blank_state for b in blocks: irsb = self.project.factory.default_engine.process( state, irsb=b, force_addr=b.addr) if irsb.successors: state = irsb.successors[0] else: break # take a look at the first argument (status) cc = angr.DEFAULT_CC[self.arch.name](self.arch) ty = angr.sim_type.parse_signature( 'void x(int, int, char*)').with_arch(self.arch) args = cc.get_args(state, ty) if args[0].concrete and state.solver.eval(args[0]) == 0: return True return False
def test_registration(): s = angr.SimState(arch='AMD64') a1 = s.solver.BVS('a', 64, key=(1, ), eternal=True) a2 = s.solver.BVS('a', 64, key=(1, ), eternal=True) assert a1 is a2 b1 = s.solver.BVS('b', 64, key=(2, ), eternal=False) s1 = s.copy() s2 = s.copy() b2 = s1.solver.BVS('b', 64, key=(2, ), eternal=False) b3 = s2.solver.BVS('b', 64, key=(2, ), eternal=False) assert b1 is not b2 assert b2 is not b3 assert b1 is not b3 a3 = s1.solver.BVS('a', 64, key=(1, ), eternal=True) a4 = s2.solver.BVS('a', 64, key=(1, ), eternal=True) assert a2 is a3 assert a3 is a4 assert len(list(s.solver.get_variables(1))) == 1 assert len(list(s1.solver.get_variables(1))) == 1 assert len(list(s2.solver.get_variables(1))) == 1 assert len(list(s.solver.get_variables(2))) == 1 assert len(list(s1.solver.get_variables(2))) == 2 assert len(list(s2.solver.get_variables(2))) == 2 assert list(s.solver.describe_variables(a1)) == [(1, )] assert list(s.solver.describe_variables(b1)) == [(2, 1)] assert sorted(list(s.solver.describe_variables(a1 + b1))) == [(1, ), (2, 1)]
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState(project=self.project, mode="fastpath") # set up the stack pointer blank_state.regs.sp = 0x7fffffff # Execute each block state = blank_state for b in blocks: # state.regs.ip = next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr irsb = angr.SimEngineVEX().process(state, b, force_addr=next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) args = [ cc.arg(state, _) for _ in xrange(5) ] main, _, _, init, fini = self._extract_args(blank_state, *args) all_exits = [ (init, 'Ijk_Call'), (main, 'Ijk_Call'), (fini, 'Ijk_Call'), ] return all_exits
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState(project=self.project, mode="fastpath") # Execute each block state = blank_state for b in blocks: irsb = self.project.engines.default_engine.process(state, b, force_addr=next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr ) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) callfunc = cc.arg(state, 2) retaddr = state.memory.load(state.regs.sp, self.arch.bytes) all_exits = [ (callfunc, 'Ijk_Call'), (retaddr, 'Ijk_Ret') ] return all_exits
def test_file_unlink(): # Initialize a blank state with an arbitrary errno location state = angr.SimState(arch="AMD64", mode="symbolic") state.libc.errno_location = 0xa0000000 state.libc.errno = 0 # Create a file 'test' fd = state.posix.open(b'test', 1) state.posix.close(fd) # Ensure 'test' was in fact created assert b'/test' in state.fs._files # Store the filename in memory path_addr = 0xb0000000 state.memory.store(path_addr, b'test\x00') # Unlink 'test': should return 0 and leave ERRNO unchanged unlink = angr.SIM_PROCEDURES['posix']['unlink']() state.scratch.sim_procedure = unlink rval = unlink.execute(state, arguments=[path_addr]).ret_expr assert rval == 0 assert state.solver.eval(state.libc.errno) == 0 # Check that 'test' was in fact deleted assert state.fs._files == {} # Unlink again: should return -1 and set ERRNO to ENOENT unlink = angr.SIM_PROCEDURES['posix']['unlink']() state.scratch.sim_procedure = unlink rval = unlink.execute(state, arguments=[path_addr]).ret_expr assert rval == -1 assert state.solver.eval(state.libc.errno) == state.posix.ENOENT
def static_exits(self, blocks, **kwargs): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState( project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory) # Execute each block state = blank_state for b in blocks: irsb = self.project.factory.default_engine.process( state, b, force_addr=b.addr) if irsb.successors: state = irsb.successors[0] else: break callfunc = self.cc.get_args(state, self.prototype)[2] retaddr = state.memory.load(state.regs.sp, size=self.arch.bytes) all_exits = [ { 'address': callfunc, 'jumpkind': 'Ijk_Call', 'namehint': 'thread_entry' }, { 'address': retaddr, 'jumpkind': 'Ijk_Ret', 'namehint': None }, ] return all_exits
def test_registration(): s = angr.SimState(arch='AMD64') a1 = s.solver.BVS('a', 64, key=(1,), eternal=True) a2 = s.solver.BVS('a', 64, key=(1,), eternal=True) nose.tools.assert_is(a1, a2) b1 = s.solver.BVS('b', 64, key=(2,), eternal=False) s1 = s.copy() s2 = s.copy() b2 = s1.solver.BVS('b', 64, key=(2,), eternal=False) b3 = s2.solver.BVS('b', 64, key=(2,), eternal=False) nose.tools.assert_is_not(b1, b2) nose.tools.assert_is_not(b2, b3) nose.tools.assert_is_not(b1, b3) a3 = s1.solver.BVS('a', 64, key=(1,), eternal=True) a4 = s2.solver.BVS('a', 64, key=(1,), eternal=True) nose.tools.assert_is(a2, a3) nose.tools.assert_is(a3, a4) nose.tools.assert_equal(len(list(s.solver.get_variables(1))), 1) nose.tools.assert_equal(len(list(s1.solver.get_variables(1))), 1) nose.tools.assert_equal(len(list(s2.solver.get_variables(1))), 1) nose.tools.assert_equal(len(list(s.solver.get_variables(2))), 1) nose.tools.assert_equal(len(list(s1.solver.get_variables(2))), 2) nose.tools.assert_equal(len(list(s2.solver.get_variables(2))), 2) nose.tools.assert_equal(list(s.solver.describe_variables(a1)), [(1,)]) nose.tools.assert_equal(list(s.solver.describe_variables(b1)), [(2, 1)]) nose.tools.assert_equal(sorted(list(s.solver.describe_variables(a1 + b1))), [(1,), (2, 1)])
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState(project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory, add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY, angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS}) # set up the stack pointer blank_state.regs.sp = 0x7ffffff0 # Execute each block state = blank_state for b in blocks: irsb = self.project.factory.default_engine.process(state, irsb=b, force_addr=b.addr) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) ty = angr.sim_type.parse_signature('void x(void*, void*, void*, void*, void*)').with_arch(self.arch) args = cc.get_args(state, ty) main, _, _, init, fini = self._extract_args(blank_state, *args) all_exits = [ {'address': init, 'jumpkind': 'Ijk_Call', 'namehint': 'init'}, {'address': main, 'jumpkind': 'Ijk_Call', 'namehint': 'main'}, {'address': fini, 'jumpkind': 'Ijk_Call', 'namehint': 'fini'}, ] return all_exits
def test_unsat_core(): s = angr.SimState(arch='AMD64', mode='symbolic', add_options={angr.options.CONSTRAINT_TRACKING_IN_SOLVER}) x = s.solver.BVS('x', 32) s.add_constraints(s.solver.BVV(0, 32) == x) s.add_constraints(s.solver.BVV(1, 32) == x) assert not s.satisfiable() unsat_core = s.solver.unsat_core() assert len(unsat_core) == 2
def test_unsat_core(): s = angr.SimState(arch='AMD64', mode='symbolic', add_options={angr.options.CONSTRAINT_TRACKING_IN_SOLVER}) x = s.se.BVS('x', 32) s.add_constraints(s.se.BVV(0, 32) == x) s.add_constraints(s.se.BVV(1, 32) == x) nose.tools.assert_false(s.satisfiable()) unsat_core = s.se.unsat_core() nose.tools.assert_equal(len(unsat_core), 2)
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState( project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory, add_options={ angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY, angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS }) # set up the stack pointer blank_state.regs.sp = 0x7ffffff0 # Execute each block state = blank_state for b in blocks: # state.regs.ip = next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr irsb = self.project.factory.default_engine.process( state, b, force_addr=next( iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) args = [cc.arg(state, _) for _ in range(5)] main, _, _, init, fini = self._extract_args(blank_state, *args) all_exits = [ { 'address': init, 'jumpkind': 'Ijk_Call', 'namehint': 'init' }, { 'address': main, 'jumpkind': 'Ijk_Call', 'namehint': 'main' }, { 'address': fini, 'jumpkind': 'Ijk_Call', 'namehint': 'fini' }, ] return all_exits
def test_file_read_missing_content(): # test in tracing mode since the Reverse operator will not be optimized away s = angr.SimState(arch="AMD64", mode="tracing") fd = s.posix.open(b"/tmp/oops", Flags.O_RDWR) length = s.posix.get_fd(fd).read(0xC00000, 100) data = s.memory.load(0xC00000, length, endness="Iend_BE") assert ( data.op != "Reverse" ), "Byte strings read directly out of a file should not have Reverse operators." assert data.op == "BVS" assert len(data.variables) == 1 assert "oops" in next(iter(data.variables))
def test_gettimeofday(): proc = angr.SIM_PROCEDURES['posix']['gettimeofday']() s = angr.SimState(arch='amd64') s.regs.rdi = 0x8000 s.regs.rsi = 0 s.options.add(angr.options.USE_SYSTEM_TIMES) proc.execute(s) assert not s.mem[0x8000].qword.resolved.symbolic assert not s.mem[0x8008].qword.resolved.symbolic s.options.discard(angr.options.USE_SYSTEM_TIMES) proc.execute(s) assert s.mem[0x8000].qword.resolved.symbolic assert s.mem[0x8008].qword.resolved.symbolic
def test_file_read_missing_content(): # test in tracing mode since the Reverse operator will not be optimized away s = angr.SimState(arch='AMD64', mode="tracing") fd = s.posix.open(b"/tmp/oops", Flags.O_RDWR) length = s.posix.get_fd(fd).read(0xc00000, 100) data = s.memory.load(0xc00000, length, endness="Iend_BE") nose.tools.assert_not_equal( data.op, 'Reverse', "Byte strings read directly out of a file should not have Reverse " "operators.") nose.tools.assert_equal(data.op, "BVS") nose.tools.assert_equal(len(data.variables), 1) nose.tools.assert_in("oops", next(iter( data.variables))) # file name should be part of the variable name
def test_compatibility_layer(): s = angr.SimState(arch='AMD64', mode='symbolic') x = s.se.BVS('x', 32) s.add_constraints(x > 20) s.add_constraints(x < 40) nose.tools.assert_true(s.se.any_int(x) > 20) nose.tools.assert_true(s.se.any_int(x) < 40) nose.tools.assert_true(len(s.se.any_n_int(x, 100)), 19) y = s.se.BVS('y', 72) s.add_constraints(y == 0x696c6f766563617400) nose.tools.assert_true(s.se.any_str(y) == 'ilovecat\x00') nose.tools.assert_true(s.se.any_n_str(y, 2) == ['ilovecat\x00'])
def test_concretization_strategies(): initial_memory = {0: 'A', 1: 'B', 2: 'C', 3: 'D'} s = angr.SimState(arch='AMD64', memory_backer=initial_memory) # sanity check nose.tools.assert_equal(s.se.any_n_str(s.memory.load(3, 1), 2), ['D']) x = s.se.BVS('x', s.arch.bits) s.add_constraints(x >= 1) s.add_constraints(x <= 3) ss = s.copy() nose.tools.assert_equal( tuple(sorted(ss.se.any_n_str(ss.memory.load(x, 1), 10))), ('B', 'C', 'D')) ss = s.copy() x = s.se.BVS('x', s.arch.bits) s.add_constraints(x >= 1) ss.options.add(angr.options.CONSERVATIVE_READ_STRATEGY) ss.memory._create_default_read_strategies() nose.tools.assert_true( 'symbolic' in next(iter(ss.memory.load(x, 1).variables)))
def broken_symbolic_write(): s = angr.SimState(arch='AMD64', mode='symbolic') addr = s.se.BVS('addr', 64) s.add_constraints(s.se.Or(addr == 10, addr == 20, addr == 30)) nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) s.memory.store(10, s.se.BVV(1, 8)) s.memory.store(20, s.se.BVV(2, 8)) s.memory.store(30, s.se.BVV(3, 8)) nose.tools.assert_true(s.se.unique(s.memory.load(10, 1))) nose.tools.assert_true(s.se.unique(s.memory.load(20, 1))) nose.tools.assert_true(s.se.unique(s.memory.load(30, 1))) #print "CONSTRAINTS BEFORE:", s.constraints._solver.constraints #s.memory.store(addr, s.se.BVV(255, 8), strategy=['symbolic','any'], limit=100) s.memory.store(addr, s.se.BVV(255, 8)) nose.tools.assert_true(s.satisfiable()) print "GO TIME" nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(10, 1), 3), [1, 255]) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(20, 1), 3), [2, 255]) nose.tools.assert_items_equal(s.se.any_n_int(s.memory.load(30, 1), 3), [3, 255]) nose.tools.assert_equals(len(s.se.any_n_int(addr, 10)), 3) # see if it works when constraining the write address sa = s.copy() sa.add_constraints(addr == 20) nose.tools.assert_true(sa.satisfiable()) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(10, 1), 3), [1]) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(20, 1), 3), [255]) nose.tools.assert_items_equal(sa.se.any_n_int(sa.memory.load(30, 1), 3), [3]) nose.tools.assert_items_equal(sa.se.any_n_int(addr, 10), [20]) # see if it works when constraining a value to the written one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 255) nose.tools.assert_true(sv.satisfiable()) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(10, 1), 3), [1]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(20, 1), 3), [2]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(30, 1), 3), [255]) nose.tools.assert_items_equal(sv.se.any_n_int(addr, 10), [30]) # see if it works when constraining a value to the unwritten one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 3) nose.tools.assert_true(sv.satisfiable()) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(10, 1), 3), [1, 255]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(20, 1), 3), [2, 255]) nose.tools.assert_items_equal(sv.se.any_n_int(sv.memory.load(30, 1), 3), [3]) nose.tools.assert_items_equal(sv.se.any_n_int(addr, 10), [10, 20]) s = angr.SimState(arch='AMD64', mode='symbolic') s.memory.store(0, s.se.BVV(0x4141414141414141, 64)) length = s.se.BVS("length", 32) #s.memory.store(0, s.se.BVV(0x4242424242424242, 64), symbolic_length=length) s.memory.store(0, s.se.BVV(0x4242424242424242, 64)) for i in range(8): ss = s.copy() ss.add_constraints(length == i) nose.tools.assert_equal(ss.se.any_str(s.memory.load(0, 8)), "B" * i + "A" * (8 - i)) print "GROOVY"
def broken_symbolic_write(): s = angr.SimState(arch='AMD64', mode='symbolic') addr = s.solver.BVS('addr', 64) s.add_constraints(s.solver.Or(addr == 10, addr == 20, addr == 30)) assert len(s.solver.eval_upto(addr, 10)) == 3 s.memory.store(10, s.solver.BVV(1, 8)) s.memory.store(20, s.solver.BVV(2, 8)) s.memory.store(30, s.solver.BVV(3, 8)) assert s.solver.unique(s.memory.load(10, 1)) assert s.solver.unique(s.memory.load(20, 1)) assert s.solver.unique(s.memory.load(30, 1)) #print "CONSTRAINTS BEFORE:", s.constraints._solver.constraints #s.memory.store(addr, s.solver.BVV(255, 8), strategy=['symbolic','any'], limit=100) s.memory.store(addr, s.solver.BVV(255, 8)) assert s.satisfiable() assert len(s.solver.eval_upto(addr, 10)) == 3 assert s.solver.eval_upto(s.memory.load(10, 1), 3) == [1, 255] assert s.solver.eval_upto(s.memory.load(20, 1), 3) == [2, 255] assert s.solver.eval_upto(s.memory.load(30, 1), 3) == [3, 255] assert len(s.solver.eval_upto(addr, 10)) == 3 # see if it works when constraining the write address sa = s.copy() sa.add_constraints(addr == 20) assert sa.satisfiable() assert sa.solver.eval_upto(sa.memory.load(10, 1), 3) == [1] assert sa.solver.eval_upto(sa.memory.load(20, 1), 3) == [255] assert sa.solver.eval_upto(sa.memory.load(30, 1), 3) == [3] assert sa.solver.eval_upto(addr, 10) == [20] # see if it works when constraining a value to the written one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 255) assert sv.satisfiable() assert sv.solver.eval_upto(sv.memory.load(10, 1), 3) == [1] assert sv.solver.eval_upto(sv.memory.load(20, 1), 3) == [2] assert sv.solver.eval_upto(sv.memory.load(30, 1), 3) == [255] assert sv.solver.eval_upto(addr, 10) == [30] # see if it works when constraining a value to the unwritten one sv = s.copy() sv.add_constraints(sv.memory.load(30, 1) == 3) assert sv.satisfiable() assert sv.solver.eval_upto(sv.memory.load(10, 1), 3) == [1, 255] assert sv.solver.eval_upto(sv.memory.load(20, 1), 3) == [2, 255] assert sv.solver.eval_upto(sv.memory.load(30, 1), 3) == [3] assert sv.solver.eval_upto(addr, 10) == [10, 20] s = angr.SimState(arch='AMD64', mode='symbolic') s.memory.store(0, s.solver.BVV(0x4141414141414141, 64)) length = s.solver.BVS("length", 32) #s.memory.store(0, s.solver.BVV(0x4242424242424242, 64), symbolic_length=length) s.memory.store(0, s.solver.BVV(0x4242424242424242, 64)) for i in range(8): ss = s.copy() ss.add_constraints(length == i) assert ss.solver.eval(s.memory.load(0, 8), cast_to=bytes) == b"B" * i + b"A" * (8 - i)
def static_exits(self, blocks, cfg=None, **kwargs): # Execute those blocks with a blank state, and then dump the arguments blank_state = angr.SimState( project=self.project, mode="fastpath", cle_memory_backer=self.project.loader.memory, add_options={ angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY, angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS }) # set up the stack pointer blank_state.regs.sp = 0x7ffffff0 # special handling for x86 PIE GCC binaries # # 08049C70 xor ebp, ebp # 08049C72 pop esi # 08049C73 mov ecx, esp # 08049C75 and esp, 0FFFFFFF0h # 08049C78 push eax # 08049C79 push esp ; stack_end # 08049C7A push edx ; rtld_fini # 08049C7B call sub_8049CA3 // this is the get_pc function # // first block starts here # 08049C80 add ebx, (offset off_806B000 - $) # 08049C86 lea eax, (nullsub_2 - 806B000h)[ebx] # 08049C8C push eax ; fini # 08049C8D lea eax, (sub_805F530 - 806B000h)[ebx] # 08049C93 push eax ; init # 08049C94 push ecx ; ubp_av # 08049C95 push esi ; argc # 08049C96 mov eax, offset main # 08049C9C push eax ; main # 08049C9D call ___libc_start_main if cfg is not None and self.arch.name == "X86": first_block = blocks[0] first_node = cfg.model.get_any_node(first_block.addr) if first_node is not None: caller_nodes = cfg.model.get_predecessors( first_node, excluding_fakeret=False) if len(caller_nodes) == 1: caller_node = caller_nodes[0] succ_and_jks = caller_node.successors_and_jumpkinds() if len(succ_and_jks ) == 1 and succ_and_jks[0][1] == 'Ijk_Call': # get_pc getpc_func = cfg.functions.get_by_addr( succ_and_jks[0][0].addr) if getpc_func is not None and 'get_pc' in getpc_func.info: # GCC-generated x86-pie binary confirmed. # initialize the specified register with the block address get_pc_reg = getpc_func.info['get_pc'] setattr(blank_state.regs, "_" + get_pc_reg, first_block.addr) # Execute each block state = blank_state for b in blocks: irsb = self.project.factory.default_engine.process( state, irsb=b, force_addr=b.addr) if irsb.successors: state = irsb.successors[0] else: break cc = angr.DEFAULT_CC[self.arch.name](self.arch) ty = angr.sim_type.parse_signature( 'void x(void*, void*, void*, void*, void*)').with_arch(self.arch) args = cc.get_args(state, ty) main, _, _, init, fini = self._extract_args(blank_state, *args) all_exits = [ { 'address': init, 'jumpkind': 'Ijk_Call', 'namehint': 'init' }, { 'address': main, 'jumpkind': 'Ijk_Call', 'namehint': 'main' }, { 'address': fini, 'jumpkind': 'Ijk_Call', 'namehint': 'fini' }, ] return all_exits
# Athens 2019, Figure 2. # addi r3, r3, 0x1 # put X in r3, execute, find X+1 in r3 import angr import pyvex import archinfo import claripy import pdb arch = archinfo.ArchPPC32(archinfo.Endness.BE) s = angr.SimState(arch=arch, mode="symbolic") x = s.solver.BVS('X', 32, explicit_name=True) code = bytes(bytearray.fromhex("38630001")) # addi irsb = pyvex.IRSB(code, 0x100, arch, opt_level=0) irsb.pp() s.regs.r3 = x result = angr.SimEngineVEX().process(s, irsb).flat_successors[0] r3 = result.regs.r3 result.regs.__dir__() print "*************************" print r3