def test_concrete_memset(): def _individual_test(state, base, val, size): # time it start = time.time() memset = simuvex.SimProcedures['libc.so.6']['memset']( 0x100000, state.arch).execute(state, arguments=[base, state.se.BVV(val, 8), size]) elapsed = time.time() - start # should be done within 1 second nose.tools.assert_less_equal(elapsed, 5) # the result should be good byt_0 = memset.state.memory.load(base, 1) nose.tools.assert_equal(s.se.any_n_int(byt_0, 10), [val]) byt_1 = memset.state.memory.load(base + 1, 1) nose.tools.assert_equal(s.se.any_n_int(byt_1, 10), [val]) byt_2 = memset.state.memory.load(base + size - 1, 1) nose.tools.assert_equal(s.se.any_n_int(byt_2, 10), [val]) BASE = 0x800000 SIZE = 0x200000 # Writes many zeros VAL = 0 s = simuvex.SimState(arch='AMD64') _individual_test(s, BASE, VAL, SIZE) # Writes many ones VAL = 1 s = simuvex.SimState(arch='AMD64') _individual_test(s, BASE, VAL, SIZE)
def test_fullpage_write(): s = simuvex.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 = simuvex.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 = simuvex.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 = simuvex.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 test_files(): s = simuvex.SimState() s.posix.write(0, "HELLO", 5) s.posix.write(0, "WORLD", 5) assert s.posix.dumps(0) == "HELLOWORLD" s = simuvex.SimState() s.posix.write(0, "A" * 0x1000, 0x1000) assert s.posix.dumps(0) == "A" * 0x1000
def static_exits(self, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = simuvex.SimState(arch=self.arch, mode="fastpath") # Execute each block state = blank_state for b in blocks: irsb = simuvex.SimEngineVEX().process( state, b, force_addr=next( iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr) if irsb.successors: state = irsb.successors[0] else: break cc = simuvex.DefaultCC[self.arch.name](self.arch) callfunc = cc.arg(state, 2) retaddr = state.memory.load(state.regs.sp, self.arch.bytes) all_exits = [(callfunc, 'Ijk_Call'), (retaddr, 'Ijk_Ret')] return all_exits
def test_inspect_exit(): class counts: #pylint:disable=no-init exit_before = 0 exit_after = 0 def handle_exit_before(state): counts.exit_before += 1 exit_target = state.inspect.exit_target nose.tools.assert_equal(state.se.any_int(exit_target), 0x3f8) # change exit target state.inspect.exit_target = 0x41414141 nose.tools.assert_equal(state.inspect.exit_jumpkind, "Ijk_Boring") nose.tools.assert_true(state.inspect.exit_guard.is_true()) def handle_exit_after(state): #pylint:disable=unused-argument counts.exit_after += 1 s = simuvex.SimState(arch="AMD64", mode="symbolic") irsb = pyvex.IRSB("\x90\x90\x90\x90\xeb\x0a", mem_addr=1000, arch=archinfo.ArchAMD64()) # break on exit s.inspect.b('exit', simuvex.BP_BEFORE, action=handle_exit_before) s.inspect.b('exit', simuvex.BP_AFTER, action=handle_exit_after) # step it succ = simuvex.SimIRSB(s, irsb).successors # check nose.tools.assert_equal( succ[0].se.any_int(succ[0].ip), 0x41414141) nose.tools.assert_equal(counts.exit_before, 1) nose.tools.assert_equal(counts.exit_after, 1)
def test_symbolic_write(): s = simuvex.SimState( arch='AMD64', add_options={simuvex.options.SYMBOLIC_WRITE_ADDRESSES}) x = s.se.BVS('x', 64) y = s.se.BVS('y', 64) a = s.se.BVV('A' * 0x10) b = s.se.BVV('B') c = s.se.BVV('C') d = s.se.BVV('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.se.any_n_int(s.memory.load(i, 1), 10)) == 2 s.memory.store(x, c) for i in range(0x10, 0x20): assert len(s.se.any_n_int(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.se.any_n_int(s2.memory.load(i, 1), 10)) == 3
def static_exits(cls, arch, blocks): # Execute those blocks with a blank state, and then dump the arguments blank_state = simuvex.SimState(arch=arch, mode="fastpath") # Execute each block state = blank_state for b in blocks: # state.regs.ip = next(iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr irsb = simuvex.SimIRSB( state, b, addr=next( iter(stmt for stmt in b.statements if isinstance(stmt, pyvex.IRStmt.IMark))).addr) if irsb.successors: state = irsb.successors[0] else: break cc = simuvex.DefaultCC[arch.name](arch) args = [cc.arg(state, _) for _ in xrange(5)] main, _, _, init, fini = cls._extract_args(blank_state, *args) all_exits = [ (init, 'Ijk_Call'), (main, 'Ijk_Call'), (fini, 'Ijk_Call'), ] return all_exits
def test_lseek_end(): state = simuvex.SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file f = state.posix.get_file(fd) # Give this a fake size f.size = 16 # Part 1 # Add 5 current_pos = lseek(state,[fd,5,SEEK_END]).ret_expr current_pos = state.se.any_int(current_pos) # We should be at the end + offset nose.tools.assert_equal(current_pos,21) # Part 2 # Minus 6. End of file never actually changed current_pos = lseek(state,[fd,-6,SEEK_END]).ret_expr current_pos = state.se.any_int(current_pos) # We should be at the end + offset nose.tools.assert_equal(current_pos,10)
def test_global_condition(): s = simuvex.SimState() 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.any_n_int(s.regs.rbx, 10), [0]) nose.tools.assert_items_equal(s.se.any_n_int(s.regs.rax, 10), [30]) with s.with_condition(s.regs.rbx == 1): nose.tools.assert_equals(s.se.any_n_int(s.regs.rbx, 10), [1]) nose.tools.assert_items_equal(s.se.any_n_int(s.regs.rax, 10), [25])
def test_lseek_cur(): state = simuvex.SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file state.posix.get_file(fd) # Part 1 # Add 12 current_pos = lseek(state,[fd,12,SEEK_CUR]).ret_expr current_pos = state.se.any_int(current_pos) # We should be at the start nose.tools.assert_equal(current_pos,12) # Part 2 # Remove 3 current_pos = lseek(state,[fd,-3,SEEK_CUR]).ret_expr current_pos = state.se.any_int(current_pos) # We should be at the start nose.tools.assert_equal(current_pos,9)
def test_lseek_set(): state = simuvex.SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file state.posix.get_file(fd) # Part 1 # Seek to the top of the file current_pos = lseek(state,[fd,0,SEEK_SET]).ret_expr current_pos = state.se.any_int(current_pos) # We should be at the start nose.tools.assert_equal(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.se.any_int(current_pos) # We should be at the start nose.tools.assert_equal(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.se.any_int(current_pos) # We should be at the start nose.tools.assert_equal(current_pos,3)
def test_inspect_syscall(): class counts: #pylint:disable=no-init exit_before = 0 exit_after = 0 def handle_syscall_before(state): counts.exit_before += 1 syscall_name = state.inspect.syscall_name nose.tools.assert_equal(syscall_name, "close") def handle_syscall_after(state): counts.exit_after += 1 syscall_name = state.inspect.syscall_name nose.tools.assert_equal(syscall_name, "close") s = simuvex.SimState(arch="AMD64", mode="symbolic") # set up to call so syscall close s.regs.rax = 3 s.regs.rdi = 2 # break on syscall s.inspect.b('syscall', simuvex.BP_BEFORE, action=handle_syscall_before) s.inspect.b('syscall', simuvex.BP_AFTER, action=handle_syscall_after) # step it simuvex.SimProcedures['syscalls']['close'](s, addr=s.se.any_int(s.ip), ret_to=s.ip, syscall_name='close') # check counts nose.tools.assert_equal(counts.exit_before, 1) nose.tools.assert_equal(counts.exit_after, 1)
def test_fast_memory(): s = simuvex.SimState(add_options={simuvex.o.FAST_REGISTERS, simuvex.o.FAST_MEMORY}) s.regs.rax = 0x4142434445464748 s.regs.rbx = 0x5555555544444444 assert (s.regs.rax == 0x4142434445464748).is_true() assert (s.regs.rbx == 0x5555555544444444).is_true() _concrete_memory_tests(s)
def test_registers(): s = simuvex.SimState(arch='AMD64') expr = s.registers.load('rax') nose.tools.assert_true(s.se.symbolic(expr)) s.registers.store('rax', 0x31) expr = s.registers.load('rax') nose.tools.assert_false(s.se.symbolic(expr)) nose.tools.assert_equals(s.se.any_int(expr), 0x00000031)
def test_false_condition(): s = simuvex.SimState(arch='AMD64') asdf = s.se.BVV('asdf') fdsa = s.se.BVV('fdsa') s.memory.store(0x1000, asdf) s.memory.store(0x1000, fdsa, condition=s.se.false) s.memory.store(0, fdsa, condition=s.se.false) assert s.memory.load(0x1000, 4) is asdf assert 0 not in s.memory.mem._pages
def test_mmap_base_copy(): state = simuvex.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_lseek_symbolic_whence(): # symbolic whence is currently not possible state = simuvex.SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file state.posix.get_file(fd) whence = state.se.BVS('whence',64) # This should cause the exception lseek(state,[fd,0,whence])
def test_lseek_symbolic_seek(): # symbolic seek is currently not possible state = simuvex.SimState(arch="AMD64", mode="symbolic") # This could be any number above 2 really fd = 3 # Create a file state.posix.get_file(fd) seek = state.se.BVS('seek',64) # This should cause the exception lseek(state,[fd,seek,SEEK_SET])
def test_load_bytes(): s = simuvex.SimState(arch='AMD64') asdf = s.se.BVS('asdf', 0x1000*8) s.memory.store(0x4000, asdf) items = s.memory.mem.load_objects(0x4000, 0x1000) assert len(items) == 1 fdsa = s.se.BVV('fdsa') s.memory.store(0x4004, fdsa) items = s.memory.mem.load_objects(0x4000, 0x1000) assert len(items) == 3 items = s.memory.mem.load_objects(0x8000, 0x2000) assert len(items) == 0
def test_state(): s = simuvex.SimState(arch='AMD64') s.registers.store('sp', 0x7ffffffffff0000) nose.tools.assert_equals(s.se.any_int(s.registers.load('sp')), 0x7ffffffffff0000) s.stack_push(s.se.BVV("ABCDEFGH")) nose.tools.assert_equals(s.se.any_int(s.registers.load('sp')), 0x7fffffffffefff8) s.stack_push(s.se.BVV("IJKLMNOP")) nose.tools.assert_equals(s.se.any_int(s.registers.load('sp')), 0x7fffffffffefff0) a = s.stack_pop() nose.tools.assert_equals(s.se.any_int(s.registers.load('sp')), 0x7fffffffffefff8) nose.tools.assert_equals(s.se.any_str(a), "IJKLMNOP") b = s.stack_pop() nose.tools.assert_equals(s.se.any_int(s.registers.load('sp')), 0x7ffffffffff0000) nose.tools.assert_equals(s.se.any_str(b), "ABCDEFGH")
def test_load_bytes(): s = simuvex.SimState(arch='AMD64') asdf = s.se.BVS('asdf', 0x1000 * 8) s.memory.store(0x4000, asdf) the_bytes, missing, bytes_read = s.memory.mem.load_bytes(0x4000, 0x1000) assert len(missing) == 0 assert len(the_bytes) == 1 assert bytes_read == 0x1000 fdsa = s.se.BVV('fdsa') s.memory.store(0x4004, fdsa) the_bytes, missing, bytes_read = s.memory.mem.load_bytes(0x4000, 0x1000) assert len(missing) == 0 assert len(the_bytes) == 3 assert bytes_read == 0x1000 the_bytes, missing, bytes_read = s.memory.mem.load_bytes(0x8000, 0x2000) assert len(the_bytes) == 0 assert len(missing) == 2 assert bytes_read == 0x2000
def test_lseek_unseekable(): state = simuvex.SimState(arch="AMD64", mode="symbolic") # Illegal seek current_pos = lseek(state,[0,0,SEEK_SET]).ret_expr current_pos = state.se.any_int(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.any_int(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.any_int(current_pos) # Assert we have a negative return value nose.tools.assert_true(current_pos & (1 << 63) != 0)
def test_inspect(): class counts: #pylint:disable=no-init mem_read = 0 mem_write = 0 reg_read = 0 reg_write = 0 tmp_read = 0 tmp_write = 0 expr = 0 statement = 0 instruction = 0 constraints = 0 variables = 0 def act_mem_read(state): #pylint:disable=unused-argument counts.mem_read += 1 def act_mem_write(state): #pylint:disable=unused-argument counts.mem_write += 1 def act_reg_read(state): #pylint:disable=unused-argument counts.reg_read += 1 def act_reg_write(state): #pylint:disable=unused-argument counts.reg_write += 1 def act_tmp_read(state): #pylint:disable=unused-argument counts.tmp_read += 1 def act_tmp_write(state): #pylint:disable=unused-argument counts.tmp_write += 1 def act_expr(state): #pylint:disable=unused-argument counts.expr += 1 def act_statement(state): #pylint:disable=unused-argument counts.statement += 1 def act_instruction(state): #pylint:disable=unused-argument counts.instruction += 1 def act_variables(state): #pylint:disable=unused-argument #print "CREATING:", state.inspect.symbolic_name counts.variables += 1 # def act_constraints(state): #pylint:disable=unused-argument # counts.constraints += 1 s = simuvex.SimState(arch="AMD64", mode="symbolic") s.inspect.b('mem_write', when=simuvex.BP_AFTER, action=act_mem_write) nose.tools.assert_equals(counts.mem_write, 0) s.memory.store(100, s.se.BVV(10, 32)) nose.tools.assert_equals(counts.mem_write, 1) s.inspect.b('mem_read', when=simuvex.BP_AFTER, action=act_mem_read) s.inspect.b('mem_read', when=simuvex.BP_AFTER, action=act_mem_read, mem_read_address=100) s.inspect.b('mem_read', when=simuvex.BP_AFTER, action=act_mem_read, mem_read_address=123) s.inspect.b('mem_read', when=simuvex.BP_BEFORE, action=act_mem_read, mem_read_length=3) nose.tools.assert_equals(counts.mem_read, 0) s.memory.load(123, 4) s.memory.load(223, 3) nose.tools.assert_equals(counts.mem_read, 4) s.inspect.b('reg_read', when=simuvex.BP_AFTER, action=act_reg_read) nose.tools.assert_equals(counts.reg_read, 0) s.registers.load(16) nose.tools.assert_equals(counts.reg_read, 1) s.inspect.b('reg_write', when=simuvex.BP_AFTER, action=act_reg_write) nose.tools.assert_equals(counts.reg_write, 0) s.registers.store(16, s.se.BVV(10, 32)) nose.tools.assert_equals(counts.reg_write, 1) nose.tools.assert_equals(counts.mem_write, 1) nose.tools.assert_equals(counts.mem_read, 4) nose.tools.assert_equals(counts.reg_read, 1) s.inspect.b('tmp_read', when=simuvex.BP_AFTER, action=act_tmp_read, tmp_read_num=0) s.inspect.b('tmp_write', when=simuvex.BP_AFTER, action=act_tmp_write, tmp_write_num=0) s.inspect.b('expr', when=simuvex.BP_AFTER, action=act_expr, expr=1016, expr_unique=False) s.inspect.b('statement', when=simuvex.BP_AFTER, action=act_statement) s.inspect.b('instruction', when=simuvex.BP_AFTER, action=act_instruction, instruction=1001) s.inspect.b('instruction', when=simuvex.BP_AFTER, action=act_instruction, instruction=1000) irsb = pyvex.IRSB("\x90\x90\x90\x90\xeb\x0a", mem_addr=1000, arch=archinfo.ArchAMD64()) irsb.pp() simuvex.SimIRSB(s, irsb) nose.tools.assert_equals(counts.reg_write, 7) nose.tools.assert_equals(counts.reg_read, 2) nose.tools.assert_equals(counts.tmp_write, 1) nose.tools.assert_equals(counts.tmp_read, 1) nose.tools.assert_equals(counts.expr, 3) # one for the Put, one for the WrTmp, and one to get the next address to jump to nose.tools.assert_equals(counts.statement, 26) nose.tools.assert_equals(counts.instruction, 2) nose.tools.assert_equals(counts.constraints, 0) nose.tools.assert_equals(counts.mem_write, 1) nose.tools.assert_equals(counts.mem_read, 4) s = simuvex.SimState(arch="AMD64", mode="symbolic") s.inspect.b('symbolic_variable', when=simuvex.BP_AFTER, action=act_variables) s.memory.load(0, 10) nose.tools.assert_equals(counts.variables, 1)
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 = simuvex.SimState() s.inspect.b('address_concretization', simuvex.BP_BEFORE, action=change_symbolic_target) s.memory.store(x, 'A') assert list(s.se.eval(x, 10)) == [ 0x1000 ] assert list(s.se.eval(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 = simuvex.SimState() s.inspect.b('address_concretization', simuvex.BP_BEFORE, action=dont_add_constraints) s.memory.store(x, 'A') assert len(s.se.eval(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, simuvex.concretization_strategies.SimConcretizationStrategyRange ) and state.inspect.address_concretization_result is None ): raise UnconstrainedAbort("uh oh", state) s = simuvex.SimState() s.memory.write_strategies.insert( 0, simuvex.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', simuvex.BP_AFTER, action=abort_unconstrained) s.memory.store(y, 'A') assert list(s.se.eval(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