def cut_path(g, e, force_start_e=-1): els = grp_endloops[g] newp = Paths(self.gph) all_finish_by_jump = True for k, p in els.paths.items(): if force_start_e != -1: start = index(p, force_start_e) else: start = prev_cut_idx[k] stop = -1 if e == -1 else index(p, e) if stop == -1: stop = len(p) if force_start_e == -1: prev_cut_idx[k] = start loop_idx = -1 if stop == len(p): loop_idx = els.__get_loop_idx(k) if start == 0 and stop == len(p): p2 = p else: p2 = p[start:stop] if not p2: continue newp.add_path(k, p2, loop_idx) # If it's an internal loop, we don't have to check # if the last instruction is a jump. if els.__is_looping(k, last_loop_idx): continue # Check if the last instruction is a jump and # go to the endpoint. if p[stop - 1] in self.gph_link_out: nxt = self.gph_link_out[p[stop - 1]] # TODO need to check cond jumps ? if not(len(nxt) == 1 and \ p[stop-1] in self.gph_uncond_jumps_set and \ nxt[BRANCH_NEXT] == e): all_finish_by_jump = False else: # It's a return, there is nothing after. It must be # in the future dict 'next_no_jump'. all_finish_by_jump = False return newp, all_finish_by_jump
def cut_path(g, e, force_start_e=-1): els = grp_endloops[g] newp = Paths(self.gph) all_finish_by_jump = True for k, p in els.paths.items(): if force_start_e != -1: start = index(p, force_start_e) else: start = prev_cut_idx[k] stop = -1 if e == -1 else index(p, e) if stop == -1: stop = len(p) if force_start_e == -1: prev_cut_idx[k] = start loop_idx = -1 if stop == len(p): loop_idx = els.__get_loop_idx(k) if start == 0 and stop == len(p): p2 = p else: p2 = p[start:stop] if not p2: continue newp.add_path(k, p2, loop_idx) # If it's an internal loop, we don't have to check # if the last instruction is a jump. if els.__is_looping(k, last_loop_idx): continue # Check if the last instruction is a jump and # go to the endpoint. if p[stop-1] in self.gph_link_out: nxt = self.gph_link_out[p[stop-1]] # TODO need to check cond jumps ? if not(len(nxt) == 1 and \ p[stop-1] in self.gph_uncond_jumps_set and \ nxt[BRANCH_NEXT] == e): all_finish_by_jump = False else: # It's a return, there is nothing after. It must be # in the future dict 'next_no_jump'. all_finish_by_jump = False return newp, all_finish_by_jump
def __rec_explore(self, paths, p, new): myk = self.__key_path_count self.__key_path_count += 1 paths.paths[myk] = p p_set = set(p) # optimization search while new in self.link_out: if new in p_set: # loop detected idx_node = p.index(new) l = p[idx_node:] l_idx = index(self.loops, l) if l_idx == -1: l_idx = len(self.loops) self.loops.append(l) self.loops_set.append(set(l)) paths.looping[myk] = l_idx return else: p.append(new) p_set.add(new) nxt = self.link_out[new] # much faster than: is_cond_jump(self.dis.code[new]) if len(nxt) == 2: self.__rec_explore(paths, list(p), nxt[BRANCH_NEXT_JUMP]) new = nxt[BRANCH_NEXT] p.append(new)
def save_step(k, addr, create): nonlocal new_paths, moved try: # This path is looping if index doesn't fail idx_node = self.paths.paths[k].index(addr) l = self.paths.paths[k][idx_node:] l_idx = index(self.loops, l) if l_idx == -1: l_idx = len(self.loops) self.loops.append(l) self.loops_set.append(set(l)) if create: idx_new_path = len(self.paths.paths) + len(new_paths) self.paths.looping[idx_new_path] = l_idx new_paths.append(list(self.paths.paths[k])) else: self.paths.looping[k] = l_idx except ValueError: moved = True if create: new_paths.append(self.paths.paths[k] + [addr]) else: self.paths.paths[k].append(addr)
def goto_addr(self, addr): to_remove = [] for k, p in self.paths.items(): idx = index(p, addr) if idx != -1: self.paths[k] = p[idx:] else: to_remove.append(k) all_removed = len(to_remove) == len(self.paths) for k in to_remove: self.__del_path(k) return all_removed
def dump(self, addr, lines): i_init = index(self.code_idx, addr) end = min(len(self.code_idx), i_init + lines) # set jumps color i = i_init while i < end: inst = self.code[self.code_idx[i]] if is_jump(inst) and inst.operands[0].type == X86_OP_IMM: pick_color(inst.operands[0].value.imm) i += 1 i = i_init while i < end: inst = self.code[self.code_idx[i]] if inst.address in self.binary.reverse_symbols: print_symbol(inst.address) print() print_inst(inst, 0) i += 1
def __is_in_curr_loop(self, loop): # Assume that current paths is a loop curr_loop = self.first() if loop[0] != curr_loop: return False # Check if all address of loop are in paths if not all(addr in self for addr in loop): return False # Check if the loop is in the right order for p in self.paths.values(): last_idx = -1 for addr in loop: idx = index(p, addr) if idx == -1: break elif idx < last_idx: return False else: last_idx = idx return True