def function_to_patch_locations(self, ff): # TODO tail-call is handled lazily just by considering jumping out functions as not sane if cfg_utils.is_sane_function(ff) and cfg_utils.detect_syscall_wrapper(self.patcher,ff) == None \ and not cfg_utils.is_floatingpoint_function(self.patcher,ff) and not ff.addr in self.safe_functions: if cfg_utils.is_longjmp(self.patcher, ff): self.found_longjmp = ff.addr elif cfg_utils.is_setjmp(self.patcher, ff): self.found_setjmp = ff.addr else: start = ff.startpoint ends = set() for ret_site in ff.ret_sites: bb = self.patcher.project.factory.fresh_block( ret_site.addr, ret_site.size) last_instruction = bb.capstone.insns[-1] if last_instruction.mnemonic != u"ret": msg = "bb at %s does not terminate with a ret in function %s" l.debug(msg % (hex(int(bb.addr)), ff.name)) break else: ends.add(last_instruction.address) else: if len(ends) == 0: l.debug("cannot find any ret in function %s" % ff.name) else: return int(start.addr), map( int, ends) #avoid "long" problems l.debug("function %s has problems and cannot be patched" % ff.name) return None, None
def test_setlongjmp_detection(): solutions = [ ("CADET_00003",0x80486c8,0x80486e3), ("CROMU_00008",0x804C3AC,0x804C3C7), ("Ofast/CROMU_00008",0x804ABD7,0x804ABF2), ] for tbin, setjmp, longjmp in solutions: filepath = os.path.join(bin_location, tbin) backend = DetourBackend(filepath) cfg = backend.cfg for k,ff in cfg.functions.items(): msg = "detection failure in %s (%#x vs %#x)" if cfg_utils.is_setjmp(backend,ff): nose.tools.assert_equal(setjmp,ff.addr,"setjmp " + msg %(tbin,setjmp,ff.addr)) elif cfg_utils.is_longjmp(backend,ff): nose.tools.assert_equal(longjmp,ff.addr,"longjmp " + msg %(tbin,setjmp,ff.addr))