diff options
Diffstat (limited to 'src/miasm/jitter/emulatedsymbexec.py')
| -rw-r--r-- | src/miasm/jitter/emulatedsymbexec.py | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/miasm/jitter/emulatedsymbexec.py b/src/miasm/jitter/emulatedsymbexec.py new file mode 100644 index 00000000..1c3100ae --- /dev/null +++ b/src/miasm/jitter/emulatedsymbexec.py @@ -0,0 +1,170 @@ +from miasm.core.utils import decode_hex, encode_hex +import miasm.expression.expression as m2_expr +from miasm.ir.symbexec import SymbolicExecutionEngine +from miasm.arch.x86.arch import is_op_segm + + +class EmulatedSymbExec(SymbolicExecutionEngine): + """Symbolic exec instance linked with a jitter""" + + x86_cpuid = { + 0: { + 0: 0xa, + 1: 0x756E6547, + 2: 0x6C65746E, + 3: 0x49656E69, + }, + 1: { + 0: 0x00020652, + 1: 0x00000800, + 2: 0x00000209, + 3: 0x078bf9ff + }, + 2: { + 0: 0, + 1: 0, + 2: 0, + 3: 0 + }, + 4: { + 0: 0, + 1: 0, + 2: 0, + 3: 0 + }, + 7: { + 0: 0, + 1: (1 << 0) | (1 << 3), + 2: 0, + 3: 0 + }, + 0x80000000: { + 0: 0x80000008, + 1: 0, + 2: 0, + 3: 0 + }, + 0x80000001: { + 0: 0, + 1: 0, + 2: (1 << 0) | (1 << 8), + 3: (1 << 11) | (1 << 29), + }, + } + + def __init__(self, cpu, vm, *args, **kwargs): + """Instantiate an EmulatedSymbExec, associated to CPU @cpu and bind + memory accesses. + @cpu: JitCpu instance + """ + super(EmulatedSymbExec, self).__init__(*args, **kwargs) + self.cpu = cpu + self.vm = vm + + def reset_regs(self): + """Set registers value to 0. Ignore register aliases""" + for reg in self.lifter.arch.regs.all_regs_ids_no_alias: + self.symbols.symbols_id[reg] = m2_expr.ExprInt(0, size=reg.size) + + # Memory management + 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 super(EmulatedSymbExec, self).mem_read(expr_mem) + addr = int(addr) + size = expr_mem.size // 8 + value = self.vm.get_mem(addr, size) + if self.vm.is_little_endian(): + value = value[::-1] + self.vm.add_mem_read(addr, size) + + return m2_expr.ExprInt( + int(encode_hex(value), 16), + expr_mem.size + ) + + def mem_write(self, dest, data): + """Memory read wrapper for symbolic execution + @dest: ExprMem instance + @data: Expr instance""" + + # Get the content to write + data = self.expr_simp(data) + if not isinstance(data, m2_expr.ExprInt): + raise RuntimeError("A simplification is missing: %s" % data) + to_write = int(data) + + # Format information + addr = int(dest.ptr) + size = data.size // 8 + content = hex(to_write).replace("0x", "").replace("L", "") + content = "0" * (size * 2 - len(content)) + content + content = decode_hex(content) + + if self.vm.is_little_endian(): + content = content[::-1] + + # Write in VmMngr context + self.vm.set_mem(addr, content) + + # Interaction symbexec <-> jitter + def update_cpu_from_engine(self): + """Updates @cpu instance according to new CPU values""" + + for symbol in self.symbols: + if isinstance(symbol, m2_expr.ExprId): + if hasattr(self.cpu, symbol.name): + value = self.symbols.symbols_id[symbol] + if not isinstance(value, m2_expr.ExprInt): + raise ValueError("A simplification is missing: %s" % value) + + setattr(self.cpu, symbol.name, int(value)) + else: + raise NotImplementedError("Type not handled: %s" % symbol) + + + def update_engine_from_cpu(self): + """Updates CPU values according to @cpu instance""" + + for symbol in self.symbols: + if isinstance(symbol, m2_expr.ExprId): + if hasattr(self.cpu, symbol.name): + value = m2_expr.ExprInt(getattr(self.cpu, symbol.name), + symbol.size) + self.symbols.symbols_id[symbol] = value + else: + raise NotImplementedError("Type not handled: %s" % symbol) + + # CPU specific simplifications + def _simp_handle_segm(self, e_s, expr): + """Handle 'segm' operation""" + if not is_op_segm(expr): + return expr + if not expr.args[0].is_int(): + return expr + segm_nb = int(expr.args[0]) + segmaddr = self.cpu.get_segm_base(segm_nb) + return e_s(m2_expr.ExprInt(segmaddr, expr.size) + expr.args[1]) + + def _simp_handle_x86_cpuid(self, e_s, expr): + """From miasm/jitter/op_semantics.h: x86_cpuid""" + if expr.op != "x86_cpuid": + return expr + + if any(not arg.is_int() for arg in expr.args): + return expr + a, reg_num = (int(arg) for arg in expr.args) + + # Not found error is keeped on purpose + return m2_expr.ExprInt(self.x86_cpuid[a][reg_num], expr.size) + + def enable_emulated_simplifications(self): + """Enable simplifications needing a CPU instance on associated + ExpressionSimplifier + """ + self.expr_simp.enable_passes({ + m2_expr.ExprOp: [self._simp_handle_segm, self._simp_handle_x86_cpuid], + }) |