def __init__(self, project, cfg=None, require_predecessors=True, only_find=None): self.project = project if cfg is not None: self._cfg = cfg else: self._cfg = project.analyses.CFGFast(resolve_indirect_jumps=True) self._runner = Runner(project, self._cfg) # only find if in this set self.only_find = only_find # reg list a = self.project.arch self._sp_reg = a.register_names[a.sp_offset] self._bp_reg = a.register_names[a.bp_offset] self._ip_reg = a.register_names[a.ip_offset] self._reg_list = a.default_symbolic_registers self._reg_list = filter(lambda r: r != self._sp_reg, self._reg_list) self._reg_list = filter(lambda r: r != self._ip_reg, self._reg_list) self.matches = dict() self.callsites = None self.inv_callsites = None self.func_info = dict() self.block_to_func = dict() self.map_callsites() if self._too_large(): l.warning("Too large") return self.base_symbolic_state = rop_utils.make_symbolic_state(self.project, self._reg_list) self.base_symbolic_state.options.discard(simuvex.o.SUPPORT_FLOATING_POINT) self.base_symbolic_state.regs.bp = self.base_symbolic_state.se.BVS("sreg_" + "ebp" + "-", self.project.arch.bits) for f in self._cfg.functions.values(): if f.is_syscall: continue if self.project.is_hooked(f.addr): continue # skip if no predecessors try: if require_predecessors and len(self._cfg.functions.callgraph.predecessors(f.addr)) == 0: continue except NetworkXError: if require_predecessors: continue # find the actual vars try: func_info = self.find_stack_vars_x86(f) self.func_info[f] = func_info except (SimEngineError, SimMemoryError) as ex: l.debug("angr translation error: %s", ex.message) except IdentifierException as e: l.debug("Identifier Exception: %s", e.message)
def do_trace(self, addr_trace, reverse_accesses, func_info): #pylint disable=unused-argument # get to the callsite from angrop import rop_utils s = rop_utils.make_symbolic_state(self.project, self._reg_list, stack_length=200) s.options.discard(options.AVOID_MULTIVALUED_WRITES) s.options.discard(options.AVOID_MULTIVALUED_READS) s.options.add(options.UNDER_CONSTRAINED_SYMEXEC) s.options.discard(options.LAZY_SOLVES) func_info = self.func_info[self.block_to_func[addr_trace[0]]] for i in range(func_info.frame_size / self.project.arch.bytes + 5): s.stack_push(s.se.BVS("var_" + hex(i), self.project.arch.bits)) if func_info.bp_based: s.regs.bp = s.regs.sp + func_info.bp_sp_diff s.regs.ip = addr_trace[0] addr_trace = addr_trace[1:] simgr = self.project.factory.simulation_manager( s, save_unconstrained=True) while len(addr_trace) > 0: simgr.stashes['unconstrained'] = [] simgr.step() stepped = False for ss in simgr.active: # todo could write symbolic data to pointers passed to functions if ss.history.jumpkind == "Ijk_Call": ss.regs.eax = ss.se.BVS("unconstrained_ret_%#x" % ss.addr, ss.arch.bits) ss.regs.ip = ss.stack_pop() ss.history.jumpkind = "Ijk_Ret" if ss.addr == addr_trace[0]: simgr.stashes['active'] = [ss] stepped = True break if not stepped: if len(simgr.unconstrained) > 0: s = simgr.unconstrained[0] if s.history.jumpkind == "Ijk_Call": s.regs.eax = s.se.BVS("unconstrained_ret", s.arch.bits) s.regs.ip = s.stack_pop() s.history.jumpkind = "Ijk_Ret" s.regs.ip = addr_trace[0] simgr.stashes['active'] = [s] stepped = True if not stepped: raise IdentifierException("could not get call args") addr_trace = addr_trace[1:] # step one last time to the call simgr.step() if len(simgr.active) == 0: IdentifierException("Didn't succeed call") return simgr.active[0]
def do_trace(self, addr_trace, reverse_accesses, func_info): #pylint disable=unused-argument # get to the callsite from angrop import rop_utils s = rop_utils.make_symbolic_state(self.project, self._reg_list, stack_length=200) s.options.discard(options.AVOID_MULTIVALUED_WRITES) s.options.discard(options.AVOID_MULTIVALUED_READS) s.options.add(options.UNDER_CONSTRAINED_SYMEXEC) s.options.discard(options.LAZY_SOLVES) func_info = self.func_info[self.block_to_func[addr_trace[0]]] for i in range(func_info.frame_size/self.project.arch.bytes+5): s.stack_push(s.se.BVS("var_" + hex(i), self.project.arch.bits)) if func_info.bp_based: s.regs.bp = s.regs.sp + func_info.bp_sp_diff s.regs.ip = addr_trace[0] addr_trace = addr_trace[1:] simgr = self.project.factory.simulation_manager(s, save_unconstrained=True) while len(addr_trace) > 0: simgr.stashes['unconstrained'] = [] simgr.step() stepped = False for ss in simgr.active: # todo could write symbolic data to pointers passed to functions if ss.history.jumpkind == "Ijk_Call": ss.regs.eax = ss.se.BVS("unconstrained_ret_%#x" % ss.addr, ss.arch.bits) ss.regs.ip = ss.stack_pop() ss.history.jumpkind = "Ijk_Ret" if ss.addr == addr_trace[0]: simgr.stashes['active'] = [ss] stepped = True break if not stepped: if len(simgr.unconstrained) > 0: s = simgr.unconstrained[0] if s.history.jumpkind == "Ijk_Call": s.regs.eax = s.se.BVS("unconstrained_ret", s.arch.bits) s.regs.ip = s.stack_pop() s.history.jumpkind = "Ijk_Ret" s.regs.ip = addr_trace[0] simgr.stashes['active'] = [s] stepped = True if not stepped: raise IdentifierException("could not get call args") addr_trace = addr_trace[1:] # step one last time to the call simgr.step() if len(simgr.active) == 0: IdentifierException("Didn't succeed call") return simgr.active[0]
def do_trace(self, addr_trace, reverse_accesses, func_info): # get to the callsite s = rop_utils.make_symbolic_state(self.project, self._reg_list, stack_length=200) s.options.discard(simuvex.o.AVOID_MULTIVALUED_WRITES) s.options.discard(simuvex.o.AVOID_MULTIVALUED_READS) s.options.add(simuvex.o.UNDER_CONSTRAINED_SYMEXEC) s.options.discard(simuvex.o.LAZY_SOLVES) func_info = self.func_info[self.block_to_func[addr_trace[0]]] for i in range(func_info.frame_size / self.project.arch.bytes + 5): s.stack_push(s.se.BVS("var_" + hex(i), self.project.arch.bits)) if func_info.bp_based: s.regs.bp = s.regs.sp + func_info.bp_sp_diff s.regs.ip = addr_trace[0] addr_trace = addr_trace[1:] p = self.project.factory.path(s) while len(addr_trace) > 0: p.step() stepped = False for ss in p.successors: # todo could write symbolic data to pointers passed to functions if ss.jumpkind == "Ijk_Call": ss.state.regs.eax = ss.state.se.BVS( "unconstrained_ret_%#x" % ss.addr, ss.state.arch.bits) ss.state.regs.ip = ss.state.stack_pop() ss.state.scratch.jumpkind = "Ijk_Ret" if ss.addr == addr_trace[0]: p = ss stepped = True if not stepped: if len(p.unconstrained_successors) > 0: p = p.unconstrained_successors[0] if p.jumpkind == "Ijk_Call": p.state.regs.eax = p.state.se.BVS( "unconstrained_ret_%#x" % p.addr, p.state.arch.bits) p.state.regs.ip = p.state.stack_pop() p.state.scratch.jumpkind = "Ijk_Ret" p.state.regs.ip = addr_trace[0] stepped = True if not stepped: raise IdentifierException("could not get call args") addr_trace = addr_trace[1:] # step one last time to the call p.step() if len(p.successors) == 0: IdentifierException("Didn't succeed call") return p.successors[0]
def __init__(self, binary, crash=None): """ :param binary: path to the binary which crashed :param crash: string of input which crashed the binary """ self.binary = binary self.crash = crash # verify it actually crashes the binary r = tracer.Runner(self.binary, input=self.crash, record_stdout=True) if not r.crash_mode: raise CrashFuzzerException("input did not crash the binary") self.orig_stdout = r.stdout self.addr_ast = None try: self._p = angr.Project(self.binary) self.orig_regs = r.reg_vals s = rop_utils.make_symbolic_state(self._p, reg_list=CGC_GENERAL_REGS) self._reg_asts = dict() for r in CGC_GENERAL_REGS: ast = s.se.BVS(r, 32, explicit_name=True) self._reg_asts[r] = ast s.registers.store(r, ast) s.ip = self.orig_regs["eip"] p = self._p.factory.path(s) p.step(num_inst=1) all_succ = p.successors + p.unconstrained_successors if len(all_succ) == 0: raise CannotExploit("no successors") succ = all_succ[0] for a in succ.actions.hardcopy: if a.type == "mem" and a.action == "read": dependencies = a.addr.ast.variables self.addr_ast = a.addr.ast self.reg_deps = dependencies | {"AST"} self.orig_regs = self._fix_reg_vals(self.orig_regs) l.debug("REG DEPS: %s", self.reg_deps) except CLEError as e: l.warning("CLEError: %s", e) pass if self.addr_ast is None: self.reg_deps = set(CGC_GENERAL_REGS) l.warning("couldn't find read addr depenency") self.pool = None self.byte_analysis = dict() self._bases = dict() self.skip_bytes = set() self.skip_sets = set() self.regs_to_numbers = dict() self.used_bytes = set() self.byte_translation_funcs = list() self.byte_translation_calls = dict() self._bit_patterns = dict() self._raw_payload = None self.output_leak_idx = None self.cgc_type = 2 self.make_bases() self.run() self.post_filter() self.post_analysis()
def __init__(self, cfg=None, require_predecessors=True, only_find=None): from angrop import rop_utils # self.project = project if not isinstance(self.project.loader.main_object, CGC): l.critical("The identifier currently works only on CGC binaries. Results may be completely unexpected.") if cfg is not None: self._cfg = cfg else: self._cfg = self.project.analyses.CFGFast(resolve_indirect_jumps=True) self._runner = Runner(self.project, self._cfg) # only find if in this set self.only_find = only_find # reg list a = self.project.arch self._sp_reg = a.register_names[a.sp_offset] self._bp_reg = a.register_names[a.bp_offset] self._ip_reg = a.register_names[a.ip_offset] self._reg_list = a.default_symbolic_registers self._reg_list = filter(lambda r: r != self._sp_reg, self._reg_list) self._reg_list = filter(lambda r: r != self._ip_reg, self._reg_list) self.matches = dict() self.callsites = None self.inv_callsites = None self.func_info = dict() self.block_to_func = dict() self.map_callsites() if self._too_large(): l.warning("Too large") return self.base_symbolic_state = rop_utils.make_symbolic_state(self.project, self._reg_list) self.base_symbolic_state.options.discard(options.SUPPORT_FLOATING_POINT) self.base_symbolic_state.regs.bp = self.base_symbolic_state.se.BVS("sreg_" + "ebp" + "-", self.project.arch.bits) for f in self._cfg.functions.values(): if f.is_syscall: continue if self.project.is_hooked(f.addr): continue # skip if no predecessors try: if require_predecessors and len(self._cfg.functions.callgraph.predecessors(f.addr)) == 0: continue except NetworkXError: if require_predecessors: continue # find the actual vars try: func_info = self.find_stack_vars_x86(f) self.func_info[f] = func_info except (SimEngineError, SimMemoryError) as e: l.debug("angr translation error: %s", e.message) except IdentifierException as e: l.debug("Identifier error: %s", e.message) except SimError as e: l.debug("Simulation error: %s", e.message)