def main(argv): show_info() parser = argparse.ArgumentParser(description="afl-vcrash verifies that afl-fuzz crash samples lead to crashes in \ the target binary.", usage="afl-vcrash [-f LIST_FILENAME] [-h] [-j THREADS] [-q] [-r] [-t TIMEOUT] collection_dir -- target_command") parser.add_argument("collection_dir", help="Directory holding all crash samples that will be verified.") parser.add_argument("target_cmd", nargs="+", help="Target binary including command line \ options. Use '@@' to specify crash sample input file position (see afl-fuzz usage).") parser.add_argument("-f", "--filelist", dest="list_filename", default=None, help="Writes all crash sample file names that do not lead to crashes into a file.") parser.add_argument("-j", "--threads", dest="num_threads", default=1, help="Enable parallel verification by specifying the number of threads afl-vcrash \ will utilize.") parser.add_argument("-q", "--quiet", dest="quiet", action="store_const", const=True, default=False, help="Suppress output of crash sample file names that do not lead to crashes. This is \ particularly useful when combined with '-r' or '-f'.") parser.add_argument("-r", "--remove", dest="remove", action="store_const", const=True, default=False, help="Remove crash samples that do not lead to crashes.") parser.add_argument("-t", "--timeout", dest="timeout_secs", default=60, help="Define the timeout in seconds before killing the verification of a crash sample") args = parser.parse_args(argv[1:]) input_dir = os.path.abspath(os.path.expanduser(args.collection_dir)) if not os.path.exists(input_dir): print_err("No valid directory provided for <collection_dir>!") return num_crashes, crash_samples = afl_collect.get_samples_from_dir(input_dir, True) print_ok("Verifying %d crash samples..." % num_crashes) args.target_cmd = " ".join(args.target_cmd).split() args.target_cmd[0] = os.path.abspath(os.path.expanduser(args.target_cmd[0])) if not os.path.exists(args.target_cmd[0]): print_err("Target binary not found!") return args.target_cmd = " ".join(args.target_cmd) invalid_samples, timeout_samples = verify_samples(int(args.num_threads), crash_samples, args.target_cmd, int(args.timeout_secs)) print_warn("Found %d invalid crash samples." % len(invalid_samples)) print_warn("%d samples caused a timeout." % len(timeout_samples)) if args.remove: print_ok("Removing invalid crash samples.") remove_samples(invalid_samples, args.quiet) print_ok("Removing timeouts.") remove_samples(timeout_samples, args.quiet) elif not args.quiet: for ci in invalid_samples: print(ci) # generate filelist of collected crash samples if args.list_filename: afl_collect.generate_sample_list(args.list_filename, invalid_samples + timeout_samples) print_ok("Generated invalid crash sample list '%s'." % args.list_filename)
def main(argv): show_info() parser = argparse.ArgumentParser(description="afl-vcrash verifies that afl-fuzz crash samples lead to crashes in \ the target binary.", usage="afl-vcrash [-f LIST_FILENAME] [-h] [-j THREADS] [-q] [-r] [-t TIMEOUT] collection_dir -- target_command") parser.add_argument("collection_dir", help="Directory holding all crash samples that will be verified.") parser.add_argument("target_cmd", nargs="+", help="Target binary including command line \ options. Use '@@' to specify crash sample input file position (see afl-fuzz usage).") parser.add_argument("-f", "--filelist", dest="list_filename", default=None, help="Writes all crash sample file names that do not lead to crashes into a file.") parser.add_argument("-j", "--threads", dest="num_threads", default=1, help="Enable parallel verification by specifying the number of threads afl-vcrash \ will utilize.") parser.add_argument("-q", "--quiet", dest="quiet", action="store_const", const=True, default=False, help="Suppress output of crash sample file names that do not lead to crashes. This is \ particularly useful when combined with '-r' or '-f'.") parser.add_argument("-r", "--remove", dest="remove", action="store_const", const=True, default=False, help="Remove crash samples that do not lead to crashes.") parser.add_argument("-t", "--timeout", dest="timeout_secs", default=60, help="Define the timeout in seconds before killing the verification of a crash sample") args = parser.parse_args(argv[1:]) input_dir = os.path.abspath(os.path.expanduser(args.collection_dir)) if not os.path.exists(input_dir): print_err("No valid directory provided for <collection_dir>!") sys.exit(1) num_crashes, crash_samples = afl_collect.get_samples_from_dir(input_dir, True) print_ok("Verifying %d crash samples..." % num_crashes) args.target_cmd = build_target_cmd(args.target_cmd) os.environ["ASAN_OPTIONS"] = "abort_on_error=1:detect_leaks=0:symbolize=1:allocator_may_return_null=1" os.environ["ASAN_SYMBOLIZER_PATH"] = "/usr/lib/llvm-3.8/bin/llvm-symbolizer" invalid_samples, timeout_samples = verify_samples(int(args.num_threads), crash_samples, args.target_cmd, int(args.timeout_secs)) print_warn("Found %d invalid crash samples." % len(invalid_samples)) print_warn("%d samples caused a timeout." % len(timeout_samples)) if args.remove: print_ok("Removing invalid crash samples.") remove_samples(invalid_samples, args.quiet) print_ok("Removing timeouts.") remove_samples(timeout_samples, args.quiet) elif not args.quiet: for ci in invalid_samples: print(ci) # generate filelist of collected crash samples if args.list_filename: afl_collect.generate_sample_list(args.list_filename, invalid_samples + timeout_samples) print_ok("Generated invalid crash sample list '%s'." % args.list_filename)
def test_generate_sample_list(self): list_name = 'testdata/read_only' files_collected = ['dummy0', 'dummy1', 'dummy2'] self.assertFalse(os.path.exists('testdata/read_only')) self.assertIsNone( afl_collect.generate_sample_list(list_name, files_collected)) self.assertTrue(os.path.exists('testdata/read_only')) self.assertIsNone( afl_collect.generate_sample_list('/invalid', files_collected))
def main(argv): show_info() parser = argparse.ArgumentParser(description="afl-vcrash verifies that afl-fuzz crash samples lead to crashes in \ the target binary.", usage="afl-vcrash [-f LIST_FILENAME] [-h] [-j THREADS] [-q] [-r] collection_dir -- target_command") parser.add_argument("collection_dir", help="Directory holding all crash samples that will be verified.") parser.add_argument("target_cmd", nargs="+", help="Target binary including command line \ options. Use '@@' to specify crash sample input file position (see afl-fuzz usage).") parser.add_argument("-f", "--filelist", dest="list_filename", default=None, help="Writes all crash sample file names that do not lead to crashes into a file.") parser.add_argument("-j", "--threads", dest="num_threads", default=1, help="Enable parallel verification by specifying the number of threads afl-vcrash \ will utilize.") parser.add_argument("-q", "--quiet", dest="quiet", action="store_const", const=True, default=False, help="Suppress output of crash sample file names that do not lead to crashes. This is \ particularly useful when combined with '-r' or '-f'.") parser.add_argument("-r", "--remove", dest="remove", action="store_const", const=True, default=False, help="Remove crash samples that do not lead to crashes.") args = parser.parse_args(argv[1:]) if args.collection_dir: input_dir = args.collection_dir else: print("No valid directory provided for <collection_dir>!") return num_crashes, crash_samples = afl_collect.get_samples_from_dir(input_dir, True) print("Verifying %d crash samples..." % num_crashes) args.target_cmd = " ".join(args.target_cmd).split() args.target_cmd[0] = os.path.abspath(os.path.expanduser(args.target_cmd[0])) if not os.path.exists(args.target_cmd[0]): print("Target binary not found!") return args.target_cmd = " ".join(args.target_cmd) invalid_samples = verify_samples(int(args.num_threads), crash_samples, args.target_cmd) print("Found %d invalid crash samples." % len(invalid_samples)) if args.remove: print("Removing invalid crash samples.") remove_samples(invalid_samples, args.quiet) elif not args.quiet: for ci in invalid_samples: print(ci) # generate filelist of collected crash samples if args.list_filename: afl_collect.generate_sample_list(args.list_filename, invalid_samples) print("Generated invalid crash sample list '%s'." % args.list_filename)
def test_generate_sample_list(self): list_name = 'testdata/read_only' files_collected = [ 'dummy0', 'dummy1', 'dummy2' ] self.assertFalse(os.path.exists('testdata/read_only')) self.assertIsNone(afl_collect.generate_sample_list(list_name, files_collected)) self.assertTrue(os.path.exists('testdata/read_only')) self.assertIsNone(afl_collect.generate_sample_list('/invalid', files_collected))