def __str__(self): raise RuntimeError("oh no you di'int") s = uop_to_py(self) if not is_jcc(self.op): s += " # %s" % repr(self) if self.is_output: s += "\n" + uop_to_py_out(self, self.label) return s
def get_branch_target(tbs): taken = get_taken_tb(tbs) i, _ = first(lambda x: is_jcc(x[1][1].op), enumerate(taken.body)) remaining = set(x.op for _, x in taken.body[i+1:]) if not remaining <= junk: raise ValueError("Real instructions remain after a branch! TB Split Fail") elif 'IFLO_MOVL_EIP_IM' in remaining: eipmov = first(lambda x: x.op == 'IFLO_MOVL_EIP_IM', taken.rbody[i+1:]) return eipmov.args[0] else: return "unknown"
def __init__(self, tbs): self.tbs = tbs self.exemplar = self.tbs[1] for i, insn in tbs[0].body: if is_jcc(insn.op): self.condition = insn break else: raise RuntimeError("Unable to determine loop condition") for i, insn in reversed(tbs[0].body): if insn.op == 'IFLO_MOVL_T0_IM': self.taken = bool(insn.args[0] & 1) break else: self.taken = False
def control_dep_slice(tbdict, cfg): print "Calculating control dependencies..." start_ts = time.time() wlist = defaultdict(list) for c in cfg: if len(cfg[c]) < 2: continue for t in tbdict[c]: for i, isn in t.body: if is_jcc(isn.op) or is_dynjump(isn.op): wlist[t.trace].append( (i, uses(isn)) ) isn.mark() wlist = dict(wlist) for trace in wlist: multislice(trace, wlist[trace]) end_ts = time.time() print "Added branches in %s" % (datetime.timedelta(seconds=end_ts-start_ts))
def translate_code(tbses, tbdict, cfg): # It's translation time! transdict = {} for c in cfg: if len(cfg[c]) > 0: target = list(cfg[c])[0] transdict[c] = "label = %s" % ("'%s'" % target if isinstance(target,str) else hex(int(target))) else: transdict[c] = "label = '__end__'" if not quiet: widgets = ['Translating: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=len(cfg)).start() # Iterate over the finished CFG and translate each TB num_translated = 0 for c in cfg: cur = tbdict[c] next = list(cfg[c]) # No need to bother with these if not any(t.has_slice() for t in cur): #print "Skipping %s" % repr(cur[0]) continue if not next: # Last node (woo special cases) s = simple_translate(cur) s.append("label = '__end__'") transdict[cur[0].label] = "\n".join(s) elif len(next) == 1: #s = "\n".join("%s" % insn for _, insn in cur[0].body if insn.in_slice) s = simple_translate(cur) next_tb = tbdict[next[0]][0] s.append("label = %s" % next_tb._label_str()) transdict[cur[0].label] = "\n".join(s) elif cur[0].has_dynjump(): transdict[cur[0].label] = "\n".join(simple_translate(cur)) else: # There must be a jump to a variable target (ie conditional branch) # We need to combine the known instances of this TB and resolve its targets taken = get_branch_target(cur) if taken == "unknown": # Pick the successor to any TB where the jump is taken tb = get_taken_tb(cur) taken = tb.next._label_str() # Find the fall-through successor. tb = get_not_taken_tb(cur) succ = tb.next._label_str() s = [] for insns in zip(*[c.body for c in cur]): set_outlabel(insns) if any( insn.in_slice for _, insn in insns ): insn = insns[0][1] if is_jcc(insn.op): s.append("if (%s): label = %s" % (tr(insn), taken)) else: s.append(tr(insn)) s.append("else: label = %s" % succ) transdict[cur[0].label] = "\n".join(s) num_translated += 1 if not quiet: pbar.update(num_translated) return transdict
def tr(op): s = uop_to_py(op) if not is_jcc(op.op): s += " # %s" % repr(op) if op.is_output: s += "\n" + uop_to_py_out(op, "out") return s
def get_branch(self): return [ins for _, ins in self.body if is_jcc(ins.op) or is_dynjump(ins.op)][0]
def has_jcc(self): return any(is_jcc(ins.op) for _, ins in self.body)