def setUp(self):
        self.cfg = MockCfg()
        self.crash = MockCrasher()
        self.tempdir = tempfile.mkdtemp(prefix='minimizer_test_')
        self.crash_dst_dir = tempfile.mkdtemp(prefix='crash_', dir=self.tempdir)
        (fd, self.logfile) = tempfile.mkstemp(dir=self.tempdir)
        os.close(fd)
        os.remove(self.logfile)
        self.assertFalse(os.path.exists(self.logfile))
        certfuzz.minimizer.minimizer_base.debuggers = MockDebugger()

        self.m = Minimizer(cfg=self.cfg, crash=self.crash,
                           crash_dst_dir=self.crash_dst_dir,
                           logfile=self.logfile, tempdir=self.tempdir)
Exemplo n.º 2
0
Arquivo: bff.py Projeto: wflk/certfuzz
def analyze_crasher(cfg, crash):
    '''
    Runs multiple analyses and collects data about a crash. Returns a list of other crashes
    encountered during the process of analyzing the current crash.
    @param cfg: A BFF config object
    @param crash: A crash object
    @return: a list of Crasher objects
    '''
    other_crashers_found = []

    dbg_out_file_orig = crash.dbg.file
    logger.debug('Original debugger file: %s', dbg_out_file_orig)

    if cfg.minimizecrashers:
        # try to reduce the Hamming Distance between the crasher file and the known good seedfile
        # crash.fuzzedfile will be replaced with the minimized result
        try:
            with Minimizer(cfg=cfg,
                           crash=crash,
                           bitwise=False,
                           seedfile_as_target=True,
                           confidence=0.999,
                           tempdir=cfg.local_dir,
                           maxtime=cfg.minimizertimeout) as minimizer:
                minimizer.go()
                other_crashers_found.extend(minimizer.other_crashes.values())
        except MinimizerError, e:
            logger.warning(
                'Unable to minimize %s, proceeding with original fuzzed crash file: %s',
                crash.signature, e)
            minimizer = None
Exemplo n.º 3
0
    def setUp(self):
        self.cfg = MockCfg()
        self.crash = MockCrasher()
        self.tempdir = tempfile.mkdtemp(prefix='minimizer_test_')
        self.crash_dst_dir = tempfile.mkdtemp(prefix='crash_', dir=self.tempdir)
        (fd, self.logfile) = tempfile.mkstemp(dir=self.tempdir)
        os.close(fd)
        os.remove(self.logfile)
        self.assertFalse(os.path.exists(self.logfile))
        certfuzz.minimizer.minimizer_base.debuggers = MockDebugger()

        self.m = Minimizer(cfg=self.cfg, crash=self.crash,
                           crash_dst_dir=self.crash_dst_dir,
                           logfile=self.logfile, tempdir=self.tempdir)
Exemplo n.º 4
0
class Test(unittest.TestCase):
    def delete_file(self, f):
        os.remove(f)
        self.assertFalse(os.path.exists(f))

    def setUp(self):
        self.cfg = MockCfg()
        self.crash = MockCrasher()
        self.tempdir = tempfile.mkdtemp(prefix='minimizer_test_')
        self.crash_dst_dir = tempfile.mkdtemp(prefix='crash_',
                                              dir=self.tempdir)
        (fd, self.logfile) = tempfile.mkstemp(dir=self.tempdir)
        os.close(fd)
        os.remove(self.logfile)
        self.assertFalse(os.path.exists(self.logfile))
        certfuzz.minimizer.minimizer_base.debuggers = MockDebugger()

        self.m = Minimizer(cfg=self.cfg,
                           crash=self.crash,
                           crash_dst_dir=self.crash_dst_dir,
                           logfile=self.logfile,
                           tempdir=self.tempdir)

    def tearDown(self):
        shutil.rmtree(self.tempdir)

    def test_go(self):
        pass

    def test_have_we_seen_this_file_before(self):
        self.m.newfuzzed_md5 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

        self.assertFalse(self.m.have_we_seen_this_file_before())
        self.assertTrue(self.m.have_we_seen_this_file_before())

    def test_is_same_crash(self):
        pass

    def test_print_intermediate_log(self):
        pass

    def test_set_discard_chance(self):
        self.m.seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        self.m.fuzzed = "abcdefghijklmnopqrstuvwxyz"
        self.m.min_distance = hamming.bytewise_hd(self.m.seed, self.m.fuzzed)
        self.assertEqual(self.m.min_distance, 26)

        for tsg in xrange(1, 20):
            self.m.target_size_guess = tsg
            self.m.set_discard_chance()
            self.assertAlmostEqual(self.m.discard_chance, 1.0 / (1.0 + tsg))

    def test_set_n_misses(self):
        pass

    def test_swap_bytes(self):
        seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        fuzzed = "abcdefghijklmnopqrstuvwxyz"

        for dc in (0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9):
            self.m.discard_chance = dc
            self.m.seed = seed
            self.m.fuzzed = fuzzed
            self.m.min_distance = 26
            self.m.swap_func = self.m.bytewise_swap2
            self.m.swap_bytes()
            self.assertTrue(0 < self.m.newfuzzed_hd)
            self.assertTrue(self.m.newfuzzed_hd <= 26)
            self.assertNotEqual(self.m.newfuzzed, fuzzed)
            self.assertNotEqual(self.m.newfuzzed, seed)

    def test_update_probabilities(self):
        pass
Exemplo n.º 5
0
class Test(unittest.TestCase):
    def delete_file(self, f):
        os.remove(f)
        self.assertFalse(os.path.exists(f))

    def setUp(self):
        self.cfg = MockCfg()
        self.crash = MockCrasher()
        self.tempdir = tempfile.mkdtemp(prefix='minimizer_test_')
        self.crash_dst_dir = tempfile.mkdtemp(prefix='crash_', dir=self.tempdir)
        (fd, self.logfile) = tempfile.mkstemp(dir=self.tempdir)
        os.close(fd)
        os.remove(self.logfile)
        self.assertFalse(os.path.exists(self.logfile))
        certfuzz.minimizer.minimizer_base.debuggers = MockDebugger()

        self.m = Minimizer(cfg=self.cfg, crash=self.crash,
                           crash_dst_dir=self.crash_dst_dir,
                           logfile=self.logfile, tempdir=self.tempdir)

    def tearDown(self):
        shutil.rmtree(self.tempdir)

    def test_go(self):
        pass

    def test_have_we_seen_this_file_before(self):
        self.m.newfuzzed_md5 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

        self.assertFalse(self.m.have_we_seen_this_file_before())
        self.assertTrue(self.m.have_we_seen_this_file_before())

    def test_is_same_crash(self):
        pass

    def test_print_intermediate_log(self):
        pass

    def test_set_discard_chance(self):
        self.m.seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        self.m.fuzzed = "abcdefghijklmnopqrstuvwxyz"
        self.m.min_distance = hamming.bytewise_hd(self.m.seed, self.m.fuzzed)
        self.assertEqual(self.m.min_distance, 26)

        for tsg in xrange(1, 20):
            self.m.target_size_guess = tsg
            self.m.set_discard_chance()
            self.assertAlmostEqual(self.m.discard_chance, 1.0 / (1.0 + tsg))

    def test_set_n_misses(self):
        pass

    def test_swap_bytes(self):
        seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        fuzzed = "abcdefghijklmnopqrstuvwxyz"

        for dc in (0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9):
            self.m.discard_chance = dc
            self.m.seed = seed
            self.m.fuzzed = fuzzed
            self.m.min_distance = 26
            self.m.swap_func = self.m.bytewise_swap2
            self.m.swap_bytes()
            self.assertTrue(0 < self.m.newfuzzed_hd)
            self.assertTrue(self.m.newfuzzed_hd <= 26)
            self.assertNotEqual(self.m.newfuzzed, fuzzed)
            self.assertNotEqual(self.m.newfuzzed, seed)

    def test_update_probabilities(self):
        pass
Exemplo 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()
Exemplo n.º 7
0
Arquivo: bff.py Projeto: wflk/certfuzz
                crash.signature, e)
            minimizer = None

    touch_watchdog_file(cfg)
    # calculate the hamming distances for this crash
    # between the original seedfile and the minimized fuzzed file
    crash.calculate_hamming_distances()

    if cfg.minimize_to_string:
        # Minimize to a string of 'x's
        # crash.fuzzedfile will be replaced with the minimized result
        try:
            with Minimizer(cfg=cfg,
                           crash=crash,
                           bitwise=False,
                           seedfile_as_target=False,
                           confidence=0.9,
                           tempdir=cfg.local_dir,
                           maxtime=cfg.minimizertimeout) as min2string:
                min2string.go()
                other_crashers_found.extend(min2string.other_crashes.values())
        except MinimizerError, e:
            logger.warning(
                'Unable to minimize %s, proceeding with original fuzzed crash file: %s',
                crash.signature, e)
            min2string = None
    touch_watchdog_file(cfg)

    # get one last debugger output for the newly minimized file
    if crash.pc_in_function:
        # change the debugger template