Compare commits

...

204 Commits

Author SHA1 Message Date
5726796936 new 2024-07-21 11:41:19 +02:00
bbcb3dd53e mini performance opt 2024-07-17 13:01:39 +02:00
eac53afe7b fix autodict 2024-07-15 23:42:55 +02:00
55a2362348 code format 2024-07-14 10:33:12 +02:00
8afb60d2f9 Merge pull request #2160 from exoosh/dev
Fixing change from PR#2152, misspelled variable names
2024-07-14 10:21:24 +02:00
69a596c089 ensure this does not happen again 2024-07-14 10:20:53 +02:00
ccb952dde8 Revert "Replace gettimeofday with clock_gettime (#2159)"
This reverts commit 7c380a6612.
2024-07-14 10:18:23 +02:00
7c380a6612 Replace gettimeofday with clock_gettime (#2159) 2024-07-14 00:25:58 +02:00
88e2affe73 Fixing change from PR#2152, misspelled variable names 2024-07-13 21:29:41 +00:00
3f26818d97 Merge pull request #2157 from trail-of-forks/fix-syncid-len
check the sync_id length once
2024-07-12 23:05:30 +02:00
bd83eb0f42 check the sync_id length once 2024-07-12 16:22:17 -04:00
c5acf3f137 Merge pull request #2156 from choller/patch-1
Initialize max_length in afl_fsrv_init #2155
2024-07-12 20:13:14 +02:00
ea42feb06a Initialize max_length in afl_fsrv_init #2155 2024-07-12 20:08:52 +02:00
a09720665d Merge pull request #2154 from hazohelet/fix-missed-alias-table-recreation
Fix missed updates of alias table when INTROSPECTION is on
2024-07-10 16:53:39 +02:00
6f394842be Merge pull request #2152 from exoosh/exocad/stable
Some fixups to the GNUmakefile.llvm
2024-07-10 14:39:31 +02:00
02f4f75526 Fix missed updates of alias table when INTROSPECTION is on
In src/afl-fuzz.c `prev_queued_items` is used to decide whether the alias table should be recreated through the comparison with `afl->queued_items`.
43f462c91b/src/afl-fuzz.c (L3103-L3117)

However, this variable is also updated to `afl->queued_items` when INTROSPECTION is enabled and the `fuzz_one` appends seeds.
43f462c91b/src/afl-fuzz.c (L3135-L3140)

Due to the update of `prev_queued_items` when INTROSPECTION is on, alias table may not be recreated when it actually should be.

This can lead to potential heap buffer-overflow in `select_next_queue_entry` due to the lack of `afl_realloc` called in `create_alias_table`.

This patch fixes this bug by utilizing another variable for the INTROSPECTION part like other variables such as `prev_saved_tmouts`.
2024-07-10 21:39:04 +09:00
43f462c91b Merge pull request #2138 from meowmeowxw/ijon-set
IJON SET
2024-07-10 13:51:08 +02:00
77bad3ad23 ijon set: use __afl_coverage_interesting 2024-07-10 10:16:14 +02:00
835a4b6497 Some fixups to the GNUmakefile.llvm
* rely less on the shell and more on GNU make to parse the versions
* fixed retrieval of minor version (for 18.1.8 it gave 8 instead of 1!)
* auto-detection of llvm-config within the supported version range
* replaced backticks by `$(...)` syntax
* tested against `busybox static-sh`, `bash`, `dash` and `csh`
2024-07-10 07:55:37 +00:00
d1a7b6988c update timeout for custom mutator tests 2024-07-08 09:46:51 +02:00
365129d811 Update sample_all.sh (#2146)
Incorrect shell syntax
2024-07-08 08:34:06 +02:00
b840ac91dc Fixed the syntax errors in unicorn_loader.py within unicorn_mode. (#2144)
Replaced a Chinese comma "," with an English comma "," to ensure the code runs correctly.
2024-07-05 10:43:20 +02:00
dcd2f9ac77 Merge pull request #2143 from r-barnes/patch-1
Make fallthroughs explicit in afl-fuzz-extras.c
2024-07-01 17:12:42 +02:00
37d9afc5cc Make fallthroughs explicit in afl-fuzz-extras.c
Using `__attribute__((fallthrough))` makes fallthroughs explicit in a way the compiler can understand. This allows the enablement of `-Wimplicit-fallthrough`.
2024-07-01 06:59:37 -07:00
62b3a1e800 Merge pull request #2142 from CowBoy4mH3LL/patch-2
Update README.md to reflect latest changes
2024-07-01 11:35:53 +02:00
9c54be6cf1 Update README.md to reflect latest changes
1. fixed hook name length to 16
2. no native debug logging at this time -- will bridge with AFL++ macros latter
2024-07-01 14:54:01 +05:30
53409530b3 Merge pull request #2141 from AFLplusplus/dev
push to stable
2024-07-01 08:57:38 +02:00
43014cd465 changelog 2024-07-01 08:57:26 +02:00
e27e3622d4 Merge pull request #2140 from CowBoy4mH3LL/dev
Adding of QEMU hooking bridge
2024-07-01 08:55:00 +02:00
b169629dbd Fresh commit with all -- post revertion due to unicornafl update 2024-07-01 05:52:06 +00:00
8fbeeb1439 ijon set: discard source code instrumentation 2024-06-30 15:50:37 +02:00
2a489f844b ijon set: remove gdb_history 2024-06-29 23:08:51 +02:00
a161aac7c1 ijon set: init 2024-06-29 22:05:22 +02:00
a7f928ac31 update qemuafl 2024-06-29 16:45:01 +02:00
50ae95cee4 add AFL_OLD_FORKSERVER feature 2024-06-29 16:31:08 +02:00
f6bfa96a96 todo 2024-06-29 03:32:37 +02:00
e86dcc9f18 update qemu mode 2024-06-29 02:15:35 +02:00
9d33580aac code format 2024-06-28 16:46:42 +02:00
77cfd504cf update grammar mutator 2024-06-28 16:33:48 +02:00
f7bbd467b5 add custom_send_tcp 2024-06-28 16:00:19 +02:00
8993ba4305 add ruby dict 2024-06-27 19:42:58 +02:00
ba7313b521 AFL_CUSTOM_MUTATOR_LATE_SEND added 2024-06-27 18:51:58 +02:00
e2d30641be Merge pull request #2136 from jakelamberson/enhance-nyx-instructions
Enhance Nyx mode instructions
2024-06-27 03:26:56 +02:00
2248773566 Add nyx_mode to contribution instructions 2024-06-26 20:21:05 -04:00
5f43d0ad42 Fix and enhance Nyx mode instructions 2024-06-26 20:21:05 -04:00
af47531745 improved seed selection algorithm 2024-06-26 01:12:10 +02:00
e80bd2d30c Merge pull request #2133 from visitorckw/optimize-bit-counting
Optimize bit counting using __builtin_popcount
2024-06-24 01:37:09 +02:00
ac5815d994 Optimize bit counting using __builtin_popcount
Use the __builtin_popcount intrinsic to optimize the bit counting
function if the compiler supports it. This change replaces the manual
bit counting algorithm with the more efficient built-in function, which
leverages hardware support on compatible processors.

This modification ensures that the code remains backward-compatible by
falling back to the original implementation when __builtin_popcount is
not available.
2024-06-24 06:52:07 +08:00
540d741df0 nits atnwalk 2024-06-22 22:22:01 +02:00
ecb5854be0 add zlib compression for fast resume 2024-06-21 14:40:23 +02:00
25b650f59d Merge pull request #2132 from tylzh97/stable
Fix typo in unicorn_mode
2024-06-21 09:22:38 +02:00
ed6f19d3d8 Fix typo in unicorn_mode
in `unicorn_mode/samples`, python example floder's name is `python_simple`, there is a typo in README file.
2024-06-21 09:52:28 +08:00
aecd157244 nit 2024-06-20 18:49:40 +02:00
43a98b0ec2 todos 2024-06-20 18:49:40 +02:00
3b00cee858 Merge pull request #2130 from killerra/dev
Auto disable memory limits for FASAN
2024-06-20 08:47:20 +02:00
2fbc0aefb1 Auto disable memory limits for FASAN 2024-06-20 00:10:40 +02:00
2276a2f5c3 Merge pull request #2129 from choller/persist-code-cov
Collect persistent coverage data and dump it at the end of the run
2024-06-19 14:09:06 +02:00
8fcca6fb41 Collect persistent coverage data and dump it at the end of the run
With CODE_COVERAGE builds, we need to collect the coverage data of each
iteration in a persistant buffer that has the same size as the regular
trace buffer used for fuzzing. We dump this information at the end of
the run and when combined with pointer data and module info, this can be
used to calculate code coverage.
2024-06-19 12:36:58 +02:00
b8568034f0 code format and changelog 2024-06-18 15:42:34 +02:00
3ebf41ba34 Merge pull request #2128 from AFLplusplus/fastrestart
Fastrestart
2024-06-18 15:28:56 +02:00
304e84502d fast resume option 2024-06-18 15:24:38 +02:00
a6e42d98d9 llvm 19 fixes 2024-06-18 15:09:11 +02:00
de176a10bc nit 2024-06-17 09:31:42 +02:00
e3183f7cda Merge pull request #2125 from visitorckw/fix-libradamsa-signed-integer-overflow
Fix signed integer overflow in radamsa
2024-06-14 08:14:03 +02:00
b5e0fff6b9 Fix signed integer overflow in radamsa
When UBSan was enabled and 'make test' was executed, the following
runtime error was observed:

libradamsa.c:26055:29: runtime error: left shift of 16777215 by 8 places cannot be represented in type 'int'

This issue was caused by a left shift operation on a signed integer.
The fix involved changing the integer literal to an unsigned integer by
adding a 'U' suffix, ensuring the left shift operation produces the
correct value without overflow.

Fixes: 8178f4df ("remove radamsa, add radamsa custom mutator")
2024-06-14 09:53:57 +08:00
36db3428ab Merge pull request #2123 from AFLplusplus/dev
push to stable
2024-06-13 09:20:42 +02:00
e7da8b9d6b Revert "MONOTONIC"
This reverts commit 0c9b460cc4.
2024-06-13 09:19:11 +02:00
c134df30db Merge pull request #2121 from visitorckw/remove-Wno-shift-count-overflow
Remove -Wno-shift-count-overflow flag and hashmap from compilation
2024-06-13 07:57:06 +02:00
b5e6c2d6e2 Remove -Wno-shift-count-overflow flag and hashmap from compilation
After commit 0c9d8e59 ("Fix undefined behavior by casting to uint64_t
before left shift"), the -Wno-shift-count-overflow flag is no longer
necessary to suppress compilation warnings. This commit removes the
flag, allowing the compiler to provide appropriate warnings for any
potential future cases of shifting too many bits.

Additionally, after commit eaf4a299 ("make redqueen hashmap not
default"), the hashmap is no longer in use. Therefore, this commit also
removes the hashmap from the GNUmakefile.
2024-06-13 09:34:03 +08:00
b6f8509234 Merge pull request #2122 from visitorckw/fix-realloc-check
Fix memory allocation check in aflpp custom mutators
2024-06-12 19:27:13 +02:00
d45cd63583 Fix memory allocation check in aflpp custom mutators
The memory allocation check in afl_custom_fuzz function was incorrect.
The condition was erroneously checking if ptr was non-null, whereas it
should return 0 when ptr is null. Correct the condition to properly
handle memory allocation failures.

Fixes: 32ffa266 ("max_len support")
2024-06-13 00:42:12 +08:00
0c9b460cc4 MONOTONIC 2024-06-12 09:17:07 +02:00
dd762726dc fastresume implementation 2024-06-12 09:10:35 +02:00
e68d57feec Merge pull request #2120 from visitorckw/fix-shift-too-many-bits
Fix undefined behavior by casting to uint64_t before left shift
2024-06-12 08:23:14 +02:00
0c9d8e5929 Fix undefined behavior by casting to uint64_t before left shift
According to the C standard, left-shifting a value by an amount greater
than or equal to the width of its promoted type results in undefined
behavior. To prevent potential unexpected results, explicitly cast the
uint8_t variable type to uint64_t before performing the left shift
operation by 56 bits. This ensures the operation is well-defined and
adheres to the standard.

Fixes: 40df85d1 ("adjust cmplog header")
2024-06-12 12:48:13 +08:00
75c3fa91dc update changelog 2024-06-10 22:25:38 +02:00
a37c7e1246 Merge pull request #2119 from WorksButNotTested/frida-persistent
Frida persistent
2024-06-10 22:24:25 +02:00
392dcd57c6 Fixes to build on arm32 2024-06-10 18:16:30 +01:00
1369cf7176 Fixes for arm/arm64 2024-06-10 18:16:30 +01:00
eccd0985a0 Fixes for x86 2024-06-10 18:16:30 +01:00
0617b8898a Update comment 2024-06-10 18:16:30 +01:00
fbcdeb8439 Improve persistent mode 2024-06-10 18:16:30 +01:00
6ed0a2b4aa fast resume setup detection 2024-06-10 18:22:06 +02:00
8e50c0c103 frida verbose 2024-06-10 09:08:44 +02:00
f2cd5e1d8e v4.22a init 2024-06-09 19:15:12 +02:00
9f6b012fbf Merge pull request #2117 from AFLplusplus/dev
push to stable
2024-06-09 19:09:17 +02:00
ec0b83f127 4.21c 2024-06-09 18:39:56 +02:00
0c81982e67 nit 2024-06-09 18:32:36 +02:00
5014b86c3c fix AFL_FRIDA_DEBUG_MAPS 2024-06-09 15:44:10 +02:00
44b5e1f488 fix no_forkserver mode 2024-06-09 12:26:48 +02:00
31652eeb2a nit 2024-06-09 12:19:58 +02:00
4bb4d4ad00 fix -n 2024-06-09 12:16:32 +02:00
5331eca5d9 allow multiple -m 2024-06-09 12:02:59 +02:00
74e264a20a move function 2024-06-07 13:46:15 +02:00
f0937f96d4 target hash 2024-06-07 11:48:58 +02:00
92cbdb9f45 update unicorn 2024-06-07 11:41:35 +02:00
fe36ceaa55 minor testcache optimizations 2024-06-07 11:16:42 +02:00
0618bfd4ae fix 2024-06-07 09:58:27 +02:00
bdfd38771a add cmplog_time measurement 2024-06-07 09:47:29 +02:00
477063e9ee memory adjustments 2024-06-06 17:52:21 +02:00
e46c106b89 new seed selection algorithm 2024-06-06 10:25:23 +02:00
69630338ff Merge pull request #2114 from WorksButNotTested/frida-rlimit
Fix issue for setrlimit
2024-06-05 20:21:51 +02:00
112759cd39 Merge pull request #2113 from AFLplusplus/fix_mmap_cmplog
Fix cmplog shared memory size when USEMMAP=1
2024-06-05 20:19:38 +02:00
f8767c397b Fix issue for setrlimit 2024-06-05 18:43:20 +01:00
e8d098335b Fix cmplog shared memory size when USEMMAP=1 2024-06-05 19:33:02 +02:00
12a87cfacb nits 2024-06-05 10:40:12 +02:00
2806d6be2f optimize syncing 2024-06-05 09:20:30 +02:00
2d9b793dbb AFL_NO_SYNC 2024-06-04 14:48:02 +02:00
7f02f0da61 Merge pull request #2106 from a-shvedov/stable
feature: Added (generate_libtoken_dict.sh) script for simplified work with `libtokencap`
2024-06-04 11:29:27 +02:00
bc2ccf464f Update README.md 2024-06-03 19:14:04 +03:00
b8536ced09 Update generate_libtoken_dict.sh 2024-06-03 19:01:50 +03:00
1db82f3303 update grammar mutator 2024-06-03 09:23:43 +02:00
fd713413e8 Merge pull request #2109 from AFLplusplus/dev
fix afl-showmap
2024-06-01 16:56:35 +02:00
2d4a4ba73f fix afl-showmap 2024-06-01 16:55:56 +02:00
348f980f21 Merge pull request #2108 from AFLplusplus/dev
push to stable
2024-06-01 16:37:28 +02:00
ca55858aa7 Merge pull request #2107 from AFLplusplus/reg
fix regression
2024-06-01 16:34:50 +02:00
e639521b01 changelog 2024-06-01 16:34:23 +02:00
894339c5d7 try regression fix 2024-06-01 12:26:26 +02:00
e13dc9b7e6 todo 2024-06-01 12:17:53 +02:00
5fb657f569 Rename make_dict_v2.sh to generate_libtoken_dict.sh 2024-06-01 13:03:55 +03:00
d2700c7525 Update README.md 2024-06-01 13:03:22 +03:00
4cf358b589 Update README.md 2024-06-01 02:06:20 +03:00
5e708b23c6 Update make_dict_v2.sh
(-) removed default vars ;
(+) added LD_PRELOAD_PATH check
2024-06-01 01:18:03 +03:00
9419e39fdf nits 2024-05-31 18:32:31 +02:00
c202d80dea Update make_dict_v2.sh 2024-05-30 22:38:37 +03:00
eecbdd99e1 Update and rename make_dict.sh to make_dict_v2.sh 2024-05-30 22:26:24 +03:00
64293cdc82 Create make_dict.sh 2024-05-30 11:13:56 +03:00
f8a5f1cd9e Merge branch 'AFLplusplus:stable' into stable 2024-05-30 10:43:01 +03:00
a3125c38f4 fix afl-showmap shmmemleak 2024-05-29 12:55:28 +02:00
224add0222 update unicorn 2024-05-28 11:12:33 +02:00
19636f748c Unicornafl: Fix incorrect comment (#2103) 2024-05-28 02:24:43 +02:00
7aa5e1c443 Merge pull request #2104 from Evian-Zhang/fix-unicorn-lldb-dumper
Make lldb dumper of unicorn_mode work in modern LLDB
2024-05-27 21:18:28 +02:00
93279db71b Make lldb dumper of unicorn_mode work in modern LLDB 2024-05-27 19:15:35 +08:00
5bf760510e Merge pull request #2102 from ndrewh/testcache-fix
fix: testcache hangs for large test cases
2024-05-26 08:12:29 +02:00
03dc80afc4 fix: testcache hangs for large test cases 2024-05-25 23:44:57 +00:00
fda3106fd9 Merge pull request #2099 from Atlante45/dev
Fix dynamic_lookup linker flag for Apple clang
2024-05-24 01:33:55 +02:00
9721a77204 Fix dynamic_lookup linker flag for Apple clang 2024-05-23 11:14:53 -07:00
92a8c2804f fix the fix for symcc 2024-05-21 16:31:42 +02:00
e1521fa8eb fix symcc custom mutator 2024-05-21 11:04:25 +02:00
4e3cd8ac3f nit 2024-05-20 14:02:22 +02:00
31a8beb449 support new llvm 19 changes 2024-05-19 13:47:53 +02:00
e7d871c8bf Merge pull request #2093 from AFLplusplus/dev
push to stable
2024-05-17 23:55:55 +02:00
56d5aa3101 log 2024-05-17 23:55:43 +02:00
c6a2a4046e Merge pull request #2092 from fbeqv/dev
Fix runtime underflow & -V exiting before syncing
2024-05-17 23:41:39 +02:00
6dd5e931fc Fix runtime underflow & -V exiting before syncing
print_stats sets exit_soon even while syncing, this leaves -V 0 still broken, as we don't finish syncing.

Additionally, the change that introduced the previous -V fix also broke the runtime tracking, as runtime needs to include all time including sync, splice etc. This caused an underflow in the reported runtime.
2024-05-17 14:33:32 -07:00
635140ba43 help qemu build for some linux platforms 2024-05-17 09:45:56 +02:00
497f341eac Revert "no weights"
This reverts commit 068aa13c6b.
2024-05-16 14:27:33 +02:00
068aa13c6b no weights 2024-05-16 14:27:04 +02:00
ba7ae6c59d nits 2024-05-16 14:21:00 +02:00
6ae95271be nits 2024-05-16 09:17:59 +02:00
a2e0163cc1 Merge pull request #2091 from bet4it/collect_coverage
Fix bug of `afl-showmap` in `collect_coverage` mode
2024-05-16 09:14:15 +02:00
1db3b81d2e dump cc 2024-05-15 14:16:44 +02:00
0a16ea7487 better cmplog ci test for low memory machines 2024-05-15 10:57:46 +02:00
a26bb0b0f2 Merge pull request #2090 from AFLplusplus/dev
push to stable
2024-05-14 13:18:22 +02:00
7d3530a22e nit 2024-05-14 13:07:47 +02:00
a87ea96913 make slow systems pass our test suite 2024-05-14 12:58:45 +02:00
81609a0f42 Merge pull request #2089 from nj00001/dev
Fix afl-fuzz -G option not configuring maximum input data size for nyx
2024-05-14 12:48:16 +02:00
938edab25f consider llvm 18 stable 2024-05-14 12:45:09 +02:00
29c9870658 disable xml/curl/g_ string transform compare 2024-05-14 12:35:32 +02:00
b6c4f3775a disable xml/curl/g_ string transform compare 2024-05-14 12:34:51 +02:00
5ee5564ae2 backup afl->max_length to afl->fsrv.max_length 2024-05-14 18:28:18 +08:00
ab36756061 change MAX_FILE to fsrv->max_length 2024-05-14 18:27:12 +08:00
831b8f35d5 Keep a backup of max_length in the afl_forkserver_t structure 2024-05-14 18:23:53 +08:00
0cf78b7748 Fix bug of afl-showmap in collect_coverage mode 2024-05-14 17:17:58 +08:00
0892a2245e float laf check 2024-05-13 20:28:50 +02:00
622474e9e4 disable -> no variants 2024-05-13 19:51:38 +02:00
0cabc12f91 Merge pull request #2086 from smoelius/dev
Add `AFL_SHA1_FILENAMES` option
2024-05-13 19:32:44 +02:00
b282ce999d post_process after trim 2024-05-13 13:42:58 +02:00
24b9d74e70 compcov int fix 2024-05-13 08:44:43 +02:00
c03f2897d0 Add AFL_SHA1_FILENAMES option 2024-05-12 05:44:14 -04:00
90fbf59bf1 Merge pull request #2084 from AFLplusplus/dev
push to stable
2024-05-11 09:16:21 +02:00
93c7cbd496 update unicorn 2024-05-11 09:01:33 +02:00
db60555c1b update changelog 2024-05-11 08:59:01 +02:00
45117a3384 Merge pull request #2083 from elboulangero/i386
Re-enable i386
2024-05-11 08:55:59 +02:00
4d4880b428 afl-cc: Re-enable i386
Was disabled in 136febaf68

Closes: #2081
2024-05-11 00:48:04 +07:00
ac6ccd53df stat update during syncing 2024-05-07 16:46:24 +02:00
4ec376bd6a Merge pull request #2076 from louismerlin/fix-whatsup-time
Fix `afl_whatsup` findings timer
2024-05-02 17:30:59 +02:00
3c0448305b Guard /proc/uptime cat with a uname check 2024-05-02 17:19:37 +02:00
a6029a10cc Fix CUR_TIME computation 2024-05-02 16:12:50 +02:00
26eaf53a83 AFL_DISABLE_REDUNDANT 2024-05-02 08:35:24 +02:00
5d623a27ed try enhanced asan support 2024-04-30 11:59:49 +02:00
69e554b941 Merge pull request #2074 from Kiprey/patch-2
Fix wrong warning in SanitizerCoverageLTO.so.cc
2024-04-29 17:11:41 +02:00
7340374a7c Fix wrong warning in SanitizerCoverageLTO.so.cc 2024-04-29 16:14:49 +08:00
67d356b73f update qemuafl 2024-04-28 15:41:24 +02:00
da18f1f722 Merge pull request #2073 from Acture/dev
Fix: Removed the redundant `id` field from redqueen.c
2024-04-28 15:39:32 +02:00
58abcceff5 Bug fix: Removed the redundant id field from the debug output in the afl-fuzz-redqueen.c file since cmp_header no longer have this field. 2024-04-28 16:24:52 +08:00
ad0d0c77fb Merge pull request #2071 from AFLplusplus/dev
Push to stable
2024-04-26 16:17:41 +02:00
2c3f761ede changes 2024-04-26 16:16:21 +02:00
70c60cfba7 work with spaces in filenames 2024-04-26 16:14:50 +02:00
f3b6d64ad3 Merge pull request #2066 from ahuo1/dev
fix: initialize n_fuzz_entry in perform_dry_run.
2024-04-26 09:44:49 +02:00
43e9a13921 add schedule check. 2024-04-26 07:45:58 +08:00
526dbe8f16 fix: initialize n_fuzz_entry in perform_dry_run. 2024-04-25 21:28:58 +08:00
951a0e5225 fix AFL_PERSISTENT_RECORD 2024-04-25 10:04:58 +02:00
458b939bc4 LTO fix 2024-04-19 17:34:50 +02:00
476aca5b67 nits 2024-04-19 15:45:00 +02:00
96bf0f8323 Merge pull request #2061 from jschwartzentruber/change_smm_vis
Specify shared memory visibility
2024-04-18 17:30:51 +02:00
58206a3180 Set explicit visibility on shared memory variables. 2024-04-17 14:40:41 -04:00
f138ab8ac6 Merge pull request #2059 from elboulangero/afl-gcc
Fix afl-gcc
2024-04-17 12:55:34 +02:00
50839cf6e9 afl-cc: Complete fix for afl-as
Look for afl-as, and then make sure that there's a 'as' binary in the
same directory, that seems to be either a symlink to, or a copy of,
afl-as.
2024-04-17 16:41:03 +07:00
626a4434ed afl-cc: Use afl-as (rather than as) to find obj path 2024-04-17 16:40:58 +07:00
d84cc73d13 afl-cc: Add missing debug statement
For each path that is tried, there's a debug log printed, _except_ for
this one. Fix it.
2024-04-17 16:40:55 +07:00
6b049536f1 v4.21 init 2024-04-13 11:54:08 +02:00
629edb1e78 Merge pull request #2 from AFLplusplus/stable
push to stable (#1734)
2023-05-22 16:57:45 +03:00
8012b555a8 Merge pull request #1 from AFLplusplus/stable
sync
2023-05-05 23:27:13 +03:00
132 changed files with 8824 additions and 1285 deletions

View File

@ -5,7 +5,6 @@ on:
branches:
- stable
- dev
- 420
pull_request:
branches:
- dev # No need for stable-pull-request, as that equals dev-push

View File

@ -34,6 +34,7 @@ file in one the following folders:
* [docs/](docs/) (this is where you can find most of our docs content)
* [frida_mode/](frida_mode/)
* [instrumentation/](instrumentation/)
* [nyx_mode/](nyx_mode/)
* [qemu_mode/](qemu_mode/)
* [unicorn_mode/](unicorn_mode/)

View File

@ -441,6 +441,14 @@ test_shm:
@echo "[-] shmat seems not to be working, switching to mmap implementation"
endif
ifeq "$(shell echo '$(HASH)include <zlib.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
override SPECIAL_PERFORMANCE += -DHAVE_ZLIB
override LDFLAGS += -lz
$(info [+] ZLIB detected)
else
$(info [!] Warning: no ZLIB detected)
endif
.PHONY: test_python
ifeq "$(PYTHON_OK)" "1"
test_python:
@ -471,8 +479,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)

View File

@ -32,6 +32,9 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2
SYS = $(shell uname -s)
override LLVM_TOO_NEW_DEFAULT := 18
override LLVM_TOO_OLD_DEFAULT := 13
ifeq "$(SYS)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
@ -39,24 +42,30 @@ ifeq "$(SYS)" "OpenBSD"
$(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
endif
else
LLVM_CONFIG ?= llvm-config
# Small function to use Bash to detect the latest available clang and clang++ binaries, if using them by that name fails
override _CLANG_VERSIONS_TO_TEST := $(patsubst %,-%,$(shell seq $(LLVM_TOO_NEW_DEFAULT) -1 $(LLVM_TOO_OLD_DEFAULT)))
detect_newest=$(shell for v in "" $(_CLANG_VERSIONS_TO_TEST); do test -n "$$(command -v -- $1$$v)" && { echo "$1$$v"; break; }; done)
LLVM_CONFIG ?= $(call detect_newest,llvm-config)
endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 )
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
LLVM_STDCXX = gnu++11
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
LLVM_LTO = 0
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
LLVM_STDCXX := gnu++11
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
LLVM_LTO := 0
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-8]\.' && echo 1 || echo 0)
# Uncomment to see the values assigned above
# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
ifeq "$(LLVMVER)" ""
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
@ -245,7 +254,7 @@ endif
AFL_CLANG_FUSELD=
ifeq "$(LLVM_LTO)" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=$$(command -v ld) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_FUSELD=1
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_LDPATH=1
@ -300,8 +309,8 @@ endif
ifneq "$(LLVM_CONFIG)" ""
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
endif
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS)
# wasm fuzzing: disable thread-local storage and unset LLVM debug flag
ifdef WAFL_MODE
@ -319,7 +328,7 @@ else
endif
ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline
# Needed for unwind symbols
@ -417,7 +426,7 @@ endif
endif
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_MIN_4_0_1)" "0"

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.20c
GitHub version: 4.22a
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -2,6 +2,8 @@
## Must
- ijon support?
- check for null ptr for xml/curl/g_ string transform functions
- hardened_usercopy=0 page_alloc.shuffle=0
- add value_profile but only enable after 15 minutes without finds
- cmplog max items env?
@ -16,6 +18,7 @@
## Should
- afl-crash-analysis
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
- support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
- afl-plot to support multiple plot_data

View File

@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
# awk script to minimize a test corpus of input files
#
# based on afl-cmin bash script written by Michal Zalewski
# rewritten by Heiko Eißfeldt (hexcoder-)
# rewritten by Heiko Eissfeldt (hexcoder-)
# tested with:
# gnu awk (x86 Linux)
# bsd awk (x86 *BSD)
@ -603,8 +603,8 @@ BEGIN {
# create path for the trace file from afl-showmap
tracefile_path = trace_dir"/"fn
# ensure the file size is not zero
cmd = "du -b "tracefile_path
"ls -l "tracefile_path
cmd = "du -b \""tracefile_path"\""
# "ls -l \""tracefile_path"\""
cmd | getline output
close(cmd)
split(output, result, "\t")

View File

@ -152,6 +152,7 @@ Minimization settings:
-e - solve for edge coverage only, ignore hit counts
For additional tips, please consult README.md.
This script cannot read filenames that end with a space ' '.
Environment variables used:
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory

View File

@ -111,7 +111,13 @@ if [ -z "$NO_COLOR" ]; then
RESET="$NC"
fi
CUR_TIME=`date +%s`
PLATFORM=`uname -s`
if [ "$PLATFORM" = "Linux" ] ; then
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
else
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
CUR_TIME=`date +%s`
fi
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
trap "rm -f $TMP" 1 2 3 13 15

View File

@ -48,7 +48,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 *ptr = realloc(data->buf, max_size);
if (ptr) {
if (!ptr) {
return 0;

View File

@ -53,7 +53,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 *ptr = realloc(data->buf, max_size);
if (ptr) {
if (!ptr) {
return 0;

View File

@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`.
**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
```bash
# create the required a random seed first
# create the required random seed first
mkdir -p ~/campaign/example/seeds
cd ~/campaign/example/seeds
head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded

View File

@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
if (fd_socket != -1) { close(fd_socket); }
*out_buf = NULL;
return 0;
fprintf(stderr, "atnwalk.socket not found in current directory!\n");
exit(-1);
}

View File

@ -0,0 +1,7 @@
all: custom_send_tcp.so
custom_send_tcp.so:
$(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c
clean:
rm -f custom_send_tcp.so *.o *~ core

View File

@ -0,0 +1,13 @@
# Send testcases via TCP custom mutator
This custom mutator sends the fuzzing testcases via TCP.
`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set!
`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense)
`CUSTOM_SEND_PORT` - the TCP port to send to
`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target
Example:
```
CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ...
```

View File

@ -0,0 +1,113 @@
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include "afl-fuzz.h"
static int my_debug = 0;
static int my_read = 0;
#define DEBUG(...) if (my_debug) printf(__VA_ARGS__)
typedef struct tcp_send_mutator {
afl_state_t* afl;
struct sockaddr_in server_addr;
} tcp_send_mutator_t;
void *afl_custom_init(afl_state_t* afl, uint32_t seed) {
const char* ip = getenv("CUSTOM_SEND_IP");
const char* port = getenv("CUSTOM_SEND_PORT");
if (getenv("AFL_DEBUG")) my_debug = 1;
if (getenv("CUSTOM_SEND_READ")) my_read = 1;
if (!ip || !port) {
fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n");
exit(1);
}
tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t));
if (!mutator) {
fprintf(stderr, "Failed to allocate mutator struct\n");
exit(1);
}
mutator->afl = afl;
bzero(&mutator->server_addr, sizeof(mutator->server_addr));
mutator->server_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) {
fprintf(stderr, "Could not convert target ip address!\n");
exit(1);
}
mutator->server_addr.sin_port = htons(atoi(port));
printf("[+] Custom tcp send mutator setup ready to go!\n");
return mutator;
}
int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) {
while (max_attempts > 0) {
if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) {
return 0;
}
// Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the
// application under test having started to listen for connections and
// afl_custom_fuzz_send being called. To address this race, we attempt
// to connect N times and sleep a short period of time in between
// connection attempts.
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = 100;
nanosleep(&t, NULL);
--max_attempts;
}
return 1;
}
void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
int written = 0;
if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) {
DEBUG("connected, write()\n");
written = write(sock, buf, buf_size);
} else {
DEBUG("socket() or connect() error: %d\n", errno);
}
if (written < 0) {
DEBUG("write() error: %d\n", errno);
} else if (my_read) {
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int select_res = select(sock + 1, &set, NULL, NULL, &timeout);
if (select_res == -1) {
DEBUG("select() error: %d\n", errno);
} else if (select_res == 0) {
DEBUG("read() timeout!\n");
} else {
uint8_t buf[64];
(void)read(sock, buf, sizeof(buf));
}
}
close(sock);
}
void afl_custom_deinit(tcp_send_mutator_t* mutator) {
free(mutator);
}

View File

@ -1 +1 @@
5ed4f8d
05d8f53

View File

@ -3707,7 +3707,7 @@ typedef intptr_t wdiff;
1024 * 1024 * 8 /* static malloc'd heap size if used as a library */
#define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */
#define FMAX \
((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
*/
#define MAXOBJ 0xffff /* max words in tuple including header */
#define MAXPAYL \

View File

@ -22,10 +22,10 @@ afl_state_t *afl_struct;
typedef struct my_mutator {
afl_state_t *afl;
u8 * mutator_buf;
u8 * out_dir;
u8 * tmp_dir;
u8 * target;
u8 *mutator_buf;
u8 *out_dir;
u8 *tmp_dir;
u8 *target;
uint32_t seed;
} my_mutator_t;
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
/* When a new queue entry is added we run this input with the symcc
instrumented binary */
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
const uint8_t *filename_new_queue,
const uint8_t *filename_orig_queue) {
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
struct dirent **nl;
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
u8 * origin_name = basename(filename_new_queue);
u8 *origin_name = basename(filename_new_queue);
int32_t i;
if (items > 0) {
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
DBG("test=%s\n", fn);
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
u8 *destination_name =
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
origin_name, nl[i]->d_name);
rename(source_name, destination_name);
ck_free(destination_name);
DBG("found=%s\n", source_name);
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
for (i = 0; i < (u32)items; ++i) {
struct stat st;
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
DBG("test=%s\n", fn);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
if (items <= 0) return 0;
for (i = 0; i < (u32)items; ++i) {
for (i = 0; i < (s32)items; ++i) {
struct stat st;
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (!done) {
if (done == 0) {
struct stat st;
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
}
unlink(fn);
ck_free(fn);
}
ck_free(fn);
free(nl[i]);
}

5713
dictionaries/ruby.dict Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,71 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.22a (dev)
- afl-fuzz:
- fastresume feature added. if you abort fuzzing and resume fuzzing
with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed
then a dump will be loaded and the calibration phase skipped.
to disable this feature set `AFL_NO_FASTRESUME=1`
zlib compression is used if zlib is found at compile time
- improved seed selection algorithm
- added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send()
function after the target has been restarted.
- frida_mode:
- AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just
a function entry
- AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE
- AFL_FRIDA_DEBUG_MAPS now works as expected
- qemu_mode:
- new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to
@CowBoy4mH3LL
- custom mutators:
- custom_send_tcp custom mutator added, thanks to @dergoegge
- afl-cc
- new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla
AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with
AFL_LLVM_INSTRUMENT=CLASSIC
### Version ++4.21c (release)
* afl-fuzz
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
do a switch from gettimeofday() to clock_gettime() which should be rather
three times faster. The reason for this is unknown.
- new queue selection algorithm based on 2 core years of queue data
analysis. gives a noticable improvement on coverage although the results
seem counterintuitive :-)
- added AFL_DISABLE_REDUNDANT for huge queues
- added `AFL_NO_SYNC` environment variable that does what you think it does
- fix AFL_PERSISTENT_RECORD
- run custom_post_process after standard trimming
- prevent filenames in the queue that have spaces
- minor fix for FAST schedules
- more frequent stats update when syncing (todo: check performance impact)
- now timing of calibration, trimming and syncing is measured seperately,
thanks to @eqv!
- -V timing is now accurately the fuzz time (without syncing), before
long calibration times and syncing could result in now fuzzing being
made when the time was already run out until then, thanks to @eqv!
- fix -n uninstrumented mode when ending fuzzing
- enhanced the ASAN configuration
- make afl-fuzz use less memory with cmplog and fix a memleak
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode for i386
- fix COMPCOV split compare for old LLVMs
- disable xml/curl/g_ string transform functions because we do not check
for null pointers ... TODO
- ensure shared memory variables are visible in weird build setups
- compatability to new LLVM 19 changes
* afl-cmin
- work with input files that have a space
* afl-showmap
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
- minor fix to collect coverage -C (thanks to @bet4it)
* Fixed a shmem mmap bug (that rarely came up on MacOS)
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built
@ -36,12 +101,13 @@
- afl-whatsup:
- now also displays current average speed
- small bugfixes
- Fixes for aflpp custom mutator and standalone tool
- custom mutators:
- fixes for aflpp custom mutator and standalone tool
- important fix to the symcc custom mutator
- Minor edits to afl-persistent-config
- Prevent temporary files being left behind on aborted afl-whatsup
- More CPU benchmarks added to benchmark/
### Version ++4.10c (release)
- afl-fuzz:
- default power schedule is now EXPLORE, due a fix in fast schedules

View File

@ -198,6 +198,11 @@ def deinit(): # optional for Python
This method can be used if you want to send data to the target yourself,
e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
that you start the target with afl-fuzz.
Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
function after the target has been restarted. (This is needed for e.g. TCP
services.)
Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
- `queue_new_entry` (optional):
@ -266,6 +271,11 @@ trimmed input. Here's a quick API description:
Omitting any of three trimming methods will cause the trimming to be disabled
and trigger a fallback to the built-in default trimming routine.
**IMPORTANT** If you have a custom post process mutator that needs to be run
after trimming, you must call it yourself at the end of your successful
trimming!
### Environment Variables
Optionally, the following environment variables are supported:

View File

@ -331,7 +331,26 @@ mode.
the target performs only a few loops, then this will give a small
performance boost.
## 4) Settings for afl-fuzz
## 4) Runtime settings
The following environment variables are for a compiled AFL++ target.
- Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will
dump the map size of the target and exit.
- Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver.
This makes only sense when you
a) compile in a classic colliding coverage mode (e.g.
AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is
below MAP_SIZE (65536 by default), AND
b) you want to use this compiled AFL++ target with a different tool
that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc.
You would use this option together with the target fuzzing application.
- Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting
instrumentation. (More of an internal option.)
## 5) Settings for afl-fuzz
The main fuzzer binary accepts several options that disable a couple of sanity
checks or alter some of the more exotic semantics of the tool:
@ -368,6 +387,10 @@ checks or alter some of the more exotic semantics of the tool:
XML or other highly flexible structured input. For details, see
[custom_mutators.md](custom_mutators.md).
- Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
function after the target has been restarted. (This is needed for e.g. TCP
services.)
- Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time
a cycle is finished.
@ -381,6 +404,9 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
usually a bad idea!
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
This can be useful with huge queues.
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
new coverage
@ -511,6 +537,8 @@ checks or alter some of the more exotic semantics of the tool:
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
the snapshot lkm is loaded.
- `AFL_NO_FASTRESUME` will not try to read or write a fast resume file.
- Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints
some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe.
@ -547,6 +575,9 @@ checks or alter some of the more exotic semantics of the tool:
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
arguments.
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
of their contents, rather than use the standard `id:000000,...` names.
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
by some users for unorthodox parallelized fuzzing setups, but not advisable
otherwise.
@ -582,6 +613,9 @@ checks or alter some of the more exotic semantics of the tool:
between fuzzing instances synchronization. Default sync time is 30 minutes,
note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
other syncing parameters.
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
@ -627,7 +661,7 @@ checks or alter some of the more exotic semantics of the tool:
Note that will not be exact and with slow targets it can take seconds
until there is a slice for the time test.
## 5) Settings for afl-qemu-trace
## 6) Settings for afl-qemu-trace
The QEMU wrapper used to instrument binary-only code supports several settings:
@ -699,7 +733,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when
counting crashes based on a file count in that directory.
## 7) Settings for afl-frida-trace
## 8) Settings for afl-frida-trace
The FRIDA wrapper used to instrument binary-only code supports many of the same
options as `afl-qemu-trace`, but also has a number of additional advanced
@ -789,7 +823,7 @@ support.
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
killing the process whilst it is being dumped.
## 8) Settings for afl-cmin
## 9) Settings for afl-cmin
The corpus minimization script offers very little customization:
@ -807,7 +841,7 @@ The corpus minimization script offers very little customization:
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed.
This can help when embedding `afl-cmin` or `afl-showmap` in other scripts.
## 9) Settings for afl-tmin
## 10) Settings for afl-tmin
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be
searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a
@ -818,12 +852,12 @@ to match when minimizing crashes. This will make minimization less useful, but
may prevent the tool from "jumping" from one crashing condition to another in
very buggy software. You probably want to combine it with the `-e` flag.
## 10) Settings for afl-analyze
## 11) Settings for afl-analyze
You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
of decimal.
## 11) Settings for libdislocator
## 12) Settings for libdislocator
The library honors these environment variables:
@ -845,12 +879,12 @@ The library honors these environment variables:
- `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that
may be useful for pinpointing the cause of any observed issues.
## 11) Settings for libtokencap
## 13) Settings for libtokencap
This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
discovered tokens should be written.
## 12) Third-party variables set by afl-fuzz & other tools
## 14) Third-party variables set by afl-fuzz & other tools
Several variables are not directly interpreted by afl-fuzz, but are set to
optimal values if not already present in the environment:

View File

@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE
arm:
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all
arm64:
ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

View File

@ -6,34 +6,39 @@
#define UNUSED_PARAMETER(x) (void)(x)
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
{
UNUSED_PARAMETER (size);
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
ElfW(Addr) * base = data;
UNUSED_PARAMETER(size);
ElfW(Addr) *base = data;
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
return 0;
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
return 0;
}
int main (int argc, char** argv, char** envp) {
UNUSED_PARAMETER (argc);
int main(int argc, char **argv, char **envp) {
ElfW(Addr) base = 0;
UNUSED_PARAMETER(argc);
int persona = personality(ADDR_NO_RANDOMIZE);
if (persona == -1) {
ElfW(Addr) base = 0;
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
return 1;
}
int persona = personality(ADDR_NO_RANDOMIZE);
if (persona == -1) {
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
return 1;
dl_iterate_phdr(phdr_callback, &base);
}
printf("%p\n", (void *)base);
if (base == 0) { return 1; }
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
dl_iterate_phdr(phdr_callback, &base);
printf("%p\n", (void *)base);
if (base == 0) { return 1; }
return 0;
return 0;
}

View File

@ -45,6 +45,7 @@
js_api_set_stdout;
js_api_set_traceable;
js_api_set_verbose;
js_api_ijon_set;
local:
*;

View File

@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
// do a length check matching the target!
void **esp = (void **)regs->esp;
void *arg1 = esp[0];
void **arg2 = &esp[1];
void *arg1 = esp[1];
void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;

View File

@ -36,7 +36,7 @@ struct x86_64_regs {
void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
memcpy((void *)regs->rdi, input_buf, input_buf_len);
regs->rsi = input_buf_len;
@ -76,14 +76,15 @@ struct x86_regs {
void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
void **esp = (void **)regs->esp;
void * arg1 = esp[1];
void *arg1 = esp[1];
void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;
}
#elif defined(__aarch64__)
struct arm64_regs {
@ -177,9 +178,10 @@ struct arm64_regs {
void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
memcpy((void *)regs->x0, input_buf, input_buf_len);
regs->x1 = input_buf_len;
}
#else
@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) {
return 1;
}

View File

@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed;
extern uint8_t *__afl_area_ptr;
extern uint32_t __afl_map_size;
extern void __afl_coverage_interesting(uint8_t, uint32_t);
extern __thread guint64 *instrument_previous_pc_addr;
@ -72,5 +73,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data);
void instrument_regs_format(int fd, char *format, ...);
void ijon_set(uint32_t edge);
#endif

View File

@ -449,3 +449,9 @@ void instrument_regs_format(int fd, char *format, ...) {
}
void ijon_set(uint32_t edge) {
__afl_coverage_interesting(1, edge);
}

View File

@ -49,14 +49,23 @@ void instrument_cache_init(void) {
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
FFATAL("Failed to setrlimit: %d", errno);
FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
errno);
}
map_base =
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
GUM_PAGE_READ | GUM_PAGE_WRITE);
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
if (map_base == MAP_FAILED) {
FFATAL(
"Failed to map segment: %d. This can be caused by failure to setrlimit."
"Disabling or reducing the size of the allocation using "
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
errno);
}
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
GUM_ADDRESS(map_base));

View File

@ -326,6 +326,12 @@ class Afl {
static jsApiGetSymbol(name) {
return Afl.module.getExportByName(name);
}
static IJON = class {
static set(addr, val) {
Afl.jsApiIjonSet((addr ^ val) & 0xffffffff);
}
}
}
/**
* Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode
@ -377,3 +383,4 @@ Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
Afl.jsApiWrite = new NativeFunction(
/* tslint:disable-next-line:no-null-keyword */
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
Afl.jsApiIjonSet = Afl.jsApiGetFunction("js_api_ijon_set", "void", ["uint32"]);

View File

@ -316,3 +316,9 @@ __attribute__((visibility("default"))) void js_api_set_verbose(void) {
}
__attribute__((visibility("default"))) void js_api_ijon_set(uint32_t edge) {
ijon_set(edge);
}

View File

@ -33,7 +33,7 @@
// r15 - pc
static GumCpuContext saved_regs = {0};
static gpointer saved_lr = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
}
static void instrument_exit(GumArmWriter *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0);
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
GUM_ARG_REGISTER, ARM_REG_R0);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_ret));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0);
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumArmWriter *cw = output->writer.arm;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_arm_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_arm_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0);
gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm_writer_put_b_label(cw, loop);
/* done: */
gum_arm_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_loop));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);

View File

@ -16,7 +16,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_lr = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
}
static void instrument_exit(GumArm64Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
gum_arm64_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
GUM_INDEX_PRE_ADJUST);
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr));
GUM_ADDRESS(&persistent_ret));
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumArm64Writer *cw = output->writer.arm64;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_arm64_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_arm64_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm64_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm64_writer_put_b_label(cw, loop);
/* done: */
gum_arm64_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm64_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr));
GUM_ADDRESS(&persistent_loop));
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0);

View File

@ -17,7 +17,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
}
static void instrument_exit(GumX86Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
/*
* If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
}
void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
gum_x86_writer_put_label(cw, zero);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
}

View File

@ -16,8 +16,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
}
static void instrument_exit(GumX86Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0);
gum_x86_writer_put_push_reg(cw, GUM_X86_EDI);
gum_x86_writer_put_call_reg(cw, GUM_X86_EAX);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
}
@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
/*
* If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
}
void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
/* The stack should be aligned when we re-enter our loop */
gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0);
gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
}

View File

@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
if (details->file == NULL) {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
} else {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
details->file->path, details->file->offset);
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
details->file->offset);
}
@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) {
void ranges_print_debug_maps(void) {
FVERBOSE("Maps");
OKF("Maps");
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
}

View File

@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) {
if (!initialized) {
initialized = TRUE;
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) {
util_verbose = TRUE;
}
}

View File

@ -6,46 +6,45 @@
void LLVMFuzzerTestOneInput(char *buf, int len);
__asm__ (
"LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n"
" nop\n"
" nop\n"
"call_target:\n"
" ret\n"
" nop\n"
" nop\n"
"jmp_target:\n"
" callq *call_offset(%rip)\n"
" nop\n"
" nop\n"
" leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n"
" nop\n"
" ud2\n"
" nop\n"
"rax_target:\n"
" ret\n"
"\n"
"\n"
".global jmp_offset\n"
".p2align 3\n"
"jmp_offset:\n"
" .quad jmp_target\n"
"call_offset:\n"
" .quad call_target\n"
"rax_offset:\n"
" .quad rax_target\n"
);
__asm__(
"LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n"
" nop\n"
" nop\n"
"call_target:\n"
" ret\n"
" nop\n"
" nop\n"
"jmp_target:\n"
" callq *call_offset(%rip)\n"
" nop\n"
" nop\n"
" leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n"
" nop\n"
" ud2\n"
" nop\n"
"rax_target:\n"
" ret\n"
"\n"
"\n"
".global jmp_offset\n"
".p2align 3\n"
"jmp_offset:\n"
" .quad jmp_target\n"
"call_offset:\n"
" .quad call_target\n"
"rax_offset:\n"
" .quad rax_target\n");
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -6,8 +6,8 @@
static bool cmov_test(char *x, char *y, size_t len) {
register char * __rdi __asm__("rdi") = x;
register char * __rsi __asm__("rsi") = y;
register char *__rdi __asm__("rdi") = x;
register char *__rsi __asm__("rsi") = y;
register size_t __rcx __asm__("rcx") = len;
register long __rax __asm__("rax");
@ -49,10 +49,10 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -41,7 +41,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
@ -51,6 +51,7 @@ int run(char *file) {
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
break;
@ -110,8 +111,10 @@ void slow() {
}
TESTINSTR_SECTION int do_run(char * file) {
TESTINSTR_SECTION int do_run(char *file) {
return run(file);
}
int main(int argc, char **argv) {

View File

@ -19,32 +19,40 @@
typedef void (*fntestinstrlib)(char *buf, int len);
void testinstr(char *buf, int len) {
void *lib = dlopen("testinstrlib.so", RTLD_NOW);
if (lib == NULL) {
puts("Library not found");
abort();
}
fntestinstrlib fn = (fntestinstrlib)(dlsym(lib, "testinstrlib"));
if (fn == NULL) {
puts("Function not found");
abort();
}
fn(buf, len);
}
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
if (argc != 2) { return 1; }
do {
file = argv[1];
printf("file: %s\n", file);
@ -52,33 +60,43 @@ int main(int argc, char **argv) {
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
break;
}
len = lseek(fd, 0, SEEK_END);
if (len < 0) {
perror("lseek (SEEK_END)");
break;
}
if (lseek(fd, 0, SEEK_SET) != 0) {
perror("lseek (SEEK_SET)");
break;
}
printf("len: %ld\n", len);
buf = malloc(len);
if (buf == NULL) {
perror("malloc");
break;
}
n_read = read(fd, buf, len);
if (n_read != len) {
perror("read");
break;
}
dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read);
@ -95,4 +113,6 @@ int main(int argc, char **argv) {
if (fd != -1) { close(fd); }
return result;
}

View File

@ -1,6 +1,7 @@
#include <stdio.h>
void testinstrlib(char *buf, int len) {
if (len < 1) return;
buf[len] = 0;
@ -11,4 +12,6 @@ void testinstrlib(char *buf, int len) {
printf("Pretty sure that is a one!\n");
else
printf("Neither one or zero? How quaint!\n");
}

View File

@ -41,7 +41,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -35,7 +35,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -22,60 +22,60 @@
#define IGNORED_RETURN(x) (void)!(x)
const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t
crc32(const void *buf, size_t size)
{
const uint8_t *p = buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
uint32_t crc32(const void *buf, size_t size) {
const uint8_t *p = buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
/*
@ -83,11 +83,13 @@ crc32(const void *buf, size_t size)
* FRIDA to patch this function out and always return success. Otherwise, we
* could change it to actually correct the checksum.
*/
int crc32_check (char * buf, int len) {
int crc32_check(char *buf, int len) {
if (len < sizeof(uint32_t)) { return 0; }
uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)];
uint32_t calculated = crc32(buf, len - sizeof(uint32_t));
return expected == calculated;
}
/*
@ -97,27 +99,31 @@ int crc32_check (char * buf, int len) {
* cloud your output unnecessarily. Again, we can use FRIDA to patch it out.
*/
void some_boring_bug(char c) {
switch (c) {
case 'A'...'Z':
case 'a'...'z':
case 'A' ... 'Z':
case 'a' ... 'z':
__builtin_trap();
break;
}
}
extern void some_boring_bug2(char c);
__asm__ (
".text \n"
"some_boring_bug2: \n"
".global some_boring_bug2 \n"
".type some_boring_bug2, @function \n"
"mov %edi, %eax \n"
"cmp $0xb4, %al \n"
"jne ok \n"
"ud2 \n"
"ok: \n"
"ret \n");
__asm__(
".text \n"
"some_boring_bug2: \n"
".global some_boring_bug2 \n"
".type some_boring_bug2, @function \n"
"mov %edi, %eax \n"
"cmp $0xb4, %al \n"
"jne ok \n"
"ud2 \n"
"ok: \n"
"ret \n");
void LLVMFuzzerTestOneInput(char *buf, int len) {
@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
some_boring_bug2(buf[0]);
if (buf[0] == '0') {
printf("Looks like a zero to me!\n");
}
else if (buf[0] == '1') {
} else if (buf[0] == '1') {
printf("Pretty sure that is a one!\n");
}
else if (buf[0] == '2') {
} else if (buf[0] == '2') {
printf("Oh we, weren't expecting that!");
__builtin_trap();
}
else
} else
printf("Neither one or zero? How quaint!\n");
}
@ -145,7 +155,7 @@ int main(int argc, char **argv) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
@ -173,5 +183,6 @@ int main(int argc, char **argv) {
printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
return 0;
}

View File

@ -4,66 +4,68 @@
#include <stdlib.h>
#include <dlfcn.h>
//typedef for our exported target function.
// typedef for our exported target function.
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
//globals
// globals
CRASHME fpn_crashme = NULL;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
fpn_crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
fpn_crashme(data, size);
return 0;
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
return 0;
return 0;
}
__attribute__((constructor()))
void constructor(void) {
// handles to required libs
void *dylib = NULL;
__attribute__((constructor())) void constructor(void) {
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
if (dylib == NULL)
{
// handles to required libs
void *dylib = NULL;
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
if (dylib == NULL) {
}
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
printf("[+] Resolve function\n");
}
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme)
{
printf("[+] Resolve function\n");
printf("[-] Failed to find function\n");
exit(1);
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme) {
}
printf("[-] Failed to find function\n");
exit(1);
}
printf("[+] Found function.\n");
printf("[+] Found function.\n");
}

View File

@ -4,66 +4,68 @@
#include <stdlib.h>
#include <dlfcn.h>
//typedef for our exported target function.
// typedef for our exported target function.
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
//globals
// globals
CRASHME fpn_crashme = NULL;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
fpn_crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
fpn_crashme(data, size);
return 0;
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
return 0;
return 0;
}
__attribute__((constructor()))
void constructor(void) {
// handles to required libs
void *dylib = NULL;
__attribute__((constructor())) void constructor(void) {
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
if (dylib == NULL)
{
// handles to required libs
void *dylib = NULL;
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
if (dylib == NULL) {
}
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
printf("[+] Resolve function\n");
}
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme)
{
printf("[+] Resolve function\n");
printf("[-] Failed to find function\n");
exit(1);
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme) {
}
printf("[-] Failed to find function\n");
exit(1);
}
printf("[+] Found function.\n");
printf("[+] Found function.\n");
}

View File

@ -4,37 +4,42 @@
#include <stdlib.h>
#include <dlfcn.h>
extern void crashme(const uint8_t *Data, size_t Size);
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
crashme(data, size);
return 0;
}
void run (int argc, const char * argv[])
{
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
void run(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "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", argv[i], n_read);
}
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
run(argc, argv);
run(argc, argv);
return 0;
return 0;
}

View File

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <stdint.h>
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 5) return;
@ -13,5 +12,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Data[3] == '$')
if (Data[4] == '$') abort();
}

View File

@ -3,7 +3,6 @@
#include <stdint.h>
#include <string.h>
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 1) return;
@ -56,6 +55,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
}
}

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -20,22 +20,32 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
int ret = 0;
for (int i = 0; i < 1000; i++) {
switch(buf[i]) {
case 'A': ret += 2; break;
case '1': ret += 3; break;
default: ret++;
switch (buf[i]) {
case 'A':
ret += 2;
break;
case '1':
ret += 3;
break;
default:
ret++;
}
}
printf("ret: %d\n", ret);
}
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -18,7 +18,7 @@
void LLVMFuzzerTestOneInput(char *buf, int len) {
printf (">>> LLVMFuzzerTestOneInput >>>\n");
printf(">>> LLVMFuzzerTestOneInput >>>\n");
if (len < 1) return;
buf[len] = 0;
@ -40,10 +40,10 @@ void slow() {
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -48,7 +48,7 @@ all: $(TEST_BIN)
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
arm:
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN)
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN)
$(BUILD_DIR):
mkdir -p $@
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
cd $(LIBZ_DIR) && \
CFLAGS="$(CFLAGS) -fPIC" \
./configure \
--static \
--archs="$(ARCH)"
--static
$(LIBZ_LIB): | $(LIBZ_PC)
CFLAGS="$(CFLAGS) -fPIC" \
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
LDFLAGS="-L$(LIBZ_DIR)" \
./configure \
--host="$(ARCH)"
--host="$(PNG_ARCH)"
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -22,7 +22,7 @@
#define TESTINSTR_SECTION __attribute__((section(".testinstr")))
#endif
void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
void LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 1) return;
@ -30,9 +30,13 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (gettimeofday(&tv, NULL) < 0) return;
if ((tv.tv_usec % 2) == 0) {
printf ("Hooray all even\n");
printf("Hooray all even\n");
} else {
printf ("Hmm that's odd\n");
printf("Hmm that's odd\n");
}
// we support three input cases
@ -45,26 +49,33 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
}
void run_test(char * file) {
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);
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

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -116,6 +116,10 @@
#include <TargetConditionals.h>
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#undef LIST_FOREACH /* clashes with FreeBSD */
#include "list.h"
#ifndef SIMPLE_FILES
@ -139,6 +143,10 @@
#define AFL_RAND_RETURN u32
#endif
#ifndef INTERESTING_32_LEN
#error INTERESTING_32_LEN not defined - BUG!
#endif
extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32
@ -232,7 +240,6 @@ struct queue_entry {
custom, /* Marker for custom mutators */
stats_mutated; /* stats: # of mutations performed */
u8 *trace_mini; /* Trace bytes, if kept */
u32 tc_ref; /* Trace bytes ref count */
#ifdef INTROSPECTION
@ -242,13 +249,11 @@ struct queue_entry {
double perf_score, /* performance score */
weight;
u8 *testcase_buf; /* The testcase buffer, if loaded. */
u8 *cmplog_colorinput; /* the result buf of colorization */
struct tainted *taint; /* Taint information from CmpLog */
struct queue_entry *mother; /* queue entry this based on */
struct queue_entry *mother; /* queue entry this based on */
u8 *trace_mini; /* Trace bytes, if kept */
u8 *testcase_buf; /* The testcase buffer, if loaded. */
u8 *cmplog_colorinput; /* the result buf of colorization */
struct tainted *taint; /* Taint information from CmpLog */
struct skipdet_entry *skipdet_e;
};
@ -444,15 +449,17 @@ extern char *power_names[POWER_SCHEDULES_NUM];
typedef struct afl_env_vars {
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only,
afl_custom_mutator_late_send, afl_no_ui, afl_force_ui,
afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems;
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames, afl_no_sync, afl_no_fastresume;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -651,6 +658,7 @@ typedef struct afl_state {
switch_fuzz_mode, /* auto or fixed fuzz mode */
calibration_time_us, /* Time spend on calibration */
sync_time_us, /* Time spend on sync */
cmplog_time_us, /* Time spend on cmplog */
trim_time_us; /* Time spend on trimming */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
@ -1221,6 +1229,7 @@ void show_init_stats(afl_state_t *);
void update_calibration_time(afl_state_t *afl, u64 *time);
void update_trim_time(afl_state_t *afl, u64 *time);
void update_sync_time(afl_state_t *afl, u64 *time);
void update_cmplog_time(afl_state_t *afl, u64 *time);
/* StatsD */
@ -1271,6 +1280,7 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *);
u64 get_binary_hash(u8 *fn);
void check_if_tty(afl_state_t *);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);
@ -1404,6 +1414,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
char *sha1_hex(const u8 *data, size_t len);
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
char *sha1_hex_for_file(const char *fname, u32 len);
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
* enabled. */
static inline int permissive_create(afl_state_t *afl, const char *fn) {
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) {
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
PFATAL("Unable to create '%s'", fn);
}
}
return fd;
}
#if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1
#endif

View File

@ -33,6 +33,10 @@
#define MUT_STRATEGY_ARRAY_SIZE 256
#ifndef INTERESTING_32
#error INTERESTING_32 is not defined - BUG!
#endif
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.20c"
#define VERSION "++4.22a"
/******************************************************
* *
@ -324,9 +324,9 @@
#define SYNC_INTERVAL 8
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
nodes) - default is 30 minutes: */
nodes) - default is 20 minutes: */
#define SYNC_TIME (30 * 60 * 1000)
#define SYNC_TIME (20 * 60 * 1000)
/* Output directory reuse grace period (minutes): */
@ -464,7 +464,7 @@
/* Do not change this unless you really know what you are doing. */
#define MAP_SIZE (1U << MAP_SIZE_POW2)
#if MAP_SIZE <= 65536
#if MAP_SIZE <= 2097152
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
#else
#define MAP_INITIAL_SIZE MAP_SIZE

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -21,13 +21,15 @@ static char *afl_environment_variables[] = {
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN",
"AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM",
"AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
@ -38,8 +40,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE",
"AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
"AFL_FRIDA_INST_NO_SUPPRESS"
"AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE",
"AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE",
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR",
@ -48,7 +49,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE",
"AFL_FRIDA_VERBOSE",
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
@ -80,14 +81,13 @@ static char *afl_environment_variables[] = {
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
"AFL_LLVM_LTO_SKIPINIT"
"AFL_LLVM_LTO_STARTID",
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
#if defined USE_COLOR && !defined ALWAYS_COLORED
"AFL_NO_COLOR", "AFL_NO_COLOUR",
#endif
"AFL_NO_CPU_RED",
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
@ -107,15 +107,16 @@ static char *afl_environment_variables[] = {
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
"AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK",
"AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD",
"AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR",
"AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES",
"AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC",
"AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN",
"AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH",
"AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE",
"AFL_NO_FASTRESUME", NULL
};

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>>
@ -188,6 +188,8 @@ typedef struct afl_forkserver {
u8 persistent_mode;
u32 max_length;
#ifdef __linux__
nyx_plugin_handler_t *nyx_handlers;
char *out_dir_path; /* path to the output directory */
@ -204,6 +206,15 @@ typedef struct afl_forkserver {
s32 nyx_log_fd;
#endif
#ifdef __AFL_CODE_COVERAGE
u8 *persistent_trace_bits; /* Persistent copy of bitmap */
#endif
void *custom_data_ptr;
u8 *custom_input;
u32 custom_input_len;
void (*late_send)(void *, const u8 *, size_t);
} afl_forkserver_t;
typedef enum fsrv_run_result {

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -214,8 +214,12 @@ class ModuleSanitizerCoverageLTO
void SetNoSanitizeMetadata(Instruction *I) {
#if LLVM_VERSION_MAJOR >= 19
I->setNoSanitizeMetadata();
#else
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
MDNode::get(*C, None));
#endif
}
@ -225,7 +229,7 @@ class ModuleSanitizerCoverageLTO
FunctionCallee SanCovTracePCIndir;
FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
Module *CurModule;
std::string CurModuleUniqueId;
Triple TargetTriple;
@ -341,7 +345,7 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 15
PB.registerFullLinkTimeOptimizationEarlyEPCallback(
PB.registerFullLinkTimeOptimizationLastEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
@ -416,6 +420,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
PtrTy = PointerType::getUnqual(*C);
/* AFL++ START */
char *ptr;
@ -486,7 +491,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
}
@ -1350,7 +1355,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
if (F.empty()) return;
if (F.getName().find(".module_ctor") != std::string::npos)
if (F.getName().contains(".module_ctor"))
return; // Should not instrument sanitizer init functions.
#if LLVM_VERSION_MAJOR >= 18
if (F.getName().starts_with("__sanitizer_"))
@ -1372,6 +1377,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return;
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
#if LLVM_VERSION_MAJOR >= 19
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
#endif
// if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))
// return;
// if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
@ -2023,16 +2032,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
if (&F.getEntryBlock() == AllBlocks[i]) {
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
} else {
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
BlockAddress::get(AllBlocks[i]), PtrTy));
#if LLVM_VERSION_MAJOR >= 16
PCs.push_back(Constant::getNullValue(PtrTy));
#else
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy));
#endif
}

View File

@ -161,7 +161,9 @@ class ModuleSanitizerCoverageAFL
void SetNoSanitizeMetadata(Instruction *I) {
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 19
I->setNoSanitizeMetadata();
#elif LLVM_VERSION_MAJOR >= 16
I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
#else
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@ -179,7 +181,7 @@ class ModuleSanitizerCoverageAFL
FunctionCallee SanCovTraceSwitchFunction;
GlobalVariable *SanCovLowestStack;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
Module *CurModule;
std::string CurModuleUniqueId;
Triple TargetTriple;
@ -195,7 +197,7 @@ class ModuleSanitizerCoverageAFL
SanitizerCoverageOptions Options;
uint32_t instr = 0, selects = 0, unhandled = 0;
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
GlobalVariable *AFLMapPtr = NULL;
ConstantInt *One = NULL;
ConstantInt *Zero = NULL;
@ -272,13 +274,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
if (!TargetTriple.isOSBinFormatCOFF())
return std::make_pair(SecStart, SecEnd);
// Account for the fact that on windows-msvc __start_* symbols actually
// point to a uint64_t before the start of the array.
// Account for the fact that on windows-msvc __start_* symbols actually
// point to a uint64_t before the start of the array.
#if LLVM_VERSION_MAJOR >= 19
auto GEP =
IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
return std::make_pair(GEP, SecEnd);
#else
auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
ConstantInt::get(IntptrTy, sizeof(uint64_t)));
return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)),
SecEnd);
#endif
}
@ -330,6 +338,8 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
if (getenv("AFL_DEBUG")) { debug = 1; }
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
@ -368,6 +378,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
PtrTy = PointerType::getUnqual(*C);
LLVMContext &Ctx = M.getContext();
AFLMapPtr =
@ -570,7 +581,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
if (F.empty()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
if (F.getName().find(".module_ctor") != std::string::npos)
// if (F.getName().find(".module_ctor") != std::string::npos)
if (F.getName().contains(".module_ctor"))
return; // Should not instrument sanitizer init functions.
#if LLVM_VERSION_MAJOR >= 18
if (F.getName().starts_with("__sanitizer_"))
@ -593,6 +605,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return;
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
#if LLVM_VERSION_MAJOR >= 19
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
#endif
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@ -638,6 +653,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
// InjectTraceForCmp(F, CmpTraceTargets);
// InjectTraceForSwitch(F, SwitchTraceTargets);
if (dump_cc) { calcCyclomaticComplexity(&F); }
}
GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
@ -688,16 +705,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
if (&F.getEntryBlock() == AllBlocks[i]) {
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
} else {
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
BlockAddress::get(AllBlocks[i]), PtrTy));
#if LLVM_VERSION_MAJOR >= 16
PCs.push_back(Constant::getNullValue(IntptrPtrTy));
PCs.push_back(Constant::getNullValue(PtrTy));
#else
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
@ -707,10 +724,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
}
auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy,
SanCovPCsSectionName);
auto *PCArray =
CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
PCArray->setInitializer(
ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs));
ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
PCArray->setConstant(true);
return PCArray;
@ -818,7 +835,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
StringRef FuncName = Callee->getName();
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
#if LLVM_VERSION_MAJOR >= 20
// test canary
InstrumentationIRBuilder IRB(callInst);
#else
IRBuilder<> IRB(callInst);
#endif
if (!FunctionGuardArray) {

View File

@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE;
u32 __afl_dictionary_len;
u64 __afl_map_addr;
u32 __afl_first_final_loc;
u32 __afl_old_forkserver;
#ifdef __AFL_CODE_COVERAGE
typedef struct afl_module_info_t afl_module_info_t;
@ -616,7 +617,7 @@ static void __afl_map_shm(void) {
fprintf(stderr,
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
"%u, __afl_final_loc %u, __afl_map_size %u",
"%u, __afl_final_loc %u, __afl_map_size %u\n",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
__afl_final_loc, __afl_map_size);
@ -856,7 +857,7 @@ static void __afl_start_forkserver(void) {
signal(SIGTERM, at_exit);
u32 already_read_first = 0;
u32 was_killed;
u32 was_killed = 0;
u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
u32 tmp = version ^ 0xffffffff, status2, status = version;
u8 *msg = (u8 *)&status;
@ -866,75 +867,95 @@ static void __afl_start_forkserver(void) {
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
if (getenv("AFL_OLD_FORKSERVER")) {
__afl_old_forkserver = 1;
status = 0;
if (__afl_final_loc > MAP_SIZE) {
fprintf(stderr,
"Warning: AFL_OLD_FORKSERVER is used with a target compiled with "
"non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - "
"this target may crash!\n");
}
}
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
if (!__afl_old_forkserver) {
write_error("wrong forkserver message from AFL++ tool");
_exit(1);
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
}
// send the set/requested options to forkserver
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
if (__afl_dictionary_len && __afl_dictionary) {
status |= FS_NEW_OPT_AUTODICT;
}
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// Now send the parameters for the set options, increasing by option number
// FS_NEW_OPT_MAPSIZE - we always send the map size
status = __afl_map_size;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// FS_NEW_OPT_SHDMEM_FUZZ - no data
// FS_NEW_OPT_AUTODICT - send autodictionary
if (__afl_dictionary_len && __afl_dictionary) {
// pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
write(2, "Error: could not send dictionary len\n",
strlen("Error: could not send dictionary len\n"));
write_error("wrong forkserver message from AFL++ tool");
_exit(1);
}
while (len != 0) {
// send the set/requested options to forkserver
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
if (__afl_dictionary_len && __afl_dictionary) {
s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
status |= FS_NEW_OPT_AUTODICT;
if (ret < 1) {
}
write_error("could not send dictionary");
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// Now send the parameters for the set options, increasing by option number
// FS_NEW_OPT_MAPSIZE - we always send the map size
status = __afl_map_size;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// FS_NEW_OPT_SHDMEM_FUZZ - no data
// FS_NEW_OPT_AUTODICT - send autodictionary
if (__afl_dictionary_len && __afl_dictionary) {
// pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
write(2, "Error: could not send dictionary len\n",
strlen("Error: could not send dictionary len\n"));
_exit(1);
}
len -= ret;
offset += ret;
while (len != 0) {
s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
if (ret < 1) {
write_error("could not send dictionary");
_exit(1);
}
len -= ret;
offset += ret;
}
}
}
// send welcome message as final message
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// send welcome message as final message
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
}
// END forkserver handshake
@ -948,13 +969,13 @@ static void __afl_start_forkserver(void) {
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (already_read_first) {
if (unlikely(already_read_first)) {
already_read_first = 0;
} else {
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
if (unlikely(read(FORKSRV_FD, &was_killed, 4) != 4)) {
write_error("read from AFL++ tool");
_exit(1);
@ -993,10 +1014,10 @@ static void __afl_start_forkserver(void) {
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
if (unlikely(child_stopped && was_killed)) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) {
if (unlikely(waitpid(child_pid, &status, 0) < 0)) {
write_error("child_stopped && was_killed");
_exit(1);
@ -1005,12 +1026,12 @@ static void __afl_start_forkserver(void) {
}
if (!child_stopped) {
if (unlikely(!child_stopped)) {
/* Once woken up, create a clone of our process. */
child_pid = fork();
if (child_pid < 0) {
if (unlikely(child_pid < 0)) {
write_error("fork");
_exit(1);
@ -1019,7 +1040,7 @@ static void __afl_start_forkserver(void) {
/* In child process: close fds, resume execution. */
if (!child_pid) {
if (unlikely(!child_pid)) { // just to signal afl-fuzz faster
//(void)nice(-20);
@ -1044,14 +1065,15 @@ static void __afl_start_forkserver(void) {
/* In parent process: write PID to pipe, then wait for child. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
if (unlikely(write(FORKSRV_FD + 1, &child_pid, 4) != 4)) {
write_error("write to afl-fuzz");
_exit(1);
}
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) {
if (unlikely(waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) <
0)) {
write_error("waitpid");
_exit(1);
@ -1062,11 +1084,11 @@ static void __afl_start_forkserver(void) {
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status)) child_stopped = 1;
if (likely(WIFSTOPPED(status))) { child_stopped = 1; }
/* Relay wait status to pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) {
if (unlikely(write(FORKSRV_FD + 1, &status, 4) != 4)) {
write_error("writing to afl-fuzz");
_exit(1);
@ -1849,7 +1871,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
to avoid duplicate calls (which can happen as an artifact of the underlying
implementation in LLVM). */
if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries
if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries
*(start++) = ++__afl_final_loc;
@ -2704,7 +2726,7 @@ void __afl_coverage_skip() {
// mark this area as especially interesting
void __afl_coverage_interesting(u8 val, u32 id) {
__afl_area_ptr[id] = val;
__afl_area_ptr[id % __afl_map_size] = val;
}

View File

@ -26,6 +26,51 @@ static std::list<std::string> allowListFunctions;
static std::list<std::string> denyListFiles;
static std::list<std::string> denyListFunctions;
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
unsigned int numBlocks = 0;
unsigned int numEdges = 0;
unsigned int numCalls = 0;
// Iterate through each basic block in the function
for (BasicBlock &BB : *F) {
// count all nodes == basic blocks
numBlocks++;
// Count the number of successors (outgoing edges)
for (BasicBlock *Succ : successors(&BB)) {
// count edges for CC
numEdges++;
(void)(Succ);
}
for (Instruction &I : BB) {
// every call is also an edge, so we need to count the calls too
if (isa<CallInst>(&I) || isa<InvokeInst>(&I)) { numCalls++; }
}
}
// Cyclomatic Complexity V(G) = E - N + 2P
// For a single function, P (number of connected components) is 1
// Calls are considered to be an edge
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
// if (debug) {
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
F->getName().str().c_str(), CC);
//}
return CC;
}
char *getBBName(const llvm::BasicBlock *BB) {
static char *name;
@ -91,7 +136,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
for (auto const &ignoreListFunc : ignoreList) {
#if LLVM_VERSION_MAJOR >= 19
if (F->getName().starts_with(ignoreListFunc)) { return true; }
#else
if (F->getName().startswith(ignoreListFunc)) { return true; }
#endif
}

View File

@ -55,6 +55,7 @@ void initInstrumentList();
bool isInInstrumentList(llvm::Function *F, std::string Filename);
unsigned long long int calculateCollisions(uint32_t edges);
void scanForDangerousFunctions(llvm::Module *M);
unsigned int calcCyclomaticComplexity(llvm::Function *F);
#ifndef IS_EXTERN
#define IS_EXTERN

View File

@ -661,6 +661,13 @@ bool AFLdict2filePass::runOnModule(Module &M) {
Value *op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (!ilen) {
op2 = callInst->getArgOperand(1);
ilen = dyn_cast<ConstantInt>(op2);
}
if (ilen) {
uint64_t literalLength = optLen;

View File

@ -54,6 +54,12 @@
#define nullptr 0
#endif
#if LLVM_MAJOR >= 19
#define STARTSWITH starts_with
#else
#define STARTSWITH startswith
#endif
#include <set>
#include "afl-llvm-common.h"
@ -230,38 +236,38 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
isStrcmp &=
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
(!FuncName.compare("strcmp") /*|| !FuncName.compare("xmlStrcmp") ||
!FuncName.compare("xmlStrEqual") ||
!FuncName.compare("curl_strequal") ||
!FuncName.compare("strcsequal") ||
!FuncName.compare("g_strcmp0"));
!FuncName.compare("g_strcmp0")*/);
isMemcmp &=
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
!FuncName.compare("CRYPTO_memcmp") ||
!FuncName.compare("OPENSSL_memcmp") ||
!FuncName.compare("memcmp_const_time") ||
!FuncName.compare("memcmpct"));
isStrncmp &= (!FuncName.compare("strncmp") ||
isStrncmp &= (!FuncName.compare("strncmp")/* ||
!FuncName.compare("curl_strnequal") ||
!FuncName.compare("xmlStrncmp"));
!FuncName.compare("xmlStrncmp")*/);
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
!FuncName.compare("stricmp") ||
!FuncName.compare("ap_cstr_casecmp") ||
!FuncName.compare("OPENSSL_strcasecmp") ||
!FuncName.compare("xmlStrcasecmp") ||
/*!FuncName.compare("xmlStrcasecmp") ||
!FuncName.compare("g_strcasecmp") ||
!FuncName.compare("g_ascii_strcasecmp") ||
!FuncName.compare("Curl_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||*/
!FuncName.compare("cmsstrcasecmp"));
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
!FuncName.compare("strnicmp") ||
!FuncName.compare("ap_cstr_casecmpn") ||
!FuncName.compare("OPENSSL_strncasecmp") ||
!FuncName.compare("OPENSSL_strncasecmp") /*||
!FuncName.compare("xmlStrncasecmp") ||
!FuncName.compare("g_ascii_strncasecmp") ||
!FuncName.compare("Curl_strncasecompare") ||
!FuncName.compare("g_strncasecmp"));
!FuncName.compare("g_strncasecmp")*/);
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
@ -465,8 +471,20 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool isCaseInsensitive = false;
bool needs_null = false;
bool success_is_one = false;
bool nullCheck = false;
Function *Callee = callInst->getCalledFunction();
/*
fprintf(stderr, "%s - %s - %s\n",
callInst->getParent()
->getParent()
->getParent()
->getName()
.str()
.c_str(),
callInst->getParent()->getParent()->getName().str().c_str(),
Callee ? Callee->getName().str().c_str() : "NULL");*/
if (Callee) {
if (!Callee->getName().compare("memcmp") ||
@ -520,6 +538,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
}
if (!isSizedcmp) needs_null = true;
if (Callee->getName().STARTSWITH("g_") ||
Callee->getName().STARTSWITH("curl_") ||
Callee->getName().STARTSWITH("Curl_") ||
Callee->getName().STARTSWITH("xml"))
nullCheck = true;
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
@ -604,8 +627,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
/* split before the call instruction */
BasicBlock *bb = callInst->getParent();
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
BasicBlock *next_lenchk_bb = NULL;
if (nullCheck) { fprintf(stderr, "TODO: null check\n"); }
if (isSizedcmp && !isConstSized) {
next_lenchk_bb =

View File

@ -1,7 +1,7 @@
/*
* Copyright 2016 laf-intel
* extended for floating point by Heiko Eißfeldt
* adapted to new pass manager by Heiko Eißfeldt
* extended for floating point by Heiko Eissfeldt
* adapted to new pass manager by Heiko Eissfeldt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -266,8 +266,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
/* this is probably not needed but we do it anyway */
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
int constants = 0;
if (llvm::isa<llvm::Constant>(op0)) { ++constants; }
if (llvm::isa<llvm::Constant>(op1)) { ++constants; }
if (constants != 1) { continue; }
fcomps.push_back(selectcmpInst);
@ -1778,7 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
auto op0 = CI->getOperand(0);
auto op1 = CI->getOperand(1);
// has to valid operands
if (!op0 || !op1) { continue; }
// has exactly one constant and one variable
int constants = 0;
if (dyn_cast<ConstantInt>(op0)) { ++constants; }
if (dyn_cast<ConstantInt>(op1)) { ++constants; }
if (constants != 1) { continue; }
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
if (iTy1 && isa<IntegerType>(op1->getType())) {

View File

@ -23,7 +23,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel
2. Additionally, install the following packages:
```shell
apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2
apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 libcapstone-dev
```
3. As Nyx is written in Rust, install the newest rust compiler (rust packages in
@ -33,7 +33,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
4. Finally build Nyx mode:
4. Finally build Nyx mode (or use `make distrib` at the repo root to build all AFL++ modes):
```shell
./build_nyx_support.sh
@ -92,7 +92,7 @@ sudo modprobe -r kvm-intel
sudo modprobe -r kvm
sudo modprobe kvm enable_vmware_backdoor=y
sudo modprobe kvm-intel
cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echi OK || echo KVM module problem
cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echo OK || echo KVM module problem
```
All the hard parts are done, fuzzing with Nyx mode is easy - just supply the
@ -186,7 +186,7 @@ make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast
#### Nyx share directories
Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Both bootstrap scripts use several tools to communicate with the "outer world":
Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Either of these scripts can be edited to more fully prepare an environment for the target, like transferring configuration files to the target's filesystem. Both bootstrap scripts use several tools to communicate with the "outer world":
- `hcat` - this tool copies a given string to the host
- `hget` - this program requests a file from the host's share directory

View File

@ -1 +1 @@
40033af00c
847b43acb1

View File

@ -202,6 +202,8 @@ QEMU_CONF_FLAGS=" \
--disable-xfsctl \
--target-list="${CPU_TARGET}-linux-user" \
--without-default-devices \
--extra-cflags=-Wno-int-conversion \
--disable-werror \
"
if [ -n "${CROSS_PREFIX}" ]; then
@ -243,7 +245,6 @@ if [ "$DEBUG" = "1" ]; then
--enable-debug-stack-usage \
--enable-debug-tcg \
--enable-qom-cast-debug \
--enable-werror \
"
else
@ -254,7 +255,6 @@ else
--disable-debug-tcg \
--disable-qom-cast-debug \
--disable-stack-protector \
--disable-werror \
--disable-docs \
"
@ -386,6 +386,19 @@ else
make -C libqasan CC="$CROSS $CROSS_FLAGS" && echo "[+] libqasan ready"
fi
#### Hooking support
if [ "$ENABLE_HOOKING" = "1" ];then
echo "[+] ENABLING HOOKING"
set -e
cd ./hooking_bridge || exit 255
mkdir -p ./build
echo "[+] Hook compiler = $CROSS"
make CC="$CROSS $CROSS_FLAGS" GLIB_H="$GLIB_H" GLIB_CONFIG_H="$GLIB_CONFIG_H"
set +e
cd ..
fi
#### End of hooking support
echo "[+] All done for qemu_mode, enjoy!"
exit 0

View File

@ -0,0 +1,18 @@
.PHONY: clean
all: plugin
SRC=./src
BLD=./build
INC=-I./inc -I../qemuafl/include -I$(GLIB_H) -I$(GLIB_CONFIG_H)
# CC=gcc
$(BLD)/patching.o:$(SRC)/patching.c
$(CC) -c -fPIC $(INC) -o $(BLD)/patching.o $(SRC)/patching.c
plugin:$(SRC)/main.c $(BLD)/patching.o
$(CC) -c -fPIC $(INC) -o $(BLD)/plugin.o $(SRC)/main.c
$(CC) -shared -o $(BLD)/plugin.so $(BLD)/plugin.o $(BLD)/patching.o
clean:
rm -rf $(BLD)/*.o
rm -rf $(BLD)/*.so

View File

@ -0,0 +1,96 @@
# Native hooking support into QEMUAFL
* The essential idea is to have inbuilt hooking support into QEMU, instead of relying on the more expensive options UNICORN and its children.
* This solution comprises a bridge (QEMU plugin) that connects your hooks (in a shared library (.so)) with the QEMU usermode ecosystem.
* Currently, LINUX only
## Bridge compilation
Run build_qemu_support.sh as you do to compile qemuafl, additionally with three args namely:
* `ENABLE_HOOKING=1` to compile the bridge
* `GLIB_H` and `GLIB_CONFIG_H` point to headers `glib.h` and `glibconfig.h` to wherever they are installed on your system
## Writting hooks
1. Create one or more hooking functions in a shared library, say `hook.so`.
2. Include `exports.h` in your hook build. You can find this header at `<your AFL++ path>/qemu_mode/hooking_bridge/inc`.
3. Shown below is an example which will use to walkthrough hook creation
```C
struct ret* hook_000000400deadc08(){
memset (buf, 0, 8);
scanf("%s",buf);
r_reg(RSI,(void *)&h_addr);
w_mem(h_addr,8, buf);
to_ret = (struct ret){0x400deadcab, 0};
return &to_ret;
}
```
i. Hook functions must be named as `hook_<left padded hook location>`. Here, `<left padded hook location>` means `<hook location>` left padded with 0's to until 16 hex characters. The unpaded part of `<hook location>` is the absolute address where you want to place the hook. It is basically the file base address (which does not change in QEMU as of now) plus the instruction offset where the hooks is to be placed. The hook function must return a `struct ret *`, which is touched upon later.
ii. Most likely you will need to access memory or registers in the hook. So we provide four functions
```C
// Read memory (from address, num. bytes, destination buffer) -> returns 0 on success
int r_mem(unsigned long long addr, unsigned long long len, void *dest);
// Write memory (to address, num. bytes, source buffer) -> returns 0 on success
int w_mem(unsigned long long addr, unsigned long long len, void *src);
// Read register (identifier, destination buffer) -> returns number of bytes read
int r_reg(unsigned char reg, void *dest);
// Read register (identifier, source buffer) -> returns number of bytes written
int w_reg(unsigned char reg, char *src);
```
When operating on registers, the functions require a `reg` identifier. This is basically a number gdb uses to lookup a register and can be found under `<qemu(afl) path>/gdb-xml` in the architecture specific xml files. For the example case from above, `RSI` is 4 as obtained from `i386-64bit.xml`.
iii. Once done with the processing, the hooks needs to return a `struct ret` type pointer, the struct format being
```C
struct ret{
unsigned long long addr;
char remove_bp;
};
```
As we can see, there are two fields: first that indicates the address to return to and second that indicates whether the installed hook should be removed after the return. The second field becomes critical if the hook is within an ongoing loop and should be kept intact for future references.
iv. Finally, mention the list of hooks in a `configure` function that we can call and install your hooks
```C
struct conf config;
struct conf* configure(){
config.IP_reg_num = 16;
config.entry_addr = 0x4000001000;
config.num_hooks = NUMHOOKS; //1,2,3...
hooks[0] = 0x400deadc08;
// hooks[1] = 0xcafecace
// ....
config.hooks = hooks;
//Any other processing stuff you need done before fuzztime
return &config;
}
```
The `configure` function must have the signature `struct conf* configure()` i.e. it must return a pointer to the `config` object. The format of the `config` object is
```C
struct conf{
unsigned char IP_reg_num; //found in <qemudir>/gdb-xml
unsigned long long entry_addr; //Main, init, or any entry point that is executed by QEMU prior to hooking targets
unsigned long long* hooks; //list of hooked addresses
unsigned long long num_hooks; // Number of hooks
};
```
`IP_reg_num` here is the register number assigned under the architecture specific xml file under `<qemu(afl) path>/gdb-xml` to the instruction pointer.
## Running with hooks
Set `QEMU_PLUGIN="file=<AFL download path>qemu_mode/hooking_bridge/build/plugin.so,arg=<your hook .so>"` before running AFL++ in QEMU mode. Note `<your hook .so>` is the absolute path to your hooks library.
## Current limitations
1. Cannot be used to debug (-g option) when using the bridge as it uses the gdbstub internally. This is not a problem if used with AFL++, so not such a big issue.
2. Cannot put a hook on the first block after `<entry point>`. Not typically a hookable location.
3. The current implementation can only function on Linux. We have tested on the following configuration
```Bash
lsb_release -a
---------------
Distributor ID: Ubuntu
Description: Ubuntu 22.04.3 LTS
Release: 22.04
Codename: jammy
```
```Bash
uname -a
----------
Linux someone 6.5.0-28-generic #29~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 4 14:39:20 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
```

View File

@ -0,0 +1,11 @@
#ifndef COMMON_H
#define COMMON_H
#include <qemu/qemu-plugin.h>
void patch_finish_cb(void *userdata);
void patch_block_trans_cb(struct qemu_plugin_tb *tb);
void patch_vpu_init_cb(unsigned int vcpu_index);
void patch_init(char *hook_library);
#endif

View File

@ -0,0 +1,29 @@
#ifndef API_H
#define API_H
//# EXPORTS
// Returns 0 on success
int r_mem(unsigned long long addr, unsigned long long len, void *dest);
// // Returns 0 on success
int w_mem(unsigned long long addr, unsigned long long len, void *src);
// Returns num of bytes read;
int r_reg(unsigned char reg, void *dest);
// // Returns num of bytes written
int w_reg(unsigned char reg, char *src);
//NOTE hook function must be named hook_<16 hex character at_addr>
//NOTE must define function `struct conf* configure()`
struct conf{
unsigned char IP_reg_num;
unsigned long long entry_addr;
unsigned long long* hooks;
unsigned long long num_hooks;
}conf;
struct ret{
unsigned long long addr;
char remove_bp;
};
#endif

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
static void finish_cb(qemu_plugin_id_t id, void *userdata) {
patch_finish_cb(userdata);
}
static void block_trans_cb(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) {
patch_block_trans_cb(tb);
}
static void vpu_init_cb(qemu_plugin_id_t id, unsigned int vcpu_index) {
patch_vpu_init_cb(vcpu_index);
}
QEMU_PLUGIN_EXPORT
int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc,
char **argv) {
patch_init(argv[0]);
qemu_plugin_register_vcpu_init_cb(id, vpu_init_cb);
qemu_plugin_register_vcpu_tb_trans_cb(id, block_trans_cb);
qemu_plugin_register_atexit_cb(id, finish_cb, NULL);
return 0;
}

View File

@ -0,0 +1,173 @@
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <glib.h>
#include "common.h"
#include "exports.h"
void *handle;
struct conf *config;
struct conf *(*configure)();
GByteArray *out;
void *cpu;
char cbuf[100];
// region GDB Imports
#pragma region GDB Imports
void cpu_single_step(void *cpu, int enabled);
int get_sstep_flags(void);
void gdb_accept_init(int fd);
int gdb_breakpoint_insert(int type, unsigned long long addr,
unsigned long long len);
int gdb_breakpoint_remove(int type, unsigned long long addr,
unsigned long long len);
void *qemu_get_cpu(int index);
int target_memory_rw_debug(void *cpu, unsigned long long addr, void *ptr,
unsigned long long len, char is_write);
int gdb_read_register(void *cs, GByteArray *mem_buf, int n);
int gdb_write_register(void *cs, char *mem_buf, int n);
void gdb_set_cpu_pc(unsigned long long pc);
void gdb_continue(void);
#pragma endregion GDB Imports
// region API
int r_mem(unsigned long long addr, unsigned long long len, void *dest) {
return target_memory_rw_debug(cpu, addr, dest, len, 0);
}
int w_mem(unsigned long long addr, unsigned long long len, void *src) {
return target_memory_rw_debug(cpu, addr, src, len, 1);
}
int r_reg(unsigned char reg, void *dest) {
g_byte_array_steal(out, NULL);
int op = gdb_read_register(cpu, out, reg);
memcpy(dest, out->data, out->len);
return op;
}
int w_reg(unsigned char reg, char *src) {
return gdb_write_register(cpu, src, reg);
}
// region Breakpoint handling
char single_stepped;
unsigned long long gen_addr;
struct ret *(*hook)();
struct ret *returned;
// Defined and imported gdbstub.c
void set_signal_callback(void (*cb)(int));
// Breakpoints are set here
void patch_block_trans_cb(struct qemu_plugin_tb *tb) {
unsigned long long addr;
addr = qemu_plugin_tb_vaddr(tb);
if (addr == config->entry_addr) {
// NOTE This means we cannot put a BP in the first basic block
gdb_accept_init(-1);
for (int i = 0; i < config->num_hooks; i++) {
gdb_breakpoint_insert(0, config->hooks[i], 1);
}
}
}
void handle_signal_callback(int sig) {
if (single_stepped) {
single_stepped = 0;
gdb_breakpoint_insert(0, gen_addr, 1);
cpu_single_step(cpu, 0);
gdb_continue();
return;
}
r_reg(config->IP_reg_num, cbuf);
gen_addr = *(unsigned long long *)cbuf;
sprintf(cbuf, "hook_%016llx", gen_addr);
// TODO maybe find a way to put the hook function pointers in the TCG data
// structure instead of this dlsym call
*(unsigned long long **)(&hook) = dlsym(handle, cbuf);
if (!hook) {
exit(-1);
}
returned = hook();
if (returned->remove_bp ||
(returned->addr ==
gen_addr)) { //* force removal of bp in returning to the same address,
//otherwise hook will be called again
gdb_breakpoint_remove(0, gen_addr, 1);
}
if (returned->addr == gen_addr) {
single_stepped = 1;
cpu_single_step(cpu, get_sstep_flags());
} else {
//* no need to rexecute the IP instruction
gdb_set_cpu_pc(returned->addr);
}
gdb_continue();
}
// region Constructor/Destructor
void patch_finish_cb(void *userdata) {
g_byte_array_free(out, 1);
dlclose(handle);
}
void patch_vpu_init_cb(unsigned int vcpu_index) {
cpu = qemu_get_cpu(vcpu_index);
}
void patch_init(char *hook_lib) {
// TODO make OS agnostic, remove dlopen
handle = dlopen(hook_lib, RTLD_NOW);
if (!handle) {
fprintf(stderr, "DLOPEN Error: %s\n", dlerror());
exit(-1);
}
single_stepped = 0;
*(void **)(&configure) = dlsym(handle, "configure");
config = configure();
set_signal_callback(handle_signal_callback);
out = g_byte_array_new();
}

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -17,6 +17,10 @@
#define AFL_MAIN
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include "common.h"
#include "config.h"
#include "types.h"
@ -32,7 +36,9 @@
#include <limits.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@ -464,6 +470,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) {
*slash = 0;
tmp = alloc_printf("%s/%s", exepath, obj);
if (aflcc->debug) DEBUGF("Trying %s\n", tmp);
if (!access(tmp, R_OK)) { return tmp; }
ck_free(tmp);
@ -517,8 +525,8 @@ void find_built_deps(aflcc_state_t *aflcc) {
char *ptr = NULL;
#if defined(__x86_64__)
if ((ptr = find_object(aflcc, "as")) != NULL) {
#if defined(__x86_64__) || defined(__i386__)
if ((ptr = find_object(aflcc, "afl-as")) != NULL) {
#ifndef __APPLE__
// on OSX clang masquerades as GCC
@ -1261,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
aflcc->lto_mode = 1;
// force CFG
// if (!aflcc->instrument_mode) {
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
// }
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
aflcc->lto_mode = 1;
@ -1583,8 +1586,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) {
insert_param(aflcc,
"-D__AFL_FUZZ_INIT()="
"int __afl_sharedmem_fuzzing = 1;"
"extern unsigned int *__afl_fuzz_len;"
"extern unsigned char *__afl_fuzz_ptr;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned int *__afl_fuzz_len;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned char *__afl_fuzz_ptr;"
"unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
@ -1906,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
}
add_defs_fortify(aflcc, 0);
if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); }
if (!aflcc->have_asan) {
insert_param(aflcc, "-fsanitize=address");
insert_param(aflcc, "-fno-common");
}
aflcc->have_asan = 1;
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
@ -2355,8 +2366,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined");
insert_param(aflcc, "dynamic_lookup");
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
@ -2473,13 +2483,60 @@ void add_runtime(aflcc_state_t *aflcc) {
*/
void add_assembler(aflcc_state_t *aflcc) {
u8 *afl_as = find_object(aflcc, "as");
u8 *afl_as = find_object(aflcc, "afl-as");
if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as').");
if (!afl_as) FATAL("Cannot find 'afl-as'.");
u8 *slash = strrchr(afl_as, '/');
if (slash) *slash = 0;
// Search for 'as' may be unreliable in some cases (see #2058)
// so use 'afl-as' instead, because 'as' is usually a symbolic link,
// or can be a renamed copy of 'afl-as' created in the same dir.
// Now we should verify if the compiler can find the 'as' we need.
#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')"
u8 *afl_as_dup = alloc_printf("%s/as", afl_as);
int fd = open(afl_as_dup, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); }
struct stat st;
if (fstat(fd, &st) < 0) {
PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup);
}
u32 f_len = st.st_size;
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) {
PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup);
}
close(fd);
// "AFL_AS" is a const str passed to getenv in afl-as.c
if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) {
FATAL(
"Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. "
"It is a prerequisite to override system-wide 'as' for "
"instrumentation.",
afl_as_dup, afl_as);
}
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
ck_free(afl_as_dup);
#undef AFL_AS_ERR
insert_param(aflcc, "-B");
insert_param(aflcc, afl_as);
@ -2736,11 +2793,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
"MODES: NCC PERSIST DICT LAF "
"CMPLOG SELECT\n"
" [LLVM] LLVM: %s%s\n"
" PCGUARD %s yes yes module yes yes "
" PCGUARD %s yes yes module yes yes "
"yes\n"
" NATIVE AVAILABLE no yes no no "
"part. yes\n"
" CLASSIC %s no yes module yes yes "
" CLASSIC %s no yes module yes yes "
"yes\n"
" - NORMAL\n"
" - CALLER\n"
@ -2757,10 +2814,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" [GCC/CLANG] simple gcc/clang: %s%s\n"
" CLASSIC DEFAULT no no no no no "
"no\n\n",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->compiler_mode == LLVM ? " [SELECTED]" : "",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_lto ? "AVAILABLE" : "unavailable!",
aflcc->compiler_mode == LTO ? " [SELECTED]" : "",
aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!",
@ -2786,7 +2843,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -59,27 +59,6 @@ u8 last_intr = 0;
#define AFL_PATH "/usr/local/lib/afl/"
#endif
/* - Some BSD (i.e.: FreeBSD) offer the FAST clock source as
* equivalent to Linux COARSE clock source. Aliasing COARSE to
* FAST on such systems when COARSE is not already defined.
* - macOS has no support of CLOCK_MONOTONIC_COARSE clock type.
*/
#if defined(OS_DARWIN) || defined(OS_SUNOS) || defined(__APPLE__) || \
defined(__sun) || defined(__NetBSD__)
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#elif defined(OS_FREEBSD)
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST
#endif
/* Convert seconds to milliseconds. */
#define SEC_TO_MS(sec) ((sec) * 1000)
/* Convert seconds to microseconds. */
#define SEC_TO_US(sec) ((sec) * 1000000)
/* Convert nanoseconds to milliseconds. */
#define NS_TO_MS(ns) ((ns) / 1000000)
/* Convert nanoseconds to microseconds. */
#define NS_TO_US(ns) ((ns) / 1000)
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
size_t needlelen) {
@ -108,9 +87,10 @@ void set_sanitizer_defaults() {
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
u8 have_san_options = 0;
u8 default_options[1024] =
"detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
"return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
"sigfpe=0:handle_sigill=0:";
"detect_odr_violation=0:abort_on_error=1:symbolize=0:"
"allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:"
"detect_stack_use_after_return=0:check_initialization_order=0:";
if (have_asan_options || have_ubsan_options || have_msan_options ||
have_lsan_options) {
@ -996,33 +976,27 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
inline u64 get_cur_time(void) {
struct timespec ts;
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
if (rc == -1) {
struct timeval tv;
struct timezone tz;
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
strerror(errno));
// TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz);
}
return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec);
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
}
/* Get unix time in microseconds */
u64 get_cur_time_us(void) {
inline u64 get_cur_time_us(void) {
struct timespec ts;
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
if (rc == -1) {
struct timeval tv;
struct timezone tz;
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
strerror(errno));
// TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz);
}
return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec);
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
}

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -27,6 +27,9 @@
*/
#include "config.h"
#ifdef AFL_PERSISTENT_RECORD
#include "afl-fuzz.h"
#endif
#include "types.h"
#include "debug.h"
#include "common.h"
@ -238,6 +241,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL;
fsrv->child_kill_signal = SIGKILL;
fsrv->max_length = MAX_FILE;
/* exec related stuff */
fsrv->child_pid = -1;
@ -249,6 +253,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->uses_crash_exitcode = false;
fsrv->uses_asan = false;
#ifdef __AFL_CODE_COVERAGE
fsrv->persistent_trace_bits = NULL;
#endif
fsrv->init_child_func = fsrv_exec_child;
list_append(&fsrv_list, fsrv);
@ -275,12 +283,19 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal;
fsrv_to->debug = from->debug;
#ifdef __AFL_CODE_COVERAGE
fsrv_to->persistent_trace_bits = from->persistent_trace_bits;
#endif
// These are forkserver specific.
fsrv_to->out_dir_fd = -1;
fsrv_to->child_pid = -1;
fsrv_to->use_fauxsrv = 0;
fsrv_to->last_run_timed_out = 0;
fsrv_to->late_send = from->late_send;
fsrv_to->custom_data_ptr = from->custom_data_ptr;
fsrv_to->init_child_func = from->init_child_func;
// Note: do not copy ->add_extra_func or ->persistent_record*
@ -575,7 +590,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
fsrv->max_length);
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
true);
@ -1651,7 +1667,8 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
if (fsrv->fsrv_pid > 0) {
kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal);
waitpid(fsrv->fsrv_pid, NULL, 0);
usleep(25);
waitpid(fsrv->fsrv_pid, NULL, WNOHANG);
}
@ -1939,6 +1956,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
if (unlikely(fsrv->late_send)) {
fsrv->late_send(fsrv->custom_data_ptr, fsrv->custom_input,
fsrv->custom_input_len);
}
exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout,
stop_soon_p);
@ -2078,10 +2102,13 @@ store_persistent_record: {
u32 len = fsrv->persistent_record_len[entry];
if (likely(len && data)) {
snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
fsrv->persistent_record_cnt, writecnt++,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
snprintf(
fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
fsrv->persistent_record_cnt, writecnt++,
((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "",
((afl_state_t *)(fsrv->afl_ptr))->file_extension
? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension
: "");
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (fd >= 0) {

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -75,9 +75,13 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
}
#if __has_builtin(__builtin_popcount)
ret += __builtin_popcount(v);
#else
v -= ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24;
#endif
}
@ -459,7 +463,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv);
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@ -485,7 +489,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* Generating a hash on every input is super expensive. Bad idea and should
only be used for special schedules */
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv);
classified = 1;
@ -527,12 +531,24 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
queue_fn = alloc_printf(
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
describe_op(afl, new_bits + is_timeout,
NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
if (!afl->afl_env.afl_sha1_filenames) {
queue_fn = alloc_printf(
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
describe_op(afl, new_bits + is_timeout,
NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
queue_fn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
@ -542,10 +558,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn);
close(fd);
fd = permissive_create(afl, queue_fn);
if (likely(fd >= 0)) {
ck_write(fd, mem, len, queue_fn);
close(fd);
}
add_to_queue(afl, queue_fn, len, 0);
if (unlikely(afl->fuzz_mode) &&
@ -743,11 +763,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
afl->saved_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
afl->saved_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
@ -799,11 +831,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
@ -873,10 +917,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* If we're here, we apparently want to save the crash or hang
test case, too. */
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
ck_write(fd, mem, len, fn);
close(fd);
fd = permissive_create(afl, fn);
if (fd >= 0) {
ck_write(fd, mem, len, fn);
close(fd);
}
#ifdef __linux__
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {

Some files were not shown because too many files have changed in this diff Show More