def broken_sprintf(): l.info("concrete src, concrete dst, concrete len") s = SimState(mode="symbolic", arch="PPC32") format_str = s.se.BVV(0x25640000, 32) format_addr = s.se.BVV(0x2000, 32) #dst = s.se.BVV("destination", 128) dst_addr = s.se.BVV(0x1000, 32) arg = s.se.BVS("some_number", 32) s.memory.store(format_addr, format_str) sprintf(s, inline=True, 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.se.any_n_str(s2.memory.load(dst_addr, i+2), 2), repr("%d\x00" % j) nose.tools.assert_equal( s2.se.any_n_str(s2.memory.load(dst_addr, i + 2), 2), ["%d\x00" % j]) s2 = s.copy() s2.add_constraints(arg == 0) #print s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), repr("%d\x00" % 0) nose.tools.assert_equal(s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), ["%d\x00" % 0])
def test_memset(): l.info("concrete src, concrete dst, concrete len") s = SimState(arch="PPC32", mode="symbolic") dst = s.se.BitVecVal(0, 128) dst_addr = s.se.BitVecVal(0x1000, 32) char = s.se.BitVecVal(0x00000041, 32) char2 = s.se.BitVecVal(0x50505050, 32) length = s.BV("some_length", 32) s.memory.store(dst_addr, dst) memset(s, inline=True, arguments=[dst_addr, char, s.se.BitVecVal(3, 32)]) nose.tools.assert_equals(s.se.any_int(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.BV("some_length", 32) memset(s, inline=True, arguments=[dst_addr, char2, length]) l.debug("Trying 2") s_two = s.copy() s_two.add_constraints(length == 2) nose.tools.assert_equals(s_two.se.any_int(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_equals(s_zero.se.any_int(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_equals(s_five.se.any_int(s_five.memory.load(dst_addr, 6)), 0x505050505000)
def test_inline_strlen(): s = SimState(arch="AMD64", mode="symbolic") l.info("fully concrete string") a_str = s.se.BitVecVal(0x41414100, 32) a_addr = s.se.BitVecVal(0x10, 64) s.memory.store(a_addr, a_str, endness="Iend_BE") a_len = SimProcedures["libc.so.6"]["strlen"](s, inline=True, arguments=[a_addr]).ret_expr nose.tools.assert_true(s.se.unique(a_len)) nose.tools.assert_equal(s.se.any_int(a_len), 3) l.info("concrete-terminated string") b_str = s.se.Concat(s.BV("mystring", 24), s.se.BitVecVal(0, 8)) b_addr = s.se.BitVecVal(0x20, 64) s.memory.store(b_addr, b_str, endness="Iend_BE") b_len = SimProcedures["libc.so.6"]["strlen"](s, inline=True, arguments=[b_addr]).ret_expr nose.tools.assert_equal(s.se.max_int(b_len), 3) nose.tools.assert_items_equal(s.se.any_n_int(b_len, 10), (0, 1, 2, 3)) l.info("fully unconstrained") u_addr = s.se.BitVecVal(0x50, 64) u_len_sp = SimProcedures["libc.so.6"]["strlen"](s, inline=True, arguments=[u_addr]) u_len = u_len_sp.ret_expr nose.tools.assert_equal(len(s.se.any_n_int(u_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.max_int(u_len), s.libc.buf_symbolic_bytes - 1) # print u_len_sp.se.maximum_null # s.add_constraints(u_len < 16) nose.tools.assert_equal(s.se.any_n_int(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.BV("some_string", 8 * 16) c_addr = s.se.BitVecVal(0x10, 64) s.memory.store(c_addr, str_c, endness="Iend_BE") c_len = SimProcedures["libc.so.6"]["strlen"](s, inline=True, arguments=[c_addr]).ret_expr nose.tools.assert_equal(len(s.se.any_n_int(c_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.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.se.any_str(str_c).index("\x00"), 1) str_test = one_s.memory.load(c_addr, 2, endness="Iend_BE") nose.tools.assert_equal(len(one_s.se.any_n_str(str_test, 300)), 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.se.any_str(str_test).index("\x00"), i) for j in range(i): nose.tools.assert_false(test_s.se.unique(test_s.memory.load(c_addr + j, 1)))
def test_unsat_core(): s = SimState(arch='AMD64', mode='symbolic', add_options={ simuvex.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 test_strcpy(): l.info("concrete src, concrete dst") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strcpy(s, inline=True, arguments=[dst_addr, src_addr]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_str(new_dst), "BB\x00\x00") l.info("symbolic src, concrete dst") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) ln = strlen(s, inline=True, arguments=[src_addr]).ret_expr strcpy(s, inline=True, arguments=[dst_addr, src_addr]) cm = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr s.add_constraints(cm == 0) s.add_constraints(ln == 15)
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 test_unsat_core(): s = SimState(arch='AMD64', mode='symbolic', add_options={simuvex.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 broken_ccall(): s = SimState(arch="AMD64") l.debug("Testing amd64_actions_ADD") l.debug("(8-bit) 1 + 1...") arg_l = s.se.BitVecVal(1, 8) arg_r = s.se.BitVecVal(1, 8) ret = s_ccall.pc_actions_ADD(s, 8, arg_l, arg_r, 0, platform='AMD64') nose.tools.assert_equal(ret, 0) l.debug("(32-bit) (-1) + (-2)...") arg_l = s.se.BitVecVal(-1, 32) arg_r = s.se.BitVecVal(-1, 32) ret = s_ccall.pc_actions_ADD(s, 32, arg_l, arg_r, 0, platform='AMD64') nose.tools.assert_equal(ret, 0b101010) l.debug("Testing pc_actions_SUB") l.debug("(8-bit) 1 - 1...", ) arg_l = s.se.BitVecVal(1, 8) arg_r = s.se.BitVecVal(1, 8) ret = s_ccall.pc_actions_SUB(s, 8, arg_l, arg_r, 0, platform='AMD64') nose.tools.assert_equal(ret, 0b010100) l.debug("(32-bit) (-1) - (-2)...") arg_l = s.se.BitVecVal(-1, 32) arg_r = s.se.BitVecVal(-1, 32) ret = s_ccall.pc_actions_SUB(s, 32, arg_l, arg_r, 0, platform='AMD64') nose.tools.assert_equal(ret, 0)
def test_file_seek(): # TODO: Make this test more complete SEEK_SET = 0 SEEK_CUR = 1 SEEK_END = 2 state = SimState(arch="AMD64", mode='symbolic') # Normal seeking fd = state.posix.open("test", "wb") r = state.posix.seek(fd, 0, SEEK_SET) nose.tools.assert_equal(r, 0) state.posix.close(fd) # TODO: test case: seek cannot go beyond the file size or current file pos # TODO: test case: seek should not work for stdin/stdout/stderr # Seek from the end fd = state.posix.open("test", "wb") state.posix.files[fd].size = 20 state.posix.seek(fd, 0, SEEK_END) nose.tools.assert_true(state.se.is_true(state.posix.files[fd].pos == 20)) state.posix.close(fd) # cannot seek from a file whose size is unknown fd = state.posix.open("unknown_size", "wb") r = state.posix.seek(fd, 0, SEEK_END) nose.tools.assert_equal(r, -1) state.posix.close(fd)
def state_blank(self, addr=None, initial_prefix=None, **kwargs): """ Initialize a blank state. All parameters are optional. :param addr: The execution start address. :param initial_prefix: :return: The initialized SimState. :rtype: simuvex.SimState """ if kwargs.get('mode', None) is None: kwargs['mode'] = self.proj._default_analysis_mode if kwargs.get('permissions_backer', None) is None: # just a dict of address ranges to permission bits permission_map = { } for obj in self.proj.loader.all_objects: for seg in obj.segments: perms = 0 # bit values based off of protection bit values from sys/mman.h if seg.is_readable: perms |= 1 # PROT_READ if seg.is_writable: perms |= 2 # PROT_WRITE if seg.is_executable: perms |= 4 # PROT_EXEC permission_map[(obj.rebase_addr + seg.min_addr, obj.rebase_addr + seg.max_addr)] = perms permissions_backer = (self.proj.loader.main_bin.execstack, permission_map) kwargs['permissions_backer'] = permissions_backer if kwargs.get('memory_backer', None) is None: kwargs['memory_backer'] = self.proj.loader.memory if kwargs.get('arch', None) is None: kwargs['arch'] = self.proj.arch state = SimState(**kwargs) state.regs.sp = self.arch.initial_sp if initial_prefix is not None: for reg in state.arch.default_symbolic_registers: state.registers.store(reg, state.se.Unconstrained(initial_prefix + "_" + reg, state.arch.bits, explicit_name=True)) for reg, val, is_addr, mem_region in state.arch.default_register_values: if o.ABSTRACT_MEMORY in state.options and is_addr: address = state.se.ValueSet(region=mem_region, bits=state.arch.bits, val=val) state.registers.store(reg, address) else: state.registers.store(reg, val) if addr is None: addr = self.proj.entry state.regs.ip = addr state.scratch.ins_addr = addr state.scratch.bbl_addr = addr state.scratch.stmt_idx = 0 state.scratch.jumpkind = 'Ijk_Boring' state.procedure_data.hook_addr = self.continue_addr return state
def state_blank(self, addr=None, initial_prefix=None, **kwargs): if kwargs.get('mode', None) is None: kwargs['mode'] = self.proj._default_analysis_mode if kwargs.get('memory_backer', None) is None: kwargs['memory_backer'] = self.proj.loader.memory if kwargs.get('arch', None) is None: kwargs['arch'] = self.proj.arch state = SimState(**kwargs) state.regs.sp = self.arch.initial_sp if initial_prefix is not None: for reg in state.arch.default_symbolic_registers: state.registers.store(reg, state.se.Unconstrained(initial_prefix + "_" + reg, state.arch.bits, explicit_name=True)) for reg, val, is_addr, mem_region in state.arch.default_register_values: if o.ABSTRACT_MEMORY in state.options and is_addr: address = state.se.ValueSet(region=mem_region, bits=state.arch.bits, val=val) state.registers.store(reg, address) else: state.registers.store(reg, val) if addr is None: addr = self.proj.entry state.regs.ip = addr state.scratch.ins_addr = addr state.scratch.bbl_addr = addr state.scratch.stmt_idx = 0 state.scratch.jumpkind = 'Ijk_Boring' state.procedure_data.hook_addr = self.continue_addr return state
def test_concretization_strategies(): initial_memory = {0: 'A', 1: 'B', 2: 'C', 3: 'D'} s = SimState(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) ss = s.copy() nose.tools.assert_equal(ss.se.any_n_str(ss.memory.load(x, 1), 2), ['B']) ss = s.copy() ss.options.add(simuvex.o.CONSERVATIVE_READ_STRATEGY) nose.tools.assert_true('symbolic' in next(iter(ss.memory.load(x, 1).variables)))
def test_state_merge_static(): # With abstract memory # Aligned memory merging a = SimState(mode='static') se = a.se addr = a.se.ValueSet(region='global', bits=32, val=8) a.memory.store(addr, a.se.BitVecVal(42, 32)) b = a.copy() c = a.copy() a.memory.store(addr, a.se.BitVecVal(50, 32), endness='Iend_LE') b.memory.store(addr, a.se.BitVecVal(60, 32), endness='Iend_LE') c.memory.store(addr, a.se.BitVecVal(70, 32), endness='Iend_LE') merged, _, _ = a.merge(b, c) nose.tools.assert_true(merged.memory.load(addr, 4).identical(a.se.SI(bits=32, stride=10, lower_bound=50, upper_bound=70)))
def test_file_create(): # Create a state first state = SimState(arch="AMD64", mode='symbolic') # Create a file fd = state.posix.open("test", "wb") nose.tools.assert_equal(fd, 3)
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, inline=True, 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, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s.add_constraints(ss2 == 0) nose.tools.assert_false(s.satisfiable())
def test_memset(): l.info("concrete src, concrete dst, concrete len") s = SimState(arch="PPC32", mode="symbolic") dst = s.se.BVV(0, 128) dst_addr = s.se.BVV(0x1000, 32) char = s.se.BVV(0x00000041, 32) char2 = s.se.BVV(0x50505050, 32) length = s.se.BVS("some_length", 32) s.memory.store(dst_addr, dst) memset(s, inline=True, arguments=[dst_addr, char, s.se.BVV(3, 32)]) nose.tools.assert_equals(s.se.any_int(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.se.BVS("some_length", 32) memset(s, inline=True, arguments=[dst_addr, char2, length]) l.debug("Trying 2") s_two = s.copy() s_two.add_constraints(length == 2) nose.tools.assert_equals(s_two.se.any_int(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_equals(s_zero.se.any_int(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_equals(s_five.se.any_int(s_five.memory.load(dst_addr, 6)), 0x505050505000)
def test_strcmp(): l.info("concrete a, concrete b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BVV(0x10, 64) b_addr = s.se.BVV(0xb0, 64) s.memory.store(a_addr, "heck\x00") s.memory.store(b_addr, "heck\x00") r = strcmp(s, arguments=[a_addr, b_addr]).ret_expr nose.tools.assert_equal(s.se.any_n_int(r, 2), [0]) l.info("concrete a, empty b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BVV(0x10, 64) b_addr = s.se.BVV(0xb0, 64) s.memory.store(a_addr, "heck\x00") s.memory.store(b_addr, "\x00") r = strcmp(s, arguments=[a_addr, b_addr]).ret_expr nose.tools.assert_equal(s.se.any_n_int(r, 2), [1]) l.info("empty a, concrete b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BVV(0x10, 64) b_addr = s.se.BVV(0xb0, 64) s.memory.store(a_addr, "\x00") s.memory.store(b_addr, "heck\x00") r = strcmp(s, arguments=[a_addr, b_addr]).ret_expr nose.tools.assert_equal(s.se.any_n_int(r, 2), [0xffffffffffffffff]) l.info("empty a, empty b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BVV(0x10, 64) b_addr = s.se.BVV(0xb0, 64) s.memory.store(a_addr, "\x00") s.memory.store(b_addr, "\x00") r = strcmp(s, arguments=[a_addr, b_addr]).ret_expr nose.tools.assert_equal(s.se.any_n_int(r, 2), [0])
def test_state_merge_static(): # With abstract memory # Aligned memory merging a = SimState(mode='static') se = a.se addr = a.se.ValueSet(region='global', bits=32, val=8) a.memory.store(addr, a.se.BitVecVal(42, 32)) b = a.copy() c = a.copy() a.memory.store(addr, a.se.BitVecVal(50, 32), endness='Iend_LE') b.memory.store(addr, a.se.BitVecVal(60, 32), endness='Iend_LE') c.memory.store(addr, a.se.BitVecVal(70, 32), endness='Iend_LE') merged, _, _ = a.merge(b, c) nose.tools.assert_true( merged.memory.load(addr, 4).identical( a.se.SI(bits=32, stride=10, lower_bound=50, upper_bound=70)))
def test_strchr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.se.BitVecVal(0x42, 64) addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, 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.BitVecVal(0x41424300, 32) str_needle = s.BV("wtf", 64) chr_needle = str_needle[7:0] addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, 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.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_state_merge_static(): # With abstract memory # Aligned memory merging a = SimState(mode='static') addr = a.se.ValueSet(region='global', bits=32, val=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 test_abstract_memory_find(): initial_memory = {1: 'A', 2: 'B', 3: '\x00'} s = SimState( mode='static', arch="AMD64", memory_backer=initial_memory, add_options={simuvex.o.ABSTRACT_SOLVER, simuvex.o.ABSTRACT_MEMORY}) se = s.se BVV = se.BVV VS = se.VS SI = se.SI s.memory.store(4, se.TSI(bits=64)) def to_vs(region, offset): return VS(s.arch.bits, region, 0, offset) r, _, _ = s.memory.find(to_vs('global', 1), BVV(ord('A'), 8)) r_model = claripy.backends.vsa.convert(r) s_expected = claripy.backends.vsa.convert(SI(bits=64, to_conv=1)) nose.tools.assert_true(isinstance(r_model, claripy.vsa.ValueSet)) nose.tools.assert_equal(r_model.regions.keys(), ['global']) nose.tools.assert_true( claripy.backends.vsa.identical(r_model.regions['global'], s_expected)) r, _, _ = s.memory.find(to_vs('global', 1), BVV(ord('B'), 8)) r_model = claripy.backends.vsa.convert(r) s_expected = claripy.backends.vsa.convert(SI(bits=64, to_conv=2)) nose.tools.assert_true(isinstance(r_model, claripy.vsa.ValueSet)) nose.tools.assert_equal(r_model.regions.keys(), ['global']) nose.tools.assert_true( claripy.backends.vsa.identical(r_model.regions['global'], s_expected)) r, _, _ = s.memory.find(to_vs('global', 1), BVV(0, 8)) r_model = claripy.backends.vsa.convert(r) s_expected = claripy.backends.vsa.convert(SI(bits=64, to_conv=3)) nose.tools.assert_true(isinstance(r_model, claripy.vsa.ValueSet)) nose.tools.assert_equal(r_model.regions.keys(), ['global']) nose.tools.assert_true( claripy.backends.vsa.identical(r_model.regions['global'], s_expected)) # Find in StridedIntervals r, _, _ = s.memory.find(to_vs('global', 4), BVV(0, 8), max_search=8) r_model = claripy.backends.vsa.convert(r) s_expected = claripy.backends.vsa.convert( SI(bits=64, stride=1, lower_bound=4, upper_bound=11)) nose.tools.assert_true(isinstance(r_model, claripy.vsa.ValueSet)) nose.tools.assert_equal(r_model.regions.keys(), ['global']) nose.tools.assert_true( claripy.backends.vsa.identical(r_model.regions['global'], s_expected))
def test_state_merge_static(): # With abstract memory # Aligned memory merging a = SimState(mode="static") se = a.se addr = a.se.ValueSet(region="global", bits=32, val=8) a.memory.store(addr, a.se.BitVecVal(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.BitVecVal(50, 32), endness="Iend_LE") b.memory.store(addr, a.se.BitVecVal(60, 32), endness="Iend_LE") c.memory.store(addr, a.se.BitVecVal(70, 32), endness="Iend_LE") merged, _, _ = a.merge(b, c) nose.tools.assert_true( merged.memory.load(addr, 4).identical(a.se.SI(bits=32, stride=10, lower_bound=50, upper_bound=70)) )
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) sirsb = SimIRSB(state, irsb) exit_state = sirsb.default_exit nose.tools.assert_true( claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp - 4))
def test_strcpy(): l.info("concrete src, concrete dst") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strcpy(s, inline=True, arguments=[dst_addr, src_addr]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_equal(s.se.any_str(new_dst), "BB\x00\x00") l.info("symbolic src, concrete dst") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) ln = strlen(s, inline=True, arguments=[src_addr]).ret_expr strcpy(s, inline=True, arguments=[dst_addr, src_addr]) cm = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr s.add_constraints(cm == 0) s.add_constraints(ln == 15)
def test_inline_strlen(): s = SimState(arch="AMD64", mode="symbolic") l.info("fully concrete string") a_str = s.se.BVV(0x41414100, 32) a_addr = s.se.BVV(0x10, 64) s.memory.store(a_addr, a_str, endness="Iend_BE") a_len = strlen(s, arguments=[a_addr]).ret_expr nose.tools.assert_true(s.se.unique(a_len)) nose.tools.assert_equal(s.se.any_int(a_len), 3) l.info("concrete-terminated string") b_str = s.se.Concat(s.se.BVS("mystring", 24), s.se.BVV(0, 8)) b_addr = s.se.BVV(0x20, 64) s.memory.store(b_addr, b_str, endness="Iend_BE") b_len = strlen(s, arguments=[b_addr]).ret_expr nose.tools.assert_equal(s.se.max_int(b_len), 3) nose.tools.assert_items_equal(s.se.any_n_int(b_len, 10), (0, 1, 2, 3)) l.info("fully unconstrained") u_addr = s.se.BVV(0x50, 64) u_len_sp = strlen(s, arguments=[u_addr]) u_len = u_len_sp.ret_expr nose.tools.assert_equal(len(s.se.any_n_int(u_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.max_int(u_len), s.libc.buf_symbolic_bytes - 1) #print u_len_sp.se.maximum_null #s.add_constraints(u_len < 16) nose.tools.assert_equal( s.se.any_n_int(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.se.BVS("some_string", 8 * 16) c_addr = s.se.BVV(0x10, 64) s.memory.store(c_addr, str_c, endness='Iend_BE') c_len = strlen(s, arguments=[c_addr]).ret_expr nose.tools.assert_equal(len(s.se.any_n_int(c_len, 100)), s.libc.buf_symbolic_bytes) nose.tools.assert_equal(s.se.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.se.any_str(str_c).index('\x00'), 1) str_test = one_s.memory.load(c_addr, 2, endness='Iend_BE') nose.tools.assert_equal(len(one_s.se.any_n_str(str_test, 300)), 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.se.any_str(str_test).index('\x00'), i) for j in range(i): nose.tools.assert_false( test_s.se.unique(test_s.memory.load(c_addr + j, 1)))
def test_procedure_actions(): s = SimState() s.registers.store('rbx', 2) rbx = SimProcedures['testing']['retreg'](s, addr=0x10, arguments=(), sim_kwargs={ 'reg': 'rbx' }).ret_expr nose.tools.assert_is(type(rbx), simuvex.SimActionObject) nose.tools.assert_equal(s.se.any_int(rbx), 2) nose.tools.assert_equal(rbx.reg_deps, {s.arch.registers['rbx'][0]})
def test_file_read(): state = SimState(arch="AMD64", mode='symbolic') content = state.se.BVV(0xbadf00d, 32) content_size = content.size() / 8 fd = state.posix.open("test", "wb") state.posix.write(fd, content, content_size) state.posix.seek(fd, 0, 0) state.posix.read(fd, 0xc0000000, content_size) data = state.memory.load(0xc0000000, content_size) nose.tools.assert_true(state.se.is_true(data == content))
def test_procedure_actions(): s = SimState() s.registers.store('rbx', 2) proc = SimProcedures['testing']['retreg'](FAKE_ADDR, s.arch, sim_kwargs={ 'reg': 'rbx' }) SimEngineProcedure().process(s, proc) rbx = proc.ret_expr nose.tools.assert_is(type(rbx), simuvex.SimActionObject) nose.tools.assert_equal(s.se.any_int(rbx), 2) nose.tools.assert_equal(rbx.reg_deps, {s.arch.registers['rbx'][0]})
def test_state_pickle(): old_dl = ana.dl ana.set_dl(pickle_dir='/tmp/picklez') try: s = SimState() s.memory.store(100, s.se.BVV(0x4141414241414241424300, 88), endness='Iend_BE') s.regs.rax = 100 sp = pickle.dumps(s) del s gc.collect() s = pickle.loads(sp) nose.tools.assert_equals(s.se.any_str(s.memory.load(100, 10)), "AAABAABABC") finally: ana.dl = old_dl
def broken_sprintf(): l.info("concrete src, concrete dst, concrete len") s = SimState(mode="symbolic", arch="PPC32") format_str = s.se.BitVecVal(0x25640000, 32) format_addr = s.se.BitVecVal(0x2000, 32) # dst = s.se.BitVecVal("destination", 128) dst_addr = s.se.BitVecVal(0x1000, 32) arg = s.BV("some_number", 32) s.memory.store(format_addr, format_str) sprintf(s, inline=True, 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.se.any_n_str(s2.memory.load(dst_addr, i+2), 2), repr("%d\x00" % j) nose.tools.assert_equal(s2.se.any_n_str(s2.memory.load(dst_addr, i + 2), 2), ["%d\x00" % j]) s2 = s.copy() s2.add_constraints(arg == 0) # print s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), repr("%d\x00" % 0) nose.tools.assert_equal(s2.se.any_n_str(s2.memory.load(dst_addr, 2), 2), ["%d\x00" % 0])
def test_copy(): s = SimState() s.memory.store(0x100, "ABCDEFGHIJKLMNOP") s.memory.store(0x200, "XXXXXXXXXXXXXXXX") x = s.se.BV('size', s.arch.bits) s.add_constraints(s.se.ULT(x, 10)) s.memory.copy_contents(0x200, 0x100, x) nose.tools.assert_equals(sorted(s.se.any_n_int(x, 100)), range(10)) result = s.memory.load(0x200, 5) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100)), [ "ABCDE", "ABCDX", "ABCXX", "ABXXX", "AXXXX", "XXXXX" ]) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100, extra_constraints=[x==3])), [ "ABCXX" ]) s = SimState() s.posix.write(0, "ABCDEFGHIJKLMNOP", len("ABCDEFGHIJKLMNOP")) s.posix.seek(0, 0) s.memory.store(0x200, "XXXXXXXXXXXXXXXX") x = s.se.BV('size', s.arch.bits) s.add_constraints(s.se.ULT(x, 10)) s.posix.read(0, x, dst_addr=0x200) nose.tools.assert_equals(sorted(s.se.any_n_int(x, 100)), range(10)) result = s.memory.load(0x200, 5) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100)), [ "ABCDE", "ABCDX", "ABCXX", "ABXXX", "AXXXX", "XXXXX" ]) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100, extra_constraints=[x==3])), [ "ABCXX" ]) s = SimState() s.posix.write(0, "ABCDEFGHIJKLMNOP", len("ABCDEFGHIJKLMNOP")) s.posix.seek(0, 0) s.memory.store(0x200, "XXXXXXXXXXXXXXXX") x = s.se.BV('size', s.arch.bits) s.add_constraints(s.se.ULT(x, 10)) ret_x = SimProcedures['libc.so.6']['read'](s, inline=True, arguments=[0, 0x200, x]).ret_expr nose.tools.assert_equals(sorted(s.se.any_n_int(x, 100)), range(10)) result = s.memory.load(0x200, 5) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100)), [ "ABCDE", "ABCDX", "ABCXX", "ABXXX", "AXXXX", "XXXXX" ]) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100, extra_constraints=[x==3])), [ "ABCXX" ]) nose.tools.assert_equals(sorted(s.se.any_n_int(ret_x, 100)), range(10)) nose.tools.assert_equals(sorted(s.se.any_n_str(result, 100, extra_constraints=[ret_x==3])), [ "ABCXX" ])
def test_strchr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.se.BitVecVal(0x42, 64) addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, 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.BitVecVal(0x41424300, 32) str_needle = s.BV("wtf", 64) chr_needle = str_needle[7:0] addr_haystack = s.se.BitVecVal(0x10, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") ss_res = strchr(s, inline=True, 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.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_calling_conventions(): # # SimProcedures # from simuvex.s_cc import SimCCCdecl args = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000, 100000, 1000000, 2000000, 14, 15, 16 ] arches = [ ('X86', SimCCCdecl), ('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 = SimProcedures['testing']['manyargs'](s, inline=True, convention=cc( s.arch)) else: manyargs = SimProcedures['testing']['manyargs'](s, inline=True) # Simulate a call if s.arch.call_pushes_ret: manyargs.state.registers.store( s.arch.sp_offset, manyargs.state.regs.sp + s.arch.stack_change) manyargs.set_args(args) for index, arg in enumerate(args): nose.tools.assert_true(s.se.is_true(manyargs.arg(index) == arg))
def test_getchar(): s = SimState(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, inline=True, 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, inline=True, 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, inline=True, 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, inline=True, 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_getc(): s = SimState(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]) # The argument of getc should be a FILE * c = getc(s, arguments=[0]).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 = getc(s, arguments=[0]).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 = getc(s, arguments=[0]).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 = getc(s, arguments=[0]).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_concretization_strategies(): initial_memory = {0: 'A', 1: 'B', 2: 'C', 3: 'D'} s = SimState(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(simuvex.o.CONSERVATIVE_READ_STRATEGY) ss.memory._create_default_read_strategies() nose.tools.assert_true( 'symbolic' in next(iter(ss.memory.load(x, 1).variables)))
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.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xB0, 64) # len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, inline=True, 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, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s.add_constraints(ss2 == 0) nose.tools.assert_false(s.satisfiable())
def test_state_merge(): a = SimState(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.any_int(a.memory.load(1, 1)), 42) nose.tools.assert_equal(b.se.any_int(b.memory.load(1, 1)), 42) nose.tools.assert_equal(c.se.any_int(c.memory.load(1, 1)), 42) # make sure the byte at 2 is right nose.tools.assert_equal(a.se.any_int(a.memory.load(2, 1)), 43) nose.tools.assert_equal(b.se.any_int(b.memory.load(2, 1)), 84) nose.tools.assert_equal(c.se.any_int(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('simuvex.plugins.symbolic_memory').setLevel( logging.DEBUG) m, merge_conditions, merging_occurred = a.merge(b, c) logging.getLogger('simuvex.plugins.symbolic_memory').setLevel( logging.WARNING) nose.tools.assert_true(merging_occurred) #nose.tools.assert_equals(sorted(m.se.any_n_int(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.any_n_int(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.any_int(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.any_int(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.any_int(a_c.memory.load(2, 1)), 21) # test different sets of plugins a = SimState(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(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 broken_symbolic_write(): s = 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 = 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 state_blank(self, addr=None, initial_prefix=None, stack_size=1024 * 1024 * 8, **kwargs): """ Initialize a blank state. All parameters are optional. :param addr: The execution start address. :param initial_prefix: :return: The initialized SimState. :rtype: simuvex.SimState """ if kwargs.get('mode', None) is None: kwargs['mode'] = self.proj._default_analysis_mode if kwargs.get('permissions_backer', None) is None: # just a dict of address ranges to permission bits permission_map = {} for obj in self.proj.loader.all_objects: for seg in obj.segments: perms = 0 # bit values based off of protection bit values from sys/mman.h if seg.is_readable: perms |= 1 # PROT_READ if seg.is_writable: perms |= 2 # PROT_WRITE if seg.is_executable: perms |= 4 # PROT_EXEC permission_map[(obj.rebase_addr + seg.min_addr, obj.rebase_addr + seg.max_addr)] = perms permissions_backer = (self.proj.loader.main_bin.execstack, permission_map) kwargs['permissions_backer'] = permissions_backer if kwargs.get('memory_backer', None) is None: kwargs['memory_backer'] = self.proj.loader.memory if kwargs.get('arch', None) is None: kwargs['arch'] = self.proj.arch if kwargs.get('os_name', None) is None: kwargs['os_name'] = self.name state = SimState(**kwargs) stack_end = state.arch.initial_sp if o.ABSTRACT_MEMORY not in state.options: state.memory.mem._preapproved_stack = IRange( stack_end - stack_size, stack_end) if o.INITIALIZE_ZERO_REGISTERS in state.options: highest_reg_offset, reg_size = max(state.arch.registers.values()) for i in range(0, highest_reg_offset + reg_size, state.arch.bytes): state.registers.store(i, state.se.BVV(0, state.arch.bits)) state.regs.sp = stack_end if initial_prefix is not None: for reg in state.arch.default_symbolic_registers: state.registers.store( reg, claripy.BVS(initial_prefix + "_" + reg, state.arch.bits, explicit_name=True)) for reg, val, is_addr, mem_region in state.arch.default_register_values: region_base = None # so pycharm does not complain if is_addr: if isinstance(mem_region, tuple): # unpack it mem_region, region_base = mem_region elif mem_region == 'global': # Backward compatibility region_base = 0 else: raise AngrSimOSError( 'You must specify the base address for memory region "%s". ' % mem_region) if o.ABSTRACT_MEMORY in state.options and is_addr: address = claripy.ValueSet(state.arch.bits, mem_region, region_base, val) state.registers.store(reg, address) else: state.registers.store(reg, val) if addr is None: addr = self.proj.entry state.regs.ip = addr state.scratch.ins_addr = addr state.scratch.bbl_addr = addr state.scratch.stmt_idx = 0 state.scratch.jumpkind = 'Ijk_Boring' state.procedure_data.hook_addr = self.continue_addr return state
def test_abstract_memory(): from claripy.vsa import TrueResult initial_memory = {0: 'A', 1: 'B', 2: 'C', 3: 'D'} s = SimState(mode='static', arch="AMD64", memory_backer=initial_memory, add_options={simuvex.o.ABSTRACT_SOLVER, simuvex.o.ABSTRACT_MEMORY}) se = s.se def to_vs(region, offset): return s.se.VS(region=region, bits=s.arch.bits, val=offset) # Load a single-byte constant from global region expr = s.memory.load(to_vs('global', 2), 1) nose.tools.assert_equal(s.se.any_int(expr), 0x43) nose.tools.assert_equal(s.se.max_int(expr), 0x43) nose.tools.assert_equal(s.se.min_int(expr), 0x43) # Store a single-byte constant to global region s.memory.store(to_vs('global', 1), s.se.BitVecVal(ord('D'), 8), 1) expr = s.memory.load(to_vs('global', 1), 1) nose.tools.assert_equal(s.se.any_int(expr), 0x44) # Store a single-byte StridedInterval to global region si_0 = s.se.StridedInterval(bits=8, stride=2, lower_bound=10, upper_bound=20) s.memory.store(to_vs('global', 4), si_0) # Load the single-byte StridedInterval from global region expr = s.memory.load(to_vs('global', 4), 1) nose.tools.assert_equal(s.se.min_int(expr), 10) nose.tools.assert_equal(s.se.max_int(expr), 20) nose.tools.assert_equal(s.se.any_n_int(expr, 100), [10, 12, 14, 16, 18, 20]) # Store a two-byte StridedInterval object to global region si_1 = s.se.StridedInterval(bits=16, stride=2, lower_bound=10, upper_bound=20) s.memory.store(to_vs('global', 5), si_1) # Load the two-byte StridedInterval object from global region expr = s.memory.load(to_vs('global', 5), 2) nose.tools.assert_true(expr.identical(si_1)) # Store a four-byte StridedInterval object to global region si_2 = s.se.StridedInterval(bits=32, stride=2, lower_bound=8000, upper_bound=9000) s.memory.store(to_vs('global', 7), si_2) # Load the four-byte StridedInterval object from global region expr = s.memory.load(to_vs('global', 7), 4) nose.tools.assert_true(expr.identical(s.se.StridedInterval(bits=32, stride=2, lower_bound=8000, upper_bound=9000))) # Test default values s.options.remove(simuvex.o.SYMBOLIC_INITIAL_VALUES) expr = s.memory.load(to_vs('global', 100), 4) nose.tools.assert_true(expr.identical(s.se.StridedInterval(bits=32, stride=0, lower_bound=0, upper_bound=0))) # Test default values (symbolic) s.options.add(simuvex.o.SYMBOLIC_INITIAL_VALUES) expr = s.memory.load(to_vs('global', 104), 4) nose.tools.assert_true(expr.identical(s.se.StridedInterval(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff))) nose.tools.assert_true(expr.identical(s.se.StridedInterval(bits=32, stride=1, lower_bound=-0x80000000, upper_bound=0x7fffffff))) # # Merging # # Merging two one-byte values s.memory.store(to_vs('function_merge', 0), s.se.StridedInterval(bits=8, stride=0, lower_bound=0x10, upper_bound=0x10)) a = s.copy() a.memory.store(to_vs('function_merge', 0), s.se.StridedInterval(bits=8, stride=0, lower_bound=0x20, upper_bound=0x20)) b = s.merge(a)[0] expr = b.memory.load(to_vs('function_merge', 0), 1) nose.tools.assert_true(expr.identical(s.se.StridedInterval(bits=8, stride=0x10, lower_bound=0x10, upper_bound=0x20))) # | MO(value_0) | # | MO(value_1) | # 0x20 0x24 # Merge one byte in value_0/1 means merging the entire MemoryObject a = s.copy() a.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x100000, upper_bound=0x100000)) b = s.copy() b.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x100001, upper_bound=0x100001)) c = a.merge(b)[0] expr = c.memory.load(to_vs('function_merge', 0x20), 4) nose.tools.assert_true(expr.identical(se.SI(bits=32, stride=1, lower_bound=0x100000, upper_bound=0x100001))) c_mem = c.memory.regions['function_merge'].memory.mem object_set = set([ c_mem[0x20], c_mem[0x20], c_mem[0x22], c_mem[0x23]]) nose.tools.assert_equal(len(object_set), 1) a = s.copy() a.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0x100000, lower_bound=0x100000, upper_bound=0x200000)) b = s.copy() b.memory.store(to_vs('function_merge', 0x20), se.SI(bits=32, stride=0, lower_bound=0x300000, upper_bound=0x300000)) c = a.merge(b)[0] expr = c.memory.load(to_vs('function_merge', 0x20), 4) nose.tools.assert_true(expr.identical(se.SI(bits=32, stride=0x100000, lower_bound=0x100000, upper_bound=0x300000))) object_set = set([c_mem[0x20], c_mem[0x20], c_mem[0x22], c_mem[0x23]]) nose.tools.assert_equal(len(object_set), 1) # # Widening # a = s.se.SI(bits=32, stride=1, lower_bound=1, upper_bound=2) b = s.se.SI(bits=32, stride=1, lower_bound=1, upper_bound=3) a = a.reversed b = b.reversed
def test_memory(): initial_memory = { 0: 'A', 1: 'A', 2: 'A', 3: 'A', 10: 'B' } s = SimState(arch="AMD64", memory_backer=initial_memory, add_options={simuvex.o.REVERSE_MEMORY_NAME_MAP, simuvex.o.REVERSE_MEMORY_HASH_MAP}) # Store a 4-byte variable to memory directly... s.memory.store(100, s.se.BitVecVal(0x1337, 32)) # ... then load it expr = s.memory.load(100, 4) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0x1337, 32).model) expr = s.memory.load(100, 2) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0, 16).model) expr = s.memory.load(102, 2) nose.tools.assert_equal(expr.model, s.se.BitVecVal(0x1337, 16).model) # concrete address and partially symbolic result expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) expr = s.memory.load(2, 4) nose.tools.assert_true(s.se.symbolic(expr)) nose.tools.assert_false(s.se.unique(expr)) nose.tools.assert_greater_equal(s.se.any_int(expr), 0x41410000) nose.tools.assert_less_equal(s.se.any_int(expr), 0x41420000) nose.tools.assert_equal(s.se.min_int(expr), 0x41410000) nose.tools.assert_equal(s.se.max_int(expr), 0x4141ffff) # concrete address and concrete result expr = s.memory.load(0, 4) # Returns: a z3 BitVec representing 0x41414141 nose.tools.assert_false(s.se.symbolic(expr)) nose.tools.assert_equal(s.se.any_int(expr), 0x41414141) # symbolicize v = s.memory.make_symbolic("asdf", 0, length=4) nose.tools.assert_equal(v.size(), 32) nose.tools.assert_true(s.se.unique(v)) nose.tools.assert_equal(s.se.any_int(v), 0x41414141) expr = s.memory.load(0, 4) # Returns: a z3 BitVec representing 0x41414141 nose.tools.assert_true(s.se.symbolic(expr)) nose.tools.assert_equal(s.se.any_int(expr), 0x41414141) nose.tools.assert_true(s.se.unique(expr)) c = s.BV('condition', 8) expr = s.memory.load(10, 1, condition=c==1, fallback=s.BVV('X')) nose.tools.assert_equal(s.se.any_n_str(expr, 10, extra_constraints=[c==1]), [ 'B' ]) nose.tools.assert_equal(s.se.any_n_str(expr, 10, extra_constraints=[c!=1]), [ 'X' ]) x = s.BV('ref_test', 16, explicit_name=True) s.memory.store(0x1000, x) s.memory.store(0x2000, x) nose.tools.assert_equal(set(s.memory.addrs_for_name('ref_test')), set((0x1000,0x1001,0x2000,0x2001))) nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), set((0x1000, 0x1001, 0x2000, 0x2001))) s2 = s.copy() y = s2.BV('ref_test2', 16, explicit_name=True) s2.memory.store(0x2000, y) nose.tools.assert_equal(set(s.memory.addrs_for_name('ref_test')), set((0x1000,0x1001,0x2000,0x2001))) nose.tools.assert_equal(set(s.memory.addrs_for_hash(hash(x))), set((0x1000,0x1001,0x2000,0x2001))) nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test')), set((0x1000, 0x1001))) nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(x))), set((0x1000, 0x1001))) nose.tools.assert_equal(set(s2.memory.addrs_for_name('ref_test2')), set((0x2000, 0x2001))) nose.tools.assert_equal(set(s2.memory.addrs_for_hash(hash(y))), set((0x2000, 0x2001))) s.memory.store(0x3000, s.BV('replace_old', 32, explicit_name=True)) s.memory.store(0x3001, s.BVV('AB')) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set((0x3000, 0x3003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) n = s.BV('replace_new', 32, explicit_name=True) c = s.BV('replace_cool', 32, explicit_name=True) mo = s.memory.memory_objects_for_name('replace_old') nose.tools.assert_equal(len(mo), 1) s.memory.replace_memory_object(next(iter(mo)), n) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set((0x3000, 0x3003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) s.memory.store(0x4000, s.se.If(n == 0, n+10, n+20)) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set((0x3000, 0x3003, 0x4000, 0x4001, 0x4002, 0x4003))) s.memory.replace_all(n, c) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_cool')), set((0x3000, 0x3003, 0x4000, 0x4001, 0x4002, 0x4003))) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) z = s.BVV(0, 32) s.memory.replace_all(c, z) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_old')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_new')), set()) nose.tools.assert_equal(set(s.memory.addrs_for_name('replace_cool')), set()) nose.tools.assert_equal(s.se.any_n_str(s.memory.load(0x3001, 2), 10), ["AB"]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(0x3000, 4), 10), [0x00414200]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(0x4000, 4), 10), [0x0000000a]) # symbolic length x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) n = s.BV('size', 32) s.memory.store(0x5000, x) s.memory.store(0x5000, y, size=n) nose.tools.assert_equal(set(s.se.any_n_int(s.memory.load(0x5000, 4), 10)), { 0x11223344, 0xAA223344, 0xAABB3344, 0xAABBCC44, 0xAABBCCDD }) s1 = s.copy() s1.add_constraints(n == 1) nose.tools.assert_equal(set(s1.se.any_n_int(s1.memory.load(0x5000, 4), 10)), { 0xAA223344 }) s4 = s.copy() s4.add_constraints(n == 4) nose.tools.assert_equal(set(s4.se.any_n_int(s4.memory.load(0x5000, 4), 10)), { 0xAABBCCDD }) # condition without fallback x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) c = s.BV('condition', 32) s.memory.store(0x6000, x) s.memory.store(0x6000, y, condition=c==1) nose.tools.assert_equal(set(s.se.any_n_int(s.memory.load(0x6000, 4), 10)), { 0x11223344, 0xAABBCCDD }) s0 = s.copy() s0.add_constraints(c == 0) nose.tools.assert_equal(set(s0.se.any_n_int(s0.memory.load(0x6000, 4), 10)), { 0x11223344 }) s1 = s.copy() s1.add_constraints(c == 1) nose.tools.assert_equal(set(s1.se.any_n_int(s1.memory.load(0x6000, 4), 10)), { 0xAABBCCDD }) # condition with symbolic size x = s.BVV(0x11223344, 32) y = s.BVV(0xAABBCCDD, 32) c = s.BV('condition', 32) n = s.BV('size', 32) s.memory.store(0x8000, x) s.memory.store(0x8000, y, condition=c==1, size=n) s0 = s.copy() s0.add_constraints(c == 0) nose.tools.assert_equal(set(s0.se.any_n_int(s0.memory.load(0x8000, 4), 10)), { 0x11223344 }) s1 = s.copy() s1.add_constraints(c == 1) nose.tools.assert_equal(set(s1.se.any_n_int(s1.memory.load(0x8000, 4), 10)), { 0x11223344, 0xAA223344, 0xAABB3344, 0xAABBCC44, 0xAABBCCDD })
def test_inline_strcmp(): s = SimState(arch="AMD64", mode="symbolic") str_a = s.se.BitVecVal(0x41414100, 32) str_b = s.BV("mystring", 32) a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(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 = SimProcedures["libc.so.6"]["strcmp"](s_cmp, inline=True, arguments=[a_addr, b_addr]).ret_expr 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.se.unique(str_b)) nose.tools.assert_false(s_nomatch.se.unique(str_b)) nose.tools.assert_equal(s_match.se.any_str(str_b), "AAA\x00") s_ncmp = s.copy() ncmpres = SimProcedures["libc.so.6"]["strncmp"]( s_ncmp, inline=True, arguments=[a_addr, b_addr, s.se.BitVecVal(2, s.arch.bits)] ).ret_expr 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.se.unique(str_b)) nose.tools.assert_true(s_match.se.unique(s_match.memory.load(b_addr, 2))) nose.tools.assert_equal(len(s_match.se.any_n_int(s_match.memory.load(b_addr, 3), 300)), 256) nose.tools.assert_false(s_nomatch.se.unique(str_b)) l.info("concrete a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") str_a = s.se.BitVecVal(0x41424300, 32) str_b = s.BV("mystring", 32) a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(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, inline=True, arguments=[a_addr, b_addr, s.se.BitVecVal(2, s_cmp.arch.bits)]).ret_expr 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.se.solution(str_b, 0x41420000)) nose.tools.assert_true(s_match.se.solution(str_b, 0x41421234)) nose.tools.assert_true(s_match.se.solution(str_b, 0x41424300)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41420000)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41421234)) nose.tools.assert_false(s_nomatch.se.solution(str_b, 0x41424300)) l.info("symbolic a, symbolic b") s = SimState(arch="AMD64", mode="symbolic") a_addr = s.se.BitVecVal(0x10, 64) b_addr = s.se.BitVecVal(0xB0, 64) s_cmp = s.copy() cmpres = strcmp(s_cmp, inline=True, arguments=[a_addr, b_addr]).ret_expr 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, inline=True, arguments=[a_addr, b_addr]).ret_expr s_match.add_constraints(m_res != 0) nm_res = strcmp(s_nomatch, inline=True, arguments=[a_addr, b_addr]).ret_expr s_nomatch.add_constraints(nm_res == 0) nose.tools.assert_false(s_match.satisfiable()) nose.tools.assert_false(s_match.satisfiable())
def broken_strtok_r(): l.debug("CONCRETE MODE") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(100, s.se.BitVecVal(0x4141414241414241424300, 88), endness="Iend_BE") s.memory.store(200, s.se.BitVecVal(0x4200, 16), endness="Iend_BE") str_ptr = s.se.BitVecVal(100, s.arch.bits) delim_ptr = s.se.BitVecVal(200, s.arch.bits) state_ptr = s.se.BitVecVal(300, s.arch.bits) st1 = strtok_r(s, inline=True, arguments=[str_ptr, delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st1.ret_expr, 10), [104]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st1.ret_expr - 1, 1), 10), [0]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(200, 2), 10), [0x4200]) st2 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st2.ret_expr, 10), [107]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st2.ret_expr - 1, 1), 10), [0]) st3 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st3.ret_expr, 10), [109]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st3.ret_expr - 1, 1), 10), [0]) st4 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st4.ret_expr, 10), [0]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109]) st5 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st5.ret_expr, 10), [0]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(300, s.arch.bytes, endness=s.arch.memory_endness), 10), [109]) s.memory.store(1000, s.se.BitVecVal(0x4141414241414241424300, 88), endness="Iend_BE") s.memory.store(2000, s.se.BitVecVal(0x4200, 16), endness="Iend_BE") str_ptr = s.se.BitVecVal(1000, s.arch.bits) delim_ptr = s.se.BitVecVal(2000, s.arch.bits) state_ptr = s.se.BitVecVal(3000, s.arch.bits) st1 = strtok_r(s, inline=True, arguments=[str_ptr, delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st1.ret_expr, 10), [1004]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st1.ret_expr - 1, 1), 10), [0]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(2000, 2), 10), [0x4200]) st2 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st2.ret_expr, 10), [1007]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st2.ret_expr - 1, 1), 10), [0]) st3 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st3.ret_expr, 10), [1009]) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st3.ret_expr - 1, 1), 10), [0]) st4 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st4.ret_expr, 10), [0]) nose.tools.assert_equal( s.se.any_n_int(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009] ) st5 = strtok_r(s, inline=True, arguments=[s.se.BitVecVal(0, s.arch.bits), delim_ptr, state_ptr]) nose.tools.assert_equal(s.se.any_n_int(st5.ret_expr, 10), [0]) nose.tools.assert_equal( s.se.any_n_int(s.memory.load(3000, s.arch.bytes, endness=s.arch.memory_endness), 10), [1009] ) print "LIGHT FULLY SYMBOLIC TEST" s = SimState(arch="AMD64", mode="symbolic") str_ptr = s.se.BitVecVal(100, s.arch.bits) delim_ptr = s.se.BitVecVal(200, s.arch.bits) state_ptr = s.se.BitVecVal(300, s.arch.bits) s.add_constraints(s.memory.load(delim_ptr, 1) != 0) st1 = strtok_r(s, inline=True, arguments=[str_ptr, delim_ptr, state_ptr]) s.add_constraints(st1.ret_expr != 0) nose.tools.assert_equal(s.se.any_n_int(s.memory.load(st1.ret_expr - 1, 1), 10), [0])
def test_some_vector_ops(): from simuvex.vex.irop import translate s = SimState() a = s.BVV(0xffff0000000100020003000400050006, 128) b = s.BVV(0x00020002000200020002000200020002, 128) calc_result = translate(s, 'Iop_Sub16x8', (a, b)) correct_result = s.BVV(0xfffdfffeffff00000001000200030004, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_CmpEQ16x8', (a, b)) correct_result = s.BVV(0x000000000000ffff0000000000000000, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_CmpEQ8x16', (a, b)) correct_result = s.BVV(0x0000ff00ff00ffffff00ff00ff00ff00, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_CmpGT16Sx8', (a, b)) correct_result = s.BVV(0x0000000000000000ffffffffffffffff, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_CmpGT16Ux8', (a, b)) correct_result = s.BVV(0xffff000000000000ffffffffffffffff, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_InterleaveLO16x8', (a, b)) correct_result = s.BVV(0x00030002000400020005000200060002, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_InterleaveLO8x16', (a, b)) correct_result = s.BVV(0x00000302000004020000050200000602, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_Min8Ux16', (a, b)) correct_result = s.BVV(0x00020000000100020002000200020002, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_Min8Sx16', (a, b)) correct_result = s.BVV(0xffff0000000100020002000200020002, 128) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) c = s.BVV(0xff008877, 32) d = s.BVV(0x11111111, 32) calc_result = translate(s, 'Iop_HAdd8Sx4', (c, d)) correct_result = s.BVV(0x0808cc44, 32) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_QAdd8Sx4', (c, d)) correct_result = s.BVV(0x1011997f, 32) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_QAdd8Ux4', (c, d)) correct_result = s.BVV(0xff119988, 32) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_QSub8Sx4', (c, d)) correct_result = s.BVV(0xeeef8066, 32) nose.tools.assert_true(s.se.is_true(calc_result == correct_result)) calc_result = translate(s, 'Iop_QSub8Ux4', (c, d)) correct_result = s.BVV(0xee007766, 32) nose.tools.assert_true(s.se.is_true(calc_result == correct_result))
def broken_inline_strstr(): l.info("concrete haystack and needle") s = SimState(arch="AMD64", mode="symbolic") str_haystack = s.se.BitVecVal(0x41424300, 32) str_needle = s.se.BitVecVal(0x42430000, 32) addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xB0, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") s.memory.store(addr_needle, str_needle, endness="Iend_BE") ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_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.BitVecVal(0x41424300, 32) str_needle = s.BV("wtf", 32) addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xB0, 64) s.memory.store(addr_haystack, str_haystack, endness="Iend_BE") s.memory.store(addr_needle, str_needle, endness="Iend_BE") ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_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) match_needle = str_needle[31:16] nose.tools.assert_equal(len(s_match.se.any_n_int(match_needle, 300)), 259) nose.tools.assert_equal(len(s_match.se.any_n_int(str_needle, 10)), 10) l.info("symbolic haystack, symbolic needle") s = SimState(arch="AMD64", mode="symbolic") s.libc.buf_symbolic_bytes = 5 addr_haystack = s.se.BitVecVal(0x10, 64) addr_needle = s.se.BitVecVal(0xB0, 64) len_needle = strlen(s, inline=True, arguments=[addr_needle]) ss_res = strstr(s, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr nose.tools.assert_false(s.se.unique(ss_res)) nose.tools.assert_equal(len(s.se.any_n_int(ss_res, 100)), s.libc.buf_symbolic_bytes) s_match = s.copy() s_nomatch = s.copy() s_match.add_constraints(ss_res != 0) s_nomatch.add_constraints(ss_res == 0) match_cmp = strncmp(s_match, inline=True, arguments=[ss_res, addr_needle, len_needle.ret_expr]).ret_expr nose.tools.assert_items_equal(s_match.se.any_n_int(match_cmp, 10), [0]) r_mm = strstr(s_match, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s_match.add_constraints(r_mm == 0) nose.tools.assert_false(s_match.satisfiable()) nose.tools.assert_true(s_nomatch.satisfiable()) s_nss = s_nomatch.copy() nomatch_ss = strstr(s_nss, inline=True, arguments=[addr_haystack, addr_needle]).ret_expr s_nss.add_constraints(nomatch_ss != 0) nose.tools.assert_false(s_nss.satisfiable())
def test_memcpy(): l.info("concrete src, concrete dst, concrete len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BVV(0x41414141, 32) dst_addr = s.se.BVV(0x1000, 64) src = s.se.BVV(0x42424242, 32) src_addr = s.se.BVV(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BVV(4, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), [ "BBBB" ]) l.info("giant copy") s = SimState(arch="AMD64", mode="symbolic", remove_options=simuvex.o.simplification) s.memory._maximum_symbolic_size = 0x2000000 size = s.se.BVV(0x1000000, 64) dst_addr = s.se.BVV(0x2000000, 64) src_addr = s.se.BVV(0x4000000, 64) memcpy(s, inline=True, arguments=[dst_addr, src_addr, size]) nose.tools.assert_is(s.memory.load(dst_addr, size), s.memory.load(src_addr, size)) l.debug("... partial copy") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BVV(2, 64)]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), [ "BBAA" ]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BVV(0x41414141, 32) dst_addr = s.se.BVV(0x1000, 64) src = s.se.BVS("src", 32) src_addr = s.se.BVV(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BVV(4, 64)]) nose.tools.assert_true(s.satisfiable()) s.add_constraints(src != s.memory.load(dst_addr, 4)) nose.tools.assert_false(s.satisfiable()) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BVV(0x41414141, 32) dst_addr = s.se.BVV(0x1000, 64) src = s.se.BVS("src", 32) src_addr = s.se.BVV(0x2000, 64) cpylen = s.se.BVS("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) result = s.memory.load(dst_addr, 4, endness='Iend_BE') # make sure it copies it all s1 = s.copy() s1.add_constraints(cpylen == 1) nose.tools.assert_true(s1.se.unique(s1.memory.load(dst_addr+1, 3))) nose.tools.assert_equals(len(s1.se.any_n_int(s1.memory.load(dst_addr, 1), 300)), 256) s2 = s.copy() s2.add_constraints(cpylen == 2) nose.tools.assert_equals(len(s2.se.any_n_int(result[31:24], 300)), 256) nose.tools.assert_equals(len(s2.se.any_n_int(result[23:16], 300)), 256) nose.tools.assert_equals(s2.se.any_n_str(result[15:0], 300), [ 'AA' ]) l.info("concrete src, concrete dst, symbolic len") dst = s2.se.BVV(0x41414141, 32) dst_addr = s2.se.BVV(0x1000, 64) src = s2.se.BVV(0x42424242, 32) src_addr = s2.se.BVV(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) cpylen = s.se.BVS("len", 64) s.add_constraints(s.se.ULE(cpylen, 4)) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) new_dst = s.memory.load(dst_addr, 4, endness='Iend_BE') nose.tools.assert_items_equal(s.se.any_n_str(new_dst, 300), [ 'AAAA', 'BAAA', 'BBAA', 'BBBA', 'BBBB' ])
def test_inline_strncmp(): l.info("symbolic left, symbolic right, symbolic len") s = SimState(arch="AMD64", mode="symbolic") left = s.BV("left", 32) left_addr = s.se.BitVecVal(0x1000, 64) right = s.BV("right", 32) right_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(left_addr, left) s.memory.store(right_addr, right) s.add_constraints(strlen(s, inline=True, arguments=[left_addr]).ret_expr == 3) s.add_constraints(strlen(s, inline=True, arguments=[right_addr]).ret_expr == 0) s.add_constraints(maxlen != 0) c = strncmp(s, inline=True, arguments=[left_addr, right_addr, maxlen]).ret_expr s_match = s.copy() s_match.add_constraints(c == 0) nose.tools.assert_false(s_match.satisfiable()) # nose.tools.assert_equals(s_match.se.min_int(maxlen), 3) s_nomatch = s.copy() s_nomatch.add_constraints(c != 0) nose.tools.assert_true(s_nomatch.satisfiable()) # nose.tools.assert_equals(s_nomatch.se.max_int(maxlen), 2) l.info("zero-length") s = SimState(arch="AMD64", mode="symbolic") left = s.BV("left", 32) left_addr = s.se.BitVecVal(0x1000, 64) right = s.BV("right", 32) right_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) left_len = strlen(s, inline=True, arguments=[left_addr]).ret_expr right_len = strlen(s, inline=True, arguments=[right_addr]).ret_expr c = strncmp(s, inline=True, arguments=[left_addr, right_addr, maxlen]).ret_expr s.add_constraints(right_len == 0) s.add_constraints(left_len == 0) # s.add_constraints(c == 0) s.add_constraints(maxlen == 0) nose.tools.assert_true(s.satisfiable())
def test_cased_store(): initial_memory = { 0: 'A', 1: 'A', 2: 'A', 3: 'A' } so = SimState(arch="AMD64", memory_backer=initial_memory) # sanity check nose.tools.assert_equal(so.se.any_n_str(so.memory.load(0, 4), 2), ['AAAA']) # the values values = [ None, so.BVV('B'), so.BVV('CC'), so.BVV('DDD'), so.BVV('EEEE') ] # try the write s = so.copy() x = s.se.BV('x', 32) s.memory.store_cases(0, values, [ x == i for i in range(len(values)) ]) for i,v in enumerate(values): v = '' if v is None else s.se.any_str(v) w = s.se.any_n_str(s.memory.load(0, 4), 2, extra_constraints=[x==i]) nose.tools.assert_equal(w, [v.ljust(4, 'A')]) # and now with a fallback y = s.se.BV('y', 32) s.memory.store_cases(0, values, [ y == i for i in range(len(values)) ], fallback=s.BVV('XXXX')) for i,v in enumerate(values): v = '' if v is None else s.se.any_str(v) w = s.se.any_n_str(s.memory.load(0, 4), 2, extra_constraints=[y==i]) nose.tools.assert_equal(w, [v.ljust(4, 'X')]) # and now with endness y = s.se.BV('y', 32) s.memory.store_cases(0, values, [ y == i for i in range(len(values)) ], fallback=s.BVV('XXXX'), endness="Iend_LE") for i,v in enumerate(values): v = '' if v is None else s.se.any_str(v) w = s.se.any_n_str(s.memory.load(0, 4), 2, extra_constraints=[y==i]) print w, v.rjust(4, 'X') nose.tools.assert_equal(w, [v.rjust(4, 'X')]) # and write all Nones s = so.copy() z = s.se.BV('z', 32) s.memory.store_cases(0, [ None, None, None ], [ z == 0, z == 1, z == 2]) for i in range(len(values)): w = s.se.any_n_str(s.memory.load(0, 4), 2, extra_constraints=[z==i]) nose.tools.assert_equal(w, ['AAAA']) # and all Nones with a fallback u = s.se.BV('w', 32) s.memory.store_cases(0, [ None, None, None ], [ u == 0, u == 1, u == 2], fallback=s.BVV('WWWW')) for i,v in enumerate(values): w = s.se.any_n_str(s.memory.load(0, 4), 2, extra_constraints=[u==i]) nose.tools.assert_equal(w, ['WWWW']) # and all identical values s = so.copy() #t = s.se.BV('t', 32) s.memory.store_cases(0, [ s.BVV('AA'), s.BVV('AA'), s.BVV('AA') ], [ u == 0, u == 1, u == 2], fallback=s.BVV('AA')) r = s.memory.load(0, 2) nose.tools.assert_equal(r.op, 'I') nose.tools.assert_equal(s.se.any_n_str(r, 2), ['AA']) # and all identical values, with varying fallback s = so.copy() #t = s.se.BV('t', 32) s.memory.store_cases(0, [ s.BVV('AA'), s.BVV('AA'), s.BVV('AA') ], [ u == 0, u == 1, u == 2], fallback=s.BVV('XX')) r = s.memory.load(0, 2) nose.tools.assert_equal(s.se.any_n_str(r, 3), ['AA', 'XX']) # and some identical values s = so.copy() #q = s.se.BV('q', 32) values = [ 'AA', 'BB', 'AA' ] s.memory.store_cases(0, [ s.BVV(v) for v in values ], [ u == i for i in range(len(values))], fallback=s.BVV('XX')) r = s.memory.load(0, 2) for i,v in enumerate(values + ['XX']): w = s.se.any_n_str(s.memory.load(0, 2), 2, extra_constraints=[u==i]) nose.tools.assert_equal(w, [(values+['XX'])[i]])
def test_state_merge(): a = SimState(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.any_int(a.memory.load(1, 1)), 42) nose.tools.assert_equal(b.se.any_int(b.memory.load(1, 1)), 42) nose.tools.assert_equal(c.se.any_int(c.memory.load(1, 1)), 42) # make sure the byte at 2 is right nose.tools.assert_equal(a.se.any_int(a.memory.load(2, 1)), 43) nose.tools.assert_equal(b.se.any_int(b.memory.load(2, 1)), 84) nose.tools.assert_equal(c.se.any_int(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('simuvex.plugins.symbolic_memory').setLevel(logging.DEBUG) m, merge_flag, merging_occurred = a.merge(b, c) logging.getLogger('simuvex.plugins.symbolic_memory').setLevel(logging.WARNING) nose.tools.assert_true(merging_occurred) nose.tools.assert_equals(sorted(m.se.any_n_int(merge_flag, 10)), [ 0,1,2 ]) # 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.any_n_int(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_flag == 0) nose.tools.assert_true(a_a.se.unique(a_a.memory.load(2, 1))) nose.tools.assert_equal(a_a.se.any_int(a_a.memory.load(2, 1)), 43) a_b = m.copy() a_b.add_constraints(merge_flag == 1) nose.tools.assert_true(a_b.se.unique(a_b.memory.load(2, 1))) nose.tools.assert_equal(a_b.se.any_int(a_b.memory.load(2, 1)), 84) a_c = m.copy() a_c.add_constraints(merge_flag == 2) nose.tools.assert_true(a_c.se.unique(a_c.memory.load(2, 1))) nose.tools.assert_equal(a_c.se.any_int(a_c.memory.load(2, 1)), 21) # test different sets of plugins a = SimState(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(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_memcpy(): l.info("concrete src, concrete dst, concrete len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42424242, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBBB"]) l.debug("... partial copy") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(2, 64)]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBAA"]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all memcpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]) nose.tools.assert_true(s.satisfiable()) s.add_constraints(src != s.memory.load(dst_addr, 4)) nose.tools.assert_false(s.satisfiable()) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) cpylen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) result = s.memory.load(dst_addr, 4, endness="Iend_BE") # make sure it copies it all s1 = s.copy() s1.add_constraints(cpylen == 1) nose.tools.assert_true(s1.se.unique(s1.memory.load(dst_addr + 1, 3))) nose.tools.assert_equals(len(s1.se.any_n_int(s1.memory.load(dst_addr, 1), 300)), 256) s2 = s.copy() s2.add_constraints(cpylen == 2) nose.tools.assert_equals(len(s2.se.any_n_int(result[31:24], 300)), 256) nose.tools.assert_equals(len(s2.se.any_n_int(result[23:16], 300)), 256) nose.tools.assert_equals(s2.se.any_n_str(result[15:0], 300), ["AA"]) l.info("concrete src, concrete dst, symbolic len") dst = s2.se.BitVecVal(0x41414141, 32) dst_addr = s2.se.BitVecVal(0x1000, 64) src = s2.se.BitVecVal(0x42424242, 32) src_addr = s2.se.BitVecVal(0x2000, 64) s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) cpylen = s.BV("len", 64) s.add_constraints(s.se.ULE(cpylen, 4)) memcpy(s, inline=True, arguments=[dst_addr, src_addr, cpylen]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_items_equal(s.se.any_n_str(new_dst, 300), ["AAAA", "BAAA", "BBAA", "BBBA", "BBBB"])
def test_strncpy(): l.info("concrete src, concrete dst, concrete len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(3, 64)]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_equal(s.se.any_str(new_dst), "BB\x00\x00") l.debug("... partial copy") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(2, 64)]) new_dst = s.memory.load(dst_addr, 4, endness="Iend_BE") nose.tools.assert_equal(s.se.any_n_str(new_dst, 2), ["BBA\x00"]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all s.add_constraints(strlen(s, inline=True, arguments=[src_addr]).ret_expr == 2) # sanity check s_false = s.copy() s_false.add_constraints(strlen(s_false, inline=True, arguments=[src_addr]).ret_expr == 3) nose.tools.assert_false(s_false.satisfiable()) strncpy(s, inline=True, arguments=[dst_addr, src_addr, 3]) nose.tools.assert_true(s.satisfiable()) c = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr nose.tools.assert_items_equal(s.se.any_n_int(c, 10), [0]) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all s.add_constraints(strlen(s, inline=True, arguments=[src_addr]).ret_expr == 2) strncpy(s, inline=True, arguments=[dst_addr, src_addr, maxlen]) c = strcmp(s, inline=True, arguments=[dst_addr, src_addr]).ret_expr s_match = s.copy() s_match.add_constraints(c == 0) nose.tools.assert_equals(s_match.se.min_int(maxlen), 3) s_nomatch = s.copy() s_nomatch.add_constraints(c != 0) nose.tools.assert_equals(s_nomatch.se.max_int(maxlen), 2) l.info("concrete src, concrete dst, symbolic len") l.debug("... full copy") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414100, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42420000, 32) src_addr = s.se.BitVecVal(0x2000, 64) maxlen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) strncpy(s, inline=True, arguments=[dst_addr, src_addr, maxlen]) r = s.memory.load(dst_addr, 4, endness="Iend_BE") # print repr(r.se.any_n_str(10)) nose.tools.assert_items_equal(s.se.any_n_str(r, 10), ["AAA\x00", "BAA\x00", "BBA\x00", "BB\x00\x00"])
def broken_symbolic_write(): s = SimState(arch='AMD64', mode='symbolic') addr = s.BV('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.BitVecVal(1, 8)) s.memory.store(20, s.se.BitVecVal(2, 8)) s.memory.store(30, s.se.BitVecVal(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.BitVecVal(255, 8), strategy=['symbolic','any'], limit=100) s.memory.store(addr, s.se.BitVecVal(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 = SimState(arch='AMD64', mode='symbolic') s.memory.store(0, s.se.BitVecVal(0x4141414141414141, 64)) length = s.BV("length", 32) #s.memory.store(0, s.se.BitVecVal(0x4242424242424242, 64), symbolic_length=length) s.memory.store(0, s.se.BitVecVal(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 test_memcmp(): l.info("concrete src, concrete dst, concrete len") l.debug("... full cmp") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.se.BitVecVal(0x42424242, 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.BVV(4, 64)]).ret_expr nose.tools.assert_true(s.satisfiable()) s_pos = s.copy() s_pos.add_constraints(r.SGE(0)) nose.tools.assert_false(s_pos.satisfiable()) s_neg = s.copy() s_neg.add_constraints(r.SLT(0)) nose.tools.assert_true(s_neg.satisfiable()) l.debug("... zero cmp") s = SimState(arch="AMD64", mode="symbolic") s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(0, 64)]).ret_expr nose.tools.assert_equals(s.se.any_n_int(r, 2), [0]) l.info("symbolic src, concrete dst, concrete len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) # make sure it copies it all r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, s.se.BitVecVal(4, 64)]).ret_expr s_match = s.copy() s_match.add_constraints(r == 0) m = s_match.memory.load(src_addr, 4) nose.tools.assert_equal(s_match.se.any_n_int(m, 2), [0x41414141]) s_nomatch = s.copy() s_nomatch.add_constraints(r != 0) m = s_nomatch.memory.load(src_addr, 4) nose.tools.assert_false(s_nomatch.se.solution(m, 0x41414141)) l.info("symbolic src, concrete dst, symbolic len") s = SimState(arch="AMD64", mode="symbolic") dst = s.se.BitVecVal(0x41414141, 32) dst_addr = s.se.BitVecVal(0x1000, 64) src = s.BV("src", 32) src_addr = s.se.BitVecVal(0x2000, 64) cmplen = s.BV("len", 64) s.memory.store(dst_addr, dst) s.memory.store(src_addr, src) r = memcmp(s, inline=True, arguments=[dst_addr, src_addr, cmplen]).ret_expr # look at effects of different lengths s1 = s.copy() s1.add_constraints(cmplen == 1) s1.add_constraints(r == 0) l.debug("... simplifying") s1.se._solver.simplify() l.debug("... solving") nose.tools.assert_equals(s1.se.any_n_int(src[31:24], 2), [0x41]) nose.tools.assert_false(s1.se.unique(src[31:16])) l.debug("... solved") s2 = s.copy() s2.add_constraints(cmplen == 2) s2.add_constraints(r == 0) nose.tools.assert_equals(s2.se.any_n_int(s2.memory.load(src_addr, 2), 2), [0x4141]) nose.tools.assert_false(s2.se.unique(s2.memory.load(src_addr, 3))) s2u = s.copy() s2u.add_constraints(cmplen == 2) s2u.add_constraints(r == 1) nose.tools.assert_false(s2u.se.solution(s2u.memory.load(src_addr, 2), 0x4141))