Example #1
0
 def _setup_workdir(self):
     # make_directories silently skips existing dirs, so it's okay to call
     # it even if work_dir_base already exists
     filetools.make_directories(self.work_dir_base)
     # now we're sure work_dir_base exists, so it's safe to create temp dirs
     self.working_dir = tempfile.mkdtemp(prefix='campaign_',
                                         dir=self.work_dir_base)
     self.seed_dir_local = os.path.join(self.working_dir, 'seedfiles')
 def test_write_version(self):
     vf = os.path.join(self.campaign.outdir, 'version.txt')
     filetools.make_directories(self.campaign.outdir)
     self.assertTrue(os.path.isdir(self.campaign.outdir))
     self.assertFalse(os.path.exists(vf))
     self.campaign._write_version()
     self.assertTrue(os.path.exists(vf))
     self.assertTrue(os.path.getsize(vf) > 0)
Example #3
0
 def test_write_version(self):
     vf = os.path.join(self.campaign.outdir, 'version.txt')
     filetools.make_directories(self.campaign.outdir)
     self.assertTrue(os.path.isdir(self.campaign.outdir))
     self.assertFalse(os.path.exists(vf))
     self.campaign._write_version()
     self.assertTrue(os.path.exists(vf))
     self.assertTrue(os.path.getsize(vf) > 0)
 def _setup_workdir(self):
     # make_directories silently skips existing dirs, so it's okay to call
     # it even if work_dir_base already exists
     filetools.make_directories(self.work_dir_base)
     # now we're sure work_dir_base exists, so it's safe to create temp dirs
     self.working_dir = tempfile.mkdtemp(
         prefix='campaign_', dir=self.work_dir_base)
     self.seed_dir_local = os.path.join(self.working_dir, 'seedfiles')
Example #5
0
 def test_write_version(self):
     self.campaign.outdir = self.tmpdir
     vf = self.campaign._version_file
     filetools.make_directories(self.campaign.outdir)
     self.assertTrue(os.path.isdir(self.campaign.outdir))
     self.assertFalse(os.path.exists(vf))
     self.campaign._write_version()
     self.assertTrue(os.path.exists(vf))
     self.assertTrue(os.path.getsize(vf) > 0)
 def test_write_version(self):
     self.campaign.outdir = self.tmpdir
     vf = self.campaign._version_file
     filetools.make_directories(self.campaign.outdir)
     self.assertTrue(os.path.isdir(self.campaign.outdir))
     self.assertFalse(os.path.exists(vf))
     self.campaign._write_version()
     self.assertTrue(os.path.exists(vf))
     self.assertTrue(os.path.getsize(vf) > 0)
    def __init__(self, mydir, create=False):
        self.dir = mydir

        if create and not os.path.isdir(self.dir):
            if not os.path.exists(self.dir) and not os.path.islink(self.dir):
                filetools.make_directories(self.dir)
            else:
                raise DirectoryError('Cannot create dir %s - the path already exists, but is not a dir.' % self.dir)

        self._verify_dir()

        self.files = []
        self.refresh()
Example #8
0
def setup_logfile(logdir, log_basename='bff.log', level=logging.DEBUG,
                  max_bytes=1e8, backup_count=5):
    '''
    Creates a log file in <logdir>/<log_basename> at level <level>
    @param logdir: the directory where the log file should reside
    @param log_basename: the basename of the logfile (defaults to 'bff_log.txt')
    @param level: the logging level (defaults to logging.DEBUG)
    '''
    filetools.make_directories(logdir)
    logfile = os.path.join(logdir, log_basename)
    handler = RotatingFileHandler(logfile, maxBytes=max_bytes, backupCount=backup_count)
    formatter = logging.Formatter("%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s")
    add_log_handler(logger, level, handler, formatter)
    logger.info('Logging %s at %s', logging.getLevelName(level), logfile)
Example #9
0
    def __init__(self, mydir, create=False):
        self.dir = mydir

        if create and not os.path.isdir(self.dir):
            if not os.path.exists(self.dir) and not os.path.islink(self.dir):
                filetools.make_directories(self.dir)
            else:
                raise DirectoryError(
                    'Cannot create dir %s - the path already exists, but is not a dir.'
                    % self.dir)

        self._verify_dir()

        self.files = []
        self.refresh()
Example #10
0
File: bff.py Project: wflk/certfuzz
def setup_logfile(logdir,
                  log_basename='bff.log',
                  level=logging.DEBUG,
                  max_bytes=1e8,
                  backup_count=5):
    '''
    Creates a log file in <logdir>/<log_basename> at level <level>
    @param logdir: the directory where the log file should reside
    @param log_basename: the basename of the logfile (defaults to 'bff_log.txt')
    @param level: the logging level (defaults to logging.DEBUG)
    '''
    filetools.make_directories(logdir)
    logfile = os.path.join(logdir, log_basename)
    handler = RotatingFileHandler(logfile,
                                  maxBytes=max_bytes,
                                  backupCount=backup_count)
    formatter = logging.Formatter(
        "%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s")
    add_log_handler(logger, level, handler, formatter)
    logger.info('Logging %s at %s', logging.getLevelName(level), logfile)
Example #11
0
    def test_make_directories(self):
        d1 = tempfile.mkdtemp(dir=self.tempdir)
        d2 = tempfile.mkdtemp(dir=self.tempdir)

        # now that we have file names,
        # delete them so we can recreate them in our test
        for d in (d1, d2):
            os.removedirs(d)

        for d in (d1, d2):
            self.assertFalse(os.path.exists(d))

        make_directories(d1, d2)

        # they should be there now
        for d in (d1, d2):
            self.assertTrue(os.path.exists(d))
            self.assertTrue(os.path.isdir(d))

        # clean up
        for d in (d1, d2):
            os.removedirs(d)
            self.assertFalse(os.path.exists(d))
    def test_make_directories(self):
        d1 = tempfile.mkdtemp(dir=self.tempdir)
        d2 = tempfile.mkdtemp(dir=self.tempdir)

        # now that we have file names,
        # delete them so we can recreate them in our test
        for d in (d1, d2):
            os.removedirs(d)

        for d in (d1, d2):
            self.assertFalse(os.path.exists(d))

        make_directories(d1, d2)

        # they should be there now
        for d in (d1, d2):
            self.assertTrue(os.path.exists(d))
            self.assertTrue(os.path.isdir(d))

        # clean up
        for d in (d1, d2):
            os.removedirs(d)
            self.assertFalse(os.path.exists(d))
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()
Example #14
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()
Example #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('-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)')
    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/bff.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 testcase 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 = "../configs/bff.yaml"
    logger.debug('WindowsConfig 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)

    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.path)
    else:
        parser.error('fuzzedfile must be specified')

    cfg = load_and_fix_config(cfg_file)

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

    min2seed = not options.stringmode
    filename_modifier = ''
    retries = 0
    debugger_class = msec.MsecDebugger

    cmd_as_args = get_command_args_list(
        cfg['target']['cmdline_template'], fuzzed_file.path)[1]

    # Figure out an appropriate timeout to use based on the config
    winver = sys.getwindowsversion().major
    machine = platform.machine()
    hook_incompatible = winver > 5 or machine == 'AMD64'
    debugger_timeout = cfg['runner']['runtimeout']
    if not hook_incompatible:
        # Assume the user has tuned timeout to the hook.
        # Allow extra time for the debugger to run
        debugger_timeout *= 2
        if debugger_timeout < 10:
            debugger_timeout = 10
    cfg['debugger']['runtimeout'] = debugger_timeout

    with WindowsTestcase(cfg=cfg,
                         seedfile=seedfile,
                         fuzzedfile=fuzzed_file,
                         program=cfg['target']['program'],
                         cmd_template=cfg['target']['cmdline_template'],
                         debugger_timeout=cfg['debugger']['runtimeout'],
                         cmdlist=cmd_as_args,
                         dbg_opts=cfg['debugger'],
                         workdir_base=outdir,
                         keep_faddr=options.keep_uniq_faddr,
                         heisenbug_retries=retries
                         ) 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, 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_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)

            f = open(metasploit_file, 'wb')
            try:
                f.writelines(targetstring)
            finally:
                f.close()
        testcase.copy_files(outdir)
        testcase.clean_tmpdir()
Example #16
0
 def _setup_output(self):
     # construct run output directory
     filetools.make_directories(self.outdir)
     # copy config to run output dir
     filetools.copy_file(self.config_file, self.outdir)
     self._write_version()
Example #17
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)',
                      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).')

    (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("../conf.d/bff.cfg"):
            cfg_file = "../conf.d/bff.cfg"
        elif os.path.isfile("conf.d/bff.cfg"):
            cfg_file = "conf.d/bff.cfg"
        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"

    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)
    else:
        parser.error('fuzzedfile must be specified')

    cfg = read_config_options(cfg_file)

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

    min2seed = not options.stringmode
    filename_modifier = ''

    crashers_dir = '.'

    with BffCrash(cfg, seedfile, fuzzed_file, cfg.program,
                  cfg.debugger_timeout, cfg.killprocname, cfg.backtracelevels,
                  crashers_dir, options.keep_uniq_faddr) 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)

        with Minimizer(cfg=cfg,
                       crash=crash,
                       crash_dst_dir=outdir,
                       seedfile_as_target=min2seed,
                       bitwise=options.bitwise,
                       confidence=confidence,
                       logfile='./min_log.txt',
                       tempdir=crash.tempdir,
                       maxtime=options.timeout,
                       preferx=options.prefer_x_target,
                       keep_uniq_faddr=options.keep_uniq_faddr) as minimize:
            minimize.save_others = False
            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)

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

        crash.copy_files(outdir)
        crash.clean_tmpdir()
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()
 def _setup_output(self):
     # construct run output directory
     filetools.make_directories(self.outdir)
     # copy config to run output dir
     filetools.copy_file(self.config_file, self.outdir)
     self._write_version()