def _combined_stdout_stderr(self, binary, gdb_run, hint): executer = Executer(self.config) for path, _, files in os.walk(self.search_dir): for filename in files: if filename.endswith(self.config.run_extension): continue filepath = os.path.join(path, filename) if gdb_run: command = self.config.get_gdb_command_line(binary, filepath) new_filename = filename+"-"+os.path.basename(binary)+hint+self.config.gdb_prefix else: command = self.config.get_command_line(binary, filepath) new_filename = filename+"-"+os.path.basename(binary)+hint Logger.debug("Looking for stdout/stderr output:", command, debug_level=4) if self.output_dir: output_file_name = get_new_output_file_name(self.output_dir, new_filename, self.config.run_extension, self.config.max_digets) new_filepath = os.path.join(self.output_dir, output_file_name) else: output_file_name = get_new_output_file_name(path, new_filename, self.config.run_extension, self.config.max_digets) new_filepath = os.path.join(path, output_file_name) fp = file(new_filepath, "w") executer.get_output_for_run(command, fp, env=self.config.env) fp.close()
class FeelingLuckyExploiter: """ Simple idea: We replace a couple of bytes in the input file with something else and check if the crashing eip is changing. """ def __init__(self, config, search_dir=None, output_dir=None): self.config = config self.search_dir = search_dir if self.search_dir is None: self.search_dir = self.config.original_crashes_directory self.output_dir = output_dir if self.output_dir is None: self.output_dir = os.path.join(self.config.output_dir, "byte-changing-offsets") self.lucky_hex_values = "EEDDCCBB".decode("hex") #self.lucky_hex_values_upper_bound = hex(int(self.lucky_hex_values.encode("hex"),16)+0xFF)[2:].decode("hex") self.lucky_hex_values_upper_bound = "EEDDCDBB".decode("hex") self.gdb_script = """info registers eip""" self.gdb_script_path = self.config.prepare_gdb_script(self.gdb_script) self.regular_expr = re.compile("eip +(0x[0-9a-fA-F]{8})") self.executer = Executer(self.config) def run_forest_run(self): if self.output_dir is not None and not os.path.exists(self.output_dir): os.mkdir(self.output_dir) new_file_path = os.path.join(self.config.tmp_dir, "feelingLucky.txt") cmd = self.config.get_gdb_command_line(self.config.get_most_standard_binary(), new_file_path, self.gdb_script_path) for path, _, files in os.walk(self.search_dir): for filename in files: eips = [] indexes = [] if filename.endswith(self.config.run_extension): continue Logger.info("Trying my luck with", filename) filepath = os.path.join(path, filename) orig_file = file(filepath, "rb").read() Logger.debug(filepath, debug_level=4) for index in xrange(0,len(orig_file)-len(self.lucky_hex_values)): new_file = orig_file[:index] + self.lucky_hex_values + orig_file[index+len(self.lucky_hex_values):] #Logger.debug(new_file[:100]) file(new_file_path, "w").write(new_file) crash_eip = self.get_crash_eip(cmd) if crash_eip: if not crash_eip in eips: eips.append(crash_eip) indexes.append(index) if self.lucky_hex_values <= crash_eip and crash_eip <= self.lucky_hex_values_upper_bound: o = os.path.join(self.output_dir, filename) Logger.info("WTF, we actually were able to control EIP! See file ", o) file(o, "w").write(new_file) # else: # Logger.debug("Binary crashed, but at eip:", hex(crash_eip), "index to put lucky hex value in file:", index, debug_level=7) Logger.info("Seen the following crashing eips for this file:", list_as_intervals(eips, as_hex=True)) Logger.info("File indexes that lead to different crashes for this file:", list_as_intervals(indexes)) def get_crash_eip(self, cmd): eip = None Logger.busy() gdb_output = self.executer.get_output_for_run(cmd, self.executer.pipe, self.config.run_timeout_tmin, env=self.config.env, stderr=self.executer.pipe) #Logger.debug("GDB output:", gdb_output) m = self.regular_expr.search(gdb_output) if m: eip = m.group(1) eip = int(eip, 16) #if not signal == SignalFinder.TIMEOUT_SIGNAL: # Logger.error("Minimizing this file took too long, aborted") return eip