push to stable (#973)

* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

* v3.13c release

* back push (#952)

* Dev (#949)

* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>

* v3.13c release (#950)

* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

* v3.13c release

Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>

Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>
Co-authored-by: hexcoder- <heiko@hexco.de>

* v3.14a init

* remove redundant unsetenv (#947)

* update MacOS Install information

* add missing clean action for frida_mode

* ensure memory is there before free

* adapt to incompatible LLVM 13 API

* fix stupid typos

* add fix info

* build afl-compiler-rt even with broken llvm

* fix -F with slash option

* dynamic_list and afl-compiler-rt rework

* detect partial linking in afl-cc

* partial linking with -Wl

* Add proper name and URL for Zafl (#959)

* move link

* add known frontends for supported compiler infrastructures

* add Rust

* fix ui fuzzing stage index (#960)

* fix overflowing UI fields 'now processing'

* restored timeout handling (with SIGALRM for now)

* On non-Linux systems make clean may fail for frida_mode

* give hint how to set env var for path to llvm-config tool

* setting AFL_CC for test-llvm.sh on FreeBSD is not necessary anymore

* remove -D from -M

* write target errors to out_dir/error.txt

* add changelog entry

* add changelog

* format

* more info for error logging

* Forkserver for afl-analyze (#963)

* afl-analyze forkserver

* added missing vars to forkserver

* synchronized a bit more with afl-tmin

* more debugging, runs now, but need to suppress target output

* fix dev/null setting

* afl-analyze info:

Co-authored-by: hexcoder- <heiko@hexco.de>

* proper newlines

* reenable LLVM 3.8 ( Ubuntu 16.04 )

* FRIDA AARCH64 support (#965)

Co-authored-by: Your Name <you@example.com>

* adapt docs to minimum LLVM version

* adapt to minimum llvm version

* remove warning regarding core_pattern (was wrong/unnecessary anyway)

* avoid code duplication, symlink header file

* clippy fixes

* add test cases for splitting integer comparisons

* Revert "add test cases for splitting integer comparisons"

This reverts commit e0aa411647.

* add test cases for splitting integer comparisons

* FRIDA - Remove need for AFL_FRIDA_PERSISTENT_RETADDR_OFFSET (#970)

Co-authored-by: Your Name <you@example.com>

* fix AFL_CAL_FAST

* fix cmplog screen update crash

* Frida complog fix (#971)

* Fix complog issue with changing address space

* Added support for printing command line and environment during startup

* Review fixes

Co-authored-by: Your Name <you@example.com>

* Improve tracing support to include real addresses and edge ids and also support logging edges only once (#972)

Co-authored-by: Your Name <you@example.com>

* split-comparison llvm pass refactor for smaller compilation times (and a small bug fix) (#964)

* Refactored split compare pass to be more efficient in LTO usage and allow splitting to other minimum bitwidths.

Efficiency: avoid looping over the whole llvm module N times, when once is also enough.

Bitwidth: Previously, due to fallthrough in switch-case, all comparisons were split to 8-bit, which might not be desirable e.g., 16 or 32 bit might be enough. So now all comparison are split until they are smaller or equal to the target bitwidth, which is controlled through the `AFL_LLVM_LAF_SPLIT_COMPARES_BITW` environment variable.

* fixed miscompilation due to incorrectly trying to split a signed comparison operator

* minor formatting updates and use IRBuilder when inserting multiple instructions

* added @hexcoder-'s test-int_cases.c to make test

* Avoid recursion; switch to smallvector in splitAndSimplify; use switch case for icmp type;

* Fixed issue when splitting < where the inverse comparison was not further split

* some cleanup

* code format

* fix to instrument global c++ namespace functions

* update changelog

* document frida changes

* Fix typo in README.md (#974)

* adapt for LLVM 3.8.0

* fix README

* little inline

* Add debug output to alert user to calibration progress/issues (#969)

* aflppdriver help output

* code format

Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>
Co-authored-by: terrynini <terrynini38514@gmail.com>
Co-authored-by: jdhiser <hiser@virginia.edu>
Co-authored-by: yuan <ssspeed00@gmail.com>
Co-authored-by: Michael Rodler <michael.rodler@paluno.uni-due.de>
Co-authored-by: Artis <32833063+Artis24106@users.noreply.github.com>
This commit is contained in:
van Hauser
2021-06-14 23:48:47 +02:00
committed by GitHub
parent 48c878a76d
commit 7bcd4e2901
37 changed files with 1962 additions and 1037 deletions

View File

@ -88,20 +88,20 @@ behaviours and defaults:
with laf-intel and redqueen, frida mode, unicorn mode, gcc plugin, full *BSD,
Mac OS, Solaris and Android support and much, much, much more.
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode |
| -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:|
| Threadsafe counters | | x(3) | | | | |
| NeverZero | x86[_64]| x(1) | x | x | x | x |
| Persistent Mode | | x | x | x86[_64] | x86[_64]/arm[64] | x |
| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm |
| CmpLog | | x | | x86[_64] | x86[_64]/arm[64] | |
| Selective Instrumentation| | x | x | x | x | |
| Non-Colliding Coverage | | x(4) | | | (x)(5) | |
| Ngram prev_loc Coverage | | x(6) | | | | |
| Context Coverage | | x(6) | | | | |
| Auto Dictionary | | x(7) | | | | |
| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | |
| Shared Memory Testcases | | x | x | x | x | x |
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode |
| -------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|
| Threadsafe counters | | x(3) | | | | |
| NeverZero | x86[_64]| x(1) | x | x | x | x |
| Persistent Mode | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x |
| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] |
| CmpLog | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | |
| Selective Instrumentation| | x | x | x | x | |
| Non-Colliding Coverage | | x(4) | | | (x)(5) | |
| Ngram prev_loc Coverage | | x(6) | | | | |
| Context Coverage | | x(6) | | | | |
| Auto Dictionary | | x(7) | | | | |
| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | |
| Shared Memory Testcases | | x | x | x86[_64]/arm64 | x | x |
1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
@ -796,7 +796,7 @@ If you do not have to use Unicorn the following setup is recommended to use
qemu_mode:
* run 1 afl-fuzz -Q instance with CMPLOG (`-c 0` + `AFL_COMPCOV_LEVEL=2`)
* run 1 afl-fuzz -Q instance with QASAN (`AFL_USE_QASAN=1`)
* run 1 afl-fuzz -Q instance with LAF (``AFL_PRELOAD=libcmpcov.so` + `AFL_COMPCOV_LEVEL=2`)
* run 1 afl-fuzz -Q instance with LAF (`AFL_PRELOAD=libcmpcov.so` + `AFL_COMPCOV_LEVEL=2`)
Alternatively you can use frida_mode, just switch `-Q` with `-O` and remove the
LAF instance.

View File

@ -1,342 +0,0 @@
#ifndef CUSTOM_MUTATOR_HELPERS
#define CUSTOM_MUTATOR_HELPERS
#include "config.h"
#include "types.h"
#include <stdlib.h>
#define INITIAL_GROWTH_SIZE (64)
#define RAND_BELOW(limit) (rand() % (limit))
/* Use in a struct: creates a name_buf and a name_size variable. */
#define BUF_VAR(type, name) \
type * name##_buf; \
size_t name##_size;
/* this filles in `&structptr->something_buf, &structptr->something_size`. */
#define BUF_PARAMS(struct, name) \
(void **)&struct->name##_buf, &struct->name##_size
typedef struct {
} afl_t;
static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
static s8 interesting_8[] = {INTERESTING_8};
static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
switch (RAND_BELOW(12)) {
case 0: {
/* Flip a single bit somewhere. Spooky! */
s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8);
out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7);
break;
}
case 1: {
/* Set byte to interesting value. */
u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))];
out_buf[(RAND_BELOW(end - begin) + begin)] = val;
break;
}
case 2: {
/* Set word to interesting value, randomly choosing endian. */
if (end - begin < 2) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 1) break;
switch (RAND_BELOW(2)) {
case 0:
*(u16 *)(out_buf + byte_idx) =
interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)];
break;
case 1:
*(u16 *)(out_buf + byte_idx) =
SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]);
break;
}
break;
}
case 3: {
/* Set dword to interesting value, randomly choosing endian. */
if (end - begin < 4) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 3) break;
switch (RAND_BELOW(2)) {
case 0:
*(u32 *)(out_buf + byte_idx) =
interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
break;
case 1:
*(u32 *)(out_buf + byte_idx) =
SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
break;
}
break;
}
case 4: {
/* Set qword to interesting value, randomly choosing endian. */
if (end - begin < 8) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 7) break;
switch (RAND_BELOW(2)) {
case 0:
*(u64 *)(out_buf + byte_idx) =
(s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
break;
case 1:
*(u64 *)(out_buf + byte_idx) = SWAP64(
(s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
break;
}
break;
}
case 5: {
/* Randomly subtract from byte. */
out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX);
break;
}
case 6: {
/* Randomly add to byte. */
out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX);
break;
}
case 7: {
/* Randomly subtract from word, random endian. */
if (end - begin < 2) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 1) break;
if (RAND_BELOW(2)) {
*(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
} else {
u16 num = 1 + RAND_BELOW(ARITH_MAX);
*(u16 *)(out_buf + byte_idx) =
SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num);
}
break;
}
case 8: {
/* Randomly add to word, random endian. */
if (end - begin < 2) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 1) break;
if (RAND_BELOW(2)) {
*(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
} else {
u16 num = 1 + RAND_BELOW(ARITH_MAX);
*(u16 *)(out_buf + byte_idx) =
SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num);
}
break;
}
case 9: {
/* Randomly subtract from dword, random endian. */
if (end - begin < 4) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 3) break;
if (RAND_BELOW(2)) {
*(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
} else {
u32 num = 1 + RAND_BELOW(ARITH_MAX);
*(u32 *)(out_buf + byte_idx) =
SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num);
}
break;
}
case 10: {
/* Randomly add to dword, random endian. */
if (end - begin < 4) break;
s32 byte_idx = (RAND_BELOW(end - begin) + begin);
if (byte_idx >= end - 3) break;
if (RAND_BELOW(2)) {
*(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
} else {
u32 num = 1 + RAND_BELOW(ARITH_MAX);
*(u32 *)(out_buf + byte_idx) =
SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num);
}
break;
}
case 11: {
/* Just set a random byte to a random value. Because,
why not. We use XOR with 1-255 to eliminate the
possibility of a no-op. */
out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255);
break;
}
}
}
/* This function calculates the next power of 2 greater or equal its argument.
@return The rounded up power of 2 (if no overflow) or 0 on overflow.
*/
static inline size_t next_pow2(size_t in) {
if (in == 0 || in > (size_t)-1)
return 0; /* avoid undefined behaviour under-/overflow */
size_t out = in - 1;
out |= out >> 1;
out |= out >> 2;
out |= out >> 4;
out |= out >> 8;
out |= out >> 16;
return out + 1;
}
/* This function makes sure *size is > size_needed after call.
It will realloc *buf otherwise.
*size will grow exponentially as per:
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
Will return NULL and free *buf if size_needed is <1 or realloc failed.
@return For convenience, this function returns *buf.
*/
static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
/* No need to realloc */
if (likely(size_needed && *size >= size_needed)) return *buf;
/* No initial size was set */
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
/* grow exponentially */
size_t next_size = next_pow2(size_needed);
/* handle overflow */
if (!next_size) { next_size = size_needed; }
/* alloc */
*buf = realloc(*buf, next_size);
*size = *buf ? next_size : 0;
return *buf;
}
/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2,
size_t *size2) {
void * scratch_buf = *buf1;
size_t scratch_size = *size1;
*buf1 = *buf2;
*size1 = *size2;
*buf2 = scratch_buf;
*size2 = scratch_size;
}
#undef INITIAL_GROWTH_SIZE
#endif

View File

@ -0,0 +1 @@
../examples/custom_mutator_helpers.h

View File

@ -9,20 +9,29 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++3.14a (release)
- Fix for llvm 13
- afl-fuzz:
- fix -F when a '/' was part of the parameter
- fixed a crash for cmplog for very slow inputs
- removed implied -D determinstic from -M main
- if the target becomes unavailable check out out/default/error.txt for
an indicator why
- afl-cc
- if the target becomes unavailable check out out/default/error.txt
for an indicator why
- AFL_CAL_FAST was a dead env, now does the same as AFL_FAST_CAL
- afl-cc:
- Update to COMPCOV/laf-intel that speeds up the instrumentation
process a lot - thanks to Michael Rodler/f0rki for the PR!
- Fix to instrument global namespace functions in c++
- Fix for llvm 13
- support partial linking
- We do support llvm versions from 3.8 again
- afl_analyze
- fix timeout handling and support forkserver
- We do support llvm versions from 3.8 to 5.0 again
- frida_mode:
- fix for cmplog
- remove need for AFL_FRIDA_PERSISTENT_RETADDR_OFFSET
- feature parity of aarch64 with intel now (persistent, cmplog,
in-memory testcases, asan)
- afl_analyze:
- fix timeout handling
- add forkserver support for better performance
- ensure afl-compiler-rt is built for gcc_module
- afl-analyze now uses the forkserver for increased performance
### Version ++3.13c (release)
- Note: plot_data switched to relative time from unix time in 3.10

View File

@ -3,6 +3,7 @@
## Contents
* [What is the difference between afl and afl++?](#what-is-the-difference-between-afl-and-afl)
* [I got a weird compile error from clang](#i-got-a-weird-compile-error-from-clang)
* [How to improve the fuzzing speed?](#how-to-improve-the-fuzzing-speed)
* [How do I fuzz a network service?](#how-do-i-fuzz-a-network-service)
* [How do I fuzz a GUI program?](#how-do-i-fuzz-a-gui-program)
@ -35,6 +36,26 @@ flexible and feature rich guided fuzzer available as open source.
And in independent fuzzing benchmarks it is one of the best fuzzers available,
e.g. [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html)
## I got a weird compile error from clang
If you see this kind of error when trying to instrument a target with afl-cc/
afl-clang-fast/afl-clang-lto:
```
/prg/tmp/llvm-project/build/bin/clang-13: symbol lookup error: /usr/local/bin/../lib/afl//cmplog-instructions-pass.so: undefined symbol: _ZNK4llvm8TypeSizecvmEv
clang-13: error: unable to execute command: No such file or directory
clang-13: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 13.0.0 (https://github.com/llvm/llvm-project 1d7cf550721c51030144f3cd295c5789d51c4aad)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /prg/tmp/llvm-project/build/bin
clang-13: note: diagnostic msg:
********************
```
Then this means that your OS updated the clang installation from an upgrade
package and because of that the afl++ llvm plugins do not match anymore.
Solution: `git pull ; make clean install` of afl++
## How to improve the fuzzing speed?
1. Use [llvm_mode](docs/llvm_mode/README.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended)

View File

@ -108,9 +108,6 @@ make fairly broad use of environmental variables instead:
- Setting `AFL_QUIET` will prevent afl-cc and afl-as banners from being
displayed during compilation, in case you find them distracting.
- Setting `AFL_CAL_FAST` will speed up the initial calibration, if the
application is very slow.
## 2) Settings for LLVM and LTO: afl-clang-fast / afl-clang-fast++ / afl-clang-lto / afl-clang-lto++
The native instrumentation helpers (instrumentation and gcc_plugin) accept a subset
@ -386,6 +383,7 @@ checks or alter some of the more exotic semantics of the tool:
- `AFL_FAST_CAL` keeps the calibration stage about 2.5x faster (albeit less
precise), which can help when starting a session against a slow target.
`AFL_CAL_FAST` works too.
- The CPU widget shown at the bottom of the screen is fairly simplistic and
may complain of high load prematurely, especially on systems with low core

View File

@ -20,6 +20,7 @@ RT_CFLAGS:=-Wno-unused-parameter \
-Wno-unused-function \
-Wno-unused-result \
-Wno-int-to-pointer-cast \
-Wno-pointer-sign \
LDFLAGS+=-shared \
-lpthread \

View File

@ -75,7 +75,6 @@ following options are currently supported:
* `AFL_FRIDA_PERSISTENT_CNT` - See `AFL_QEMU_PERSISTENT_CNT`
* `AFL_FRIDA_PERSISTENT_HOOK` - See `AFL_QEMU_PERSISTENT_HOOK`
* `AFL_FRIDA_PERSISTENT_RET` - See `AFL_QEMU_PERSISTENT_RET`
* `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` - See `AFL_QEMU_PERSISTENT_RETADDR_OFFSET`
To enable the powerful CMPLOG mechanism, set `-c 0` for `afl-fuzz`.
@ -156,16 +155,17 @@ instrumentation (the default where available). Required to use
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default the child will
report instrumented blocks back to the parent so that it can also instrument
them and they be inherited by the next child on fork.
* `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks
`AFL_FRIDA_INST_NO_OPTIMIZE`.
* `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks,
requires `AFL_FRIDA_INST_NO_OPTIMIZE`.
* `AFL_FRIDA_INST_TRACE_UNIQUE` - As per `AFL_FRIDA_INST_TRACE`, but each edge
is logged only once, requires `AFL_FRIDA_INST_NO_OPTIMIZE`.
* `AFL_FRIDA_OUTPUT_STDOUT` - Redirect the standard output of the target
application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
* `AFL_FRIDA_OUTPUT_STDERR` - Redirect the standard error of the target
application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
* `AFL_FRIDA_PERSISTENT_DEBUG` - Insert a Breakpoint into the instrumented code
at `AFL_FRIDA_PERSISTENT_HOOK` and `AFL_FRIDA_PERSISTENT_RET` to allow the user
to determine the value of `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` using a
debugger.
to detect issues in the persistent loop using a debugger.
```

View File

@ -1,3 +1,8 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <syscall.h>
#include "frida-gum.h"
#include "debug.h"
@ -5,10 +10,13 @@
#include "util.h"
#define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
#define FD_TMP_MAX_SIZE 65536
extern struct cmp_map *__afl_cmp_map;
static GArray *cmplog_ranges = NULL;
static int fd_tmp = -1;
static ssize_t fd_tmp_size = 0;
static gboolean cmplog_range(const GumRangeDetails *details,
gpointer user_data) {
@ -27,6 +35,40 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) {
}
static int cmplog_create_temp(void) {
const char *tmpdir = g_get_tmp_dir();
OKF("CMPLOG Temporary directory: %s", tmpdir);
gchar *fname = g_strdup_printf("%s/frida-cmplog-XXXXXX", tmpdir);
OKF("CMPLOG Temporary file template: %s", fname);
int fd = mkstemp(fname);
OKF("CMPLOG Temporary file: %s", fname);
if (fd < 0) {
FATAL("Failed to create temp file: %s, errno: %d", fname, errno);
}
if (unlink(fname) < 0) {
FATAL("Failed to unlink temp file: %s (%d), errno: %d", fname, fd, errno);
}
if (ftruncate(fd, 0) < 0) {
FATAL("Failed to ftruncate temp file: %s (%d), errno: %d", fname, fd,
errno);
}
g_free(fname);
return fd;
}
void cmplog_init(void) {
if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
@ -44,6 +86,13 @@ void cmplog_init(void) {
}
/*
* We can't use /dev/null or /dev/zero for this since it appears that they
* don't validate the input buffer. Persumably as an optimization because they
* don't actually write any data. The file will be deleted on close.
*/
fd_tmp = cmplog_create_temp();
}
static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
@ -67,6 +116,9 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
*/
if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
/* Check our addres/length don't wrap around */
if (SIZE_MAX - addr < size) { return false; }
GumAddress inner_base = addr;
GumAddress inner_limit = inner_base + size;
@ -81,6 +133,38 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
}
/*
* Our address map can change (e.g. stack growth), use write as a fallback to
* validate our address.
*/
ssize_t written = syscall(__NR_write, fd_tmp, (void *)addr, size);
/*
* If the write succeeds, then the buffer must be valid otherwise it would
* return EFAULT
*/
if (written > 0) {
fd_tmp_size += written;
if (fd_tmp_size > FD_TMP_MAX_SIZE) {
/*
* Truncate the file, we don't want our temp file to continue growing!
*/
if (ftruncate(fd_tmp, 0) < 0) {
FATAL("Failed to truncate fd_tmp (%d), errno: %d", fd_tmp, errno);
}
fd_tmp_size = 0;
}
if ((size_t)written == size) { return true; }
}
return false;
}

View File

@ -1,4 +1,6 @@
#include <unistd.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include "frida-gum.h"
@ -18,44 +20,50 @@
static gboolean tracing = false;
static gboolean optimize = false;
static gboolean unique = false;
static GumStalkerTransformer *transformer = NULL;
__thread uint64_t previous_pc = 0;
static GumAddress previous_rip = 0;
static u8 * edges_notified = NULL;
static void trace_debug(char *format, ...) {
va_list ap;
char buffer[4096] = {0};
int ret;
int len;
va_start(ap, format);
ret = vsnprintf(buffer, sizeof(buffer) - 1, format, ap);
va_end(ap);
if (ret < 0) { return; }
len = strnlen(buffer, sizeof(buffer));
IGNORED_RETURN(write(STDOUT_FILENO, buffer, len));
}
__attribute__((hot)) static void on_basic_block(GumCpuContext *context,
gpointer user_data) {
UNUSED_PARAMETER(context);
/*
* This function is performance critical as it is called to instrument every
* basic block. By moving our print buffer to a global, we avoid it affecting
* the critical path with additional stack adjustments if tracing is not
* enabled. If tracing is enabled, then we're printing a load of diagnostic
* information so this overhead is unlikely to be noticeable.
*/
static char buffer[200];
int len;
GumAddress current_pc = GUM_ADDRESS(user_data);
uint8_t * cursor;
uint64_t value;
if (unlikely(tracing)) {
/* Avoid any functions which may cause an allocation since the target app
* may already be running inside malloc and it isn't designed to be
* re-entrant on a single thread */
len = snprintf(buffer, sizeof(buffer),
"current_pc: 0x%016" G_GINT64_MODIFIER
"x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n",
current_pc, previous_pc);
GumAddress current_rip = GUM_ADDRESS(user_data);
GumAddress current_pc;
GumAddress edge;
uint8_t * cursor;
uint64_t value;
IGNORED_RETURN(write(STDOUT_FILENO, buffer, len + 1));
}
current_pc = (current_pc >> 4) ^ (current_pc << 8);
current_pc = (current_rip >> 4) ^ (current_rip << 8);
current_pc &= MAP_SIZE - 1;
cursor = &__afl_area_ptr[current_pc ^ previous_pc];
edge = current_pc ^ previous_pc;
cursor = &__afl_area_ptr[edge];
value = *cursor;
if (value == 0xff) {
@ -71,6 +79,23 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
*cursor = value;
previous_pc = current_pc >> 1;
if (unlikely(tracing)) {
if (!unique || edges_notified[edge] == 0) {
trace_debug("TRACE: edge: %10" G_GINT64_MODIFIER
"d, current_rip: 0x%016" G_GINT64_MODIFIER
"x, previous_rip: 0x%016" G_GINT64_MODIFIER "x\n",
edge, current_rip, previous_rip);
}
if (unique) { edges_notified[edge] = 1; }
previous_rip = current_rip;
}
}
static void instr_basic_block(GumStalkerIterator *iterator,
@ -164,18 +189,28 @@ void instrument_init(void) {
optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
if (!instrument_is_coverage_optimize_supported()) optimize = false;
OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' ');
OKF("Instrumentation - unique [%c]", unique ? 'X' : ' ');
if (tracing && optimize) {
FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible");
FATAL("AFL_FRIDA_INST_TRACE requires AFL_FRIDA_INST_NO_OPTIMIZE");
}
if (unique && optimize) {
FATAL("AFL_FRIDA_INST_TRACE_UNIQUE requires AFL_FRIDA_INST_NO_OPTIMIZE");
}
if (unique) { tracing = TRUE; }
if (__afl_map_size != 0x10000) {
FATAL("Bad map size: 0x%08x", __afl_map_size);
@ -185,6 +220,28 @@ void instrument_init(void) {
transformer =
gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
if (unique) {
int shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); }
edges_notified = shmat(shm_id, NULL, 0);
g_assert(edges_notified != MAP_FAILED);
/*
* Configure the shared memory region to be removed once the process dies.
*/
if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
}
/* Clear it, not sure it's necessary, just seems like good practice */
memset(edges_notified, '\0', MAP_SIZE);
}
instrument_debug_init();
asan_init();
cmplog_init();

View File

@ -1,4 +1,5 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
@ -27,6 +28,8 @@
#include "stats.h"
#include "util.h"
#define PROC_MAX 65536
#ifdef __APPLE__
extern mach_port_t mach_task_self();
extern GumAddress gum_darwin_find_entrypoint(mach_port_t task);
@ -78,7 +81,7 @@ static void on_main_os(int argc, char **argv, char **envp) {
#endif
static void embedded_init() {
static void embedded_init(void) {
static gboolean initialized = false;
if (!initialized) {
@ -90,7 +93,84 @@ static void embedded_init() {
}
void afl_frida_start() {
static void afl_print_cmdline(void) {
char * buffer = g_malloc0(PROC_MAX);
gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
int fd = open(fname, O_RDONLY);
if (fd < 0) {
FATAL("Failed to open /proc/self/cmdline, errno: (%d)", errno);
}
ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1);
if (bytes_read < 0) {
FATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno);
}
int idx = 0;
for (ssize_t i = 0; i < bytes_read; i++) {
if (i == 0 || buffer[i - 1] == '\0') {
OKF("AFL - COMMANDLINE: argv[%d] = %s", idx++, &buffer[i]);
}
}
close(fd);
g_free(fname);
g_free(buffer);
}
static void afl_print_env(void) {
char * buffer = g_malloc0(PROC_MAX);
gchar *fname = g_strdup_printf("/proc/%d/environ", getppid());
int fd = open(fname, O_RDONLY);
if (fd < 0) {
FATAL("Failed to open /proc/self/cmdline, errno: (%d)", errno);
}
ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1);
if (bytes_read < 0) {
FATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno);
}
int idx = 0;
for (ssize_t i = 0; i < bytes_read; i++) {
if (i == 0 || buffer[i - 1] == '\0') {
OKF("AFL - ENVIRONMENT %3d: %s", idx++, &buffer[i]);
}
}
close(fd);
g_free(fname);
g_free(buffer);
}
void afl_frida_start(void) {
afl_print_cmdline();
afl_print_env();
embedded_init();
stalker_init();

View File

@ -13,7 +13,6 @@ afl_persistent_hook_fn hook = NULL;
guint64 persistent_start = 0;
guint64 persistent_count = 0;
guint64 persistent_ret = 0;
guint64 persistent_ret_offset = 0;
gboolean persistent_debug = FALSE;
void persistent_init(void) {
@ -23,8 +22,6 @@ void persistent_init(void) {
persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR");
persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT");
persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET");
persistent_ret_offset =
util_read_address("AFL_FRIDA_PERSISTENT_RETADDR_OFFSET");
if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; }
@ -44,14 +41,6 @@ void persistent_init(void) {
}
if (persistent_ret_offset != 0 && persistent_ret == 0) {
FATAL(
"AFL_FRIDA_PERSISTENT_RET must be specified if "
"AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is");
}
if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000;
if (persistent_count != 0 && persistent_count < 100)
@ -68,8 +57,6 @@ void persistent_init(void) {
OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)",
persistent_ret == 0 ? ' ' : 'X', persistent_ret);
OKF("Instrumentation - persistent ret offset [%c] (%" G_GINT64_MODIFIER "d)",
persistent_ret_offset == 0 ? ' ' : 'X', persistent_ret_offset);
if (hook_name != NULL) {

View File

@ -268,13 +268,15 @@ static void instrument_persitent_restore_regs(GumArm64Writer * cw,
ARM64_REG_X0, (16 * 14),
GUM_INDEX_SIGNED_OFFSET);
/* Don't restore RIP or RSP, use x1-x3 as clobber */
/* LR & Adjusted SP (clobber x1) */
/* LR & Adjusted SP (use x1 as clobber) */
gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X1,
ARM64_REG_X0, (16 * 15),
GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_SP, ARM64_REG_X1);
/* Don't restore RIP use x1-x3 as clobber */
/* PC (x2) & CPSR (x1) */
gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X1,
ARM64_REG_X0, (16 * 16),
@ -404,7 +406,6 @@ void persistent_prologue(GumStalkerOutput *output) {
gconstpointer loop = cw->code + 1;
/* Stack must be 16-byte aligned per ABI */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
@ -450,9 +451,6 @@ void persistent_epilogue(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP,
persistent_ret_offset);
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr));

View File

@ -43,6 +43,7 @@ struct x86_64_regs {
typedef struct x86_64_regs arch_api_regs;
static arch_api_regs saved_regs = {0};
static gpointer saved_ret = NULL;
gboolean persistent_is_supported(void) {
@ -104,7 +105,7 @@ static void instrument_persitent_save_regs(GumX86Writer * cw,
/* RED_ZONE + Saved flags, RAX, alignment */
gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX,
GUM_RED_ZONE_SIZE + (0x8 * 3));
GUM_RED_ZONE_SIZE + (0x8 * 2));
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16),
GUM_REG_RBX);
@ -159,7 +160,9 @@ static void instrument_persitent_restore_regs(GumX86Writer * cw,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX,
(0x8 * 14));
/* Don't restore RIP or RSP */
/* Don't restore RIP */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX,
(0x8 * 16));
/* Restore RBX, RAX & Flags */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
@ -242,6 +245,31 @@ static void persistent_prologue_hook(GumX86Writer * cw,
}
static void instrument_persitent_save_ret(GumX86Writer *cw) {
/* Stack usage by this function */
gssize offset = GUM_RED_ZONE_SIZE + (3 * 8);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_RAX, GUM_REG_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
(GUM_RED_ZONE_SIZE));
}
void persistent_prologue(GumStalkerOutput *output) {
/*
@ -268,11 +296,10 @@ void persistent_prologue(GumStalkerOutput *output) {
gconstpointer loop = cw->code + 1;
/* Stack must be 16-byte aligned per ABI */
instrument_persitent_save_regs(cw, &saved_regs);
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8);
/* pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8));
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
@ -304,6 +331,8 @@ void persistent_prologue(GumStalkerOutput *output) {
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
}
@ -314,9 +343,15 @@ void persistent_epilogue(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
persistent_ret_offset);
gum_x86_writer_put_ret(cw);
/* The stack should be aligned when we re-enter our loop */
gconstpointer zero = cw->code + 1;
gum_x86_writer_put_test_reg_u32(cw, GUM_REG_RSP, 0xF);
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, zero, GUM_NO_HINT);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -8);
gum_x86_writer_put_label(cw, zero);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_RAX);
}

View File

@ -39,6 +39,7 @@ struct x86_regs {
typedef struct x86_regs arch_api_regs;
static arch_api_regs saved_regs = {0};
static gpointer saved_ret = NULL;
gboolean persistent_is_supported(void) {
@ -117,7 +118,9 @@ static void instrument_persitent_restore_regs(GumX86Writer * cw,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX,
(0x4 * 6));
/* Don't restore RIP or RSP */
/* Don't restore RIP */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX,
(0x4 * 8));
/* Restore RBX, RAX & Flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
@ -184,6 +187,26 @@ static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
}
static void instrument_persitent_save_ret(GumX86Writer *cw) {
/* Stack usage by this function */
gssize offset = (3 * 4);
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_EAX, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_popfx(cw);
}
void persistent_prologue(GumStalkerOutput *output) {
/*
@ -210,11 +233,10 @@ void persistent_prologue(GumStalkerOutput *output) {
gconstpointer loop = cw->code + 1;
/* Stack must be 16-byte aligned per ABI */
instrument_persitent_save_regs(cw, &saved_regs);
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4));
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4);
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
@ -244,6 +266,8 @@ void persistent_prologue(GumStalkerOutput *output) {
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
}
@ -254,10 +278,8 @@ void persistent_epilogue(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP,
persistent_ret_offset);
gum_x86_writer_put_ret(cw);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_EAX);
}

View File

@ -38,8 +38,6 @@ ifeq "$(ARCH)" "x86"
AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x56555000)
endif
AFL_FRIDA_PERSISTENT_RETADDR_OFFSET:=0x50
.PHONY: all 32 clean qemu frida
all: $(TESTINSTBIN)
@ -76,7 +74,6 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
$(ROOT)afl-fuzz \
-D \
-O \
@ -89,7 +86,6 @@ debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
gdb \
--ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \
--ex 'set environment AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET)' \
--ex 'set environment AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET)' \
--ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \
--ex 'set environment AFL_DEBUG_CHILD=1' \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
@ -99,7 +95,6 @@ debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
run: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
AFL_DEBUG_CHILD=1 \
LD_PRELOAD=$(ROOT)afl-frida-trace.so \
$(TESTINSTBIN) $(TESTINSTR_DATA_FILE)

View File

@ -0,0 +1,90 @@
PWD:=$(shell pwd)/
ROOT:=$(shell realpath $(PWD)../../..)/
BUILD_DIR:=$(PWD)build/
UNSTABLE_DATA_DIR:=$(BUILD_DIR)in/
UNSTABLE_DATA_FILE:=$(UNSTABLE_DATA_DIR)in
UNSTABLE_BIN:=$(BUILD_DIR)unstable
UNSTABLE_SRC:=$(PWD)unstable.c
QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out
ifndef ARCH
ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64"
ARCH:=arm64
endif
ifeq "$(ARCH)" "i686"
ARCH:=x86
endif
endif
AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(UNSTABLE_BIN) -s run_test -b 0x4000000000)
ifeq "$(ARCH)" "aarch64"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(UNSTABLE_BIN) -s run_test -b 0x0000aaaaaaaaa000)
endif
ifeq "$(ARCH)" "x86_64"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(UNSTABLE_BIN) -s run_test -b 0x0000555555554000)
endif
ifeq "$(ARCH)" "x86"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(UNSTABLE_BIN) -s run_test -b 0x56555000)
endif
.PHONY: all 32 clean qemu frida
all: $(UNSTABLE_BIN)
make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR):
mkdir -p $@
$(UNSTABLE_DATA_DIR): | $(BUILD_DIR)
mkdir -p $@
$(UNSTABLE_DATA_FILE): | $(UNSTABLE_DATA_DIR)
echo -n "000" > $@
$(UNSTABLE_BIN): $(UNSTABLE_SRC) | $(BUILD_DIR)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean:
rm -rf $(BUILD_DIR)
qemu: $(UNSTABLE_BIN) $(UNSTABLE_DATA_FILE)
AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
$(ROOT)afl-fuzz \
-D \
-Q \
-i $(UNSTABLE_DATA_DIR) \
-o $(QEMU_OUT) \
-- \
$(UNSTABLE_BIN) @@
frida: $(UNSTABLE_BIN) $(UNSTABLE_DATA_FILE)
AFL_DEBUG=1 \
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
AFL_FRIDA_INST_TRACE_UNIQUE=1 \
AFL_FRIDA_INST_NO_OPTIMIZE=1 \
$(ROOT)afl-fuzz \
-D \
-O \
-i $(UNSTABLE_DATA_DIR) \
-o $(FRIDA_OUT) \
-- \
$(UNSTABLE_BIN) @@
debug:
gdb \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
--ex 'set disassembly-flavor intel' \
--args $(UNSTABLE_BIN) $(UNSTABLE_DATA_FILE)

View File

@ -0,0 +1,19 @@
all:
@echo trying to use GNU make...
@gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean:
@gmake clean
qemu:
@gmake qemu
frida:
@gmake frida
debug:
@gmake debug

View File

@ -0,0 +1,36 @@
#!/usr/bin/python3
import argparse
from elftools.elf.elffile import ELFFile
def process_file(file, symbol, base):
with open(file, 'rb') as f:
elf = ELFFile(f)
symtab = elf.get_section_by_name('.symtab')
mains = symtab.get_symbol_by_name(symbol)
if len(mains) != 1:
print ("Failed to find main")
return 1
main_addr = mains[0]['st_value']
main = base + main_addr
print ("0x%016x" % main)
return 0
def hex_value(x):
return int(x, 16)
def main():
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('-f', '--file', dest='file', type=str,
help='elf file name', required=True)
parser.add_argument('-s', '--symbol', dest='symbol', type=str,
help='symbol name', required=True)
parser.add_argument('-b', '--base', dest='base', type=hex_value,
help='elf base address', required=True)
args = parser.parse_args()
return process_file (args.file, args.symbol, args.base)
if __name__ == "__main__":
ret = main()
exit(ret)

View File

@ -0,0 +1,67 @@
/*
american fuzzy lop++ - a trivial program to test the build
--------------------------------------------------------
Originally written by Michal Zalewski
Copyright 2014 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
#define TESTINSTR_SECTION
#else
#define TESTINSTR_SECTION __attribute__((section(".testinstr")))
#endif
void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 1) return;
int r = rand();
if ((r % 2) == 0) {
printf ("Hooray all even\n");
} else {
printf ("Hmm that's odd\n");
}
// we support three input cases
if (data[0] == '0')
printf("Looks like a zero to me!\n");
else if (data[0] == '1')
printf("Pretty sure that is a one!\n");
else
printf("Neither one or zero? How quaint!\n");
}
void run_test(char * file) {
fprintf(stderr, "Running: %s\n", file);
FILE *f = fopen(file, "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char*)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", file, n_read);
}
int main(int argc, char **argv) {
srand(1);
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
for (int i = 1; i < argc; i++) {
run_test(argv[i]);
}
}

View File

@ -478,9 +478,7 @@ typedef struct afl_state {
u32 hang_tmout; /* Timeout used for hang det (ms) */
u8 cal_cycles, /* Calibration cycles defaults */
cal_cycles_long, /* Calibration cycles defaults */
havoc_stack_pow2, /* HAVOC_STACK_POW2 */
u8 havoc_stack_pow2, /* HAVOC_STACK_POW2 */
no_unlink, /* do not unlink cur_input */
debug, /* Debug mode */
custom_only, /* Custom mutator only mode */

View File

@ -60,6 +60,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_NO_PREFETCH",
"AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_TRACE",
"AFL_FRIDA_INST_UNSTABLE",
"AFL_FRIDA_OUTPUT_STDOUT",
"AFL_FRIDA_OUTPUT_STDERR",
"AFL_FRIDA_PERSISTENT_ADDR",
@ -67,7 +68,6 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_PERSISTENT_DEBUG",
"AFL_FRIDA_PERSISTENT_HOOK",
"AFL_FRIDA_PERSISTENT_RET",
"AFL_FRIDA_PERSISTENT_RETADDR_OFFSET",
"AFL_FRIDA_STATS_FILE",
"AFL_FRIDA_STATS_INTERVAL",
"AFL_FRIDA_STATS_TRANSITIONS",

View File

@ -96,9 +96,8 @@ bool isIgnoreFunction(const llvm::Function *F) {
static constexpr const char *ignoreSubstringList[] = {
"__asan", "__msan", "__ubsan", "__lsan",
"__san", "__sanitize", "__cxx", "_GLOBAL__",
"DebugCounter", "DwarfDebug", "DebugLoc"
"__asan", "__msan", "__ubsan", "__lsan", "__san", "__sanitize",
"__cxx", "DebugCounter", "DwarfDebug", "DebugLoc"
};

File diff suppressed because it is too large Load Diff

View File

@ -167,7 +167,7 @@ static inline u8 anything_set(void) {
static void at_exit_handler(void) {
unlink(fsrv.out_file); /* Ignore errors */
unlink(fsrv.out_file); /* Ignore errors */
}
@ -643,12 +643,14 @@ static void set_up_environment(char **argv) {
}
fsrv.out_file = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid());
fsrv.out_file =
alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid());
}
unlink(fsrv.out_file);
fsrv.out_fd = open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
fsrv.out_fd =
open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); }
@ -1118,7 +1120,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv.target_path) { ck_free(fsrv.target_path); }
if (in_data) { ck_free(in_data); }
exit(0);
}

View File

@ -751,6 +751,8 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
}
/* Get unix time in milliseconds */
u64 get_cur_time(void) {
struct timeval tv;

View File

@ -73,7 +73,7 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) {
/* Helper to choose random block len for block operations in fuzz_one().
Doesn't return zero, provided that max_len is > 0. */
static u32 choose_block_len(afl_state_t *afl, u32 limit) {
static inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
u32 min_value, max_value;
u32 rlim = MIN(afl->queue_cycle, (u32)3);

View File

@ -252,7 +252,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u64 start_time = get_cur_time();
#endif
u32 screen_update = 1000000 / afl->queue_cur->exec_us;
u32 screen_update;
u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@ -261,6 +261,24 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
afl->stage_max = (len << 1);
afl->stage_cur = 0;
if (likely(afl->queue_cur->exec_us)) {
if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
screen_update = 100000 / afl->queue_cur->exec_us;
} else {
screen_update = 1;
}
} else {
screen_update = 100000;
}
// in colorization we do not classify counts, hence we have to calculate
// the original checksum.
if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
@ -905,17 +923,16 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..."
s64 diff = pattern - b_val;
s64 o_diff = o_pattern - o_b_val;
/*
fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
b_val, diff);*/
/* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
b_val, diff); */
if (diff == o_diff && diff) {
// this could be an arithmetic transformation
u64 new_repl = (u64)((s64)repl - diff);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@ -935,15 +952,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
diff = pattern ^ b_val;
s64 o_diff = o_pattern ^ o_b_val;
/* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
"DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
/* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (diff == o_diff && diff) {
// this could be a XOR transformation
u64 new_repl = (u64)((s64)repl ^ diff);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@ -982,15 +1001,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
/* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
"DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
/* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask));
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@ -1029,15 +1050,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
/* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
"DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
/* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl | (0x2020202020202020 & mask));
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@ -1383,7 +1406,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
//#endif /* CMPLOG_SOLVE_ARITHMETIC
//#endif /*
// CMPLOG_SOLVE_ARITHMETIC
return 0;
@ -2152,7 +2176,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
memcpy(buf + idx, tmp, i + 1);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex, *status);
// fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex,
// *status);
}
@ -2235,7 +2260,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] - arith_val[j];
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith, *status);
// fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith,
// *status);
}
@ -2328,16 +2354,17 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
/*
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
h->shape, h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x",
o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr,
"%02x", o->v1[j]); fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u
o0=", hh->hits, hh->id, hh->shape, hh->attribute); for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_o->v1[j]);
fprintf(stderr, "\n");
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits,
h->id, h->shape, h->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]);
fprintf(stderr, " v1=");
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]);
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=",
hh->hits, hh->id, hh->shape, hh->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]);
fprintf(stderr, "\n");
*/
t = taint;

View File

@ -314,7 +314,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
++q->cal_failed;
afl->stage_name = "calibration";
afl->stage_max = afl->fast_cal ? 3 : CAL_CYCLES;
afl->stage_max = afl->afl_env.afl_cal_fast ? 3 : CAL_CYCLES;
/* Make sure the forkserver is up before we do anything, and let's not
count its spin-up time toward binary calibration. */
@ -355,6 +355,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
if (unlikely(afl->debug)) {
DEBUGF("calibration stage %d/%d\n", afl->stage_cur + 1, afl->stage_max);
}
u64 cksum;
write_to_testcase(afl, use_mem, q->len);
@ -402,8 +408,24 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
if (unlikely(!var_detected)) {
// note: from_queue seems to only be set during initialization
if (afl->afl_env.afl_no_ui || from_queue) {
WARNF("instability detected during calibration\n");
} else if (afl->debug) {
DEBUGF("instability detected during calibration\n");
}
}
var_detected = 1;
afl->stage_max = afl->fast_cal ? CAL_CYCLES : CAL_CYCLES_LONG;
afl->stage_max =
afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG;
} else {

View File

@ -96,8 +96,6 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->splicing_with = -1; /* Splicing with which test case? */
afl->cpu_to_bind = -1;
afl->havoc_stack_pow2 = HAVOC_STACK_POW2;
afl->cal_cycles = CAL_CYCLES;
afl->cal_cycles_long = CAL_CYCLES_LONG;
afl->hang_tmout = EXEC_TIMEOUT;
afl->exit_on_time = 0;
afl->stats_update_freq = 1;
@ -341,6 +339,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_cal_fast =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_FAST_CAL",
afl_environment_variable_len)) {
afl->afl_env.afl_cal_fast =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_STATSD",
afl_environment_variable_len)) {

View File

@ -1276,7 +1276,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
if (get_afl_env("AFL_FAST_CAL")) { afl->fast_cal = 1; }
if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
if (afl->afl_env.afl_autoresume) {
@ -1489,14 +1488,6 @@ int main(int argc, char **argv_orig, char **envp) {
check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
if (afl->afl_env.afl_cal_fast) {
/* Use less calibration cycles, for slow applications */
afl->cal_cycles = 3;
afl->cal_cycles_long = 5;
}
if (afl->afl_env.afl_custom_mutator_only) {
/* This ensures we don't proceed to havoc/splice */

View File

@ -56,11 +56,6 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CODE=1
}
# now we want to be sure that afl-fuzz is working
# make sure core_pattern is set to core on linux
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
true
}) ||
# make sure crash reporter is disabled on Mac OS X
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"
@ -176,11 +171,6 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CODE=1
}
# now we want to be sure that afl-fuzz is working
# make sure core_pattern is set to core on linux
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
true
}) ||
# make sure crash reporter is disabled on Mac OS X
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"

View File

@ -52,10 +52,6 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
CODE=1
}
# now we want to be sure that afl-fuzz is working
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
true
}) ||
# make sure crash reporter is disabled on Mac OS X
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"

424
test/test-int_cases.c Normal file
View File

@ -0,0 +1,424 @@
/* test cases for integer comparison transformations
* compile with -DINT_TYPE="signed char"
* or -DINT_TYPE="short"
* or -DINT_TYPE="int"
* or -DINT_TYPE="long"
* or -DINT_TYPE="long long"
*/
#include <assert.h>
int main() {
volatile INT_TYPE a, b;
/* different values */
a = -21;
b = -2; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = 1;
b = 8; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 255) { /* short or bigger */
volatile short a, b;
a = 2;
b = 256+1; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -1 - 256;
b = -8; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 65535) { /* int or bigger */
volatile int a, b;
a = 2;
b = 65536+1; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -1 - 65536;
b = -8; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 4294967295) { /* long or bigger */
volatile long a, b;
a = 2;
b = 4294967296+1; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -1 - 4294967296;
b = -8; /* signs equal */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
}
}
}
a = -1;
b = 1; /* signs differ */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = 0; /* signs differ */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -2;
b = 8; /* signs differ */
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -2; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 8;
b = 1; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 255) {
volatile short a, b;
a = 1 + 256;
b = 3; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -256; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 65535) {
volatile int a, b;
a = 1 + 65536;
b = 3; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -65536; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 4294967295) {
volatile long a, b;
a = 1 + 4294967296;
b = 3; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -4294967296; /* signs equal */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
}
}
}
a = 1;
b = -1; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 0;
b = -1; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 8;
b = -2; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 1;
b = -2; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 255) {
volatile short a, b;
a = 1 + 256;
b = -2; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -2 - 256; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 65535) {
volatile int a, b;
a = 1 + 65536;
b = -2; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -2 - 65536; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((unsigned)(INT_TYPE)(~0) > 4294967295) {
volatile long a, b;
a = 1 + 4294967296;
b = -2; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = -1;
b = -2 - 4294967296; /* signs differ */
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
}
}
}
/* equal values */
a = 0;
b = 0;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -0;
b = 0;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = 1;
b = 1;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = 5;
b = 5;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -1;
b = -1;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -5;
b = -5;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((unsigned)(INT_TYPE)(~0) > 255) {
volatile short a, b;
a = 1 + 256;
b = 1 + 256;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -2 - 256;
b = -2 - 256;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((unsigned)(INT_TYPE)(~0) > 65535) {
volatile int a, b;
a = 1 + 65536;
b = 1 + 65536;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -2 - 65536;
b = -2 - 65536;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((unsigned)(INT_TYPE)(~0) > 4294967295) {
volatile long a, b;
a = 1 + 4294967296;
b = 1 + 4294967296;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = -2 - 4294967296;
b = -2 - 4294967296;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
}
}
}
}

View File

@ -122,10 +122,6 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
CODE=1
}
# now we want to be sure that afl-fuzz is working
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
true
}) ||
# make sure crash reporter is disabled on Mac OS X
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"
@ -190,6 +186,29 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
}
rm -f test-instr.plain
$ECHO "$GREY[*] llvm_mode laf-intel/compcov testing splitting integer types (this might take some time)"
for testcase in ./test-int_cases.c ./test-uint_cases.c; do
for I in char short int long "long long"; do
for BITS in 8 16 32 64; do
bin="$testcase-split-$I-$BITS.compcov"
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
if ! test -e "$bin"; then
cat test.out
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
CODE=1
break
fi
if ! "$bin"; then
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting resulted in miscompilation (type $I split to $BITS)!";
CODE=1
break
fi
rm -f "$bin" test.out || true
done
done
done
rm -f test-int-split*.compcov test.out
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1
test -e test-compcov.compcov && test_compcov_binary_functionality ./test-compcov.compcov && {
grep --binary-files=text -Eq " [ 123][0-9][0-9] location| [3-9][0-9] location" test.out && {

217
test/test-uint_cases.c Normal file
View File

@ -0,0 +1,217 @@
/*
* compile with -DINT_TYPE="char"
* or -DINT_TYPE="short"
* or -DINT_TYPE="int"
* or -DINT_TYPE="long"
* or -DINT_TYPE="long long"
*/
#include <assert.h>
int main() {
volatile unsigned INT_TYPE a, b;
a = 1;
b = 8;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
if ((INT_TYPE)(~0) > 255) {
volatile unsigned short a, b;
a = 256+2;
b = 256+21;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = 21;
b = 256+1;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
if ((INT_TYPE)(~0) > 65535) {
volatile unsigned int a, b;
a = 65536+2;
b = 65536+21;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = 21;
b = 65536+1;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
}
if ((INT_TYPE)(~0) > 4294967295) {
volatile unsigned long a, b;
a = 4294967296+2;
b = 4294967296+21;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
a = 21;
b = 4294967296+1;
assert((a < b));
assert((a <= b));
assert(!(a > b));
assert(!(a >= b));
assert((a != b));
assert(!(a == b));
}
}
a = 8;
b = 1;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((INT_TYPE)(~0) > 255) {
volatile unsigned short a, b;
a = 256+2;
b = 256+1;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 256+2;
b = 6;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((INT_TYPE)(~0) > 65535) {
volatile unsigned int a, b;
a = 65536+2;
b = 65536+1;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 65536+2;
b = 6;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
if ((INT_TYPE)(~0) > 4294967295) {
volatile unsigned long a, b;
a = 4294967296+2;
b = 4294967296+1;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
a = 4294967296+2;
b = 6;
assert((a > b));
assert((a >= b));
assert(!(a < b));
assert(!(a <= b));
assert((a != b));
assert(!(a == b));
}
}
}
a = 0;
b = 0;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
a = 1;
b = 1;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((INT_TYPE)(~0) > 255) {
volatile unsigned short a, b;
a = 256+5;
b = 256+5;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((INT_TYPE)(~0) > 65535) {
volatile unsigned int a, b;
a = 65536+5;
b = 65536+5;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
if ((INT_TYPE)(~0) > 4294967295) {
volatile unsigned long a, b;
a = 4294967296+5;
b = 4294967296+5;
assert(!(a < b));
assert((a <= b));
assert(!(a > b));
assert((a >= b));
assert(!(a != b));
assert((a == b));
}
}
}
}

View File

@ -48,7 +48,7 @@ fn parse_locs(loc_name: &str) -> Result<Vec<u64>, io::Error> {
let contents = &read_file(&format!("../target.offsets.{}", loc_name))?;
//println!("Read: {:?}", contents);
Ok(str_from_u8_unchecked(&contents)
.split("\n")
.split('\n')
.map(|x| {
//println!("Trying to convert {}", &x[2..]);
let result = u64::from_str_radix(&x[2..], 16);
@ -90,7 +90,8 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
let mut unicorn = Unicorn::new(Arch::X86, Mode::MODE_64, 0)?;
let mut uc: UnicornHandle<'_, _> = unicorn.borrow();
let binary = read_file(BINARY).expect(&format!("Could not read modem image: {}", BINARY));
let binary =
read_file(BINARY).unwrap_or_else(|_| panic!("Could not read modem image: {}", BINARY));
let _aligned_binary_size = align(binary.len() as u64);
// Apply constraints to the mutated input
if binary.len() as u64 > CODE_SIZE_MAX {
@ -151,7 +152,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
already_allocated_malloc.set(true);
};
let already_allocated_free = already_allocated.clone();
let already_allocated_free = already_allocated;
// No real free, just set the "used"-flag to false.
let hook_free = move |mut uc: UnicornHandle<'_, _>, addr, size| {
if already_allocated_free.get() {
@ -190,7 +191,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
}
for addr in parse_locs("magicfn").unwrap() {
uc.add_code_hook(addr, addr, Box::new(hook_magicfn.clone()))?;
uc.add_code_hook(addr, addr, Box::new(hook_magicfn))?;
}
let place_input_callback =
@ -225,7 +226,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
match ret {
Ok(_) => {}
Err(e) => panic!(format!("found non-ok unicorn exit: {:?}", e)),
Err(e) => panic!("found non-ok unicorn exit: {:?}", e),
}
Ok(())

View File

@ -204,21 +204,23 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
int main(int argc, char **argv) {
printf(
"============================== INFO ================================\n"
"This binary is built for afl++.\n"
"To use with afl-cmin or afl-cmin.bash pass '-' as single command line "
"option\n"
"To run the target function on individual input(s) execute this:\n"
" %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
"To fuzz with afl-fuzz execute this:\n"
" afl-fuzz [afl-flags] -- %s [-N]\n"
"afl-fuzz will run N iterations before re-spawning the process (default: "
"INT_MAX)\n"
"For stdin input processing, pass '-' as single command line option.\n"
"For file input processing, pass '@@' as single command line option.\n"
"===================================================================\n",
argv[0], argv[0]);
if (argc < 2 || strncmp(argv[1], "-h", 2) == 0)
printf(
"============================== INFO ================================\n"
"This binary is built for afl++.\n"
"To use with afl-cmin or afl-cmin.bash pass '-' as single command line "
"option\n"
"To run the target function on individual input(s) execute this:\n"
" %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
"To fuzz with afl-fuzz execute this:\n"
" afl-fuzz [afl-flags] -- %s [-N]\n"
"afl-fuzz will run N iterations before re-spawning the process "
"(default: "
"INT_MAX)\n"
"For stdin input processing, pass '-' as single command line option.\n"
"For file input processing, pass '@@' as single command line option.\n"
"===================================================================\n",
argv[0], argv[0]);
if (getenv("AFL_GDB")) {