def run_calloc_multiplies(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) s.heap.malloc(30) sc = s.copy() s.heap.malloc(100) sc.heap.calloc(4, 25) nose.tools.assert_true(same_heap_states(s, sc))
def test_fullpage_write(): s = SimState(arch='AMD64') a = s.se.BVV('A'*0x2000) s.memory.store(0, a) #assert len(s.memory.mem._pages) == 2 #assert len(s.memory.mem._pages[0].keys()) == 0 #assert len(s.memory.mem._pages[1].keys()) == 0 assert s.memory.load(0, 0x2000) is a assert a.variables != s.memory.load(0x2000, 1).variables s = SimState(arch='AMD64') a = s.se.BVV('A'*2) s.memory.store(0x1000, a) s.memory.store(0x2000, a) assert a.variables == s.memory.load(0x2000, 1).variables assert a.variables == s.memory.load(0x2001, 1).variables assert a.variables != s.memory.load(0x2002, 1).variables s = SimState(arch='AMD64') x = s.se.BVV('X') a = s.se.BVV('A'*0x1000) s.memory.store(1, x) s2 = s.copy() s2.memory.store(0, a) assert len(s.memory.changed_bytes(s2.memory)) == 0x1000 s = SimState(arch='AMD64') s.memory._maximum_symbolic_size = 0x2000000 a = s.se.BVS('A', 0x1000000*8) s.memory.store(0, a) b = s.memory.load(0, 0x1000000) assert b is a
def run_unusable_amount_returns_null(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) s.heap.malloc(0x1000 - 4 * s.heap._chunk_size_t_size) sc = s.copy() p = s.heap.malloc(1) nose.tools.assert_equals(p, 0) nose.tools.assert_true(same_heap_states(s, sc))
def run_realloc_no_space_returns_null(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) p1 = s.heap.malloc(20) sc = s.copy() p2 = s.heap.realloc(p1, 0x2000) nose.tools.assert_equals(p2, 0) nose.tools.assert_true(same_heap_states(s, sc))
def test_memset(): l.info("concrete src, concrete dst, concrete len") s = SimState(arch="PPC32", mode="symbolic") dst = s.solver.BVV(0, 128) dst_addr = s.solver.BVV(0x1000, 32) char = s.solver.BVV(0x00000041, 32) char2 = s.solver.BVV(0x50505050, 32) length = s.solver.BVS("some_length", 32) s.memory.store(dst_addr, dst) memset(s, arguments=[dst_addr, char, s.solver.BVV(3, 32)]) nose.tools.assert_equal(s.solver.eval(s.memory.load(dst_addr, 4)), 0x41414100) l.debug("Symbolic length") s = SimState(arch="PPC32", mode="symbolic") s.memory.store(dst_addr, dst) length = s.solver.BVS("some_length", 32) memset(s, arguments=[dst_addr, char2, length]) l.debug("Trying 2") s_two = s.copy() s_two.add_constraints(length == 2) nose.tools.assert_equal(s_two.solver.eval(s_two.memory.load(dst_addr, 4)), 0x50500000) l.debug("Trying 0") s_zero = s.copy() s_zero.add_constraints(length == 0) nose.tools.assert_equal(s_zero.solver.eval(s_zero.memory.load(dst_addr, 4)), 0x00000000) l.debug("Trying 5") s_five = s.copy() s_five.add_constraints(length == 5) nose.tools.assert_equal(s_five.solver.eval(s_five.memory.load(dst_addr, 6)), 0x505050505000)
def test_symbolic_write(): s = SimState(arch='AMD64', add_options={o.SYMBOLIC_WRITE_ADDRESSES}) x = s.solver.BVS('x', 64) y = s.solver.BVS('y', 64) a = s.solver.BVV(b'A'*0x10) b = s.solver.BVV(b'B') c = s.solver.BVV(b'C') d = s.solver.BVV(b'D') s.memory.store(0x10, a) s.add_constraints(x >= 0x10, x < 0x20) s.memory.store(x, b) for i in range(0x10, 0x20): assert len(s.solver.eval_upto(s.memory.load(i, 1), 10)) == 2 s.memory.store(x, c) for i in range(0x10, 0x20): assert len(s.solver.eval_upto(s.memory.load(i, 1), 10)) == 2 s2 = s.copy() s2.add_constraints(y >= 0x10, y < 0x20) s2.memory.store(y, d) for i in range(0x10, 0x20): assert len(s2.solver.eval_upto(s2.memory.load(i, 1), 10)) == 3
def run_malloc_maximizes_sym_arg(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) sc = s.copy() x = s.solver.BVS("x", 32) s.solver.add(x.UGE(0)) s.solver.add(x.ULE(max_sym_var_val(s))) s.heap.malloc(x) sc.heap.malloc(max_sym_var_val(sc)) nose.tools.assert_true(same_heap_states(s, sc))
def run_free_null_preserves_state(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) s.heap.malloc(30) p = s.heap.malloc(40) s.heap.malloc(50) s.heap.free(p) s2 = s.copy() s2.heap.free(0) nose.tools.assert_true(same_heap_states(s, s2))
def run_realloc_near_same_size(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) s.heap.malloc(20) p1 = s.heap.malloc(61) s.heap.malloc(80) sc = s.copy() p2 = s.heap.realloc(p1, 62) nose.tools.assert_equals(p1, p2) nose.tools.assert_true(same_heap_states(s, sc))
def run_calloc_clears(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) s.memory.store(0xd0000000 + 2 * s.heap._chunk_size_t_size, s.solver.BVV(-1, 100 * 8)) sc = s.copy() p1 = s.heap.calloc(6, 5) p2 = sc.heap.malloc(30) v1 = s.memory.load(p1, 30) v2 = sc.memory.load(p2, 30) nose.tools.assert_true(s.solver.is_true(v1 == 0)) nose.tools.assert_true(sc.solver.is_true(v2 == -1))
def test_inline_strlen(): s = SimState(arch="AMD64", mode="symbolic") l.info("fully concrete string") a_str = s.solver.BVV(0x41414100, 32) a_addr = s.solver.BVV(0x10, 64) s.memory.store(a_addr, a_str, endness="Iend_BE") a_len = strlen(s, arguments=[a_addr]) nose.tools.assert_true(s.solver.unique(a_len)) nose.tools.assert_equal(s.solver.eval(a_len), 3) l.info("concrete-terminated string") b_str = s.solver.Concat(s.solver.BVS("mystring", 24), s.solver.BVV(0, 8)) b_addr = s.solver.BVV(0x20, 64) s.memory.store(b_addr, b_str, endness="Iend_BE") b_len = strlen(s, arguments=[b_addr]) nose.tools.assert_equal(s.solver.max_int(b_len), 3) nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(b_len, 10)), (0,1,2,3)) l.info("fully unconstrained") u_addr = s.solver.BVV(0x50, 64) u_len_sp = strlen(s, arguments=[u_addr]) u_len = u_len_sp nose.tools.assert_equal(len(s.solver.eval_upto(u_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.solver.max_int(u_len), s.libc.buf_symbolic_bytes-1) #print u_len_sp.solver.maximum_null #s.add_constraints(u_len < 16) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(0x50 + u_len, 1), 300), [0]) # # This tests if a strlen can influence a symbolic str. # l.info("Trying to influence length.") s = SimState(arch="AMD64", mode="symbolic") str_c = s.solver.BVS("some_string", 8*16) c_addr = s.solver.BVV(0x10, 64) s.memory.store(c_addr, str_c, endness='Iend_BE') c_len = strlen(s, arguments=[c_addr]) nose.tools.assert_equal(len(s.solver.eval_upto(c_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.solver.max_int(c_len), s.libc.buf_symbolic_bytes-1) one_s = s.copy() one_s.add_constraints(c_len == 1) nose.tools.assert_equal(one_s.solver.eval(str_c, cast_to=bytes).index(b'\x00'), 1) str_test = one_s.memory.load(c_addr, 2, endness='Iend_BE') nose.tools.assert_equal(len(one_s.solver.eval_upto(str_test, 300, cast_to=bytes)), 255) for i in range(16): test_s = s.copy() test_s.add_constraints(c_len == i) str_test = test_s.memory.load(c_addr, i + 1, endness='Iend_BE') nose.tools.assert_equal(test_s.solver.eval(str_test, cast_to=bytes).index(b'\x00'), i) for j in range(i): nose.tools.assert_false(test_s.solver.unique(test_s.memory.load(c_addr+j, 1)))
def test_store_simplification(): state = SimState(arch='X86') state.regs.esp = state.se.BVS('stack_pointer', 32) state.regs.ebp = state.se.BVS('base_pointer', 32) state.regs.eax = state.se.BVS('base_eax', 32) irsb = pyvex.IRSB('PT]\xc2\x10\x00', 0x4000, state.arch) sim_successors = SimEngineVEX().process(state.copy(), irsb) exit_state = sim_successors.all_successors[0] nose.tools.assert_true(claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp - 4))
def run_calloc_maximizes_sym_arg(arch): s = SimState(arch=arch, plugins={'heap': SimHeapPTMalloc(heap_base=0xd0000000, heap_size=0x1000)}) sc = s.copy() x = s.solver.BVS("x", 32) s.solver.add(x.UGE(0)) s.solver.add(x.ULE(20)) y = s.solver.BVS("y", 32) s.solver.add(y.UGE(0)) s.solver.add(y.ULE(6)) s.heap.calloc(x, y) sc.heap.calloc(20, 6) nose.tools.assert_true(same_heap_states(s, sc))
def test_mmap_base_copy(): state = SimState(arch="AMD64", mode="symbolic") mmap_base = 0x12345678 state.libc.mmap_base = mmap_base # Sanity check nose.tools.assert_equal(state.libc.mmap_base, mmap_base) state_copy = state.copy() nose.tools.assert_equal(state_copy.libc.mmap_base, mmap_base)
def test_aarch64_32bit_ccalls(): # GitHub issue #1238 s = SimState(arch="AArch64") x = s.solver.BVS("x", 32) # A normal operation flag_z, _ = s_ccall.arm64g_calculate_flag_z(s, s_ccall.ARM64G_CC_OP_ADD32, x, s.solver.BVV(1, 32), 0) nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 0,))) nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 1,))) # What VEX does flag_z, _ = s_ccall.arm64g_calculate_flag_z(s, s_ccall.ARM64G_CC_OP_ADD32, x.zero_extend(32), s.solver.BVV(1, 64), 0) nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 0,))) nose.tools.assert_true(s.satisfiable(extra_constraints=(flag_z == 1,)))
def test_global_condition(): s = SimState(arch="AMD64") s.regs.rax = 10 old_rax = s.regs.rax with s.with_condition(False): nose.tools.assert_false(s.se.satisfiable()) s.regs.rax = 20 nose.tools.assert_is(s._global_condition, None) nose.tools.assert_is(old_rax, s.regs.rax) with s.with_condition(True): s.regs.rax = 20 nose.tools.assert_is(s._global_condition, None) nose.tools.assert_is_not(old_rax, s.regs.rax) nose.tools.assert_is(s.se.BVV(20, s.arch.bits), s.regs.rax) with s.with_condition(s.regs.rbx != 0): s.regs.rax = 25 nose.tools.assert_is(s._global_condition, None) nose.tools.assert_is_not(s.se.BVV(25, s.arch.bits), s.regs.rax) with s.with_condition(s.regs.rbx != 1): s.regs.rax = 30 nose.tools.assert_is(s._global_condition, None) nose.tools.assert_is_not(s.se.BVV(30, s.arch.bits), s.regs.rax) with s.with_condition(s.regs.rbx == 0): nose.tools.assert_equals(s.se.eval_upto(s.regs.rbx, 10), [ 0 ]) nose.tools.assert_items_equal(s.se.eval_upto(s.regs.rax, 10), [ 30 ]) with s.with_condition(s.regs.rbx == 1): nose.tools.assert_equals(s.se.eval_upto(s.regs.rbx, 10), [ 1 ]) nose.tools.assert_items_equal(s.se.eval_upto(s.regs.rax, 10), [ 25 ])
def test_strchr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.solver.BVV(0x41424300, 32) str_needle = s.solver.BVV(0x42, 64) addr_haystack = s.solver.BVV(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, arguments=[addr_haystack, str_needle]) nose.tools.assert_true(s.solver.unique(ss_res)) nose.tools.assert_equal(s.solver.eval(ss_res), 0x11) l.info("concrete haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.solver.BVV(0x41424300, 32) str_needle = s.solver.BVS("wtf", 64) chr_needle = str_needle[7:0] addr_haystack = s.solver.BVV(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, arguments=[addr_haystack, str_needle]) nose.tools.assert_false(s.solver.unique(ss_res)) nose.tools.assert_equal(len(s.solver.eval_upto(ss_res, 10)), 5) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) nose.tools.assert_true(s_match.satisfiable()) nose.tools.assert_true(s_nomatch.satisfiable()) nose.tools.assert_equal(len(s_match.solver.eval_upto(chr_needle, 300)), 4) nose.tools.assert_equal(len(s_nomatch.solver.eval_upto(chr_needle, 300)), 252) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(ss_res, 300)), [ 0x10, 0x11, 0x12, 0x13 ]) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(chr_needle, 300)), [ 0x00, 0x41, 0x42, 0x43 ]) s_match.memory.store(ss_res, s_match.solver.BVV(0x44, 8)) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x10, 1), 300)), [ 0x41, 0x44 ]) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x11, 1), 300)), [ 0x42, 0x44 ]) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x12, 1), 300)), [ 0x43, 0x44 ]) nose.tools.assert_sequence_equal(sorted(s_match.solver.eval_upto(s_match.memory.load(0x13, 1), 300)), [ 0x00, 0x44 ]) return
def test_state_merge_3way(): a = SimState(arch='AMD64', mode='symbolic') b = a.copy() c = a.copy() conds = [ a.solver.BoolS('cond_0'), a.solver.BoolS('cond_1') ] a.add_constraints(conds[0]) b.add_constraints(a.solver.Not(conds[0]), conds[1]) c.add_constraints(a.solver.Not(conds[0]), a.solver.Not(conds[1])) a.memory.store(0x400000, a.solver.BVV(8, 32)) b.memory.store(0x400000, b.solver.BVV(9, 32)) c.memory.store(0x400000, c.solver.BVV(10, 32)) m, _, _ = a.merge(b) m, _, _ = m.merge(c) assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 8,)) assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 9,)) assert m.satisfiable(extra_constraints=(m.memory.load(0x400000, 4) == 10,))
def test_state_merge_static(): # With abstract memory # Aligned memory merging a = SimState(arch='AMD64', mode='static') addr = a.se.ValueSet(32, 'global', 0, 8) a.memory.store(addr, a.se.BVV(42, 32)) # Clear a_locs, so further writes will not try to merge with value 42 a.memory.regions['global']._alocs = { } b = a.copy() c = a.copy() a.memory.store(addr, a.se.BVV(50, 32), endness='Iend_LE') b.memory.store(addr, a.se.BVV(60, 32), endness='Iend_LE') c.memory.store(addr, a.se.BVV(70, 32), endness='Iend_LE') merged, _, _ = a.merge(b, c) actual = claripy.backends.vsa.convert(merged.memory.load(addr, 4)) expected = claripy.backends.vsa.convert(a.se.SI(bits=32, stride=10, lower_bound=50, upper_bound=70)) nose.tools.assert_true(actual.identical(expected))
def broken_sprintf(): l.info("concrete src, concrete dst, concrete len") s = SimState(mode="symbolic", arch="PPC32") format_str = s.solver.BVV(0x25640000, 32) format_addr = s.solver.BVV(0x2000, 32) #dst = s.solver.BVV("destination", 128) dst_addr = s.solver.BVV(0x1000, 32) arg = s.solver.BVS("some_number", 32) s.memory.store(format_addr, format_str) sprintf(s, arguments=[dst_addr, format_addr, arg]) for i in range(9): j = random.randint(10**i, 10**(i+1)) s2 = s.copy() s2.add_constraints(arg == j) #print s2.solver.eval_upto(s2.memory.load(dst_addr, i+2), 2, cast_to=bytes), repr(b"%d\x00" % j) nose.tools.assert_equal(s2.solver.eval_upto(s2.memory.load(dst_addr, i+2), 2, cast_to=bytes), [b"%d\x00" % j]) s2 = s.copy() s2.add_constraints(arg == 0) #print s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes), repr(b"%d\x00" % 0) nose.tools.assert_equal(s2.solver.eval_upto(s2.memory.load(dst_addr, 2), 2, cast_to=bytes), [b"%d\x00" % 0])
def test_state(): s = SimState(arch='AMD64') s.registers.store('sp', 0x7ffffffffff0000) nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7ffffffffff0000) s.stack_push(s.se.BVV("ABCDEFGH")) nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff8) s.stack_push(s.se.BVV("IJKLMNOP")) nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff0) a = s.stack_pop() nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7fffffffffefff8) nose.tools.assert_equals(s.se.eval(a, cast_to=str), "IJKLMNOP") b = s.stack_pop() nose.tools.assert_equals(s.se.eval(s.registers.load('sp')), 0x7ffffffffff0000) nose.tools.assert_equals(s.se.eval(b, cast_to=str), "ABCDEFGH")
def test_fullpage_write(): if os.environ.get("APPVEYOR", "false").lower() == "true": # Skip as AppVeyor boxes do not have enough memory to run this test raise nose.SkipTest() s = SimState(arch='AMD64') a = s.solver.BVV(b'A'*0x2000) s.memory.store(0, a) #assert len(s.memory.mem._pages) == 2 #assert len(s.memory.mem._pages[0].keys()) == 0 #assert len(s.memory.mem._pages[1].keys()) == 0 assert s.memory.load(0, 0x2000) is a assert a.variables != s.memory.load(0x2000, 1).variables s = SimState(arch='AMD64') a = s.solver.BVV(b'A'*2) s.memory.store(0x1000, a) s.memory.store(0x2000, a) assert a.variables == s.memory.load(0x2000, 1).variables assert a.variables == s.memory.load(0x2001, 1).variables assert a.variables != s.memory.load(0x2002, 1).variables s = SimState(arch='AMD64') x = s.solver.BVV(b'X') a = s.solver.BVV(b'A'*0x1000) s.memory.store(1, x) s2 = s.copy() s2.memory.store(0, a) assert len(s.memory.changed_bytes(s2.memory)) == 0x1000 s = SimState(arch='AMD64') s.memory._maximum_symbolic_size = 0x2000000 a = s.solver.BVS('A', 0x1000000*8) s.memory.store(0, a) b = s.memory.load(0, 0x1000000) assert b is a
def test_light_memory(): s = SimState(arch='AMD64', plugins={'registers': SimLightRegisters()}) assert type(s.registers) is SimLightRegisters assert s.regs.rax.symbolic s.regs.rax = 0x4142434445464748 assert (s.regs.rax == 0x4142434445464748).is_true() assert s.regs.rbx.symbolic s.regs.rbx = 0x5555555544444444 assert (s.regs.rbx == 0x5555555544444444).is_true() assert s.regs.rcx.symbolic s.regs.ah = 0 assert (s.regs.rax == 0x4142434445460048).is_true() s.regs.cl = 0 assert s.regs.rcx.symbolic
def test_wcscmp(): # concrete cases for the wide char version sufficiently overlap with strcmp and friends l.info("concrete a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") heck = 'heck\x00'.encode('utf-16')[2:] # remove encoding prefix a_addr = s.solver.BVV(0x10, 64) b_addr = s.solver.BVV(0xb0, 64) b_bvs = s.solver.BVS('b', len(heck) * 8) s.memory.store(a_addr, heck) s.memory.store(b_addr, b_bvs) r = wcscmp(s, arguments=[a_addr, b_addr]) solutions = s.solver.eval_upto(b_bvs, 2, cast_to=bytes, extra_constraints=(r == 0, )) nose.tools.assert_equal(solutions, [heck])
def test_getchar(): s = SimState(arch='AMD64', mode='symbolic') stdin = s.posix.files[0] stdin.content.store(0, "1234") nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [0]) c = getchar(s, arguments=[]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x31]) nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [1]) c = getchar(s, arguments=[]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x32]) nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [2]) c = getchar(s, arguments=[]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x33]) nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [3]) c = getchar(s, arguments=[]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 300), [0x34]) nose.tools.assert_items_equal(s.se.any_n_int(stdin.pos, 300), [4])
def test_struct_bitfield_complex(): bitfield_struct2 = angr.types.parse_type("""struct bitfield_struct2 { uint64_t target : 36, high8 : 8, reserved : 7, next : 12, bind : 1; }""") angr.types.register_types(bitfield_struct2) state = SimState(arch="AMD64") state.memory.store(0x1000, b"\xb3\xc7\xe9|\xad\xd7\xee$") # store some random data struct = state.mem[0x1000].struct.bitfield_struct2.concrete assert struct.target == 0xD7CE9C7B3 assert struct.high8 == 0x7A assert struct.next == 0x49D assert struct.bind == 0 pass
def test_alignment(): for arch in all_arches: if arch.name in DEFAULT_CC: # There is nothing to test for soot about stack alignment if isinstance(arch, ArchSoot): continue l.info("Testing stack alignment for %s", arch.name) st = SimState(arch=arch) cc = DEFAULT_CC[arch.name](arch=arch) st.regs.sp = -1 # setup callsite with one argument (0x1337), "returning" to 0 cc.setup_callsite(st, 0, [0x1337]) # ensure stack alignment is correct nose.tools.assert_true( st.solver.is_true(((st.regs.sp + cc.STACKARG_SP_DIFF) % cc.STACK_ALIGNMENT == 0)), 'non-zero stack alignment after setup_callsite for %s' % cc)
def test_struct_bitfield_complex(): bitfield_struct2 = angr.types.parse_type("""struct bitfield_struct2 { uint64_t target : 36, high8 : 8, reserved : 7, next : 12, bind : 1; }""") angr.types.register_types(bitfield_struct2) state = SimState(arch='AMD64') state.memory.store(0x1000, b'\xb3\xc7\xe9|\xad\xd7\xee$') # store some random data struct = state.mem[0x1000].struct.bitfield_struct2.concrete nose.tools.assert_equal(struct.target, 0xD7CE9C7B3) nose.tools.assert_equal(struct.high8, 0x7A) nose.tools.assert_equal(struct.next, 0x49D) nose.tools.assert_equal(struct.bind, 0) pass
def excption_0(): import claripy ins_code = "mov eax,-1 ; test eax,eax" address = 0x76fcbcfe encoding = pwn.asm(ins_code) count = len(encoding) print((str(encoding))) print(count) add_options = {angr.options.NO_SYMBOLIC_SYSCALL_RESOLUTION, angr.options.LAZY_SOLVES, angr.options.INITIALIZE_ZERO_REGISTERS, angr.options.SIMPLIFY_REGISTER_WRITES, angr.options.SIMPLIFY_MEMORY_WRITES, # angr.options.CONCRETIZE, # angr.options.FAST_MEMORY } bc_arr = "" bc_arr = encoding irsb = pyvex.IRSB(bc_arr, 0x76fcbcfe, archinfo.ArchX86(), len(bc_arr)) state = SimState(arch='X86', add_options=add_options) state.regs.eax = 0x5a4d state.regs.esi = 0x753e0001 state.regs.esp = 0x12f8c0 state.regs.eip = 0x76fcbcfe taint_len = 0x8000 # taint_len = 0xd4000 state.memory.store(0x753e0000, claripy.BVS( "TAINT_MapView", taint_len * 8), endness="Iend_LE") engine = angr.SimEngineVEX() irsb.pp() engine.process(state, irsb, inline=True)
def test_calling_conventions(): # # SimProcedures # from angr.calling_conventions import SimCCCdecl, SimCCMicrosoftFastcall args = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000, 100000, 1000000, 2000000, 14, 15, 16 ] arches = [ ('X86', SimCCCdecl), ('X86', SimCCMicrosoftFastcall), ('AMD64', None), ('ARMEL', None), ('MIPS32', None), ('PPC32', None), ('PPC64', None), ] # x86, cdecl for arch, cc in arches: s = SimState(arch=arch) for reg, val, _, _ in s.arch.default_register_values: s.registers.store(reg, val) if cc is not None: manyargs = SIM_PROCEDURES['testing']['manyargs']( cc=cc(s.arch)).execute(s) else: manyargs = SIM_PROCEDURES['testing']['manyargs']().execute(s) # Simulate a call if s.arch.call_pushes_ret: s.regs.sp = s.regs.sp + s.arch.stack_change manyargs.set_args(args) for index, arg in enumerate(args): nose.tools.assert_true( s.solver.is_true(manyargs.arg(index) == arg))
def test_pwrite(): pwrite = SIM_PROCEDURES['posix']['pwrite64']() state = SimState(arch="AMD64", mode='symbolic') simfile = SimFile('concrete_file', content='hello world!\n') state.fs.insert('test', simfile) fd = state.posix.open(b"test", 1) buf_addr = 0xd0000000 state.memory.store(buf_addr, b'test!') pwrite.execute(state, arguments=[fd, buf_addr, 5, 6]) simfd = state.posix.get_fd(fd) simfd.seek(0) res = 0xc0000000 simfd.read(res, 13) data = state.solver.eval(state.mem[res].string.resolved, cast_to=bytes) nose.tools.assert_true(data == b'hello test!!\n') state.posix.close(fd)
def simprocedure(self, state: angr.SimState): proc = state.inspect.simprocedure if proc is None: # Handle syscall SimProcedures log.debug("Reached a syscall SimProcedure") return proc_name = proc.display_name if proc_name not in self.functions_monitored: return if "external_c&c" not in state.globals: state.globals["external_c&c"] = {} if proc_name == "InternetOpenUrlA": handle = proc.handle url_ptr = proc.arg(1) try: url = get_string_a(state, url_ptr) except SimUnsatError: url = None if "open_url" not in state.globals["external_c&c"]: state.globals["external_c&c"]["open_url"] = {} state.globals["external_c&c"]["open_url"][handle] = (url, url_ptr) elif proc_name == "InternetOpenUrlW": handle = proc.handle url_ptr = proc.arg(1) try: url = get_string_w(state, url_ptr) except SimUnsatError: url = None if "open_url" not in state.globals["external_c&c"]: state.globals["external_c&c"]["open_url"] = {} state.globals["external_c&c"]["open_url"][handle] = (url, url_ptr) elif proc_name == "InternetReadFile": handle = proc.arg(0) try: handle = state.solver.eval(handle, cast_to=int, exact=True) except SimUnsatError: handle = None # bufptr = proc.arg(1) # bufsz = proc.arg(2) if "read_file" not in state.globals["external_c&c"]: state.globals["external_c&c"]["read_file"] = [] state.globals["external_c&c"]["read_file"].append(handle) self._analyze(state)
def test_getc(): s = SimState(arch='AMD64', mode='symbolic') stdin = s.posix.files[0] stdin.content.store(0, "1234") nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [0]) # The argument of getc should be a FILE * c = getc(s, arguments=[0]).ret_expr nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x31]) nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [1]) c = getc(s, arguments=[0]).ret_expr nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x32]) nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [2]) c = getc(s, arguments=[0]).ret_expr nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x33]) nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [3]) c = getc(s, arguments=[0]).ret_expr nose.tools.assert_items_equal(s.se.eval_upto(c, 300), [0x34]) nose.tools.assert_items_equal(s.se.eval_upto(stdin.pos, 300), [4])
def test_strchr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BVV(0x41424300, 32) str_needle = s.se.BVV(0x42, 64) addr_haystack = s.se.BVV(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, arguments=[addr_haystack, str_needle]).ret_expr nose.tools.assert_true(s.se.unique(ss_res)) nose.tools.assert_equal(s.se.any_int(ss_res), 0x11) l.info("concrete haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BVV(0x41424300, 32) str_needle = s.se.BVS("wtf", 64) chr_needle = str_needle[7:0] addr_haystack = s.se.BVV(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, arguments=[addr_haystack, str_needle]).ret_expr nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_equal(len(s.se.any_n_int(ss_res, 10)), 4) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) nose.tools.assert_true(s_match.satisfiable()) nose.tools.assert_true(s_nomatch.satisfiable()) nose.tools.assert_equal(len(s_match.se.any_n_int(chr_needle, 300)), 3) nose.tools.assert_equal(len(s_nomatch.se.any_n_int(chr_needle, 300)), 253) nose.tools.assert_items_equal(s_match.se.any_n_int(ss_res, 300), [0x10, 0x11, 0x12]) nose.tools.assert_items_equal(s_match.se.any_n_int(chr_needle, 300), [0x41, 0x42, 0x43]) s_match.memory.store(ss_res, s_match.se.BVV(0x44, 8)) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x10, 1), 300), [0x41, 0x44]) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x11, 1), 300), [0x42, 0x44]) nose.tools.assert_items_equal( s_match.se.any_n_int(s_match.memory.load(0x12, 1), 300), [0x43, 0x44]) return
def test_pread(): pwrite = SIM_PROCEDURES['posix']['pread64']() state = SimState(arch="AMD64", mode='symbolic') simfile = SimFile('concrete_file', content='hello world!\n') state.fs.insert('test', simfile) fd = state.posix.open(b"test", 1) buf1_addr = 0xd0000000 buf2_addr = 0xd0001000 pwrite.execute(state, arguments=[fd, buf1_addr, 6, 6]) pwrite.execute(state, arguments=[fd, buf2_addr, 5, 0]) data1 = state.solver.eval(state.mem[buf1_addr].string.resolved, cast_to=bytes) data2 = state.solver.eval(state.mem[buf2_addr].string.resolved, cast_to=bytes) nose.tools.assert_true(data1 == b'world!') nose.tools.assert_true(data2 == b'hello') state.posix.close(fd)
def simprocedure(self, state: angr.SimState): # Init globals if "key_spying" not in state.globals: state.globals["key_spying"] = defaultdict(list) # Handle procedure proc = state.inspect.simprocedure if proc is None: # Handle syscall SimProcedures log.debug("Reached a syscall SimProcedure") return proc_name = proc.display_name if proc_name == "RegisterHotKey": state.globals["key_spying"]["RegisterHotKey"].append(proc.arg(0)) elif proc_name == "SetWindowsHookExA" or proc_name == "SetWindowsHookExW": state.globals["key_spying"]["SetWindowsHookEx"].append(proc.arg(0)) elif proc_name == "GetMessageA" or proc_name == "GetMessageW": # Final function in sequence self._analyze(state, proc.arg(1))
def test_hex_dump(): s = SimState(arch='AMD64') addr = s.heap.allocate(0x20) s.memory.store( addr, claripy.Concat( claripy.BVV('ABCDEFGH'), claripy.BVS('symbolic_part', 24 * s.arch.bits) ) ) dump = s.memory.hex_dump(addr, 0x20) assert dump == 'c0000000: 41424344 45464748 ???????? ???????? ABCDEFGH????????\n'\ 'c0000010: ???????? ???????? ???????? ???????? ????????????????\n' dump = s.memory.hex_dump( addr, 0x20, extra_constraints=(s.memory.load(addr+0x10, 4) == 0xdeadbeef,), solve=True, endianness='Iend_LE' ) assert dump == 'c0000000: 44434241 48474645 ???????? ???????? ABCDEFGH????????\n' 'c0000010: efbeadde ???????? ???????? ???????? ....????????????\n'
def __init__(self, project, addr, state=None, taint_region=None): self.project = project self.addr = addr self.block_addr = addr self.taint_region = taint_region self.state = state self.tempstore = None self.tags = [] self.write_targets = [] if self.state is None: self.state = SimState(arch=project.arch, mode='symbolic', special_memory_filler=lambda name, bits, _state: BiHead(claripy.BVV(0, bits), claripy.BVV(0, bits)), add_options={sim_options.ABSTRACT_MEMORY, sim_options.SPECIAL_MEMORY_FILL} ) self.state.scratch.ins_addr = 0 if project.arch.name.startswith('ARM'): it = self.state.regs.itstate it.taints['it'] = True self.state.regs.itstate = it
def test_strcpy(): l.info("concrete src, concrete dst") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.solver.BVV(0x41414100, 32) dst_addr = s.solver.BVV(0x1000, 64) src = s.solver.BVV(0x42420000, 32) src_addr = s.solver.BVV(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strcpy(s, arguments=[dst_addr, src_addr]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') assert s.solver.eval(new_dst, cast_to=bytes) == b"BB\x00\x00" l.info("symbolic src, concrete dst") dst = s.solver.BVV(0x41414100, 32) dst_addr = s.solver.BVV(0x1000, 64) src = s.solver.BVS("src", 32) src_addr = s.solver.BVV(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) ln = strlen(s, arguments=[src_addr]) strcpy(s, arguments=[dst_addr, src_addr]) cm = strcmp(s, arguments=[dst_addr, src_addr]) s.add_constraints(cm == 0) s.add_constraints(ln == 15)
def simprocedure(self, state: angr.SimState): """ Tracks all SimProcedure calls and checks if it is calling a monitored function """ proc = state.inspect.simprocedure if proc is None: # Handle syscall SimProcedures log.debug("Reached a syscall SimProcedure") return proc_name = proc.display_name if proc_name not in self.functions_monitored: return if "file_exfiltration" not in state.globals: state.globals["file_exfiltration"] = defaultdict(list) if proc_name == "OpenFile": data = {"return": state.inspect.simprocedure_result} state.globals["file_exfiltration"]["OpenFile"].append(data) elif proc_name == "ReadFile": data = { "lpBytesRead": state.memory.load(proc.arg(3), disable_actions=True, inspect=False) } state.globals["file_exfiltration"]["ReadFile"].append(data) elif proc_name == "Send": data = { "buf": state.memory.load(proc.arg(1), disable_actions=True, inspect=False) } state.globals["file_exfiltration"]["Send"].append(data) self._analyze(state)
def test_lseek_unseekable(): state = SimState(arch="AMD64", mode="symbolic") # Illegal seek current_pos = lseek(state, [0, 0, SEEK_SET]).ret_expr current_pos = state.se.eval(current_pos) # Assert we have a negative return value nose.tools.assert_true(current_pos & (1 << 63) != 0) # Illegal seek current_pos = lseek(state, [1, 0, SEEK_SET]).ret_expr current_pos = state.se.eval(current_pos) # Assert we have a negative return value nose.tools.assert_true(current_pos & (1 << 63) != 0) # Illegal seek current_pos = lseek(state, [2, 0, SEEK_SET]).ret_expr current_pos = state.se.eval(current_pos) # Assert we have a negative return value nose.tools.assert_true(current_pos & (1 << 63) != 0)
def test_loadg_no_constraint_creation(): state = SimState(arch='armel', mode='symbolic') from angr.engines.vex.statements.loadg import SimIRStmt_LoadG state.scratch.temps[1] = state.solver.BVS('tmp_1', 32) stmt = pyvex.IRStmt.LoadG('Iend_LE', 'ILGop_16Uto32', pyvex.IRExpr.Const(pyvex.const.U32(0x1000)), pyvex.IRExpr.Const(pyvex.const.U32(0x2000)), pyvex.IRExpr.Const(pyvex.const.U32(0x1337)), pyvex.IRExpr.RdTmp(1) # guard ) tyenv = pyvex.IRTypeEnv(state.arch) tyenv.types = [ None, 'Ity_I32' ] state.scratch.tyenv = tyenv loadg = SimIRStmt_LoadG(stmt, state) loadg._execute() # LOADG should not create new constraints - it is a simple conditional memory read. The conditions should only be # used inside the value AST to guard the memory read. assert not state.solver.constraints
def test_lseek_unseekable(self): state = SimState(arch="AMD64", mode="symbolic") # Illegal seek current_pos = lseek(state,[0,0,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # Assert we have a negative return value assert current_pos & (1 << 63) != 0 # Illegal seek current_pos = lseek(state,[1,0,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # Assert we have a negative return value assert current_pos & (1 << 63) != 0 # Illegal seek current_pos = lseek(state,[2,0,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # Assert we have a negative return value assert current_pos & (1 << 63) != 0
def test_multivalued_list_page(): state = SimState(arch='AMD64', mode='symbolic', plugins={'memory': MultiValuedMemory()}) # strong update state.memory.store(0x100, claripy.BVV(0x40, 64)) state.memory.store(0x100, claripy.BVV(0x80818283, 64)) a = state.memory.load(0x100, size=8).one_value() assert a is not None assert a is claripy.BVV(0x80818283, 64) # strong update with partial overwrites state.memory.store(0x100, claripy.BVV(0x0, 64)) state.memory.store(0x104, claripy.BVV(0x1337, 32)) a = state.memory.load(0x100, size=8).one_value() assert a is not None assert a is claripy.BVV(0x1337, 64) # weak updates state.memory.store(0x120, claripy.BVV(0x40, 64)) state.memory.store(0x120, claripy.BVV(0x85868788, 64), weak=True) a = state.memory.load(0x120, size=8) assert len(a.values) == 1 assert 0 in a.values assert len(a.values[0]) == 2 assert set(state.solver.eval_exact(item, 1)[0] for item in a.values[0]) == { 0x40, 0x85868788 } # weak updates with symbolic values A = claripy.BVS("a", 64) state.memory.store(0x140, A, endness=state.arch.memory_endness) state.memory.store(0x141, claripy.BVS("b", 64), endness=state.arch.memory_endness, weak=True) a = state.memory.load(0x140, size=8) assert len(a.values) == 2 assert 0 in a.values assert 1 in a.values assert len(a.values[0]) == 1 assert next(iter(a.values[0])) is A[7:0] assert len(a.values[1]) == 2
def test_strstr_inconsistency(): l.info("symbolic haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") s.libc.buf_symbolic_bytes = 2 addr_haystack = s.solver.BVV(0x10, 64) addr_needle = s.solver.BVV(0xb0, 64) #len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, arguments=[addr_haystack, addr_needle]) #slh_res = strlen(s, inline=True, arguments=[addr_haystack]) #sln_res = strlen(s, inline=True, arguments=[addr_needle]) #print "LENH:", s.solver.eval_upto(slh_res, 100) #print "LENN:", s.solver.eval_upto(sln_res, 100) assert not s.solver.unique(ss_res) assert sorted(s.solver.eval_upto(ss_res, 100)) == [0] + list(range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1)) s.add_constraints(ss_res != 0) ss2 = strstr(s, arguments=[addr_haystack, addr_needle]) s.add_constraints(ss2 == 0) assert not s.satisfiable()
def test_lseek_set(self): state = SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file state.fs.insert('/tmp/qwer', SimFile(name='qwer', size=100)) assert fd == state.posix.open(b'/tmp/qwer', 2) # Part 1 # Seek to the top of the file current_pos = lseek(state,[fd,0,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # We should be at the start assert current_pos == 0 # Part 2 # Seek to the top of the file current_pos = lseek(state,[fd,8,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # We should be at the start assert current_pos == 8 # Part 3 # Seek to the top of the file current_pos = lseek(state,[fd,3,SEEK_SET]).ret_expr current_pos = state.solver.eval(current_pos) # We should be at the start assert current_pos == 3
def checkUAF(cur_state: angr.SimState): # has not FREE yet if "FREE_LIST" not in cur_state.globals: cur_state.globals["ACTS_BEFORE_FREE"] = [ act for act in reversed(cur_state.history.actions.hardcopy) ] # after FREE occured else: new_actions = [ act for act in reversed(cur_state.history.actions.hardcopy) if act not in cur_state.globals["ACTS_BEFORE_FREE"] ] for act in new_actions: if (act.type == 'mem') \ and (act.action == 'read' or act.action == 'write') \ and (act.actual_addrs[0] in cur_state.globals["FREE_LIST"]) \ and not isSimilarPath([bbl_addr for bbl_addr in cur_state.history.bbl_addrs], paths_with_bug, ratio=0.95): log("USE AFTER FREE detected! IO dump :", RED) print("{}< stdin >{}\n".format(DRED, RST), cur_state.posix.dumps(0)) print("{}< stdout >{}\n".format(DRED, RST), cur_state.posix.dumps(1).decode()) paths_with_bug.append( [bbl_addr for bbl_addr in cur_state.history.bbl_addrs])
def test_crosspage_store(): for memcls in [UltraPageMemory, ListPageMemory]: state = SimState(arch='x86', mode='symbolic', plugins={'memory': memcls()}) state.regs.sp = 0xbaaafffc state.memory.store(state.regs.sp, b"\x01\x02\x03\x04" + b"\x05\x06\x07\x08") assert state.solver.eval(state.memory.load(state.regs.sp, 8)) == 0x0102030405060708 state.memory.store(state.regs.sp, b"\x01\x02\x03\x04" + b"\x05\x06\x07\x08", endness='Iend_LE') assert state.solver.eval(state.memory.load(state.regs.sp, 8)) == 0x0807060504030201 symbol = claripy.BVS('symbol', 64) state.memory.store(state.regs.sp, symbol) assert state.memory.load(state.regs.sp, 8) is symbol state.memory.store(state.regs.sp, symbol, endness='Iend_LE') assert state.memory.load(state.regs.sp, 8) is symbol.reversed
def test_loadg_no_constraint_creation(): state = SimState(arch='armel', mode='symbolic') engine = HeavyVEXMixin(None) stmt = pyvex.IRStmt.LoadG('Iend_LE', 'ILGop_16Uto32', 0, # dst pyvex.IRExpr.Const(pyvex.const.U32(0x2000)), # addr (src) pyvex.IRExpr.Const(pyvex.const.U32(0x1337)), # alt pyvex.IRExpr.RdTmp(1) # guard ) tyenv = pyvex.IRTypeEnv(state.arch) tyenv.types = [ 'Ity_I32', 'Ity_I32' ] state.scratch.set_tyenv(tyenv) state.scratch.temps[1] = state.solver.BVS('tmp_1', 32) engine.state = state engine._handle_vex_stmt(stmt) # LOADG should not create new constraints - it is a simple conditional memory read. The conditions should only be # used inside the value AST to guard the memory read. assert not state.solver.constraints assert state.scratch.temps[0] is not None assert state.scratch.temps[0].variables.issuperset(state.scratch.temps[1].variables) assert state.scratch.temps[0].op == 'If'
def simprocedure(self, state: angr.SimState): # Init globals if "screen_spying" not in state.globals: state.globals["screen_spying"] = defaultdict(list) # Handle procedure proc = state.inspect.simprocedure if proc is None: # Handle syscall SimProcedures log.debug("Reached a syscall SimProcedure") return proc_name = proc.display_name if proc_name == "GetDC": return_value = state.inspect.simprocedure_result state.globals["screen_spying"]["GetDC"].append(return_value) elif proc_name == "GetWindowDC": return_value = state.inspect.simprocedure_result state.globals["screen_spying"]["GetWindowDC"].append(return_value) elif proc_name == "CreateCompatibleBitmap": # Final function in sequence self._analyze(state, proc.arg(0))
def test_strstr_inconsistency(n=2): l.info("symbolic haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") s.libc.buf_symbolic_bytes = n addr_haystack = s.se.BVV(0x10, 64) addr_needle = s.se.BVV(0xb0, 64) #len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, arguments=[addr_haystack, addr_needle]).ret_expr #slh_res = strlen(s, inline=True, arguments=[addr_haystack]).ret_expr #sln_res = strlen(s, inline=True, arguments=[addr_needle]).ret_expr #print "LENH:", s.se.any_n_int(slh_res, 100) #print "LENN:", s.se.any_n_int(sln_res, 100) nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_items_equal(s.se.any_n_int( ss_res, 100), [0] + range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1)) s.add_constraints(ss_res != 0) ss2 = strstr(s, arguments=[addr_haystack, addr_needle]).ret_expr s.add_constraints(ss2 == 0) nose.tools.assert_false(s.satisfiable())
def test_strstr_inconsistency(): l.info("symbolic haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") s.libc.buf_symbolic_bytes = 2 addr_haystack = s.solver.BVV(0x10, 64) addr_needle = s.solver.BVV(0xb0, 64) #len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, arguments=[addr_haystack, addr_needle]) #slh_res = strlen(s, inline=True, arguments=[addr_haystack]) #sln_res = strlen(s, inline=True, arguments=[addr_needle]) #print "LENH:", s.solver.eval_upto(slh_res, 100) #print "LENN:", s.solver.eval_upto(sln_res, 100) nose.tools.assert_false(s.solver.unique(ss_res)) nose.tools.assert_sequence_equal(sorted(s.solver.eval_upto(ss_res, 100)), [0] + list(range(0x10, 0x10 + s.libc.buf_symbolic_bytes - 1))) s.add_constraints(ss_res != 0) ss2 = strstr(s, arguments=[addr_haystack, addr_needle]) s.add_constraints(ss2 == 0) nose.tools.assert_false(s.satisfiable())
def test_strcpy(): l.info("concrete src, concrete dst") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.solver.BVV(0x41414100, 32) dst_addr = s.solver.BVV(0x1000, 64) src = s.solver.BVV(0x42420000, 32) src_addr = s.solver.BVV(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strcpy(s, arguments=[dst_addr, src_addr]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.solver.eval(new_dst, cast_to=bytes), b"BB\x00\x00") l.info("symbolic src, concrete dst") dst = s.solver.BVV(0x41414100, 32) dst_addr = s.solver.BVV(0x1000, 64) src = s.solver.BVS("src", 32) src_addr = s.solver.BVV(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) ln = strlen(s, arguments=[src_addr]) strcpy(s, arguments=[dst_addr, src_addr]) cm = strcmp(s, arguments=[dst_addr, src_addr]) s.add_constraints(cm == 0) s.add_constraints(ln == 15)
def test_state_merge(): a = SimState(arch='AMD64', mode='symbolic') a.memory.store(1, a.se.BVV(42, 8)) b = a.copy() c = b.copy() a.memory.store(2, a.memory.load(1, 1)+1) b.memory.store(2, b.memory.load(1, 1)*2) c.memory.store(2, c.memory.load(1, 1)/2) # make sure the byte at 1 is right nose.tools.assert_equal(a.se.eval(a.memory.load(1, 1)), 42) nose.tools.assert_equal(b.se.eval(b.memory.load(1, 1)), 42) nose.tools.assert_equal(c.se.eval(c.memory.load(1, 1)), 42) # make sure the byte at 2 is right nose.tools.assert_equal(a.se.eval(a.memory.load(2, 1)), 43) nose.tools.assert_equal(b.se.eval(b.memory.load(2, 1)), 84) nose.tools.assert_equal(c.se.eval(c.memory.load(2, 1)), 21) # the byte at 2 should be unique for all before the merge nose.tools.assert_true(a.se.unique(a.memory.load(2, 1))) nose.tools.assert_true(b.se.unique(b.memory.load(2, 1))) nose.tools.assert_true(c.se.unique(c.memory.load(2, 1))) logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.DEBUG) m, merge_conditions, merging_occurred = a.merge(b, c) logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.WARNING) nose.tools.assert_true(merging_occurred) #nose.tools.assert_equals(sorted(m.se.eval_upto(merge_flag, 10)), [ 0,1,2 ]) assert len(merge_conditions) == 3 # the byte at 2 should now *not* be unique for a nose.tools.assert_false(m.se.unique(m.memory.load(2, 1))) nose.tools.assert_true(a.se.unique(a.memory.load(2, 1))) nose.tools.assert_true(b.se.unique(b.memory.load(2, 1))) nose.tools.assert_true(c.se.unique(c.memory.load(2, 1))) # the byte at 2 should have the three values nose.tools.assert_items_equal(m.se.eval_upto(m.memory.load(2, 1), 10), (43, 84, 21)) # we should be able to select them by adding constraints a_a = m.copy() a_a.add_constraints(merge_conditions[0]) nose.tools.assert_true(a_a.se.unique(a_a.memory.load(2, 1))) nose.tools.assert_equal(a_a.se.eval(a_a.memory.load(2, 1)), 43) a_b = m.copy() a_b.add_constraints(merge_conditions[1]) nose.tools.assert_true(a_b.se.unique(a_b.memory.load(2, 1))) nose.tools.assert_equal(a_b.se.eval(a_b.memory.load(2, 1)), 84) a_c = m.copy() a_c.add_constraints(merge_conditions[2]) nose.tools.assert_true(a_c.se.unique(a_c.memory.load(2, 1))) nose.tools.assert_equal(a_c.se.eval(a_c.memory.load(2, 1)), 21) # test different sets of plugins a = SimState(arch='AMD64', mode='symbolic') nose.tools.assert_true(a.has_plugin('memory')) nose.tools.assert_true(a.has_plugin('registers')) nose.tools.assert_false(a.has_plugin('libc')) b = a.copy() a.get_plugin('libc') nose.tools.assert_true(a.has_plugin('libc')) nose.tools.assert_false(b.has_plugin('libc')) c = a.copy().merge(b.copy())[0] d = b.copy().merge(a.copy())[0] nose.tools.assert_true(c.has_plugin('libc')) nose.tools.assert_true(d.has_plugin('libc')) # test merging posix with different open files a = SimState(arch='AMD64', mode='symbolic') b = a.copy() a.posix.get_file(3) nose.tools.assert_equal(len(a.posix.files), 4) nose.tools.assert_equal(len(b.posix.files), 3) c = a.copy().merge(b.copy())[0] d = b.copy().merge(a.copy())[0] nose.tools.assert_equal(len(c.posix.files), 4) nose.tools.assert_equal(len(d.posix.files), 4)
def test_inline_strcmp(): s = SimState(arch="AMD64", mode="symbolic") str_a = s.solver.BVV(0x41414100, 32) str_b = s.solver.BVS("mystring", 32) a_addr = s.solver.BVV(0x10, 64) b_addr = s.solver.BVV(0xb0, 64) s.memory.store(a_addr, str_a, endness="Iend_BE") s.memory.store(b_addr, str_b, endness="Iend_BE") s_cmp = s.copy() cmpres = strcmp(s_cmp, arguments=[a_addr, b_addr]) s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) nose.tools.assert_true(s_match.solver.unique(str_b)) nose.tools.assert_false(s_nomatch.solver.unique(str_b)) nose.tools.assert_equal(s_match.solver.eval(str_b, cast_to=bytes), b"AAA\x00") s_ncmp = s.copy() ncmpres = strncmp(s_ncmp, arguments=[a_addr, b_addr, s.solver.BVV(2, s.arch.bits)]) s_match = s_ncmp.copy() s_nomatch = s_ncmp.copy() s_match.add_constraints(ncmpres == 0) s_nomatch.add_constraints(ncmpres != 0) nose.tools.assert_false(s_match.solver.unique(str_b)) nose.tools.assert_true(s_match.solver.unique(s_match.memory.load(b_addr, 2))) nose.tools.assert_equal(len(s_match.solver.eval_upto(s_match.memory.load(b_addr, 3), 300)), 256) nose.tools.assert_false(s_nomatch.solver.unique(str_b)) l.info("concrete a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") str_a = s.solver.BVV(0x41424300, 32) str_b = s.solver.BVS("mystring", 32) a_addr = s.solver.BVV(0x10, 64) b_addr = s.solver.BVV(0xb0, 64) s.memory.store(a_addr, str_a, endness="Iend_BE") s.memory.store(b_addr, str_b, endness="Iend_BE") s_cmp = s.copy() cmpres = strncmp(s_cmp, arguments=[a_addr, b_addr, s.solver.BVV(2, s_cmp.arch.bits)]) s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) nose.tools.assert_true(s_match.solver.solution(str_b, 0x41420000)) nose.tools.assert_true(s_match.solver.solution(str_b, 0x41421234)) nose.tools.assert_true(s_match.solver.solution(str_b, 0x41424300)) nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41420000)) nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41421234)) nose.tools.assert_false(s_nomatch.solver.solution(str_b, 0x41424300)) l.info("symbolic a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.solver.BVV(0x10, 64) b_addr = s.solver.BVV(0xb0, 64) s_cmp = s.copy() cmpres = strcmp(s_cmp, arguments=[a_addr, b_addr]) s_match = s_cmp.copy() s_nomatch = s_cmp.copy() s_match.add_constraints(cmpres == 0) s_nomatch.add_constraints(cmpres != 0) m_res = strcmp(s_match, arguments=[a_addr, b_addr]) s_match.add_constraints(m_res != 0) nm_res = strcmp(s_nomatch, arguments=[a_addr, b_addr]) s_nomatch.add_constraints(nm_res == 0) nose.tools.assert_false(s_match.satisfiable()) nose.tools.assert_false(s_match.satisfiable())
def test_inspect_concretization(): # some values for the test x = claripy.BVS('x', 64) y = claripy.BVS('y', 64) # # This tests concretization-time address redirection. # def change_symbolic_target(state): if state.inspect.address_concretization_action == 'store': state.inspect.address_concretization_expr = claripy.BVV(0x1000, state.arch.bits) s = SimState(arch='AMD64') s.inspect.b('address_concretization', BP_BEFORE, action=change_symbolic_target) s.memory.store(x, 'A') assert list(s.se.eval_upto(x, 10)) == [ 0x1000 ] assert list(s.se.eval_upto(s.memory.load(0x1000, 1), 10)) == [ 0x41 ] # # This tests disabling constraint adding through siminspect -- the write still happens # def dont_add_constraints(state): state.inspect.address_concretization_add_constraints = False s = SimState(arch='AMD64') s.inspect.b('address_concretization', BP_BEFORE, action=dont_add_constraints) s.memory.store(x, 'A') assert len(s.se.eval_upto(x, 10)) == 10 # # This tests raising an exception if symbolic concretization fails (i.e., if the address # is too unconstrained). The write aborts. # class UnconstrainedAbort(Exception): def __init__(self, message, state): Exception.__init__(self, message) self.state = state def abort_unconstrained(state): print state.inspect.address_concretization_strategy, state.inspect.address_concretization_result if ( isinstance( state.inspect.address_concretization_strategy, concretization_strategies.SimConcretizationStrategyRange ) and state.inspect.address_concretization_result is None ): raise UnconstrainedAbort("uh oh", state) s = SimState(arch='AMD64') s.memory.write_strategies.insert( 0, concretization_strategies.SimConcretizationStrategyRange(128) ) s.memory._write_address_range = 1 s.memory._write_address_range_approx = 1 s.add_constraints(y == 10) s.inspect.b('address_concretization', BP_AFTER, action=abort_unconstrained) s.memory.store(y, 'A') assert list(s.se.eval_upto(s.memory.load(y, 1), 10)) == [ 0x41 ] try: s.memory.store(x, 'A') print "THIS SHOULD NOT BE REACHED" assert False except UnconstrainedAbort as e: assert e.state.memory is s.memory
def broken_strtok_r(): l.debug("CONCRETE MODE") s = SimState(arch='AMD64', mode='symbolic') s.memory.store(100, s.solver.BVV(0x4141414241414241424300, 88), endness='Iend_BE') s.memory.store(200, s.solver.BVV(0x4200, 16), endness='Iend_BE') str_ptr = s.solver.BVV(100, s.arch.bits) delim_ptr = s.solver.BVV(200, s.arch.bits) state_ptr = s.solver.BVV(300, s.arch.bits) st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st1, 10), [104]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(200, 2), 10), [0x4200]) st2 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st2, 10), [107]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st2-1, 1), 10), [0]) st3 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st3, 10), [109]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st3-1, 1), 10), [0]) st4 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st4, 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109]) st5 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st5, 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109]) s.memory.store(1000, s.solver.BVV(0x4141414241414241424300, 88), endness='Iend_BE') s.memory.store(2000, s.solver.BVV(0x4200, 16), endness='Iend_BE') str_ptr = s.solver.BVV(1000, s.arch.bits) delim_ptr = s.solver.BVV(2000, s.arch.bits) state_ptr = s.solver.BVV(3000, s.arch.bits) st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st1, 10), [1004]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(2000, 2), 10), [0x4200]) st2 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st2, 10), [1007]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st2-1, 1), 10), [0]) st3 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st3, 10), [1009]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st3-1, 1), 10), [0]) st4 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st4, 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009]) st5 = strtok_r(s, arguments=[s.solver.BVV(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.solver.eval_upto(st5, 10), [0]) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009]) s = SimState(arch='AMD64', mode='symbolic') str_ptr = s.solver.BVV(100, s.arch.bits) delim_ptr = s.solver.BVV(200, s.arch.bits) state_ptr = s.solver.BVV(300, s.arch.bits) s.add_constraints(s.memory.load(delim_ptr, 1) != 0) st1 = strtok_r(s, arguments=[str_ptr, delim_ptr, state_ptr]) s.add_constraints(st1 != 0) nose.tools.assert_equal(s.solver.eval_upto(s.memory.load(st1-1, 1), 10), [0])
class BlockState(object): def __init__(self, project, addr, state=None, taint_region=None): self.project = project self.addr = addr self.block_addr = addr self.taint_region = taint_region self.state = state self.tempstore = None self.tags = [] self.write_targets = [] if self.state is None: self.state = SimState(arch=project.arch, mode='symbolic', special_memory_filler=lambda name, bits, _state: BiHead(claripy.BVV(0, bits), claripy.BVV(0, bits)), add_options={sim_options.ABSTRACT_MEMORY, sim_options.SPECIAL_MEMORY_FILL} ) self.state.scratch.ins_addr = 0 if project.arch.name.startswith('ARM'): it = self.state.regs.itstate it.taints['it'] = True self.state.regs.itstate = it def copy(self, newaddr): return BlockState(self.project, newaddr, state=self.state.copy(), taint_region=self.taint_region) def get_reg(self, offset, ty): if isinstance(ty, int): ty = 'Ity_I%d' % ty size = vexutils.extract_int(ty) val = self.state.registers.load(offset, size//8) if ty.startswith('Ity_F'): val = val.raw_to_fp() return val def put_reg(self, offset, val): self.state.registers.store(offset, val) def get_tmp(self, tmpnum): return self.tempstore.read(tmpnum) def put_tmp(self, tmpnum, val): self.tempstore.write(tmpnum, val) def get_mem(self, addr, ty): if isinstance(ty, int): ty = 'Ity_I%d' % ty size = vexutils.extract_int(ty) addr_vs = self.state.solver.VS(bits=self.state.arch.bits, region=addr.taints['pointer'] if addr.taints['pointer'] else 'global', val=addr.as_unsigned) val = self.state.memory.load(addr_vs, size//8, endness=self.state.arch.memory_endness) if ty.startswith('Ity_F'): val = val.raw_to_fp() return val def put_mem(self, addr, val): if not addr.taints['pointer']: return # don't store anything to memory that's not an accounted-for region addr_vs = self.state.solver.VS(bits=self.state.arch.bits, region=addr.taints['pointer'], val=addr.as_unsigned) self.state.scratch.ins_addr += 1 self.state.memory.store(addr_vs, val, endness=self.state.arch.memory_endness) self.write_targets.append((addr_vs, val.length//8)) def access(self, addr_expression, access_type): if addr_expression.taints['pointer'] != self.taint_region: return self.tags.append(('ACCESS', PendingBinaryData.make_bindata(addr_expression, self.addr, access_type))) def alloc(self, addr_expression): self.tags.append(('ALLOC', PendingBinaryData.make_bindata(addr_expression, self.addr, 0))) def handle_irsb(self, block): self.tempstore = TempStore(block.tyenv) for stmt_idx, stmt in enumerate(block.statements): path = ['statements', stmt_idx] self.handle_statement(stmt, block.tyenv, path) def handle_statement(self, stmt, tyenv, path): if stmt.tag in ('Ist_NoOp', 'Ist_AbiHint', 'Ist_MBE'): pass elif stmt.tag == 'Ist_IMark': self.addr = stmt.addr + stmt.delta elif stmt.tag == 'Ist_Exit': self.handle_expression(stmt.dst, tyenv, path + ['dst']) # Let the cfg take care of control flow! elif stmt.tag == 'Ist_WrTmp': expression = self.handle_expression(stmt.data, tyenv, path + ['data']) self.put_tmp(stmt.tmp, expression) elif stmt.tag == 'Ist_Store': expression = self.handle_expression(stmt.data, tyenv, path + ['data']) address = self.handle_expression(stmt.addr, tyenv, path + ['addr']) self.put_mem(address, expression) self.access(address, ACCESS_WRITE) self.access(expression, ACCESS_POINTER) elif stmt.tag == 'Ist_Put': expression = self.handle_expression(stmt.data, tyenv, path + ['data']) self.put_reg(stmt.offset, expression) if stmt.offset == self.project.arch.sp_offset: if not expression.taints['concrete']: l.warning("This function appears to use alloca(). Abort.") raise FidgetAnalysisFailure self.alloc(expression) elif stmt.tag == 'Ist_LoadG': # Conditional loads. Lots of bullshit. addr_expression = self.handle_expression(stmt.addr, tyenv, path + ['addr']) self.access(addr_expression, ACCESS_READ) # load the actual data data_expression = self.get_mem(addr_expression, stmt.cvt_types[0]) # it then needs a type conversion applied to it conv_diff = vexutils.extract_int(stmt.cvt_types[1]) - vexutils.extract_int(stmt.cvt_types[0]) if conv_diff != 0: concrete = data_expression.taints['concrete'] deps = data_expression.taints['deps'] if 'S' in stmt.cvt: data_expression = data_expression.sign_extend(conv_diff) else: data_expression = data_expression.zero_extend(conv_diff) data_expression.taints['concrete'] = concrete data_expression.taints['deps'] = deps self.put_tmp(stmt.dst, data_expression) self.handle_expression(stmt.guard, tyenv, path + ['guard']) self.handle_expression(stmt.alt, tyenv, path + ['alt']) elif stmt.tag == 'Ist_StoreG': # Conditional store addr_expr = self.handle_expression(stmt.addr, tyenv, path + ['addr']) value_expr = self.handle_expression(stmt.data, tyenv, path + ['data']) self.handle_expression(stmt.guard, tyenv, path + ['guard']) self.put_mem(addr_expr, value_expr) self.access(addr_expr, ACCESS_WRITE) self.access(value_expr, ACCESS_POINTER) elif stmt.tag == 'Ist_PutI': # haha no self.handle_expression(stmt.data, tyenv, path + ['data']) elif stmt.tag == 'Ist_CAS': # HA ha no if stmt.oldLo != 4294967295: self.tempstore.default(stmt.oldLo) if stmt.oldHi != 4294967295: self.tempstore.default(stmt.oldHi) elif stmt.tag == 'Ist_Dirty': # hahAHAHAH NO if stmt.tmp != 4294967295: self.tempstore.default(stmt.tmp) else: raise FidgetUnsupportedError("Unknown vex instruction???", stmt) def handle_expression(self, expr, tyenv, path): size = expr.result_size(tyenv) if not expr.tag.startswith('Ico_') else expr.size ty = expr.result_type(tyenv) if not expr.tag.startswith('Ico_') else expr.type addr = self.addr if expr.tag == 'Iex_Get': return self.get_reg(expr.offset, ty) elif expr.tag == 'Iex_RdTmp': return self.get_tmp(expr.tmp) elif expr.tag == 'Iex_Load': addr_expression = self.handle_expression(expr.addr, tyenv, path + ['addr']) self.access(addr_expression, ACCESS_READ) return self.get_mem(addr_expression, ty) elif expr.tag == 'Iex_Const' or expr.tag.startswith('Ico_'): if expr.tag == 'Iex_Const': expr = expr.con if 'F' in ty: if size == 32: values = BiHead( claripy.FPV(expr.value, claripy.fp.FSORT_FLOAT), claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_FLOAT) ) elif size == 64: values = BiHead( claripy.FPV(expr.value, claripy.fp.FSORT_DOUBLE), claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_DOUBLE) ) else: raise FidgetUnsupportedError("Why is there a FP const of size %d" % size) else: values = BiHead( claripy.BVV(expr.value, size), claripy.BVS('%x_%d' % (addr, path[1]), size) ) values.taints['deps'].append(PendingBinaryData(self.project, self.addr, values, path)) values.taints['concrete'] = True values.taints['concrete_root'] = True return values elif expr.tag == 'Iex_ITE': false_expr = self.handle_expression(expr.iffalse, tyenv, path + ['iffalse']) truth_expr = self.handle_expression(expr.iftrue, tyenv, path + ['iftrue']) values = truth_expr if truth_expr.taints['pointer'] else false_expr cond_expr = self.handle_expression(expr.cond, tyenv, path + ['cond']) if not cond_expr.taints['it']: values.taints['concrete'] = false_expr.taints['concrete'] and truth_expr.taints['concrete'] values.taints['it'] = false_expr.taints['it'] or truth_expr.taints['it'] return values elif expr.tag in ('Iex_Unop','Iex_Binop','Iex_Triop','Iex_Qop'): args = [] for i, sub_expr in enumerate(expr.args): arg = self.handle_expression(sub_expr, tyenv, path + ['args', i]) if expr.op.startswith('Iop_Mul') or expr.op.startswith('Iop_And') \ or (i == 0 and expr.op in ROUNDING_IROPS): if arg.taints['concrete_root']: arg = BiHead(arg.cleanval, arg.cleanval) arg.taints['concrete'] = True args.append(arg) try: values = BiHead( operations[expr.op].calculate(*(x.cleanval for x in args)), operations[expr.op].calculate(*(x.dirtyval for x in args)) ) except SimOperationError: l.exception("SimOperationError while running op '%s', returning null", expr.op) return BiHead.default(ty) except KeyError: l.error("Unsupported operation '%s', returning null", expr.op) return BiHead.default(ty) else: # propogate the taints correctly values.taints['concrete'] = True for arg in args: values.taints['deps'].extend(arg.taints['deps']) values.taints['concrete'] = values.taints['concrete'] and arg.taints['concrete'] values.taints['it'] = values.taints['it'] or arg.taints['it'] if expr.op.startswith('Iop_Add') or expr.op.startswith('Iop_And') or \ expr.op.startswith('Iop_Or') or expr.op.startswith('Iop_Xor'): t1 = args[0].taints['pointer'] t2 = args[1].taints['pointer'] values.taints['pointer'] = (t1 if t1 else t2) if (bool(t1) ^ bool(t2)) else False elif expr.op.startswith('Iop_Sub'): t1 = args[0].taints['pointer'] t2 = args[1].taints['pointer'] values.taints['pointer'] = t1 if t1 and not t2 else False return values elif expr.tag == 'Iex_CCall': values = BiHead.default(ty) for i, expr in enumerate(expr.args): arg = self.handle_expression(expr, tyenv, path + ['args', i]) values.taints['it'] = values.taints['it'] or arg.taints['it'] return values elif expr.tag == 'Iex_GetI': return BiHead.default(ty) else: raise FidgetUnsupportedError('Unknown expression tag ({:#x}): {!r}'.format(addr, expr.tag)) def end(self, clean=False): for name in self.project.arch.default_symbolic_registers: offset = self.project.arch.registers[name][0] if offset in (self.project.arch.sp_offset, self.project.arch.bp_offset, self.project.arch.ip_offset): continue if name == 'r7' and self.project.arch.name.startswith('ARM') and self.addr & 1 == 1: continue # values remaining in registers at end-of-block are pointers! Probably. value = getattr(self.state.regs, name) if value.taints['already_pointered']: continue self.access(value, ACCESS_POINTER) value.taints['already_pointered'] = True if value.taints['concrete'] and not value.taints['pointer']: # Don't let nonpointer values persist between block states value = BiHead(value.cleanval, value.cleanval) self.state.registers.store(offset, value) # If a call, scrub the return-value register if clean: self.state.registers.store(self.state.arch.ret_offset, BiHead(claripy.BVV(0, self.state.arch.bits), claripy.BVV(0, self.state.arch.bits))) # Don't let nonpointer vales persist between block state... in memory! for addr, size in self.write_targets: value = self.state.memory.load(addr, size, endness=self.state.arch.memory_endness) if not value.taints['pointer']: replacement = BiHead(value.cleanval, value.cleanval) self.state.scratch.ins_addr += 1 self.state.memory.store(addr, replacement, endness=self.state.arch.memory_endness)