aboutsummaryrefslogtreecommitdiff
path: root/utils/argv_fuzzing
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2023-01-05 13:51:20 +0100
committerGitHub <noreply@github.com>2023-01-05 13:51:20 +0100
commit3b6fcd911a860a8c823c912c4b08b423734e4cfe (patch)
treecc2599499e847c4ac661988d1c5fe7b35a5ef82e /utils/argv_fuzzing
parent60dc37a8cf09f8e9048e4b6a2204d6c90b27655a (diff)
parenta3b56e7280cb5b5cea21c66c40d4390db6f13b8f (diff)
downloadafl++-3b6fcd911a860a8c823c912c4b08b423734e4cfe.tar.gz
Merge pull request #1610 from AFLplusplus/dev4.05c
push to stable
Diffstat (limited to 'utils/argv_fuzzing')
-rw-r--r--utils/argv_fuzzing/Makefile17
-rw-r--r--utils/argv_fuzzing/README.md41
-rw-r--r--utils/argv_fuzzing/argv-fuzz-inl.h47
-rw-r--r--utils/argv_fuzzing/argv_fuzz_demo.c28
-rw-r--r--utils/argv_fuzzing/argv_fuzz_persistent_demo.c59
-rw-r--r--utils/argv_fuzzing/argvfuzz.c2
6 files changed, 183 insertions, 11 deletions
diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile
index 183f6bf8..9d1fc969 100644
--- a/utils/argv_fuzzing/Makefile
+++ b/utils/argv_fuzzing/Makefile
@@ -2,7 +2,7 @@
# american fuzzy lop++ - argvfuzz
# --------------------------------
#
-# Copyright 2019-2022 Kjell Braden <afflux@pentabarf.de>
+# Copyright 2019-2023 Kjell Braden <afflux@pentabarf.de>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
-.PHONY: all install clean
+.PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo demo
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
@@ -41,7 +41,7 @@ __M32FLAG=$(_M32FLAG:00=-mbe32)
___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32)
M32FLAG=$(___M32FLAG)
-all: argvfuzz32.so argvfuzz64.so
+all: argvfuzz32.so argvfuzz64.so demo
argvfuzz32.so: argvfuzz.c
-@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)"
@@ -54,5 +54,14 @@ install: argvfuzz32.so argvfuzz64.so
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
+argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c
+ ../../afl-cc -fsanitize=address -g -o $@ $^
+
+argv_fuzz_demo: argv_fuzz_demo.c
+ ../../afl-cc -fsanitize=address -g -o $@ $^
+
+demo: argv_fuzz_persistent_demo argv_fuzz_demo
+
clean:
- rm -f argvfuzz32.so argvfuzz64.so
+ rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo
+
diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md
index e9224995..a085c098 100644
--- a/utils/argv_fuzzing/README.md
+++ b/utils/argv_fuzzing/README.md
@@ -1,16 +1,45 @@
-# argvfuzz
+# argv_fuzzing feature
+AFL++ supports fuzzing file inputs or standard input. The argv_fuzzing feature
+allows for the fuzzing of arguments passed to a program from the command line
+interface rather than from STDIN.
-AFL++ supports fuzzing file inputs or stdin. When source is available,
-`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin.
+## With source code
+When the source code is available, a specific macro from the `argv-fuzz-inl.h`
+header file can be used to change the program's behavior to build argv from STDIN.
+### Without persistent mode
+Conditions needed to use the argv_fuzzing feature:
+1. Include `argv-fuzz-inl.h` header file (`#include "argv-fuzz-inl.h"`)
+2. Identify your main function that parses arguments
+(for example, `int main(int argc, char **argv)`)
+3. Use one of the following macros (near the beginning of the main function)
+to initialize argv with the fuzzer's input:
+ - `AFL_INIT_ARGV();` or
+ - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]`
+ (the name of the program being executed)
+
+see: [argv_fuzz_demo.c](argv_fuzz_demo.c)
+
+### With persistent mode
+Conditions needed to use the argv_fuzzing feature with persistent mode:
+1. Ensure your target can handle persistent mode fuzzing
+2. Follow instructions in the [llvm_mode persistent mode](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md)
+3. Use one of the following macros near the beginning of the main function and after
+the buffer initialization (`unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF`):
+ - `AFL_INIT_ARGV_PERSISTENT(buf)`, if you want to
+ - `AFL_INIT_SET0_PERSISTENT("name_of_binary", buf)`
+
+see: [argv_fuzz_persistent_demo.c](argv_fuzz_persistent_demo.c)
+
+## Binary only
`argvfuzz` tries to provide the same functionality for binaries. When loaded
using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace
argv using the same logic of `argv-fuzz-inl.h`.
A few conditions need to be fulfilled for this mechanism to work correctly:
-1. As it relies on hooking the loader, it cannot work on static binaries.
+1. As it relies on hooking the loader, it cannot work on static binaries
2. If the target binary does not use the default libc's `_start` implementation
(crt1.o), the hook may not run.
-3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the
- target binary expects argv to be living on the stack, things may go wrong. \ No newline at end of file
+3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`.
+Things may go wrong if the target binary expects argv to live on the stack.
diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h
index ec22c53b..cb0af2bc 100644
--- a/utils/argv_fuzzing/argv-fuzz-inl.h
+++ b/utils/argv_fuzzing/argv-fuzz-inl.h
@@ -29,6 +29,11 @@
If you would like to always preserve argv[0], use this instead:
AFL_INIT_SET0("prog_name");
+ To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with
+ buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf)
+ to preserver argv[0]. buf is a pointer to a buffer containing
+ the input data for the current test case being processed defined as:
+ unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
*/
#ifndef _HAVE_ARGV_FUZZ_INL
@@ -53,6 +58,22 @@
\
} while (0)
+#define AFL_INIT_ARGV_PERSISTENT(persistent_buff) \
+ do { \
+ \
+ argv = afl_init_argv_persistent(&argc, persistent_buff); \
+ \
+ } while (0)
+
+#define AFL_INIT_SET0_PERSISTENT(_p, persistent_buff) \
+ do { \
+ \
+ argv = afl_init_argv_persistent(&argc, persistent_buff); \
+ argv[0] = (_p); \
+ if (!argc) argc = 1; \
+ \
+ } while (0)
+
#define MAX_CMDLINE_LEN 100000
#define MAX_CMDLINE_PAR 50000
@@ -87,6 +108,32 @@ static char **afl_init_argv(int *argc) {
}
+static char **afl_init_argv_persistent(int *argc,
+ unsigned char *persistent_buff) {
+
+ static char *ret[MAX_CMDLINE_PAR];
+
+ unsigned char *ptr = persistent_buff;
+ int rc = 0;
+
+ while (*ptr && rc < MAX_CMDLINE_PAR) {
+
+ ret[rc] = (char *)ptr;
+ if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
+ rc++;
+
+ while (*ptr)
+ ptr++;
+ ptr++;
+
+ }
+
+ *argc = rc;
+
+ return ret;
+
+}
+
#undef MAX_CMDLINE_LEN
#undef MAX_CMDLINE_PAR
diff --git a/utils/argv_fuzzing/argv_fuzz_demo.c b/utils/argv_fuzzing/argv_fuzz_demo.c
new file mode 100644
index 00000000..6ab1e2e5
--- /dev/null
+++ b/utils/argv_fuzzing/argv_fuzz_demo.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <string.h>
+#include "argv-fuzz-inl.h"
+
+int main(int argc, char **argv) {
+
+ // Initialize the argv array for use with the AFL (American Fuzzy Lop) tool
+ AFL_INIT_ARGV();
+
+ /* Check the number of command line arguments and
+ compare the values of the first two arguments to specific strings.
+ If the number of arguments is not correct or the values do not match,
+ an error message is printed. If the values do match, the program
+ calls the abort() function. */
+ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) {
+
+ if (strcmp(argv[2], "TEST2") == 0) { abort(); }
+
+ } else {
+
+ printf("Bad number of arguments!\n");
+
+ }
+
+ return 0;
+
+}
+
diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c
new file mode 100644
index 00000000..016c3d35
--- /dev/null
+++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c
@@ -0,0 +1,59 @@
+/*
+This file contains a simple fuzzer for testing command line argument parsing
+using persistent mode.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "argv-fuzz-inl.h"
+
+__AFL_FUZZ_INIT();
+
+/* The main function is an entry point for a program.
+ The argc parameter is an integer that indicates the number of arguments
+ passed to the program. The argv parameter is an array of character pointers,
+ with each element pointing to a null-terminated string that represents
+ one of the arguments.
+ */
+int main(int argc, char **argv) {
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+ __AFL_INIT();
+#endif
+ unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
+
+ /* __AFL_LOOP() limits the maximum number of iterations before exiting
+ the loop and allowing the program to terminate. It protects against
+ accidental memory leaks and similar issues. */
+ while (__AFL_LOOP(100000)) {
+
+ int len = __AFL_FUZZ_TESTCASE_LEN;
+
+ // Check that the length of the test case is at least 8 bytes
+ if (len < 8) continue;
+
+ // Initialize the command line arguments using the testcase buffer
+ AFL_INIT_ARGV_PERSISTENT(buf);
+
+ /* Check if the first argument is "XYZ" and the second argument is "TEST2"
+ If so, call the "abort" function to terminate the program.
+ Otherwise, print an error message. */
+ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) {
+
+ if (strcmp(argv[2], "TEST2") == 0) { abort(); }
+
+ } else {
+
+ printf("Bad number of arguments!\n");
+
+ }
+
+ }
+
+ /* Exiting the loop allows the program to terminate normally. AFL will restart
+ the process with a clean slate for allocated memory, file descriptors, etc.
+ */
+ return 0;
+
+}
+
diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c
index e7cc6b72..41eead0c 100644
--- a/utils/argv_fuzzing/argvfuzz.c
+++ b/utils/argv_fuzzing/argvfuzz.c
@@ -2,7 +2,7 @@
american fuzzy lop++ - LD_PRELOAD for fuzzing argv in binaries
------------------------------------------------------------
- Copyright 2019-2022 Kjell Braden <afflux@pentabarf.de>
+ Copyright 2019-2023 Kjell Braden <afflux@pentabarf.de>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.