diff options
| -rw-r--r-- | example/ida/ctype_propagation.py | 3 | ||||
| -rw-r--r-- | example/jitter/trace.py | 8 | ||||
| -rw-r--r-- | miasm2/analysis/dse.py | 31 | ||||
| -rw-r--r-- | miasm2/ir/symbexec.py | 141 | ||||
| -rw-r--r-- | miasm2/ir/symbexec_top.py | 4 | ||||
| -rw-r--r-- | miasm2/ir/symbexec_types.py | 4 | ||||
| -rw-r--r-- | miasm2/jitter/emulatedsymbexec.py | 9 | ||||
| -rwxr-xr-x | test/ir/symbexec.py | 46 |
8 files changed, 53 insertions, 193 deletions
diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py index 1c883214..61bc747f 100644 --- a/example/ida/ctype_propagation.py +++ b/example/ida/ctype_propagation.py @@ -156,13 +156,10 @@ class SymbExecCTypeFix(SymbExecCType): def __init__(self, ir_arch, symbols, chandler, cst_propag_link, - func_read=None, func_write=None, sb_expr_simp=expr_simp): super(SymbExecCTypeFix, self).__init__(ir_arch, symbols, chandler, - func_read=func_read, - func_write=func_write, sb_expr_simp=expr_simp) self.cst_propag_link = cst_propag_link diff --git a/example/jitter/trace.py b/example/jitter/trace.py index aeb4c775..e1683450 100644 --- a/example/jitter/trace.py +++ b/example/jitter/trace.py @@ -24,14 +24,14 @@ def instr_hook(jitter): class ESETrackMemory(EmulatedSymbExec): """Emulated symb exec with memory access tracking""" - def _func_read(self, expr_mem): - value = super(ESETrackMemory, self)._func_read(expr_mem) + def mem_read(self, expr_mem): + value = super(ESETrackMemory, self).mem_read(expr_mem) print "Read %s: %s" % (expr_mem, value) return value - def _func_write(self, symb_exec, dest, data): + def mem_write(self, dest, data): print "Write %s: %s" % (dest, data) - return super(ESETrackMemory, self)._func_write(symb_exec, dest, data) + return super(ESETrackMemory, self).mem_write(dest, data) # Parse arguments parser = Sandbox_Linux_arml.parser(description="Tracer") diff --git a/miasm2/analysis/dse.py b/miasm2/analysis/dse.py index 3a986537..5eb924d7 100644 --- a/miasm2/analysis/dse.py +++ b/miasm2/analysis/dse.py @@ -104,25 +104,25 @@ class ESETrackModif(EmulatedSymbExec): self.dse_memory_to_expr = None # function(addr) -> Expr used to # symbolize - def _func_read(self, expr_mem): + def mem_read(self, expr_mem): if not expr_mem.ptr.is_int(): return expr_mem dst_addr = int(expr_mem.ptr) - if not self.dse_memory_range: - # Trivial case (optimization) - return super(ESETrackModif, self)._func_read(expr_mem) - # Split access in atomic accesses out = [] for addr in xrange(dst_addr, dst_addr + (expr_mem.size / 8)): if addr in self.dse_memory_range: # Symbolize memory access out.append(self.dse_memory_to_expr(addr)) + continue + atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8) + if atomic_access in self.symbols: + out.append( super(EmulatedSymbExec, self).mem_read(atomic_access)) else: # Get concrete value atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8) - out.append(super(ESETrackModif, self)._func_read(atomic_access)) + out.append(super(ESETrackModif, self).mem_read(atomic_access)) if len(out) == 1: # Trivial case (optimization) @@ -131,6 +131,10 @@ class ESETrackModif(EmulatedSymbExec): # Simplify for constant merging (ex: {ExprInt(1, 8), ExprInt(2, 8)}) return self.expr_simp(ExprCompose(*out)) + def mem_write(self, expr, data): + # Call Symbolic mem_write (avoid side effects on vm) + return super(EmulatedSymbExec, self).mem_write(expr, data) + def reset_modified(self): """Reset modified expression tracker""" self.modified_expr.clear() @@ -140,6 +144,14 @@ class ESETrackModif(EmulatedSymbExec): self.modified_expr.add(dst) +class ESENoVMSideEffects(EmulatedSymbExec): + """ + Do EmulatedSymbExec without modifying memory + """ + def mem_write(self, expr, data): + return super(EmulatedSymbExec, self).mem_write(expr, data) + + class DSEEngine(object): """Dynamic Symbolic Execution Engine @@ -174,12 +186,10 @@ class DSEEngine(object): self.symb = self.SYMB_ENGINE(self.jitter.cpu, self.jitter.vm, self.ir_arch, {}) self.symb.enable_emulated_simplifications() - self.symb_concrete = EmulatedSymbExec( + self.symb_concrete = ESENoVMSideEffects( self.jitter.cpu, self.jitter.vm, self.ir_arch, {} ) - ### Avoid side effects on jitter while using 'symb_concrete' - self.symb_concrete.func_write = None ## Update registers value self.symb.symbols[self.ir_arch.IRDst] = ExprInt( @@ -187,9 +197,6 @@ class DSEEngine(object): self.ir_arch.IRDst.size ) - # Avoid memory write - self.symb.func_write = None - # Activate callback on each instr self.jitter.jit.set_options(max_exec_per_call=1, jit_maxline=1) self.jitter.exec_cb = self.callback diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py index 1347e0e5..d2d62ff7 100644 --- a/miasm2/ir/symbexec.py +++ b/miasm2/ir/symbexec.py @@ -1,4 +1,3 @@ -import warnings import logging from collections import MutableMapping @@ -154,6 +153,9 @@ class MemArray(MutableMapping): """Mask offset""" return self._mask + def __contains__(self, offset): + return offset in self._offset_to_expr + def __getitem__(self, offset): assert 0 <= offset <= self._mask return self._offset_to_expr.__getitem__(offset) @@ -725,14 +727,6 @@ class SymbolMngr(object): """Variables of the current state""" return list(self) - def get(self, expr, default=None): - """Deprecated version of read""" - warnings.warn('DEPRECATION WARNING: use "read(self, expr)" instead of get') - ret = self.read(expr) - if default is not None and ret == expr: - return default - return ret - def merge_ptr_read(known, ptrs): """ @@ -805,8 +799,6 @@ class SymbolicExecutionEngine(object): StateEngine = SymbolicState def __init__(self, ir_arch, state=None, - func_read=None, - func_write=None, sb_expr_simp=expr_simp_explicit): self.expr_to_visitor = { @@ -828,13 +820,6 @@ class SymbolicExecutionEngine(object): for dst, src in state.iteritems(): self.symbols.write(dst, src) - if func_read: - warnings.warn('DEPRECATION WARNING: override function "mem_read(self, expr)" instead of func_read') - if func_write: - warnings.warn('DEPRECATION WARNING: override function "mem_write(self, dsr, src)" instead of func_write') - - self.func_read = func_read - self.func_write = func_write self.ir_arch = ir_arch self.expr_simp = sb_expr_simp @@ -1149,21 +1134,7 @@ class SymbolicExecutionEngine(object): Read symbolic value at ExprMem @expr @expr: ExprMem """ - - parts = self._resolve_mem_parts(expr) - - out = [] - for known, part in parts: - if not known and part.is_mem() and self.func_read is not None: - ret = self.func_read(part) - else: - ret = part - - out.append(ret) - ret = self.expr_simp(ExprCompose(*out)) - - assert ret.size == expr.size - return ret + return self.symbols.read(expr) def mem_write(self, dst, src): """ @@ -1173,106 +1144,4 @@ class SymbolicExecutionEngine(object): @dst: destination ExprMem @src: source Expression """ - if self.func_write is not None: - self.func_write(self, dst, src) - else: - self.symbols.write(dst, src) - - - # Deprecated methods - - def apply_expr_on_state(self, expr, cache): - """Deprecated version of eval_expr""" - warnings.warn('DEPRECATION WARNING: use "eval_expr" instead of apply_expr_on_state') - - if cache is None: - cache = {} - ret = self.eval_expr(expr, eval_cache=cache) - return ret - - def modified_mems(self, init_state=None): - """Deprecated version of modified(ids=False)""" - warnings.warn('DEPRECATION WARNING: use "modified(self, ids=False)" instead of modified_mems') - for mem in self.modified(init_state=init_state, ids=False): - yield mem - - def modified_regs(self, init_state=None): - """Deprecated version of modified(mems=False)""" - warnings.warn('DEPRECATION WARNING: use "modified(self, mems=False)" instead of modified_regs') - for reg in self.modified(init_state=init_state, mems=False): - yield reg - - def dump_id(self): - """Deprecated version of dump(mems=False)""" - warnings.warn('DEPRECATION WARNING: use "dump(self, mems=False)" instead of dump_id') - self.dump(mems=False) - - def dump_mem(self): - """Deprecated version of dump(ids=False)""" - warnings.warn('DEPRECATION WARNING: use "dump(self, ids=False)" instead of dump_mem') - self.dump(ids=False) - - def eval_ir_expr(self, assignblk): - """Deprecated version of eval_ir_expr(self, assignblk)""" - warnings.warn('DEPRECATION WARNING: use "eval_assignblk(self, assignblk)" instead of eval_ir_expr') - return self.eval_assignblk(assignblk).iteritems() - - def eval_ir(self, assignblk): - """Deprecated version of eval_updt_assignblk(self, assignblk)""" - warnings.warn('DEPRECATION WARNING: use "eval_assignblk(self, assignblk)" instead of eval_ir') - return self.eval_updt_assignblk(assignblk) - - def emulbloc(self, irb, step=False): - """Deprecated version of eval_updt_irblock(self, irb, step=False)""" - warnings.warn('DEPRECATION WARNING: use "eval_updt_irblock(self, irb, step=False)" instead of emulbloc') - return self.eval_updt_irblock(irb, step) - - def emul_ir_bloc(self, _, addr, step=False): - """Deprecated version of run_block_at""" - warnings.warn('DEPRECATION WARNING: use "run_block_at(self, addr, step=False)" instead of emul_ir_bloc') - return self.run_block_at(addr, step) - - def emul_ir_block(self, addr, step=False): - """Deprecated version of run_block_at""" - warnings.warn('DEPRECATION WARNING: use "run_block_at(self, addr, step=False)" instead of emul_ir_block') - return self.run_block_at(addr, step) - - def emul_ir_blocks(self, addr, lbl_stop=None, step=False): - """Deprecated version of run_at""" - warnings.warn('DEPRECATION WARNING: use "run_at(self, addr, lbl_stop=None, step=False):" instead of emul_ir_blocks') - return self.run_at(addr, lbl_stop, step) - - def emul_ir_blocs(self, _, addr, lbl_stop=None, step=False): - """Deprecated version of run_at""" - warnings.warn('DEPRECATION WARNING: use "run_at(self, addr, lbl_stop=None, step=False):" instead of emul_ir_blocs') - return self.run_at(addr, lbl_stop, step) - - def apply_expr(self, expr): - """Deprecated version of eval_updt_expr""" - warnings.warn('DEPRECATION WARNING: use "eval_updt_expr" instead of apply_expr') - return self.eval_updt_expr(expr) - - def as_assignblock(self): - """Return the current state as an AssignBlock""" - warnings.warn('DEPRECATION WARNING: use "modified(ids=True, mems=True)" instead of as_assignblock') - out = [] - for dst, src in self.modified(ids=True, mems=True): - out.append((dst, src)) - return AssignBlock(dict(out)) - - -class symbexec(SymbolicExecutionEngine): - """ - DEPRECATED object - Use SymbolicExecutionEngine instead of symbexec - """ - - def __init__(self, ir_arch, known_symbols, - func_read=None, - func_write=None, - sb_expr_simp=expr_simp_explicit): - warnings.warn("Deprecated API: use SymbolicExecutionEngine") - super(symbexec, self).__init__(ir_arch, known_symbols, - func_read, - func_write, - sb_expr_simp=sb_expr_simp) + self.symbols.write(dst, src) diff --git a/miasm2/ir/symbexec_top.py b/miasm2/ir/symbexec_top.py index 887ebe59..be48c065 100644 --- a/miasm2/ir/symbexec_top.py +++ b/miasm2/ir/symbexec_top.py @@ -86,13 +86,9 @@ class SymbExecTopNoMem(SymbolicExecutionEngine): StateEngine = SymbolicStateTop def __init__(self, ir_arch, state, regstop, - func_read=None, - func_write=None, sb_expr_simp=expr_simp): known_symbols = dict(state) super(SymbExecTopNoMem, self).__init__(ir_arch, known_symbols, - func_read, - func_write, sb_expr_simp) self.regstop = set(regstop) diff --git a/miasm2/ir/symbexec_types.py b/miasm2/ir/symbexec_types.py index 71e5d6fa..e4f37e3f 100644 --- a/miasm2/ir/symbexec_types.py +++ b/miasm2/ir/symbexec_types.py @@ -66,15 +66,11 @@ class SymbExecCType(SymbolicExecutionEngine): def __init__(self, ir_arch, symbols, chandler, - func_read=None, - func_write=None, sb_expr_simp=expr_simp): self.chandler = chandler super(SymbExecCType, self).__init__(ir_arch, {}, - func_read, - func_write, sb_expr_simp) self.symbols = dict(symbols) diff --git a/miasm2/jitter/emulatedsymbexec.py b/miasm2/jitter/emulatedsymbexec.py index 15024505..78c02fb1 100644 --- a/miasm2/jitter/emulatedsymbexec.py +++ b/miasm2/jitter/emulatedsymbexec.py @@ -28,8 +28,6 @@ class EmulatedSymbExec(SymbolicExecutionEngine): super(EmulatedSymbExec, self).__init__(*args, **kwargs) self.cpu = cpu self.vm = vm - self.func_read = self._func_read - self.func_write = self._func_write def reset_regs(self): """Set registers value to 0. Ignore register aliases""" @@ -37,13 +35,13 @@ class EmulatedSymbExec(SymbolicExecutionEngine): self.symbols.symbols_id[reg] = m2_expr.ExprInt(0, size=reg.size) # Memory management - def _func_read(self, expr_mem): + def mem_read(self, expr_mem): """Memory read wrapper for symbolic execution @expr_mem: ExprMem""" addr = expr_mem.ptr if not addr.is_int(): - return expr_mem + return super(EmulatedSymbExec, self).mem_read(expr_mem) addr = int(addr) size = expr_mem.size / 8 value = self.cpu.get_mem(addr, size) @@ -54,9 +52,8 @@ class EmulatedSymbExec(SymbolicExecutionEngine): return m2_expr.ExprInt(int(value.encode("hex"), 16), expr_mem.size) - def _func_write(self, symb_exec, dest, data): + def mem_write(self, dest, data): """Memory read wrapper for symbolic execution - @symb_exec: symbexec instance @dest: ExprMem instance @data: Expr instance""" diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py index 00ef7c10..4f01ac3c 100755 --- a/test/ir/symbexec.py +++ b/test/ir/symbexec.py @@ -26,28 +26,34 @@ class TestSymbExec(unittest.TestCase): id_d = ExprId('d', 32) id_e = ExprId('e', 64) - sb = SymbolicExecutionEngine(ira, - { - ExprMem(ExprInt(0x4, 32), 8): ExprInt(0x44, 8), - ExprMem(ExprInt(0x5, 32), 8): ExprInt(0x33, 8), - ExprMem(ExprInt(0x6, 32), 8): ExprInt(0x22, 8), - ExprMem(ExprInt(0x7, 32), 8): ExprInt(0x11, 8), + class CustomSymbExec(SymbolicExecutionEngine): + def mem_read(self, expr): + if expr == ExprMem(ExprInt(0x1000, 32), 32): + return id_x + return super(CustomSymbExec, self).mem_read(expr) - ExprMem(ExprInt(0x20, 32), 32): id_x, + sb = CustomSymbExec(ira, + { + ExprMem(ExprInt(0x4, 32), 8): ExprInt(0x44, 8), + ExprMem(ExprInt(0x5, 32), 8): ExprInt(0x33, 8), + ExprMem(ExprInt(0x6, 32), 8): ExprInt(0x22, 8), + ExprMem(ExprInt(0x7, 32), 8): ExprInt(0x11, 8), - ExprMem(ExprInt(0x40, 32), 32): id_x, - ExprMem(ExprInt(0x44, 32), 32): id_a, + ExprMem(ExprInt(0x20, 32), 32): id_x, - ExprMem(ExprInt(0x54, 32), 32): ExprInt(0x11223344, 32), + ExprMem(ExprInt(0x40, 32), 32): id_x, + ExprMem(ExprInt(0x44, 32), 32): id_a, - ExprMem(id_a, 32): ExprInt(0x11223344, 32), - id_a: ExprInt(0, 32), - id_b: ExprInt(0, 32), + ExprMem(ExprInt(0x54, 32), 32): ExprInt(0x11223344, 32), - ExprMem(id_c, 32): ExprMem(id_d + ExprInt(0x4, 32), 32), - ExprMem(id_c + ExprInt(0x4, 32), 32): ExprMem(id_d + ExprInt(0x8, 32), 32), + ExprMem(id_a, 32): ExprInt(0x11223344, 32), + id_a: ExprInt(0, 32), + id_b: ExprInt(0, 32), - }) + ExprMem(id_c, 32): ExprMem(id_d + ExprInt(0x4, 32), 32), + ExprMem(id_c + ExprInt(0x4, 32), 32): ExprMem(id_d + ExprInt(0x8, 32), 32), + + }) self.assertEqual(sb.eval_expr(ExprInt(1, 32)-ExprInt(1, 32)), ExprInt(0, 32)) @@ -101,14 +107,6 @@ class TestSymbExec(unittest.TestCase): self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x100, 32), 32)), ExprMem(ExprInt(0x100, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(id_c + ExprInt(0x2, 32), 32)), ExprMem(id_d + ExprInt(0x6, 32), 32)) - ## Func read - def custom_func_read(mem): - if mem == ExprMem(ExprInt(0x1000, 32), 32): - return id_x - return mem - - sb.func_read = custom_func_read - ## Unmodified read self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 8)), ExprInt(0x44, 8)) |