Exemplo n.º 1
0
    def _cache_app(self):
        logger.debug('cache program')
        sf = self.seedfile_set.next_item()

        # Run the program once to cache it into memory
        fullpathorig = self._full_path_original(sf.path)
        cmdargs = get_command_args_list(
            self.config['target']['cmdline_template'], infile=fullpathorig)[1]

        if 'copyfuzzedto' in self.config['target']:
            from shutil import copyfile
            copyfuzzedto = str(self.config['target'].get('copyfuzzedto', ''))
            logger.debug("Copying seed file to " + copyfuzzedto)
            copyfile(fullpathorig, copyfuzzedto)

        if 'postprocessfuzzed' in self.config['target']:
            postprocessfuzzed = str(self.config['target']['postprocessfuzzed'])
            logger.debug("Executing postprocess " + postprocessfuzzed)
            os.system(postprocessfuzzed)

        logger.info('Invoking %s' % cmdargs)
        subp.run_with_timer(
            cmdargs,
            self.config['runner']['runtimeout'] * 8,
            self.config['target']['program'],
            use_shell=False,
            seeoutput=True,
        )

        # Give target time to die
        logger.info(
            'Please ensure that the target program has just executed successfully'
        )
        time.sleep(10)
Exemplo n.º 2
0
    def __init__(self, cfg, testcase, outfile=None, timeout=None, **options):
        logger.debug('Initializing %s', self.__class__.__name__)
        self.cfg = cfg
        self.testcase = testcase

        self.cmdargs = get_command_args_list(
            self.cfg['target']['cmdline_template'],
            testcase.fuzzedfile.path)[1]
        self.outfile = outfile
        self.timeout = float(timeout)
        self.progname = self.cmdargs[1]
        self.options = options

        self.preserve_stderr = False
        self.tmpdir = testcase.fuzzedfile.dirname

        # child classes should explicitly set this to True if they need it:
        self.empty_output_ok = False
        self.missing_output_ok = False

        # keep track of retries
        self.retry_count = 0
        self.max_retries = 3

        # catch stderr if we're not already redirecting it
        # typically outfile is just going into a temp dir so we'll
        # drop a stderr file there (so it will just get deleted when
        # bff does its normal cleanup). It's really only useful if
        # there is a problem that raises an exception, which therefore
        # leaves the temp dir behind.
        if self.options.get('stderr'):
            self.preserve_stderr = True
        else:
            self._set_stderrpath()
Exemplo n.º 3
0
    def _cache_app(self):
        logger.debug(
            'Caching application %s and determining if we need to watch the CPU...',
            self.program)
        sf = self.seedfile_set.next_item()
        cmdargs = get_command_args_list(
            self.config['target']['cmdline_template'], infile=sf.path)[1]

        if 'copyfuzzedto' in self.config['target']:
            from shutil import copyfile
            copyfuzzedto = str(self.config['target'].get('copyfuzzedto', ''))
            logger.debug("Copying seed file to " + copyfuzzedto)
            copyfile(sf.path, copyfuzzedto)

        if 'postprocessfuzzed' in self.config['target']:
            postprocessfuzzed = str(self.config['target']['postprocessfuzzed'])
            logger.debug("Executing postprocess " + postprocessfuzzed)
            os.system(postprocessfuzzed)

        logger.info('Invoking %s' % cmdargs)

        # Use overriden Popen that uses a job object to make sure that
        # child processes are killed
        p = Popen(cmdargs)
        runtimeout = self.config['runner']['runtimeout']
        logger.debug('...Timer: %f', runtimeout)
        t = Timer(runtimeout, self.kill, args=[p])
        logger.debug('...timer start')
        t.start()
        p.wait()
        logger.debug('...timer stop')
        t.cancel()
        if not self.gui_app:
            logger.debug('This seems to be a CLI application.')
        try:
            runner_watchcpu = str(self.config['runner']['watchcpu']).lower()
            debugger_watchcpu = runner_watchcpu
        except KeyError:
            self.config['runner']['watchcpu'] = 'auto'
            self.config['debugger']['watchcpu'] = 'auto'
            runner_watchcpu = 'auto'
            debugger_watchcpu = 'auto'
        if runner_watchcpu == 'auto':
            logger.debug('Disabling runner CPU monitoring for dynamic timeout')
            self.config['runner']['watchcpu'] = False
        if debugger_watchcpu == 'auto':
            logger.debug(
                'Disabling debugger CPU monitoring for dynamic timeout')
            self.config['debugger']['watchcpu'] = False
        elif debugger_watchcpu == 'true':
            logger.debug('Manually enabling CPU watching for debugger')
            self.config['debugger']['watchcpu'] = True

        logger.info(
            'Please ensure that the target program has just executed successfully'
        )
        time.sleep(10)
Exemplo n.º 4
0
 def update_crash_details(self):
     # We might be updating crash details because we have a new fuzzedfile
     # (with a different path)
     self.cmdlist = get_command_args_list(self.cmd_template,
                                          infile=self.fuzzedfile.path)[1]
     self.cmdargs = self.cmdlist[1:]
     self.tempdir = tempfile.mkdtemp(prefix=self._tmp_pfx,
                                     suffix=self._tmp_sfx,
                                     dir=self.workdir_base)
     self.copy_files_to_temp()
    def test_get_command_args_list(self):
        cmd = 'program arg1 arg2 $SEEDFILE arg3 arg4'
        cmd_template = string.Template(cmd)
        infile = 'foobar'

        result = clt.get_command_args_list(cmd_template, infile)
        self.assertEqual(2, len(result))

        (as_string, as_list) = result

        for substring in ['program', 'arg1', 'arg2', 'arg3', 'arg4', 'foobar']:
            self.assertTrue(substring in as_string)
            self.assertTrue(substring in as_list)
Exemplo n.º 6
0
def _create_minimizer_cfg(cfg):
    class DummyCfg(object):
        pass
    config = DummyCfg()
    config.backtracelevels = 5  # doesn't matter what this is, we don't use it
    config.debugger_timeout = cfg['runner']['runtimeout'] * 2
    if config.debugger_timeout < 10:
        config.debugger_timeout = 10
    template = string.Template(cfg['target']['cmdline_template'])
    config.get_command_args_list = lambda x: get_command_args_list(
        template, x)[1]
    config.program = cfg['target']['program']
    config.exclude_unmapped_frames = False
    config.watchdogfile = os.devnull
    return config
Exemplo n.º 7
0
    def __init__(self, options, cmd_template, fuzzed_file, workingdir_base):
        RunnerBase.__init__(self, options, cmd_template, fuzzed_file,
                            workingdir_base)

        logger.debug('Initialize Runner')

        self.exceptions = [
            0x80000001,  # STATUS_GUARD_PAGE_VIOLATION
            0x80000002,  # EXCEPTION_DATATYPE_MISALIGNMENT
            0x80000005,  # STATUS_BUFFER_OVERFLOW
            0xC0000005,  # STATUS_ACCESS_VIOLATION
            0xC0000009,  # STATUS_BAD_INITIAL_STACK
            0xC000000A,  # STATUS_BAD_INITIAL_PC
            0xC000001D,  # STATUS_ILLEGAL_INSTRUCTION
            0xC0000025,  # EXCEPTION_NONCONTINUABLE_EXCEPTION
            0xC0000026,  # EXCEPTION_INVALID_DISPOSITION
            0xC000008C,  # EXCEPTION_ARRAY_BOUNDS_EXCEEDED
            0xC000008D,  # STATUS_FLOAT_DENORMAL_OPERAND
            0xC000008E,  # EXCEPTION_FLT_DIVIDE_BY_ZERO
            0xC000008F,  # EXCEPTION_FLOAT_INEXACT_RESULT
            0xC0000090,  # EXCEPTION_FLT_INVALID_OPERATION
            0xC0000091,  # EXCEPTION_FLT_OVERFLOW
            0xC0000092,  # EXCEPTION_FLT_STACK_CHECK
            0xC0000093,  # EXCEPTION_FLT_UNDERFLOW
            0xC0000094,  # EXCEPTION_INT_OVERFLOW
            0xC0000095,  # EXCEPTION_INT_OVERFLOW
            0xC0000096,  # STATUS_PRIVILEGED_INSTRUCTION
            0xC00000FD,  # STATUS_STACK_OVERFLOW
            0xC00002B4,  # STATUS_FLOAT_MULTIPLE_FAULTS
            0xC00002B5,  # STATUS_FLOAT_MULTIPLE_TRAPS
            0xC00002C5,  # STATUS_DATATYPE_MISALIGNMENT_ERROR
            0xC00002C9,  # STATUS_REG_NAT_CONSUMPTION
        ]

        self.watchcpu = options.get('watchcpu', False)
        (self.cmd,
         self.cmdlist) = get_command_args_list(cmd_template, fuzzed_file)
        logger.debug('Command: %s', self.cmd)

        find_or_create_dir(self.workingdir)

        self.t = None
        self.returncode = None
        self.remembered = []

        if not hasattr(self, 'verify_architecture'):
            # check the architecture unless our options have already set it
            self.verify_architecture = True
Exemplo n.º 8
0
    def _construct_testcase(self):
        with WindowsTestcase(
                cfg=self.cfg,
                seedfile=self.seedfile,
                fuzzedfile=BasicFile(self.fuzzer.output_file_path),
                program=self.cfg['target']['program'],
                cmd_template=self.cmd_template,
                debugger_timeout=self.cfg['debugger']['runtimeout'],
                cmdlist=get_command_args_list(self.cmd_template,
                                              self.fuzzer.output_file_path)[1],
                dbg_opts=self.cfg['debugger'],
                workdir_base=self.working_dir,
                keep_faddr=self.cfg['runoptions'].get('keep_unique_faddr',
                                                      False),
                heisenbug_retries=self.retries,
                copy_fuzzedfile=self.fuzzer.fuzzed_changes_input) as testcase:

            # put it on the list for the analysis pipeline
            self.testcases.append(testcase)
Exemplo n.º 9
0
    def _cache_app(self):
        logger.debug('cache program')
        sf = self.seedfile_set.next_item()

        # Run the program once to cache it into memory
        fullpathorig = self._full_path_original(sf.path)
        cmdargs = get_command_args_list(
            self.config['target']['cmdline_template'], infile=fullpathorig)[1]
        logger.info('Invoking %s' % cmdargs)
        subp.run_with_timer(
            cmdargs,
            self.config['runner']['runtimeout'] * 8,
            self.config['target']['program'],
            use_shell=False,
            seeoutput=True,
        )

        # Give target time to die
        logger.info(
            'Please ensure that the target program has just executed successfully'
        )
        time.sleep(10)
Exemplo n.º 10
0
    def run_debugger(self, infile, outfile):
        self.debugger_runs += 1
        cmd_args = get_command_args_list(
            self.cfg['target']['cmdline_template'], infile)[1]
        cmd = cmd_args[0]
        cmd_args = cmd_args[1:]

        exclude_unmapped_frames = self.cfg['analyzer'].get(
            'exclude_unmapped_frames', True)

        dbg = self._debugger_cls(
            cmd,
            cmd_args,
            outfile,
            self.debugger_timeout,
            template=self.testcase.debugger_template,
            exclude_unmapped_frames=exclude_unmapped_frames,
            keep_uniq_faddr=self.keep_uniq_faddr,
            workingdir=self.tempdir,
            watchcpu=self.watchcpu)
        parsed_debugger_output = dbg.go()

        return parsed_debugger_output
Exemplo n.º 11
0
 def _construct_testcase(self):
     with LinuxTestcase(
             cfg=self.cfg,
             seedfile=self.seedfile,
             fuzzedfile=BasicFile(self.fuzzer.output_file_path),
             program=self.cfg['target']['program'],
             cmd_template=self.cmd_template,
             debugger_timeout=self.cfg['debugger']['runtimeout'],
             cmdlist=get_command_args_list(
                 self.cmd_template,
                 infile=self.fuzzer.output_file_path,
                 posix=True)[1],
             backtrace_lines=self.cfg['debugger']['backtracelevels'],
             crashers_dir=self.testcase_base_dir,
             workdir_base=self.working_dir,
             keep_faddr=self.cfg['runoptions'].get('keep_unique_faddr',
                                                   False),
             save_failed_asserts=self.cfg['analyzer'].get(
                 'savefailedasserts', False),
             exclude_unmapped_frames=self.cfg['analyzer']
         ['exclude_unmapped_frames']) as testcase:
         # put it on the list for the analysis pipeline
         self.testcases.append(testcase)
Exemplo n.º 12
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('-e',
                      '--edb',
                      dest='use_edb',
                      action='store_true',
                      help='Use edb instead of gdb')
    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.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 = []

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

    if options.debugger:
        debugger_app = options.debugger
    elif options.use_edb:
        debugger_app = 'edb'
    elif platform.system() == 'Darwin':
        debugger_app = 'lldb'
    else:
        debugger_app = 'gdb'
    args.append(debugger_app)

    if options.use_edb:
        args.append('--run')
    elif debugger_app == 'gdb':
        # Using gdb
        args.append('--args')
    args.extend(cmd_as_args)
    logger.info('args %s' % args)

    p = Popen(args, universal_newlines=True)
    p.wait()
Exemplo n.º 13
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('-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('WindowsConfig 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')

    config = load_and_fix_config(cfg_file)

    iterationpath = ''
    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(config['target']['cmdline_template'],
                                        fuzzed_file.path)[1]

    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 or config['debugger']['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, universal_newlines=True)
    p.wait()
Exemplo n.º 14
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()
Exemplo n.º 15
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()