def emul_lines(machine, lines): my_eip = None for l in lines: my_eip = ExprInt(uint32(l.offset)) args = [] my_eip.arg += uint32(l.l) ex = get_instr_expr(l, my_eip, args) my_eip, mem_dst = emul_full_expr(ex, l, my_eip, None, machine) for k in machine.pool: machine.pool[k] = expr_simp(machine.pool[k]) return my_eip
def x86_machine(mem_read_wrap=None, mem_write_wrap=None): init_reg_new = init_regs.copy() init_reg_new.update({ cs: ExprInt(uint32(9)), dr7: ExprInt(uint32(0)), cr0: init_cr0, #my_ret_addr:my_ret_addri }) machine = eval_abs( init_reg_new, mem_read_wrap, mem_write_wrap, ) return machine
def eval_instr(self, exprs): tmp_ops = self.get_instr_mod(exprs) mem_dst = [] for op in tmp_ops: if isinstance(op, ExprMem): ov = self.get_mem_overlapping(op) for off, x in ov: diff_mem = self.substract_mems(x, op) del (self.pool[x]) for xx, yy in diff_mem: self.pool[xx] = yy tmp = expr_simp(tmp_ops[op]) if isinstance(expr_simp(op.arg), ExprTop): raise ValueError('xx') else: tmp = tmp_ops[op] tmp = expr_simp(tmp) if isinstance(tmp, ExprInt) and isinstance( op, ExprId) and op.name in [ 'zf', 'nf', 'pf', 'of', 'cf', 'df' ]: tmp = ExprInt(uint32(tmp.arg)) self.pool[op] = tmp if isinstance(op, ExprMem): mem_dst.append(op) return mem_dst
def p_brackets_6(t): '''brackets : MINUS NUMBER PLUS symbol LBRA expression RBRA %prec UMINUS''' if not x86_afs.ad in t[6]: t[6][x86_afs.ad] = True t[0] = t[6] for f in t[4]: t[0][f] = t[4][f] t[0][x86_afs.imm] = - int(int32(uint32(int(t[2]))))
def p_brackets_5(t): '''brackets : NUMBER PLUS symbol LBRA expression RBRA ''' if not x86_afs.ad in t[5]: t[5][x86_afs.ad] = True t[0] = t[5] for f in t[3]: t[0][f] = t[3][f] t[0][x86_afs.imm] = int(int32(uint32(int(t[1]))))
def substract_mems(self, a, b): ex = ExprOp('-', b.arg, a.arg) ex = expr_simp(self.eval_expr(ex, {})) if not isinstance(ex, ExprInt): return None ptr_diff = int(int32(ex.arg)) out = [] if ptr_diff < 0: # [a ] #[b ]XXX sub_size = b.size + ptr_diff * 8 if sub_size >= a.size: pass else: ex = ExprOp('+', a.arg, ExprInt(uint32(sub_size / 8))) ex = expr_simp(self.eval_expr(ex, {})) rest_ptr = ex rest_size = a.size - sub_size val = self.pool[a][sub_size:a.size] out = [(ExprMem(rest_ptr, rest_size), val)] else: #[a ] #XXXX[b ]YY #[a ] #XXXX[b ] out = [] #part X if ptr_diff > 0: val = self.pool[a][0:ptr_diff * 8] out.append((ExprMem(a.arg, ptr_diff * 8), val)) #part Y if ptr_diff * 8 + b.size < a.size: ex = ExprOp('+', b.arg, ExprInt(uint32(b.size / 8))) ex = expr_simp(self.eval_expr(ex, {})) val = self.pool[a][ptr_diff * 8 + b.size:a.size] out.append((ExprMem(ex, val.get_size()), val)) return out
def get_mem_overlapping(self, e, eval_cache={}): if not isinstance(e, ExprMem): raise ValueError('mem overlap bad arg') ov = [] """ for k in self.pool: if not isinstance(k, ExprMem): continue ex = ExprOp('-', k.arg, e.arg) ex = expr_simp(self.eval_expr(ex, {})) if not isinstance(ex, ExprInt): continue ptr_diff = int32(ex.arg) if ptr_diff >=0 and ptr_diff < e.size/8: ov.append((-ptr_diff, k)) elif ptr_diff <0 and ptr_diff + k.size/8>0: ov.append((-ptr_diff, k)) """ # suppose max mem size is 64 bytes, compute all reachable addresses to_test = [] #comp = {} #print("FINDING %s" % e) for i in range(-7, e.size // 8): ex = expr_simp( self.eval_expr(e.arg + ExprInt(uint32(i)), eval_cache)) #print("%s %s"%(i, ex)) to_test.append((i, ex)) for i, x in to_test: if not x in self.pool.pool_mem: continue ex = expr_simp(self.eval_expr(e.arg - x, eval_cache)) if not isinstance(ex, ExprInt): raise ValueError("%s should be ExprInt instead of %s" % (ex, ex.__class__.__name__)) ptr_diff = int32(ex.arg) #print("ptrdiff %s %s'%(ptr_diff, i)) if ptr_diff >= self.pool.pool_mem[x][1].get_size() / 8: #print("too long!") continue ov.append((i, self.pool.pool_mem[x][0])) #""" """ print(ov) if len(ov)>0: print("XXXX %s" % [(x[0], str(x[1])) for x in ov]) """ return ov
from miasmX.expression.expression import ExprOp, ExprSlice, ExprCompose, \ ExprCond, ExprInt, ExprMem from miasmX.expression.expression import canonize_expr_list tab_size_int = { 1: uint1, 8: uint8, 16: uint16, 32: uint32, 64: uint64, } tab_max_uint = { 8: uint8(0xFF), 16: uint16(0xFFFF), 32: uint32(uint32.limit - 1), 64: uint64(uint64.limit - 1) } def parity(a): tmp = (a) & 0xFF cpt = 1 while tmp != 0: cpt ^= tmp & 1 tmp >>= 1 return cpt def merge_sliceto_slice(args): sources = {}
def p_brackets_4(t): '''brackets : MINUS NUMBER LBRA expression RBRA''' if not x86_afs.ad in t[4]: t[4][x86_afs.ad] = True t[0] = t[4] t[0][x86_afs.imm] = - int(int32(uint32(int(t[2]))))
def p_brackets_3(t): '''brackets : NUMBER LBRA expression RBRA ''' if not x86_afs.ad in t[3]: t[3][x86_afs.ad] = True t[0] = t[3] t[0][x86_afs.imm] = int(int32(uint32(int(t[1]))))
def p_expression_5(t): '''expression : NUMBER''' t[0] = {x86_afs.imm:int(int32(uint32(int(t[1]))))}
def emul_full_expr(e, l, my_eip, env, machine): if ((not 0xF2 in l.prefix) and (not 0xF3 in l.prefix)) or \ "MMX" in l.m.name or \ not l.m.name[:-1] in ["ins", "outs", "movs", "lods", "stos", "cmps", "scas"]: my_eip, mem_dst = emul_expr(machine, e, my_eip) else: #rep mnemo #XXX HACK 16 bit tsc_inc = 0 if 0x66 in l.prefix and l.m.name[-1] == "d": raise ValueError("not impl 16 bit string") if l.m.name[:-1] in ["cmps", "scas"]: # repz or repnz zf_w = False for x in e: if zf in x.get_w(): zf_w = True else: # rep zf_w = False def expr_depth(f): if isinstance(f, ExprOp) or isinstance(f, ExprCompose): depth = 1 for a in f.args: depth += expr_depth(a) return depth elif isinstance(f, ExprMem): return 1 + expr_depth(f.arg) elif isinstance(f, ExprCond): return expr_depth(f.cond) + expr_depth(f.src1) + expr_depth( f.src2) else: return 0 while True: my_ecx = machine.eval_expr(machine.pool[ecx], {}) if not isinstance(my_ecx, ExprInt): raise ValueError('Emulation fails for "%s". ECX value is %s' % (l, str(machine.pool[ecx]))) if l.mnemo_mode == x86_afs.u16: my_ecx.arg &= 0xFFFF if my_ecx.arg == 0: break my_edi = machine.eval_expr(machine.pool[edi], {}) if expr_depth(my_edi) > 100: raise ValueError( 'Emulation fails for "%s". EDI value is too complicated' % l) tmp, mem_dst = emul_expr(machine, e, my_eip) if my_ecx.arg > 0x1000: # This is not a valid emulation, but we don't want to loop forever break info = l.opmode, l.admode machine.eval_instr( mov(info, ecx, ExprOp('-', my_ecx, ExprInt(uint32(1))))) machine.eval_expr(machine.pool[ecx], {}) if zf_w: my_zf = machine.eval_expr(machine.pool[zf], {}) if 0xF3 in l.prefix and my_zf == 0: break if 0xF2 in l.prefix and my_zf == 1: break tsc_inc += 1 # serpillere included an emulation of TSC incrementation, # why here and nowhere else? if isinstance(machine.pool[tsc1], ExprInt): machine.pool[tsc1].arg += tsc_inc return my_eip, mem_dst
def eval_ExprMem(self, e, eval_cache={}): a_val = expr_simp(self.eval_expr(e.arg, eval_cache)) if isinstance(a_val, ExprTop): #XXX hack test ee = ExprMem(e.arg, e.size) ee.is_term = True return ee a = expr_simp(ExprMem(a_val, size=e.size)) if a in self.pool: return self.pool[a] tmp = None #test if mem lookup is known """ for k in self.pool: if not isinstance(k, ExprMem): continue if a_val == k.arg: tmp = k break """ if a_val in self.pool.pool_mem: tmp = self.pool.pool_mem[a_val][0] """ for k in self.pool: if not isinstance(k, ExprMem): continue if a_val == k.arg: tmp = k break """ if tmp is None: v = self.find_mem_by_addr(a_val) if not v: out = [] ov = self.get_mem_overlapping(a, eval_cache) off_base = 0 ov.sort() ov.reverse() for off, x in ov: off_base = off * 8 if off >= 0: m = min(a.get_size() - off_base, x.get_size()) ee = ExprSlice(self.pool[x], 0, m) ee = expr_simp(ee) out.append((ee, off_base, off_base + ee.get_size())) off_base += ee.get_size() else: m = min(a.get_size() - off * 8, x.get_size()) ee = ExprSlice(self.pool[x], -off * 8, m) ee = expr_simp(ee) out.append((ee, off_base, off_base + ee.get_size())) off_base += ee.get_size() if out: missing_slice = self.rest_slice(out, 0, a.get_size()) for sa, sb in missing_slice: ptr = expr_simp(a_val + ExprInt32(sa / 8)) out.append((ExprMem(ptr, size=sb - sa), sa, sb)) out = sorted(out, key=lambda x: x[1]) #for e, sa, sb in out: # print("%s %s %s"%(e, sa, sb)) ee = ExprSlice(ExprCompose(out), 0, a.get_size()) ee = expr_simp(ee) return ee if self.func_read and isinstance(a.arg, ExprInt): return self.func_read(self, a) else: #XXX hack test a.is_term = True return a #eq lookup if a.size == tmp.size: return self.pool[tmp] #bigger lookup if a.size > tmp.size: rest = a.size ptr = a_val out = [] ptr_index = 0 while rest: v = self.find_mem_by_addr(ptr) if v is None: #raise ValueError("cannot find %s in mem"%str(ptr)) val = ExprMem(ptr, 8) v = val diff_size = 8 elif rest >= v.size: val = self.pool[v] diff_size = v.size else: diff_size = rest val = self.pool[v][0:diff_size] val = (val, ptr_index, ptr_index + diff_size) out.append(val) ptr_index += diff_size rest -= diff_size ptr = expr_simp( self.eval_expr( ExprOp('+', ptr, ExprInt(uint32(v.size / 8))), eval_cache)) e = expr_simp(ExprCompose(out)) return e #part lookup tmp = expr_simp(ExprSlice(self.pool[tmp], 0, a.size)) return tmp
def ExprInt32(i): return ExprInt(uint32(i))