def _deobfuscate_cff_loops(self, source_block, symbols): """ :param symbols: initial symbols of symbolic execution engine to be created :param source_block: head of the graph to be deobfuscated :return: """ symb_exec = SymbolicExecutionEngine(self.ir_arch) flat_block = self.flat_loops.get_block(source_block.loc_key, symb_exec, None) # maps flattening blocks to their respective loc_keys new_head = LocKey(0) flat_block_to_loc_key = {flat_block: new_head} todo = [FlattenState(flat_block, symbols)] counter = {} while todo: state = todo.pop() block_loc_key = state.flat_block.block_loc_key self.relevant_nodes.add(block_loc_key) counter[block_loc_key] = counter.get(block_loc_key, 0) + 1 logger.debug("Processing block at 0x%x as %s; in all affected: %d; loops_id: %s; the jtc_vars are:" % (self.asmcfg.loc_db.get_location_offset(block_loc_key) or 0xBAD, str(block_loc_key), block_loc_key in self.all_affected_lines, self.flat_loops[block_loc_key].loc_key)) if counter[block_loc_key] > 500: raise Exception("Couldn't deobfuscate cff loop, either fell into an infinite loop or processing very " "big function") symb_exec.set_state(state.symbols) # evaluate all affected lines self._eval_updt_lines(symb_exec, block_loc_key) for flat_block in self._insert_flat_block(state.flat_block, symb_exec, flat_block_to_loc_key): todo.append(FlattenState(flat_block, symb_exec.get_state())) return new_head
def _recognize(self, max_loop_num): symb_engine = SymbolicExecutionEngine(self.ir_arch, regs.regs_init) todo = [(LocKey(0), symb_engine.get_state())] done_loc = set() if not max_loop_num: max_loop_num = float('inf') found_loops_num = 0 while todo: loc_key, symb_state = todo.pop() if loc_key in done_loc or loc_key not in self.ircfg.blocks: continue done_loc.add(loc_key) ir_block = self.ircfg.blocks[loc_key] symb_engine.set_state(symb_state) for ind, assignblk in enumerate(ir_block.assignblks): for dst, src in assignblk.items(): if max_loop_num < found_loops_num: return if src.is_int() and int(src) in self.func_addresses: assignblk_node = AssignblkNode(ir_block.loc_key, ind, dst) # no uses if assignblk_node not in self.analyses.defuse_edges or not \ self.analyses.defuse_edges[assignblk_node]: # possible virtual table initialization self.possible_merge_funcs.add( (int(src), frozenset(), loc_key)) elif src.is_op("call_func_stack"): self._process_call(src, dst, symb_engine, assignblk, loc_key) elif (expr_simp(src).is_int() and not is_bad_expr(dst)) \ or (ir_block.loc_key == LocKey(0) and dst == src and (not self._merging_var_candidates or dst in self._merging_var_candidates)): if self._process_assignment(ir_block, ind, dst): self._merging_var_candidates = None found_loops_num += 1 symb_engine.eval_updt_assignblk(assignblk) for succ in self.ircfg.successors(loc_key): todo.append((succ, symb_engine.get_state()))