Ejemplo n.º 1
0
def main():
    debuggers.verify_supported_platform()

    from optparse import OptionParser

    hdlr = logging.StreamHandler()
    logger.addHandler(hdlr)

    usage = "usage: %prog [options] fuzzedfile"
    parser = OptionParser(usage)
    parser.add_option('',
                      '--debug',
                      dest='debug',
                      action='store_true',
                      help='Enable debug messages (overrides --verbose)')
    parser.add_option('',
                      '--verbose',
                      dest='verbose',
                      action='store_true',
                      help='Enable verbose messages')
    parser.add_option('-c',
                      '--config',
                      default='configs/foe.yaml',
                      dest='config',
                      help='path to the configuration file to use')
    parser.add_option('-w',
                      '--windbg',
                      dest='use_windbg',
                      action='store_true',
                      help='Use windbg instead of cdb')
    parser.add_option('-b',
                      '--break',
                      dest='break_on_start',
                      action='store_true',
                      help='Break on start of debugger session')
    parser.add_option('-d',
                      '--debugheap',
                      dest='debugheap',
                      action='store_true',
                      help='Use debug heap')
    parser.add_option('-p',
                      '--debugger',
                      dest='debugger',
                      help='Use specified debugger')
    parser.add_option('-f',
                      '--filepath',
                      dest='filepath',
                      action='store_true',
                      help='Recreate original file path')
    (options, args) = parser.parse_args()

    if options.debug:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)

    cfg_file = options.config
    logger.debug('Config file: %s', cfg_file)

    if len(args) and os.path.exists(args[0]):
        fullpath_fuzzed_file = os.path.abspath(args[0])
        fuzzed_file = BasicFile(fullpath_fuzzed_file)
        logger.info('Fuzzed file is %s', fuzzed_file)
    else:
        parser.error('fuzzedfile must be specified')

    config = Config(cfg_file).config

    iterationpath = ''
    template = string.Template(config['target']['cmdline_template'])
    if options.filepath:
        # Recreate same file path as fuzz iteration
        resultdir = os.path.dirname(fuzzed_file.path)
        for msecfile in all_files(resultdir, '*.msec'):
            print '** using msecfile: %s' % msecfile
            iterationpath = getiterpath(msecfile)
            break

        if iterationpath:
            iterationdir = os.path.dirname(iterationpath)
            iterationfile = os.path.basename(iterationpath)
            mkdir_p(iterationdir)
            copy_file(fuzzed_file.path,
                      os.path.join(iterationdir, iterationfile))
            fuzzed_file.path = iterationpath

    cmd_as_args = get_command_args_list(template, fuzzed_file.path)[1]
    targetdir = os.path.dirname(cmd_as_args[0])

    args = []

    if options.use_windbg and options.debugger:
        parser.error('Options --windbg and --debugger are mutually exclusive.')

    if options.debugger:
        debugger_app = options.debugger
    elif options.use_windbg:
        debugger_app = 'windbg'
    else:
        debugger_app = 'cdb'

    args.append(debugger_app)

    if not options.debugger:
        # Using cdb or windbg
        args.append('-amsec.dll')
        if options.debugheap:
            # do not use hd, xd options if debugheap is set
            pass
        else:
            args.extend(('-hd', '-xd', 'gp'))
        if not options.break_on_start:
            args.extend(('-xd', 'bpe', '-G'))
        args.extend((
            '-xd',
            'wob',
            '-o',
        ))
    args.extend(cmd_as_args)
    logger.info('args %s' % cmd_as_args)

    p = Popen(args, cwd=targetdir, universal_newlines=True)
    p.wait()
 def __init__(self):
     fd, f = tempfile.mkstemp(suffix='.ext', prefix='fileroot')
     os.close(fd)
     self.fuzzedfile = BasicFile(f)
     self.debugger_template = 'foo'
Ejemplo n.º 3
0
def main():
    from optparse import OptionParser

    hdlr = logging.StreamHandler()
    logger.addHandler(hdlr)

    usage = "usage: %prog [options] fuzzedfile"
    parser = OptionParser(usage)
    parser.add_option('',
                      '--debug',
                      dest='debug',
                      action='store_true',
                      help='Enable debug messages (overrides --verbose)')
    parser.add_option('',
                      '--verbose',
                      dest='verbose',
                      action='store_true',
                      help='Enable verbose messages')
    parser.add_option('-t',
                      '--target',
                      dest='target',
                      help='the file to minimize to (typically the seedfile)')
    parser.add_option('-o',
                      '--outdir',
                      dest='outdir',
                      help='dir to write output to')
    parser.add_option('-s',
                      '--stringmode',
                      dest='stringmode',
                      action='store_true',
                      help='minimize to a string rather than to a target file')
    parser.add_option(
        '-x',
        '--preferx',
        dest='prefer_x_target',
        action='store_true',
        help='Minimize to \'x\' characters instead of Metasploit string pattern'
    )
    parser.add_option(
        '-f',
        '--faddr',
        dest='keep_uniq_faddr',
        action='store_true',
        help='Use exception faulting addresses as part of testcase signature')
    parser.add_option(
        '-b',
        '--bitwise',
        dest='bitwise',
        action='store_true',
        help='if set, use bitwise hamming distance. Default is bytewise')
    parser.add_option('-c',
                      '--confidence',
                      dest='confidence',
                      help='The desired confidence level (default: 0.999)',
                      type='float')
    parser.add_option('-g',
                      '--target-size-guess',
                      dest='initial_target_size',
                      help='A guess at the minimal value (int)',
                      type='int')
    parser.add_option('',
                      '--config',
                      dest='config',
                      help='path to the configuration file to use')
    parser.add_option(
        '',
        '--timeout',
        dest='timeout',
        metavar='N',
        type='int',
        default=0,
        help='Stop minimizing after N seconds (default is 0, never time out).')
    parser.add_option(
        '-k',
        '--keepothers',
        dest='keep_other_crashes',
        action='store_true',
        help='Keep other testcase hashes encountered during minimization')

    (options, args) = parser.parse_args()

    if options.debug:
        logger.setLevel(logging.DEBUG)
    elif options.verbose:
        logger.setLevel(logging.INFO)

    if options.config:
        cfg_file = os.path.expanduser(options.config)
    else:
        if os.path.isfile("../configs/bff.yaml"):
            cfg_file = "../configs/bff.yaml"
        elif os.path.isfile("configs/bff.yaml"):
            cfg_file = "configs/bff.yaml"
        else:
            parser.error(
                'Configuration file (--config) option must be specified.')
    logger.debug('Config file: %s', cfg_file)

    if options.stringmode and options.target:
        parser.error(
            'Options --stringmode and --target are mutually exclusive.')

    # Set some default options. Fast and loose if in string mode
    # More precise with minimize to seedfile
    if not options.confidence:
        if options.stringmode:
            options.confidence = 0.5
        else:
            options.confidence = 0.999
    if not options.initial_target_size:
        if options.stringmode:
            options.initial_target_size = 100
        else:
            options.initial_target_size = 1

    if options.confidence:
        try:
            options.confidence = float(options.confidence)
        except:
            parser.error('Confidence must be a float.')
    if not 0.0 < options.confidence < 1.0:
        parser.error('Confidence must be in the range 0.0 < c < 1.0')

    confidence = options.confidence

    if options.outdir:
        outdir = options.outdir
    else:
        outdir = "./minimizer_out"
    outdir = os.path.abspath(outdir)

    if not os.path.exists(outdir):
        filetools.make_directories(outdir)

    if not os.path.isdir(outdir):
        parser.error('--outdir must either already be a dir or not exist: %s' %
                     outdir)

    if len(args) and os.path.exists(args[0]):
        fuzzed_file = BasicFile(args[0])
        logger.info('Fuzzed file is: %s', fuzzed_file.path)
    else:
        parser.error('fuzzedfile must be specified')

    if options.target:
        seedfile = BasicFile(options.target)
    else:
        seedfile = None

    min2seed = not options.stringmode
    filename_modifier = ''

    crashers_dir = '.'

    cfg = load_and_fix_config(cfg_file)
    debugger_timeout = cfg['runner']['runtimeout'] * 2
    if debugger_timeout < 10:
        debugger_timeout = 10
    proc_compat = platform.system() == 'Linux'
    cfg['debugger']['proc_compat'] = proc_compat
    cfg['debugger']['runtimeout'] = debugger_timeout

    with LinuxTestcase(cfg=cfg,
                       seedfile=seedfile,
                       fuzzedfile=fuzzed_file,
                       program=cfg['target']['program'],
                       cmd_template=cfg['target']['cmdline_template'],
                       debugger_timeout=debugger_timeout,
                       cmdlist=get_command_args_list(
                           cfg['target']['cmdline_template'],
                           fuzzed_file.path)[1],
                       backtrace_lines=cfg['debugger']['backtracelevels'],
                       crashers_dir=crashers_dir,
                       workdir_base=outdir,
                       keep_faddr=options.keep_uniq_faddr) as testcase:

        filetools.make_directories(testcase.tempdir)
        logger.info('Copying %s to %s', fuzzed_file.path, testcase.tempdir)
        filetools.copy_file(fuzzed_file.path, testcase.tempdir)

        minlog = os.path.join(outdir, 'min_log.txt')

        with Minimizer(cfg=cfg,
                       testcase=testcase,
                       crash_dst_dir=outdir,
                       seedfile_as_target=min2seed,
                       bitwise=options.bitwise,
                       confidence=confidence,
                       logfile=minlog,
                       tempdir=testcase.tempdir,
                       maxtime=options.timeout,
                       preferx=options.prefer_x_target,
                       keep_uniq_faddr=options.keep_uniq_faddr) as minimize:
            minimize.save_others = options.keep_other_crashes
            minimize.target_size_guess = int(options.initial_target_size)
            minimize.go()

            if options.stringmode:
                logger.debug('x character substitution')
                length = len(minimize.fuzzed_content)
                if options.prefer_x_target:
                    # We minimized to 'x', so we attempt to get metasploit as a
                    # freebie
                    targetstring = list(text.metasploit_pattern_orig(length))
                    filename_modifier = '-mtsp'
                else:
                    # We minimized to metasploit, so we attempt to get 'x' as a
                    # freebie
                    targetstring = list('x' * length)
                    filename_modifier = '-x'

                fuzzed = list(minimize.fuzzed_content)
                for idx in minimize.bytemap:
                    logger.debug('Swapping index %d', idx)
                    targetstring[idx] = fuzzed[idx]
                filename = ''.join(
                    (testcase.fuzzedfile.root, filename_modifier,
                     testcase.fuzzedfile.ext))
                metasploit_file = os.path.join(testcase.tempdir, filename)

                with open(metasploit_file, 'wb') as f:
                    f.writelines(targetstring)

        testcase.copy_files(outdir)
        testcase.clean_tmpdir()
Ejemplo n.º 4
0
def main():
    from optparse import OptionParser

    hdlr = logging.StreamHandler()
    logger.addHandler(hdlr)

    usage = "usage: %prog [options] fuzzedfile"
    parser = OptionParser(usage)
    parser.add_option('', '--debug', dest='debug', action='store_true',
                      help='Enable debug messages (overrides --verbose)')
    parser.add_option('', '--verbose', dest='verbose', action='store_true',
                      help='Enable verbose messages')
    parser.add_option('-c', '--config', default='configs/bff.yaml',
                      dest='config', help='path to the configuration file to use')
    parser.add_option('-a', '--args', dest='print_args',
                      action='store_true',
                      help='Print function arguments')
    parser.add_option('-o', '--out', dest='outfile',
                      help='PIN output file')
    parser.add_option('-f', '--filepath', dest='filepath',
                      action='store_true', help='Recreate original file path')

    (options, args) = parser.parse_args()

    if options.debug:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)

    if options.outfile:
        outfile = options.outfile
    else:
        outfile = 'calltrace.log'

    cfg_file = options.config
    logger.debug('Config file: %s', cfg_file)

    if len(args) and os.path.exists(args[0]):
        fullpath_fuzzed_file = os.path.abspath(args[0])
        fuzzed_file = BasicFile(fullpath_fuzzed_file)
        logger.info('Fuzzed file is: %s', fuzzed_file.path)
    else:
        parser.error('fuzzedfile must be specified')

    iterationpath = ''

    if options.filepath:
        # Recreate same file path as fuzz iteration
        resultdir = os.path.dirname(fuzzed_file.path)
        for gdbfile in all_files(resultdir, '*.gdb'):
            print '** using gdb: %s' % gdbfile
            iterationpath = getiterpath(gdbfile)
            break
        if iterationpath:
            iterationdir = os.path.dirname(iterationpath)
            iterationfile = os.path.basename(iterationpath)
            if iterationdir:
                mkdir_p(iterationdir)
                copy_file(fuzzed_file.path,
                          os.path.join(iterationdir, iterationfile))
                fullpath_fuzzed_file = iterationpath

    config = load_and_fix_config(cfg_file)

    cmd_as_args = get_command_args_list(
        config['target']['cmdline_template'], fullpath_fuzzed_file)[1]
    args = []

    pin = os.path.expanduser('~/pin/pin')
    pintool = os.path.expanduser('~/pintool/calltrace.so')
    args = [pin, '-injection', 'child', '-t',
            pintool, '-o', outfile]
    if options.print_args:
        args.append('-a')
    args.append('--')
    args.extend(cmd_as_args)

    logger.info('args %s' % args)

    p = Popen(args, universal_newlines=True)
    p.wait()
Ejemplo n.º 5
0
    def go(self):
        # start by copying the fuzzed_content file since as of now it's our
        # best fit
        filetools.copy_file(self.testcase.fuzzedfile.path, self.outputfile)

        # replace the fuzzedfile object in testcase with the minimized copy
        self.testcase.fuzzedfile = BasicFile(self.outputfile)

        self.logger.info('Attempting to minimize testcase(es) [%s]',
                         self._crash_hashes_string())

        # keep going until either:
        # a. we find a minimum hd of 1
        # b. we run out of discard_chances
        # c. our discard_chance * minimum hd is less than one (we won't discard anything)
        # d. we've exhaustively searched all the possible files with hd less
        # than self.min_distance
        while not self.min_found and not self.try_exhaustive:

            if not self.set_discard_chance():
                break

            if not self.set_n_misses():
                break

            got_hit = False
            while self.consecutive_misses <= self.n_misses_allowed:

                if self.use_watchdog:
                    # touch the watchdog file so we don't reboot during long
                    # minimizations
                    open(self.watchdogfile, 'w').close()

                # Fix for BFF-208
                if self._time_exceeded():
                    logger.info(
                        'Max time for minimization exceeded, ending minimizer early.'
                    )
                    self.min_found = True
                    break

                if not self.set_discard_chance():
                    break

                if not self.set_n_misses():
                    break

                self.swap_bytes()

                self.total_tries += 1

                # have we been at this level before?
                if not self.files_tried_at_hd.get(self.min_distance):
                    # we've reached a new minimum, so create new sets
                    self.files_tried_at_hd[self.min_distance] = set()
                    self.files_tried_singlebyte_at_hd[
                        self.min_distance] = set()

                # have we exhausted all the possible files with smaller hd?
                possible_files = (2**self.min_distance) - 2
                seen_files = len(self.files_tried_at_hd[self.min_distance])

                # maybe we're done?
                if seen_files == possible_files:
                    # we've exhaustively searched everything with hd <
                    # self.min_distance
                    self.logger.info(
                        'Exhaustively searched all files shorter than %d',
                        self.min_distance)
                    self.min_found = True
                    break

                # have we exhausted all files that are 1 byte smaller hd?
                possible_singlebyte_diff_files = self.min_distance
                singlebyte_diff_files_seen = len(
                    self.files_tried_singlebyte_at_hd[self.min_distance])

                # maybe we're done?
                if singlebyte_diff_files_seen == possible_singlebyte_diff_files:
                    self.logger.info(
                        'We have tried all %d files that are one byte closer than the current minimum',
                        self.min_distance)
                    self.min_found = True
                    break

                # remember this file for next time around
                self.files_tried_at_hd[self.min_distance].add(
                    self.newfuzzed_md5)
                if self.newfuzzed_hd == (self.min_distance - 1):
                    self.files_tried_singlebyte_at_hd[self.min_distance].add(
                        self.newfuzzed_md5)

                self.print_intermediate_log()

                if self.newfuzzed_md5 in self.files_tried:
                    # we've already seen this attempt, so skip ahead to the next one
                    # but still count it as a miss since our math assumes we're putting
                    # the marbles back in the jar after each draw
                    self.consecutive_misses += 1
                    self.total_misses += 1
                    continue

                # we didn't skip ahead, so it must have been new. Remember it
                # now
                self.files_tried.add(self.newfuzzed_md5)

                # we have a better match, write it to a file
                if not len(self.newfuzzed):
                    raise MinimizerError(
                        'New fuzzed_content content is empty.')

                self._write_file()

                if self.is_same_crash():
                    # record the result
                    # 1. copy the tempfile
                    filetools.best_effort_move(self.tempfile, self.outputfile)
                    # 2. replace the fuzzed_content file in the crasher with
                    # the current one
                    self.testcase.fuzzedfile = BasicFile(self.outputfile)
                    # 3. replace the current fuzzed_content with newfuzzed
                    self.fuzzed_content = self.newfuzzed
                    self.min_distance = self.newfuzzed_hd

                    got_hit = True

                    if self.min_distance == 1:
                        # we are done
                        self.min_found = True
                    elif self.newfuzzed_hd <= self.exhaustivesearch_threshold:
                        self._set_bytemap()
                        logger.info(
                            'Exhaustively checking remaining %s bytes' %
                            self.newfuzzed_hd)
                        self.try_exhaustive = True
                        break
                    else:
                        # set up for next iteration
                        self.consecutive_misses = 0
                        if not self.set_discard_chance():
                            break
                        if not self.set_n_misses():
                            break
                else:
                    # we missed. increment counter and try again
                    self.total_misses += 1
                    self.consecutive_misses += 1

                    # Fix for BFF-225
                    # There may be some situation that causes testcase uniqueness
                    # hashing to break. (e.g. BFF-224 ). Minimizer should bail
                    # if the number of unique crashes encountered exceeds some
                    # threshold. e.g. 20 maybe?
                    if len(self.other_crashes
                           ) > MAX_OTHER_CRASHES and self.seedfile_as_target:
                        logger.info(
                            'Exceeded maximum number of other crashes (%d), ending minimizer early.',
                            MAX_OTHER_CRASHES)
                        self.min_found = True
                        break

            if not got_hit:
                # we are self.confidence_level sure that self.target_size_guess is wrong
                # so increment it by 1
                self.target_size_guess += 1

        if self.try_exhaustive:
            for offset in list(self.bytemap):
                logger.debug('Verifying byte location: %s' % hex(offset))
                self.revert_byte(offset)
                self._write_file()
                if self.is_same_crash():
                    logger.debug('Fuzzed byte at offset %s is not relevant' %
                                 hex(offset))
                    filetools.best_effort_move(self.tempfile, self.outputfile)
                    self.testcase.fuzzedfile = BasicFile(self.outputfile)
                    self.fuzzed_content = self.newfuzzed
                    self.bytemap.remove(offset)

        # We're done minimizing. Set the bytemap (kept bytes)
        self._set_bytemap()
        self.logger.info('We were looking for [%s] ...',
                         self._crash_hashes_string())
        for (md5, count) in self.crash_sigs_found.items():
            self.logger.info('\t...and found %s\t%d times', md5, count)
        if self.bytemap:
            hex_bytemap = []
            for offset in self.bytemap:
                hex_bytemap.append(hex(offset))
            self.logger.info('Bytemap: %s', hex_bytemap)
Ejemplo n.º 6
0
def main():
    debuggers.verify_supported_platform()

    from optparse import OptionParser

    hdlr = logging.StreamHandler()
    logger.addHandler(hdlr)

    usage = "usage: %prog [options] fuzzedfile"
    parser = OptionParser(usage)
    parser.add_option('',
                      '--debug',
                      dest='debug',
                      action='store_true',
                      help='Enable debug messages (overrides --verbose)')
    parser.add_option('',
                      '--verbose',
                      dest='verbose',
                      action='store_true',
                      help='Enable verbose messages')
    parser.add_option('-t',
                      '--target',
                      dest='target',
                      help='the file to minimize to (typically the seedfile)')
    parser.add_option('-o',
                      '--outdir',
                      dest='outdir',
                      help='dir to write output to')
    parser.add_option('-s',
                      '--stringmode',
                      dest='stringmode',
                      action='store_true',
                      help='minimize to a string rather than to a target file')
    parser.add_option(
        '-x',
        '--preferx',
        dest='prefer_x_target',
        action='store_true',
        help='Minimize to \'x\' characters instead of Metasploit string pattern'
    )
    parser.add_option(
        '-f',
        '--faddr',
        dest='keep_uniq_faddr',
        action='store_true',
        help='Use exception faulting addresses as part of crash signature')
    parser.add_option(
        '-b',
        '--bitwise',
        dest='bitwise',
        action='store_true',
        help='if set, use bitwise hamming distance. Default is bytewise')
    parser.add_option('-c',
                      '--confidence',
                      dest='confidence',
                      help='The desired confidence level (default: 0.999)')
    parser.add_option('-g',
                      '--target-size-guess',
                      dest='initial_target_size',
                      help='A guess at the minimal value (int)')
    parser.add_option('',
                      '--config',
                      default='configs/foe.yaml',
                      dest='config',
                      help='path to the configuration file to use')
    parser.add_option(
        '',
        '--timeout',
        dest='timeout',
        metavar='N',
        type='int',
        default=0,
        help='Stop minimizing after N seconds (default is 0, never time out).')
    parser.add_option(
        '-k',
        '--keepothers',
        dest='keep_other_crashes',
        action='store_true',
        help='Keep other crash hashes encountered during minimization')
    (options, args) = parser.parse_args()

    if options.debug:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)

    if options.config:
        cfg_file = options.config
    else:
        cfg_file = "../conf.d/bff.cfg"
    logger.debug('Config file: %s', cfg_file)

    if options.stringmode and options.target:
        parser.error(
            'Options --stringmode and --target are mutually exclusive.')

    # Set some default options. Fast and loose if in string mode
    # More precise with minimize to seedfile
    if not options.confidence:
        if options.stringmode:
            options.confidence = 0.5
        else:
            options.confidence = 0.999
    if not options.initial_target_size:
        if options.stringmode:
            options.initial_target_size = 100
        else:
            options.initial_target_size = 1

    if options.confidence:
        try:
            options.confidence = float(options.confidence)
        except:
            parser.error('Confidence must be a float.')
    if not 0.0 < options.confidence < 1.0:
        parser.error('Confidence must be in the range 0.0 < c < 1.0')

    confidence = options.confidence

    if options.outdir:
        outdir = options.outdir
    else:
        mydir = os.path.dirname(os.path.abspath(__file__))
        parentdir = os.path.abspath(os.path.join(mydir, '..'))
        outdir = os.path.abspath(os.path.join(parentdir, 'minimizer_out'))

    filetools.make_directories(outdir)

    if len(args) and os.path.exists(args[0]):
        fuzzed_file = BasicFile(args[0])
        logger.info('Fuzzed file is %s', fuzzed_file)
    else:
        parser.error('fuzzedfile must be specified')

    config = Config(cfg_file).config
    cfg = _create_minimizer_cfg(config)

    if options.target:
        seedfile = BasicFile(options.target)
    else:
        seedfile = None

    min2seed = not options.stringmode
    filename_modifier = ''
    retries = 0
    debugger_class = msec.MsecDebugger
    template = string.Template(config['target']['cmdline_template'])
    cmd_as_args = get_command_args_list(template, fuzzed_file.path)[1]
    with FoeCrash(template, seedfile, fuzzed_file, cmd_as_args, None,
                  debugger_class, config['debugger'], outdir,
                  options.keep_uniq_faddr, config['target']['program'],
                  retries) as crash:
        filetools.make_directories(crash.tempdir)
        logger.info('Copying %s to %s', fuzzed_file.path, crash.tempdir)
        filetools.copy_file(fuzzed_file.path, crash.tempdir)

        minlog = os.path.join(outdir, 'min_log.txt')

        with Minimizer(cfg=cfg,
                       crash=crash,
                       crash_dst_dir=outdir,
                       seedfile_as_target=min2seed,
                       bitwise=options.bitwise,
                       confidence=confidence,
                       tempdir=outdir,
                       logfile=minlog,
                       maxtime=options.timeout,
                       preferx=options.prefer_x_target) as minimize:
            minimize.save_others = options.keep_other_crashes
            minimize.target_size_guess = int(options.initial_target_size)
            minimize.go()

        if options.stringmode:
            logger.debug('x character substitution')
            length = len(minimize.fuzzed)
            if options.prefer_x_target:
                #We minimized to 'x', so we attempt to get metasploit as a freebie
                targetstring = list(text.metasploit_pattern_orig(length))
                filename_modifier = '-mtsp'
            else:
                #We minimized to metasploit, so we attempt to get 'x' as a freebie
                targetstring = list('x' * length)
                filename_modifier = '-x'

            fuzzed = list(minimize.fuzzed)
            for idx in minimize.bytemap:
                logger.debug('Swapping index %d', idx)
                targetstring[idx] = fuzzed[idx]
            filename = ''.join((crash.fuzzedfile.root, filename_modifier,
                                crash.fuzzedfile.ext))
            metasploit_file = os.path.join(crash.tempdir, filename)

            f = open(metasploit_file, 'wb')
            try:
                f.writelines(targetstring)
            finally:
                f.close()
        crash.copy_files(outdir)
        crash.clean_tmpdir()