From dc8088e9be8f9593b5dfb641e6c2f1ea5ead9d7f Mon Sep 17 00:00:00 2001 From: Thomas HUET Date: Thu, 21 May 2015 05:42:18 +0200 Subject: [PATCH] 1.79b --- Makefile | 2 +- afl-fuzz.c | 31 +++++++++++-- docs/ChangeLog | 10 +++++ docs/README | 3 +- docs/sister_projects.txt | 13 ++++++ testcases/README.testcases | 10 +++++ testcases/_extras/sql.dict | 68 ++++++++++++++++++++++++++++ testcases/_extras/sql_pragmas.dict | 71 ------------------------------ 8 files changed, 131 insertions(+), 77 deletions(-) delete mode 100644 testcases/_extras/sql_pragmas.dict diff --git a/Makefile b/Makefile index a9ed46c7..82a8115f 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ # PROGNAME = afl -VERSION = 1.78b +VERSION = 1.79b PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin diff --git a/afl-fuzz.c b/afl-fuzz.c index 00641889..57ecef2f 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -1355,7 +1355,8 @@ static int compare_extras_use_d(const void* p1, const void* p2) { /* Read extras from a file, sort by size. */ -static void load_extras_file(u8* fname, u32* min_len, u32* max_len) { +static void load_extras_file(u8* fname, u32* min_len, u32* max_len, + u32 dict_level) { FILE* f; u8 buf[MAX_LINE]; @@ -1399,6 +1400,16 @@ static void load_extras_file(u8* fname, u32* min_len, u32* max_len) { while (isalnum(*lptr) || *lptr == '_') lptr++; + /* If @number follows, parse that. */ + + if (*lptr == '@') { + + lptr++; + if (atoi(lptr) > dict_level) continue; + while (isdigit(*lptr)) lptr++; + + } + /* Skip whitespace and = signs. */ while (isspace(*lptr) || *lptr == '=') lptr++; @@ -1485,16 +1496,26 @@ static void load_extras(u8* dir) { DIR* d; struct dirent* de; - u32 min_len = MAX_DICT_FILE, max_len = 0; + u32 min_len = MAX_DICT_FILE, max_len = 0, dict_level = 0; + u8* x; + + /* If the name ends with @, extract level and continue. */ - ACTF("Loading extra dictionary from '%s'...", dir); + if ((x = strchr(dir, '@'))) { + + *x = 0; + dict_level = atoi(x + 1); + + } + + ACTF("Loading extra dictionary from '%s' (level %u)...", dir, dict_level); d = opendir(dir); if (!d) { if (errno == ENOTDIR) { - load_extras_file(dir, &min_len, &max_len); + load_extras_file(dir, &min_len, &max_len, dict_level); goto check_and_sort; } @@ -1502,6 +1523,8 @@ static void load_extras(u8* dir) { } + if (x) FATAL("Dictinary levels not supported for directories."); + while ((de = readdir(d))) { struct stat st; diff --git a/docs/ChangeLog b/docs/ChangeLog index 94d5ea4c..e061d5bb 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -16,6 +16,16 @@ Not sure if you should upgrade? The lowest currently recommended version is 1.76b. If you're stuck on an earlier release, it's strongly advisable to get on with the times. +-------------- +Version 1.79b: +-------------- + + - Added support for dictionary levels, see testcases/README.testcases. + + - Reworked the SQL dictionary to use levels. + + - Added a note about Preeny. + -------------- Version 1.78b: -------------- diff --git a/docs/README b/docs/README index e66315f8..3d3094fe 100644 --- a/docs/README +++ b/docs/README @@ -385,7 +385,8 @@ Here are some of the most important caveats for AFL: - There is no direct support for fuzzing network services, background daemons, or interactive apps that require UI interaction to work. You may need to make simple code changes to make them behave in a more traditional - way. + way. Preeny may offer a relatively simple option, too - see: + https://github.com/zardus/preeny - AFL doesn't output human-readable coverage data. If you want to monitor coverage, use afl-cov from Michael Rash: https://github.com/mrash/afl-cov diff --git a/docs/sister_projects.txt b/docs/sister_projects.txt index 714f9b68..dcf5e3b7 100644 --- a/docs/sister_projects.txt +++ b/docs/sister_projects.txt @@ -52,6 +52,19 @@ AFL-style in-process fuzzer for LLVM (Kostya Serebryany) http://llvm.org/docs/LibFuzzer.html +---------------- +Network fuzzing: +---------------- + +Preeny (Yan Shoshitaishvili) +---------------------------- + + Provides a fairly simple way to convince dynamically linked network-centric + programs to read from a file or not fork. Not AFL-specific, but described as + useful by many users. Some assembly required. + + https://github.com/zardus/preeny + ---------------------------------------- Crash triage and other helper utilities: ---------------------------------------- diff --git a/testcases/README.testcases b/testcases/README.testcases index 7f3e7aa3..d19cb6e1 100644 --- a/testcases/README.testcases +++ b/testcases/README.testcases @@ -57,5 +57,15 @@ Custom dictionaries can be created in two ways: The fuzzer auto-selects the appropriate mode depending on whether the -x parameter is a file or a directory. +In the file mode, every name field can be optionally followed by @, e.g.: + + keyword_foo@1 = "foo" + +Such entries will be loaded only if the requested dictionary level is equal or +higher than this number. The default level is zero; a higher value can be set +by appending @ to the dictionary file name, like so: + + -x path/to/dictionary.dct@2 + Good examples of dictionaries can be found in _extras/xml.dict and _extras/png.dict. diff --git a/testcases/_extras/sql.dict b/testcases/_extras/sql.dict index 5ab248d8..58342473 100644 --- a/testcases/_extras/sql.dict +++ b/testcases/_extras/sql.dict @@ -5,6 +5,12 @@ # Modeled based on SQLite documentation, contains some number of SQLite # extensions. Other dialects of SQL may benefit from customized dictionaries. # +# If you append @1 to the file name when loading this dictionary, afl-fuzz +# will also additionally load a selection of pragma keywords that are very +# specific to SQLite (and are probably less interesting from the security +# standpoint, because they are usually not allowed in non-privileged +# contexts). +# # Created by Michal Zalewski # @@ -212,3 +218,65 @@ snippet_string_pair=" \"a\",\"b\"" string_dbl_q=" \"a\"" string_escaped_q=" 'a''b'" string_single_q=" 'a'" + +pragma_application_id@1=" application_id" +pragma_auto_vacuum@1=" auto_vacuum" +pragma_automatic_index@1=" automatic_index" +pragma_busy_timeout@1=" busy_timeout" +pragma_cache_size@1=" cache_size" +pragma_cache_spill@1=" cache_spill" +pragma_case_sensitive_like@1=" case_sensitive_like" +pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync" +pragma_collation_list@1=" collation_list" +pragma_compile_options@1=" compile_options" +pragma_count_changes@1=" count_changes" +pragma_data_store_directory@1=" data_store_directory" +pragma_database_list@1=" database_list" +pragma_default_cache_size@1=" default_cache_size" +pragma_defer_foreign_keys@1=" defer_foreign_keys" +pragma_empty_result_callbacks@1=" empty_result_callbacks" +pragma_encoding@1=" encoding" +pragma_foreign_key_check@1=" foreign_key_check" +pragma_foreign_key_list@1=" foreign_key_list" +pragma_foreign_keys@1=" foreign_keys" +pragma_freelist_count@1=" freelist_count" +pragma_full_column_names@1=" full_column_names" +pragma_fullfsync@1=" fullfsync" +pragma_ignore_check_constraints@1=" ignore_check_constraints" +pragma_incremental_vacuum@1=" incremental_vacuum" +pragma_index_info@1=" index_info" +pragma_index_list@1=" index_list" +pragma_integrity_check@1=" integrity_check" +pragma_journal_mode@1=" journal_mode" +pragma_journal_size_limit@1=" journal_size_limit" +pragma_legacy_file_format@1=" legacy_file_format" +pragma_locking_mode@1=" locking_mode" +pragma_max_page_count@1=" max_page_count" +pragma_mmap_size@1=" mmap_size" +pragma_page_count@1=" page_count" +pragma_page_size@1=" page_size" +pragma_parser_trace@1=" parser_trace" +pragma_query_only@1=" query_only" +pragma_quick_check@1=" quick_check" +pragma_read_uncommitted@1=" read_uncommitted" +pragma_recursive_triggers@1=" recursive_triggers" +pragma_reverse_unordered_selects@1=" reverse_unordered_selects" +pragma_schema_version@1=" schema_version" +pragma_secure_delete@1=" secure_delete" +pragma_short_column_names@1=" short_column_names" +pragma_shrink_memory@1=" shrink_memory" +pragma_soft_heap_limit@1=" soft_heap_limit" +pragma_stats@1=" stats" +pragma_synchronous@1=" synchronous" +pragma_table_info@1=" table_info" +pragma_temp_store@1=" temp_store" +pragma_temp_store_directory@1=" temp_store_directory" +pragma_threads@1=" threads" +pragma_user_version@1=" user_version" +pragma_vdbe_addoptrace@1=" vdbe_addoptrace" +pragma_vdbe_debug@1=" vdbe_debug" +pragma_vdbe_listing@1=" vdbe_listing" +pragma_vdbe_trace@1=" vdbe_trace" +pragma_wal_autocheckpoint@1=" wal_autocheckpoint" +pragma_wal_checkpoint@1=" wal_checkpoint" +pragma_writable_schema@1=" writable_schema" diff --git a/testcases/_extras/sql_pragmas.dict b/testcases/_extras/sql_pragmas.dict deleted file mode 100644 index acf413af..00000000 --- a/testcases/_extras/sql_pragmas.dict +++ /dev/null @@ -1,71 +0,0 @@ -# -# AFL dictionary add-on for SQLite pragmas -# ---------------------------------------- -# -# Concatenate with sql.dict before use. This provides additional keywords -# for highly SQLite-specific pragma directives. -# -# Created by Michal Zalewski -# - -pragma_application_id=" application_id" -pragma_auto_vacuum=" auto_vacuum" -pragma_automatic_index=" automatic_index" -pragma_busy_timeout=" busy_timeout" -pragma_cache_size=" cache_size" -pragma_cache_spill=" cache_spill" -pragma_case_sensitive_like=" case_sensitive_like" -pragma_checkpoint_fullfsync=" checkpoint_fullfsync" -pragma_collation_list=" collation_list" -pragma_compile_options=" compile_options" -pragma_count_changes=" count_changes" -pragma_data_store_directory=" data_store_directory" -pragma_database_list=" database_list" -pragma_default_cache_size=" default_cache_size" -pragma_defer_foreign_keys=" defer_foreign_keys" -pragma_empty_result_callbacks=" empty_result_callbacks" -pragma_encoding=" encoding" -pragma_foreign_key_check=" foreign_key_check" -pragma_foreign_key_list=" foreign_key_list" -pragma_foreign_keys=" foreign_keys" -pragma_freelist_count=" freelist_count" -pragma_full_column_names=" full_column_names" -pragma_fullfsync=" fullfsync" -pragma_ignore_check_constraints=" ignore_check_constraints" -pragma_incremental_vacuum=" incremental_vacuum" -pragma_index_info=" index_info" -pragma_index_list=" index_list" -pragma_integrity_check=" integrity_check" -pragma_journal_mode=" journal_mode" -pragma_journal_size_limit=" journal_size_limit" -pragma_legacy_file_format=" legacy_file_format" -pragma_locking_mode=" locking_mode" -pragma_max_page_count=" max_page_count" -pragma_mmap_size=" mmap_size" -pragma_page_count=" page_count" -pragma_page_size=" page_size" -pragma_parser_trace=" parser_trace" -pragma_query_only=" query_only" -pragma_quick_check=" quick_check" -pragma_read_uncommitted=" read_uncommitted" -pragma_recursive_triggers=" recursive_triggers" -pragma_reverse_unordered_selects=" reverse_unordered_selects" -pragma_schema_version=" schema_version" -pragma_secure_delete=" secure_delete" -pragma_short_column_names=" short_column_names" -pragma_shrink_memory=" shrink_memory" -pragma_soft_heap_limit=" soft_heap_limit" -pragma_stats=" stats" -pragma_synchronous=" synchronous" -pragma_table_info=" table_info" -pragma_temp_store=" temp_store" -pragma_temp_store_directory=" temp_store_directory" -pragma_threads=" threads" -pragma_user_version=" user_version" -pragma_vdbe_addoptrace=" vdbe_addoptrace" -pragma_vdbe_debug=" vdbe_debug" -pragma_vdbe_listing=" vdbe_listing" -pragma_vdbe_trace=" vdbe_trace" -pragma_wal_autocheckpoint=" wal_autocheckpoint" -pragma_wal_checkpoint=" wal_checkpoint" -pragma_writable_schema=" writable_schema"