def callback(self, tracer): # runs when this breakpoint is hit getter = ArgumentGetter(tracer, self.calling_convention) arguments = getter.get_arguments(self.description) argument_strings, argument_values = arguments argument_string = ', '.join(argument_strings) sys.stderr.write('%s(%s)' % (self.name, argument_string)) if 'ret' in self.description: # This is a terrible idea. While it does work the majority of the # time, it causes kernel panics without the "safe_to_hook" check, # and because of the "safe_to_hook" check doesn't work when a # library functions calls another library function through the # stubs section (usually when the a library comparison function, # like strcmp, is passed in to a library sort function, like # qsort). A better approach may be to add a memory-access # breakpoint on the return address. return_address = tracer.read_struct(tracer.sp, tracer.pointer_format)[0] safe_to_hook = debug.vm_region(tracer.task, return_address).inheritance if safe_to_hook: breakpoint = ReturnValueBreakpoint(self.calling_convention, self.description['ret']) tracer.add_breakpoint(return_address, breakpoint) else: sys.stderr.write('\n') else: sys.stderr.write('\n')
def search_memory(self, values): assert not self.running # find all allocated memory regions = [] address = 1 while 1: try: region = debug.vm_region(self.task, address) except OSError as e: break regions.append(region) address = regions[-1].address + regions[-1].size for region in regions: address = region.address size = region.size try: data = debug.vm_read_wrapper(self.task, address, size) except OSError as e: continue if values in data: return address + data.index(values) return None