Compare commits

...

464 Commits
4.00c ... 4.04c

Author SHA1 Message Date
cbfa5207ba Merge pull request #1551 from AFLplusplus/dev
push to stable
2022-10-11 15:40:55 +02:00
bac6ba8907 v4.04c 2022-10-11 15:39:27 +02:00
de9d1ff4a0 doc fixes 2022-10-11 12:43:06 +02:00
e6e82948bf fastexit + code format 2022-10-11 08:53:49 +02:00
c5008362c6 Merge pull request #1543 from quinox/feat-make-on-gentoo
Support building LTO on Gentoo
2022-10-10 17:08:01 +02:00
db4fa9319d Fix #1548 2022-10-10 14:37:16 +02:00
680e6e91a1 Support building LTO on Gentoo 2022-10-08 09:51:26 +02:00
2107ece114 auto shmem fuzzing (#1541)
* auto shmem fuzzing

* print warning when forcing shmem fuzzing

* typos

* Shmem always

* typo fix

* fixes

Co-authored-by: Dominik Maier <dmnk@google.com>
2022-10-07 15:40:04 +02:00
5e04c9693b fix qemu_mode speed bug 2022-10-04 08:39:07 +02:00
9e4137a3eb Enabled tricore arch for unicornafl 2022-10-03 22:58:21 +02:00
jma
97fb0b5099 fix Rust speedtest example dependency (#1542) 2022-10-03 12:06:43 +02:00
9c6aebba05 typos 2022-10-03 11:04:23 +02:00
3e0fe86465 Merge pull request #1539 from devnexen/reallocarr
libdislocator adding netbsd's reallocarr
2022-10-01 18:27:02 +02:00
0eeddda2c8 libdislocator adding netbsd's reallocarr 2022-10-01 16:12:32 +01:00
586aec7116 Fixed typo in README.llvm.md (#1538)
Co-authored-by: van Hauser <vh@thc.org>
2022-09-29 12:42:04 +02:00
7e0171006a Merge pull request #1537 from AFLplusplus/dev
push to stable
2022-09-28 22:56:28 +02:00
96b7742611 enhancements to afl-persistent-config and afl-system-config 2022-09-28 21:36:25 +02:00
3c21e9f0d1 another attempt at stand-alone map fix 2022-09-27 15:51:16 +02:00
0f72a7473f Fix docs for fuzz_count in python 2022-09-27 13:45:39 +00:00
1ce0dcac3f fix standalone running with shared libs 2022-09-26 11:55:03 +02:00
77f253c1b9 fix custom mutator build scripts 2022-09-26 03:43:45 +02:00
ed54532f29 make gcc_plugin compilable for gcc 3.6.0 2022-09-23 23:19:10 +02:00
6ed40d5a08 4.04a init 2022-09-20 18:12:37 +02:00
ad4b727476 Merge pull request #1527 from AFLplusplus/dev
push to stable
2022-09-20 17:37:20 +02:00
41fe8b6ab9 update qemuafl 2022-09-20 12:58:20 +02:00
38ab1eda6e 4.03c 2022-09-19 12:15:10 +02:00
6afca4f073 fix help links 2022-09-17 14:05:24 +02:00
9cfe1d1394 afl-cmin -A 2022-09-17 13:44:34 +02:00
badd9694d2 Merge pull request #1525 from AFLplusplus/dev
push to stable
2022-09-17 11:58:41 +02:00
0623a73a5c fix docs 2022-09-17 11:56:39 +02:00
2e8a459d0b Merge pull request #1523 from lszekeres/stable
Fix null pointers.
2022-09-17 11:53:54 +02:00
02db8685f1 Fix null pointers. 2022-09-16 23:04:47 -04:00
2f0cc088b5 Merge pull request #1522 from AFLplusplus/dev
fix unicornafl
2022-09-16 14:42:07 +02:00
05b1e49bc2 fix unicornafl 2022-09-16 12:29:45 +02:00
9d45e8d810 Merge pull request #1521 from AFLplusplus/dev
update unicorn
2022-09-16 11:54:37 +02:00
5435d5c175 update unicorn 2022-09-16 11:54:12 +02:00
869138aa41 Merge pull request #1519 from AFLplusplus/dev
push to stable
2022-09-16 11:51:17 +02:00
5bf8bffd4a changelog 2022-09-16 10:57:54 +02:00
af5e8370af fix LLVMFuzzerRunDriver 2022-09-16 10:57:13 +02:00
9d9d2cada9 Typo 2022-09-16 10:53:53 +02:00
4e73828645 Added unicorn changes to changelog 2022-09-15 18:24:26 +02:00
d610821679 Re-enabled unicorn for aarch64 2022-09-15 18:23:07 +02:00
453d554fb5 Correctly multi-process unicorn builds 2022-09-15 17:33:07 +02:00
9a0cee6ce1 add temporary fix for uc until unicorn publishes a new release 2022-09-15 17:15:15 +02:00
2125950a81 undo tmp changes in unicorn_mode 2022-09-15 15:50:51 +02:00
8e3aee8a1a Fixed unicorn_mode for aarch64, update unicorn 2022-09-15 15:43:00 +02:00
636025df9a forgot correct callback 2022-09-15 10:32:34 +02:00
b7a2c7e698 try LLVMFuzzerRunDriver support 2022-09-15 10:13:46 +02:00
a7877416a8 update changelog 2022-09-15 10:00:05 +02:00
061bd75953 Merge pull request #1518 from nikic/fix-lto
Fix LTO with LLVM 15
2022-09-15 09:58:03 +02:00
b27a4a3689 Fix loading and registeration of LTO pass for new pass manager 2022-09-14 15:54:29 +02:00
a194a82bcd Fixed typo in README.lto.md (#1517)
typo fixed
2022-09-14 15:05:30 +02:00
5452d4652b Fix naming clash between AFL's sancov LTO pass and upstream sancov pass
There was some confusion here due to name reuse. The
initializeModuleSanitizerCoverageLegacyPassPass() function was
actually calling the initialization of the upstream pass (which
no longer supports legacy PM and thus fails to build on LLVM 15).
The intention was to call the LTO initialization here.

Fix this by renaming symbols to avoid collision.
2022-09-14 11:36:05 +02:00
9b6ad933cd Allow building LTO component with LLVM 15 2022-09-14 11:35:55 +02:00
36c46b9579 Fix LLVM 15 build
By removing ModuleSanitizerCoverageLegacyPass, which is completely
unused.

There was some confusing between the initialization function for
the upstream sancov pass and AFLs own implementation.
2022-09-14 10:58:22 +02:00
08f44f4e5d code format 2022-09-10 19:09:32 +02:00
f12ee5c7d2 Merge pull request #1512 from devnexen/libdislocator_attrs
libdislocator apply few attributes for few compiler optimisations.
2022-09-10 18:45:47 +02:00
258f4ee529 libdislocator apply few attributes for few compiler optimisations. 2022-09-10 11:43:19 +01:00
c06c297933 Merge pull request #1511 from tocic/fix/docs_typos
Fix typos in docs
2022-09-10 10:06:20 +02:00
ffad6f3f09 Fix typos in docs 2022-09-10 07:41:19 +03:00
3e30b700dd Dockerfile enhancements 2022-09-09 10:20:30 +02:00
05ac236a6b update changelog 2022-09-07 17:10:03 +02:00
6bb2500707 Merge pull request #1509 from CodeLogicError/stable
analyze_run_target return dataconversion
2022-09-07 17:07:15 +02:00
d06f8b2a93 analyze_run_target return dataconversion
analyze_run_target create u64 data and return u32
2022-09-07 19:59:20 +08:00
0fe39e4768 egrep -> grep -e 2022-09-05 13:57:32 +02:00
0c122aeee6 Merge pull request #1505 from tokatoka/stable
Fix my name in Changelog.md
2022-08-31 10:45:47 +02:00
3a31c5c985 update qemuafl 2022-08-30 16:07:35 +02:00
644b544bc0 fix my name 2022-08-30 13:05:22 +02:00
147654f871 Merge pull request #1504 from AFLplusplus/dev
pcguard off-by-one fix
2022-08-26 23:52:44 +02:00
2775271b17 pcguard off-by-one fix 2022-08-26 18:27:38 +02:00
413e68ab6d Merge pull request #1499 from AFLplusplus/dev
push to stable
2022-08-25 15:56:36 +02:00
eb5a914ef6 fix pizza mode 2022-08-25 15:52:46 +02:00
88ff8aa81e fix gcc_mode cmplog 2022-08-25 08:47:30 +02:00
804e845a94 Merge pull request #1500 from kobrineli/fix-dummy-mapsize
Change map size dummy value.
2022-08-19 13:46:15 +02:00
47d5dbbead Fix. 2022-08-19 14:33:15 +03:00
4ebde72f28 Change map size dummy value. 2022-08-19 14:33:15 +03:00
b4cb3784a5 add malloc check 2022-08-19 13:17:01 +02:00
7b2145b914 shorter calibration 2022-08-19 09:16:17 +02:00
361263b0f2 better no dry run 2022-08-18 08:06:17 +02:00
eeab1afd57 alt no cal 2022-08-17 12:50:15 +02:00
843ef46b21 fix docs 2022-08-16 10:05:52 +02:00
d7abf6936c fix afl-cmin 2022-08-16 09:46:11 +02:00
2462c61df9 fix new map size extraction for afl-gcc 2022-08-15 19:22:46 +02:00
ba14c353c0 get map size from binaries within afl-cmin* 2022-08-15 18:31:45 +02:00
f00d83afbc filter pipe in gcc_mode 2022-08-15 17:38:53 +02:00
4e98071385 better handling of -fsanitize=..,...,.. lists 2022-08-14 14:40:26 +02:00
1a3b463c4c add build report 2022-08-14 13:00:55 +02:00
dae5843b0e Merge pull request #1496 from devnexen/libtokencap_update_hotsummer
libtokencap annotate overriden calls to pyt them together in a special
2022-08-14 12:49:52 +02:00
3200e6515b add AFL_NO_STARTUP_CALIBRATION feature 2022-08-14 12:30:23 +02:00
130b1f7864 libtokencap annotate overriden calls to pyt them together in a special
elf (sub)section and improve their locality.
2022-08-13 07:23:34 +01:00
89d6e306f2 Merge pull request #1494 from WorksButNotTested/armhf
Armhf
2022-08-11 20:19:28 +02:00
2c8228dbe4 Changes to allow cross-compilation of pngtest 2022-08-11 17:55:23 +01:00
b5002d74b4 Fixed warnings about format strings 2022-08-11 17:55:23 +01:00
ddea91de1d Fixed makefile formatting 2022-08-11 17:55:23 +01:00
39dadab065 fix qemu_mode 2022-08-10 09:05:13 +02:00
e377ee3c57 Merge pull request #1491 from WorksButNotTested/unstable
Fix unstable test makefile
2022-08-09 10:51:07 +02:00
38fba71546 add env var 2022-08-09 10:49:05 +02:00
3c811de917 update qemuafl 2022-08-09 10:19:16 +02:00
63b12c5f86 Fix unstable test makefile 2022-08-09 08:25:00 +01:00
79a69b14ef 4.03a 2022-08-08 15:30:48 +02:00
3e2986dd78 Merge pull request #1489 from AFLplusplus/dev
push to stable
2022-08-08 15:27:07 +02:00
1f06b55a8b 4.02c 2022-08-08 15:26:56 +02:00
7b6ee28291 code format 2022-08-06 09:07:49 +02:00
94fe62ad8d Merge pull request #1467 from WorksButNotTested/droid
Android Fixes
2022-08-06 09:02:02 +02:00
608ea5f8ab Add support for Android SHM 2022-08-05 20:57:54 +01:00
00b5d3792d Changes to abstract shared memory 2022-08-05 20:56:14 +01:00
e9cb939956 Fixes to formatting 2022-08-05 20:56:14 +01:00
7b6743f14c Android fixes 2022-08-05 20:56:14 +01:00
4b9c560b07 Merge pull request #1486 from WorksButNotTested/be8
Be8
2022-08-04 21:36:59 +02:00
9d5a2d1b8e Add support for using hook on ARM32 2022-08-04 18:46:29 +01:00
1e524d1f43 Added support for ARM32 inline assembly 2022-08-04 18:46:29 +01:00
7c50ec5d05 Added support for ARM32 persistent mode 2022-08-04 18:46:29 +01:00
7bdb22c70c Added build of FRIDA mode shared library to enable embedding 2022-08-04 18:46:29 +01:00
3562de440e Changes to add option for absolute coverage data 2022-08-04 18:46:29 +01:00
98e8838755 Fix formatting 2022-08-04 18:46:29 +01:00
a2f3c3ee51 Merge pull request #1478 from AFLplusplus/dev
Push to stable
2022-08-03 11:08:10 +02:00
6056d4b140 fix pcguard vector select instrumentation 2022-08-03 10:06:52 +02:00
d745da0c93 Merge pull request #1484 from WorksButNotTested/regs
Regs
2022-07-29 22:50:25 +02:00
4fdd64d6d6 Added framework for logging register contents at the end of each basic block 2022-07-29 19:33:31 +01:00
f2b7104cd6 Fix endianness of coverage data on big endian systems 2022-07-29 17:23:30 +01:00
c6af98bc35 fix 2022-07-25 11:49:49 +02:00
67fabcb0be update compile options 2022-07-25 11:15:14 +02:00
7b7914e1d6 code format 2022-07-25 09:09:29 +02:00
9551be3f8e Merge pull request #1482 from yuawn/fix_usage_message
Fix usage message
2022-07-25 08:47:48 +02:00
f22d28333b code format with clang-format-14 2022-07-24 10:41:50 +00:00
d8d6ea93cf fix sentence & code format 2022-07-24 10:30:21 +00:00
0540d30274 fix message overflow 2022-07-24 10:23:33 +00:00
9657b700b1 Fix some OSX incompatibilities on AARCH64 (#1479)
Co-authored-by: Your Name <you@example.com>
2022-07-21 19:48:21 +02:00
6c26434a63 fix pizza mode 2022-07-21 13:41:43 +02:00
42c677aa7b fix compilation for llvm 10.0 2022-07-19 23:03:20 +02:00
0373628adf fix custom mutator examples 2022-07-19 17:28:57 +02:00
d090232452 remove debug 2022-07-19 17:06:23 +02:00
4d20b2d28b fix 2022-07-19 17:04:53 +02:00
c67f98865e fix 2022-07-19 14:53:43 +02:00
ca4a8c0f92 post_process 0/NULL return support 2022-07-19 12:24:03 +02:00
c57988e672 Merge pull request #1469 from AFLplusplus/dev
push to stable
2022-07-15 10:12:35 +02:00
b847e0f414 clang format 14 2022-07-12 09:04:54 +02:00
338f1ae2f8 fix mawk bug 2022-07-11 21:42:03 +02:00
1f4b45b5bf nit 2022-07-11 12:32:17 +02:00
30736ab7d6 nit 2022-07-11 12:16:33 +02:00
46fed1f43f Merge pull request #1472 from llzmb/docs_quality_assurance_5
Fix formatting, punctuation, and typos of docs
2022-07-11 11:53:03 +02:00
662662c15d Fix formatting, punctuation, and typos 2022-07-11 11:33:51 +02:00
d088c26045 Merge pull request #1470 from WorksButNotTested/frida
Updated FRIDA version
2022-07-08 19:47:53 +02:00
3d2a095f2e Updated FRIDA version 2022-07-08 18:22:05 +01:00
9abae56a37 Merge pull request #1453 from rhtenhove/dev
improve CI and container image build
2022-07-08 18:46:21 +02:00
1f17aa082d Dont codeql submodules 2022-07-08 08:32:17 -04:00
c7c7476453 disable formatter 2022-07-07 17:10:42 +00:00
b883faa942 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2022-07-07 17:07:57 +00:00
b1e0d6e640 fix macos ci 2022-07-07 18:39:21 +02:00
ada61204f3 Merge pull request #1468 from waugustus/add-missing-dependencies
add missing dependencies for "make source-only"
2022-07-07 15:17:35 +02:00
72344a2f5f move the apt call 2022-07-07 18:48:02 +08:00
0bb8cc46b4 build nyx in docker 2022-07-07 12:47:12 +02:00
05080f32ee fixes 2022-07-07 11:10:12 +02:00
32c4be4773 add missing dependencies for "make source-only" 2022-07-07 17:01:36 +08:00
1759859ae2 fix double free on exit for -c 0 on src cmplog 2022-07-07 09:03:46 +02:00
e6f27c2645 add missing laf compare split predicates 2022-07-07 00:34:30 +02:00
c90dd00fc9 no longer need this line 2022-07-04 22:38:28 +00:00
0da935183f allow unset env var 2022-07-04 22:36:06 +00:00
4848c8d24c use env as base 2022-07-04 22:30:03 +00:00
250000ee79 simpler format bin selector 2022-07-04 22:27:55 +00:00
fc520a2bde fix 2022-07-04 21:57:42 +02:00
6c9c8fdc65 check code formatting (#5) 2022-07-04 14:32:48 -04:00
24458ae285 nits 2022-07-04 18:13:21 +02:00
36a0ab1193 Merge pull request #1466 from rhtenhove/cpubind
feat: show bound cpu
2022-07-04 10:01:39 +02:00
1334851e7c cmplog support for gcc_plugin by adacore 2022-07-04 09:59:47 +02:00
b077a7963b feat: show bound cpu 2022-06-30 21:11:22 +00:00
3e65e1a029 fix test using test specific build 2022-06-28 15:59:56 +00:00
e21738a248 init new dev release 2022-06-28 14:30:03 +02:00
4094750803 Merge pull request #1438 from AFLplusplus/dev
push to stable
2022-06-28 14:18:44 +02:00
92352951d7 nits 2022-06-28 11:52:05 +02:00
bb509765df added back missing memcpy to python mutators 2022-06-28 11:45:22 +02:00
6705953a49 Python mutators: Gracious error handling for illegal return type (#1464)
* python types error handling

* reverted example change

* more python

* format
2022-06-28 10:23:20 +02:00
b3edb657c2 check python too 2022-06-28 01:50:39 +00:00
a1889db9bf simpler jobs 2022-06-27 16:17:02 -04:00
c83635e1d2 Merge pull request #1462 from bostick/patch-1
Update afl-system-config
2022-06-27 19:18:28 +02:00
fd404194f2 Update afl-system-config
System Integration Protection -> System Integrity Protection
2022-06-27 11:38:33 -04:00
5fa7861149 no need for that line anymore 2022-06-27 15:37:15 +00:00
e969972c97 gcta 2022-06-27 15:35:41 +00:00
80e829f79d revert more and global replace 2022-06-27 15:30:35 +00:00
73db4fe993 use actor 2022-06-27 15:13:16 +00:00
22c3b519fa reverts, fixes and even smaller image (#3) 2022-06-27 11:05:17 -04:00
88077d4136 prepare release 2022-06-27 08:44:35 +02:00
cfb0257c99 nits 2022-06-27 08:37:21 +02:00
9a93688e3e nits 2022-06-27 08:32:06 +02:00
48c2d51689 nits 2022-06-27 08:31:03 +02:00
1dac69b1eb use container; more is built + tested; use make -i (#2) 2022-06-24 09:26:09 -04:00
0da7ddb738 concurrency and caching (#1)
* use concurrency

* run here too

* allow test failure

* only push on push

* fix coresight mode build

* support but disable coresight

* woops

* no unicorn for arm

* update codeql and fix makefile

* forgot those

* disable forward cache

* fix needing buildx

Co-authored-by: Ruben ten Hove <ruben.tenhove@tno.nl>
2022-06-22 06:36:35 -04:00
6e960f78d6 arm needs qemu indeed 2022-06-21 22:01:30 +02:00
3282023047 check for package instead of if in docker 2022-06-21 21:36:02 +02:00
c7db5b67f9 just disable nyx 2022-06-21 21:30:43 +02:00
fc98d53e27 separate platforms 2022-06-21 18:54:54 +02:00
a5822c7c2f various changes 2022-06-21 18:52:43 +02:00
01cb84051a secure apt key; fix multilib 2022-06-21 16:54:47 +02:00
d9c2487c3e reduce layers, size and complexity 2022-06-21 10:30:30 -04:00
a7f3f87f41 Merge pull request #1450 from jrozner/add-22.04-to-ci
Update workflows to ubuntu 22.04
2022-06-21 07:48:49 +02:00
1a4c0d2ecd nits 2022-06-20 17:59:14 +02:00
eb37cec76e Update workflows to ubuntu 22.04
22.04 is the most recent LTS release and the official docker container
is running on it. It probably makes sense to run the unit tests on that
as well.
2022-06-19 11:42:31 -07:00
5ed993d74e Merge pull request #1440 from rhtenhove/dev
require value in env variables
2022-06-18 21:48:58 +02:00
5d5d1f70fc Merge pull request #1447 from rhtenhove/more-tags
fixes github actions
2022-06-18 21:48:10 +02:00
85b1ce00a8 fully qualified names 2022-06-18 08:35:25 -04:00
51a88b17b3 add tagged releases 2022-06-18 08:31:37 -04:00
b0e58baca2 add stable tag to docs 2022-06-18 08:21:25 -04:00
f23cac854a fix image build and push 2022-06-18 08:19:04 -04:00
0c3ba7d227 clarity 2022-06-18 07:23:06 -04:00
605f2bf969 code format 2022-06-18 09:14:44 +02:00
dc3e2e8200 update docs 2022-06-18 09:06:27 +02:00
47d4f16189 Merge pull request #1442 from rhtenhove/more-tags
Push both stable and dev
2022-06-18 08:58:49 +02:00
74f70d0c74 update name 2022-06-18 02:55:27 +02:00
be79ee7072 stable==latest 2022-06-18 02:52:57 +02:00
bf6a0159a9 formatting 2022-06-18 02:37:11 +02:00
fc3b483450 revert previous changes 2022-06-18 02:35:40 +02:00
0dd1c39b5a check for empty env var as well 2022-06-18 02:35:31 +02:00
60702fef7a Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2022-06-18 00:41:50 +02:00
a96f9a349a Merge pull request #1441 from rhtenhove/noreadme
Allow to skip README.txt creation in crashes/
2022-06-18 00:25:03 +02:00
4fdd1129f0 feat: push both dev and stable 2022-06-17 21:21:34 +02:00
4990823840 formatting 2022-06-17 21:08:37 +02:00
3d1a57deed feat: allow to skip readme creation on crash 2022-06-17 21:03:46 +02:00
47d8947471 require value in env 2022-06-17 12:10:11 -04:00
80892b8fc5 typos 2022-06-14 14:57:31 +02:00
ba21e20695 typo 2022-06-14 14:56:10 +02:00
5b471986b8 add line feed at end 2022-06-14 14:52:48 +02:00
da1b041098 update changelog 2022-06-12 08:24:32 +02:00
95aa81045b Merge pull request #1437 from Scepticz/patch-2
Fix Byte Decrement Havoc Mutation
2022-06-12 07:48:27 +02:00
b595727f2f Fix Byte Decrement Havoc Mutation
While looking at the source code of the havoc mutations I realized that there seems to be a typo / copy+paste error with the SUBBYTE_ mutation. It is currently incrementing, instead of decrementing the value.

Alternative Fix: Change the documentation to "/* Decrease byte by minus 1. */" to make it work as documented :-P
2022-06-10 18:38:37 +02:00
d798a90f04 uc update 2022-06-09 10:11:41 +02:00
35d49c7c5c fix 2022-06-08 12:46:08 +02:00
83f32c5248 honor AFL_MAP_SIZE well outside of afl++ 2022-06-08 10:56:11 +02:00
683dcc4710 remove existing shared modules when installing 2022-06-06 19:26:18 +02:00
59bb4a6cc4 Merge pull request #1431 from devnexen/malloc_good_size_apple_libdislocator
libdislocator, introduces malloc_good_size for Darwin.
2022-06-03 06:55:10 +02:00
6afccdebcd libdislocator, introduces malloc_good_size for Darwin. 2022-06-02 21:48:15 +01:00
7413316496 Merge pull request #1430 from devnexen/libdislocator_macos
libdislocator on macOS to get memory block size is malloc_size is
2022-06-01 07:32:45 +02:00
ad2a1b0574 libdislocator on macOS to get memory block size is malloc_size is
instead.
2022-05-31 21:07:02 +01:00
942b85bb77 clarify gpl3 2022-05-31 11:10:37 +02:00
50c6031cc3 remove optimin 2022-05-31 09:24:28 +02:00
066d65d846 Fix wrong memchr size in android (#1429)
Need to fix this otherwise ASAN will always complain about heap buffer overflows and refuse to run.

Co-authored-by: van Hauser <vh@thc.org>
2022-05-27 17:55:21 +02:00
1441503c43 afl-cmin: avoid messages with \r when redirection is used 2022-05-27 15:26:24 +02:00
c96238d85f Add AFL_SYNC_TIME variable for synchronization time tuning (#1425)
* Add AFL_SYNC_TIME variable for synchronization time tuning

* Documentation for AFL_SYNC_TIME variable
2022-05-27 12:52:31 +02:00
4103ee43e2 Add automaton parser (#1426)
* have compilable program

* enable read in file

* add hashmap usage

* add build hashmap; WIP; test if constructed correctly tomorrow

* add testcase to test hashmap

* add sorted symbols list

* build symbols dictionary

* clean up DEBUG

* successfully find automaton path

* fix all memory leaks

* test if automaton same with example

* able to iterate through files in a folder

* finish testing on one random queue
wip
- change macro values
- add bound checking

* add bound checking to program length

* add bound checking to program walk length

* add boundary check to terminal number, terminal lengths and program length

* commit test makefile

* add makefile

* able to add seeds to gramatron

* remove useless argument in automaton_parser

* add automaton parser to gramfuzz

* change build

* revert test.c to original state

* add makefile to test.c for testing
2022-05-26 16:21:59 +02:00
ba3c7bfe40 Merge pull request #1420 from AFLplusplus/dev
push to stable
2022-05-23 13:44:42 +02:00
5ad760a77b update changelog 2022-05-23 10:53:37 +02:00
6dfc9aaab0 disable LTO for llvm 15 :-( 2022-05-23 10:52:34 +02:00
ffdbe8a2fb Merge pull request #1411 from glandium/implicit-int
Fix build failures with clang 15
2022-05-19 11:21:32 +02:00
c5083f8982 todo 2022-05-19 11:21:09 +02:00
ca721404ef Merge pull request #1415 from che30122/dev
afl->cmplog_binary memory leak problem
2022-05-18 10:32:35 +02:00
c563faa076 fix mem leak 2022-05-17 16:47:01 +08:00
a2eb1f1412 Merge pull request #1404 from AFLplusplus/dev
push to stable
2022-05-16 12:34:38 +02:00
c08eeb95ca Merge pull request #1410 from WorksButNotTested/dynamic
A few updates
2022-05-16 11:15:21 +02:00
7c755a675f Merge pull request #1412 from HexRabbit/fix_make_deps
Fix missing dependency
2022-05-16 10:24:20 +02:00
4c0281adc8 Fix missing dependency
add `instrumentation/afl-llvm-common.o` to `SanitizerCoverageLTO.so`'s
dependency list
2022-05-16 16:10:07 +08:00
022f364661 Avoid implicit-int error in x86 test with clang 15
See 2cb2cd242c
2022-05-13 07:23:38 +09:00
3dc72ffb6b Added test for prefetch validation 2022-05-12 16:54:40 +01:00
ca361e1b6a Validate address space before prefetching 2022-05-12 16:54:40 +01:00
b36d0adb46 Update version of FRIDA 2022-05-12 16:54:40 +01:00
2a4d77abc6 Update nyx submodules (#1408) 2022-05-12 13:29:30 +02:00
dfe03a346a update unicorn 2022-05-12 09:11:25 +02:00
1605291154 Docker image update to ubuntu jammy LTS (#1406)
which brings gcc 12 and the llvm 14 suite.
2022-05-11 14:40:14 +02:00
f180109d1a Merge pull request #1405 from yuawn/fix_llvm_version
Fix LLVM version in Dockerfile comment
2022-05-11 11:29:01 +02:00
927cb770f0 fix LLVM version 2022-05-11 09:17:21 +00:00
82c6c8e563 update changelog 2022-05-10 12:18:34 +02:00
79099a01f8 fix effector map calculation 2022-05-10 11:05:43 +02:00
7c8246f18f fix 2022-05-09 14:30:40 +02:00
51942b605d support post_process's own return buffer 2022-05-09 13:18:14 +02:00
47dae21f4a Merge pull request #1401 from devnexen/fbsd_largepage
large shared segment optimisation (in TEST_MMAP mode)
2022-05-08 12:47:25 +02:00
ba12c7fc09 Merge pull request #1400 from devnexen/frida_android_bfix
frida module android build fix.
2022-05-08 12:46:33 +02:00
229a45c6a6 large shared segment optimisation (in TEST_MMAP mode)
for FreeBSD supporting such feature.

Grabbing the first kind which fit the needed size otherwise
falling back to the classic shared segment allocation.
2022-05-06 19:02:21 +01:00
45219dee80 frida module android build fix. 2022-05-06 15:56:03 +01:00
13e0fd3e1a pcguard fix for most current llvm 15 changes 2022-05-03 13:01:48 +02:00
68e8467859 fix 2022-05-02 14:11:25 +02:00
293e255734 fix mopt random selection 2022-05-02 13:09:34 +02:00
0b228fb0f5 fix token usage in normal and MOpt mode 2022-05-02 08:17:06 +02:00
01594dc416 Properly null CmpLog map in deinit (#1395)
Co-authored-by: van Hauser <vh@thc.org>
2022-04-28 09:42:49 +02:00
46d5452c86 update afl-sharedmem.c 2022-04-28 15:35:25 +08:00
c7bb0a9638 Merge pull request #1392 from AFLplusplus/dev
push to stable
2022-04-25 10:14:19 +02:00
ee409d18a6 code format 2022-04-25 10:14:04 +02:00
5d5aa430d2 add changelog 2022-04-25 09:10:59 +02:00
5792d492ed Merge pull request #1375 from wtdcode/fix_uc_static
Fix unicornafl static build
2022-04-25 09:09:18 +02:00
9ac3c53104 fix my name 2022-04-24 20:52:31 +02:00
ee50f41d29 Merge origin/dev 2022-04-24 20:13:40 +02:00
aeeca164b5 Bump unicornafl 2022-04-24 20:12:42 +02:00
b2c96f66ee unicorn 2022-04-22 10:29:56 +02:00
7f26d13345 try repeating write 2022-04-22 10:28:21 +02:00
5798c686b2 Merge pull request #1393 from jschwartzentruber/dev-wasm
instrumentation fixes for wasm
2022-04-21 10:16:41 +02:00
f53e6a6cf2 fix instrumentation for -Werror,-Wunused-but-set-variable
`used` is so it isn't optimized out. `unused` is to avoid the warning.
2022-04-20 15:39:28 -04:00
630eb943a5 use passthrough mode for wasm 2022-04-20 15:38:37 -04:00
4f42ecd815 remove WIP code 2022-04-18 13:16:10 +02:00
1d00bde6c5 code format 2022-04-18 13:14:20 +02:00
b1da7500b2 fix msg 2022-04-18 13:14:20 +02:00
223c52827a Merge pull request #1388 from mlichvar/cmin-args
afl-cmin: quote program arguments
2022-04-18 12:26:26 +02:00
e1c4a4ea7e Merge pull request #1382 from AdaCore/pr/gcc_deny_list_fix
Fix GCC plugin crash when using deny/allow list
2022-04-18 10:44:42 +02:00
b092ee4986 Merge pull request #1385 from Cornul11/update_citation
Updated citation file.
2022-04-18 10:43:38 +02:00
494c55df15 Merge pull request #1389 from yuawn/dev
update llvm version in INSTALL.md
2022-04-18 10:41:08 +02:00
35cf1fa906 Merge pull request #1390 from devnexen/map_name_libdislocator
libdislocator, new option to name an anonymous address range.
2022-04-18 10:40:27 +02:00
6e790552fe libdislocator, new option to name an anonymous address range.
For performance matter tough, disabled by default.
2022-04-15 17:34:19 +01:00
8971c9a5ce update llvm version in INSTALL.md 2022-04-14 11:26:54 +00:00
57db3e7f4f afl-cmin: quote program arguments
Quote the program arguments in the system() function to allow them to
contain spaces.
2022-04-13 13:47:51 +02:00
0540382c41 Fix persistant sample build 2022-04-13 00:43:47 +02:00
2263989e12 Fix linkage 2022-04-12 22:57:43 +02:00
6aa470d641 Sync unicornafl 2022-04-12 22:57:36 +02:00
0db57c3eec Merge origin/dev 2022-04-12 21:16:34 +02:00
ce1fc4b27d updated citation 2022-04-11 19:30:06 +02:00
5d4b0938d5 link https://github.com/fuzzah/exeptor 2022-04-08 23:28:13 +02:00
c208dcf9c5 Merge pull request #1383 from AFLplusplus/keep_tout
Keep timeouts option
2022-04-08 23:12:33 +02:00
d8317182ef update fuzzing in depth 2022-04-08 23:10:35 +02:00
e9288bcfad add AFL_KEEP_TIMEOUTS 2022-04-08 22:44:10 +02:00
396de6fc9c Fix GCC plugin crash when using deny/allow list
The provided function declaration F may not have valid location
information. Return an empty string in this case as the two callers are
already using this convention to filter out functions from being
instrumented when deny/allow list are used.
2022-04-08 09:50:08 +02:00
891f4d3c8e correct counting for tmouts 2022-04-08 09:31:39 +02:00
9933a6f3ab update grammar mutator 2022-04-07 10:21:52 +02:00
3261e86a3a save timeouts 2022-04-07 09:43:51 +02:00
3ccebbf9c5 Typo 2022-04-06 17:30:27 +02:00
9c2c35b233 Merge pull request #1381 from f0rki/no-build-nyx
add make flag to avoid building nyx mode
2022-04-06 14:31:42 +02:00
bf5b90f95a added NO_NYX flag to docs and help message 2022-04-06 14:20:36 +02:00
8385bc794a make flag to avoid building nyx mode 2022-04-06 11:54:35 +02:00
ac80678592 Merge pull request #1380 from AFLplusplus/dev
fix cmplog
2022-04-06 10:24:07 +02:00
3c5edab724 add cmplog icmp testcase to CI 2022-04-06 10:10:39 +02:00
9887f636ba Merge pull request #1376 from verifsec/patch-1
[wontfix] make error @SIMPLE_FILES
2022-04-06 09:45:15 +02:00
fc48951468 Merge pull request #1379 from devnexen/network_client_mem_leak
network client mem leak fix.
2022-04-06 09:43:34 +02:00
0e9d0ebbfe fix cmplog! 2022-04-06 09:36:57 +02:00
84e03e4a4d network client mem leak fix. 2022-04-05 22:54:36 +01:00
044d3e823e [wantfix] make error @SIMPLE_FILES
Hi there!
I tried to compile with SIMPLE_FILES, but got  an error message.
Please have a look through it.
Sincerely.

```
src/afl-fuzz-bitmap.c: In function ‘save_if_interesting’:
src/afl-fuzz-bitmap.c:706:39: error: ‘afl_state_t’ {aka ‘struct afl_state’} has no member named ‘last_kill_signal’
  706 |                afl->saved_crashes, afl->last_kill_signal);
      |                                       ^~
make: *** [GNUmakefile:437: afl-fuzz] Error 1
```
2022-04-05 17:38:34 +09:00
3fc03d4b6b Fix unicornafl static build
Signed-off-by: lazymio <mio@lazym.io>
2022-04-04 11:45:49 +02:00
15b43e6ce1 fix pizza mode 2022-04-03 19:14:59 +02:00
d9fa6af1b1 pizza mode on 1st of april 2022-04-03 09:50:18 +02:00
ef5543680a Merge pull request #1374 from CarloMara/stable
Add new mode to AFLplusplus
2022-04-03 09:31:23 +02:00
881aef21fd Merge pull request #1362 from AFLplusplus/dev
push to stable
2022-04-03 09:30:23 +02:00
26f3ec28ee Fix dyslexia and clang format 2022-04-02 13:11:39 +02:00
657e4cc812 Fix layout 2022-04-01 14:56:27 +02:00
29f0bb1c6a Add basic support for Italian users 2022-04-01 13:23:01 +02:00
c4363dd8b3 Merge pull request #1373 from rwmjones/no-circular-links
GNUmakefile.llvm: Avoid creating circular links
2022-04-01 09:42:06 +02:00
ff5882f415 Merge pull request #1372 from devnexen/frida_arm64_build_fix
frida mode fix arm64 build
2022-03-31 19:38:05 +02:00
7f56a93f5d GNUmakefile.llvm: Avoid creating circular links
Building into a DESTDIR gives circular links such as:

lrwxrwxrwx. 1 rjones rjones 17 Mar 31 18:09 /home/rjones/rpmbuild/BUILDROOT/american-fuzzy-lop-4.00c-3.git285a5cb3.fc37.x86_64/usr/lib64/afl/afl-compiler-rt.o -> afl-compiler-rt.o

I have to admit I've no idea what the original link command is trying
to achieve, but it's clearly wrong and deleting it fixes the problem.

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
2022-03-31 18:20:43 +01:00
2d7ac5f69c frida mode fix arm64 build 2022-03-31 18:11:24 +01:00
285a5cb38b Some scan-build fixes 2022-03-31 15:36:26 +00:00
51dbd0e957 ignore unused variable to let make DEBUG=1 distrib succeed 2022-03-30 20:46:57 +02:00
772e33d550 avoid compiler warning (format-truncation), needed for make DEBUG=1 all 2022-03-30 20:32:51 +02:00
77a3abfa5e remove debug 2022-03-30 17:09:00 +02:00
a436ef47e5 fix instrumentlist for LTO with clang < 13 2022-03-30 09:16:47 +02:00
b34751efbf fix qemu sigunaction tests 2022-03-29 10:34:08 +02:00
d2ea1141eb cleanup 2022-03-27 11:35:38 +02:00
3f0d642f9b fix unicornafl test 2022-03-26 19:13:49 +00:00
7598efb8e6 Merge pull request #1363 from clchrlls/stable
fix installation packages commands for debian 10
2022-03-23 17:20:03 +01:00
0dca6ee038 put back the title of the page deleted by mistake 2022-03-23 17:11:22 +01:00
a601b56627 reverted to simply changing gcc version retrieval 2022-03-23 17:09:31 +01:00
ce0db35f18 Not sure the fix is needed only for debian 10 2022-03-23 15:03:56 +01:00
d012358748 missing column 2022-03-23 15:02:47 +01:00
d4734f6d9b fix installation packages for debian 10 2022-03-23 14:57:24 +01:00
bcf123e1ee update qemu mode 2022-03-23 09:30:16 +01:00
9a87e83bf4 Merge pull request #1359 from fuzzah/fix-1333-afl-target-env
fix early return in AFL_TARGET_ENV
2022-03-21 22:47:19 +01:00
c2ae24ab96 fix early return in AFL_TARGET_ENV 2022-03-21 22:58:17 +03:00
13c8a27faa Merge pull request #1355 from rwmjones/document-linker-scripts
docs: Document linker scripts change required in some projects
2022-03-19 15:58:11 +01:00
a133aa9106 docs: Document linker scripts change required in some projects
AFL instrumentation modifies the binary to export extra symbols which
must be visible if the main binary dlopen()s an instrumented DLL.
This change was required by nbdkit since it uses a linker script to
limit the symbols exported from the main binary:

355cacb812

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
2022-03-18 15:52:50 +00:00
fa2b040476 fix LTO with cmplog and laf 2022-03-18 15:00:24 +01:00
69c9a176eb our own PCGUARD mode not for llvm 10.0.1 2022-03-18 12:57:51 +01:00
bdfac291ba fix split pass loading 2022-03-18 08:47:45 +01:00
90fd61d14a forgot one pass 2022-03-17 19:43:14 +01:00
3d1be62c96 merge fixes 2022-03-17 16:39:40 +01:00
d1f59435ca Merge pull request #1353 from AFLplusplus/newpm2
new pass manager
2022-03-17 16:30:44 +01:00
1bea949f34 Merge branch 'dev' into newpm2 2022-03-17 16:30:29 +01:00
3c11a37757 fixes for llvm < 11 2022-03-17 15:48:06 +01:00
e4f201707f make LTO pass work too plus some fixes 2022-03-17 14:35:15 +01:00
59eaed2f70 make pcguard work 2022-03-17 13:52:48 +01:00
1a65df2bee Merge pull request #1352 from cd80/patch-1
fix typo in error message when using LD_PRELOAD
2022-03-17 08:46:15 +01:00
c08304ad3d fix typo for error message when using LD_PRELOAD 2022-03-17 14:36:41 +09:00
2b8fea083e test 2022-03-15 07:35:37 +01:00
34d7a6357e Merge pull request #1347 from WorksButNotTested/cache
Add global caching of block translation to instrumentation
2022-03-08 11:44:15 +01:00
ae9897ff7b Merge pull request #1346 from mchesser/patches
Fix Shm trim bug and OOB accesses during Redqueen mutations.
2022-03-07 09:52:34 +01:00
d297738255 nits 2022-03-07 09:37:19 +01:00
981a04eb27 new compiler performance options 2022-03-07 08:13:24 +01:00
2a00f32666 Fix buffer overrun in rtn_extended_encoding
`idx + i` can range from `0` to `buf.len`, but the memcpy may try and write to offsets from `idx + i` to `idx + 2 * i`.
2022-03-07 15:26:54 +10:30
c2229b506e Fix off by one bounds check
`is_hex` reads two bytes but caller previously only ensured that one byte was in bounds.
2022-03-07 14:35:25 +10:30
70cc32dc6d Fix issue with trim in shared memory mode 2022-03-07 14:28:45 +10:30
5385cc7618 sancov will be only for llvm11+ 2022-03-04 15:03:26 +01:00
2eeba2dbf0 code format 2022-03-04 09:41:21 +01:00
09123d8617 Merge pull request #1344 from schumilo/dev
support Nyx crash logs
2022-03-04 09:37:21 +01:00
713b069f40 fix compile error on non linux targets 2022-03-04 06:01:49 +01:00
0f7419fc91 write nyx crash logs to AFL++ work directory 2022-03-04 05:41:40 +01:00
7c9b7c0bc0 update submodules 2022-03-04 05:35:27 +01:00
544b68044a fix broken code format 2022-03-04 03:36:52 +01:00
33e43b11f8 port instrumentation/afl-llvm-dict2file 2022-03-03 18:24:26 +01:00
a2d54218ad ported cmplog-routines-pass 2022-03-03 17:27:50 +01:00
899fa59ab6 port cmplog-switches-pass 2022-03-03 17:11:41 +01:00
f2831419f5 ported cmplog-instructions-pass 2022-03-03 08:55:05 +01:00
d325fa5db8 code format 2022-03-01 20:13:57 +01:00
7e67545b9d code format 2022-03-01 20:01:12 +01:00
d84a8da1e9 allow for -c0 also for src targets 2022-03-01 19:30:17 +01:00
f70760896c Revert "Merge branch 'newpm2' into dev"
This reverts commit fee1acf7e6, reversing
changes made to 675d17d737.
2022-03-01 19:21:31 +01:00
c9504867da Merge pull request #1342 from martinclauss/patch-1
Update fuzzing_in_depth.md
2022-03-01 16:27:09 +01:00
744ad172e1 Update fuzzing_in_depth.md
add libdesock as an additional way to ease the fuzzing for network servers (#1341)
2022-03-01 15:42:04 +01:00
5e9286b9ea todo list for llvm 2022-02-28 17:43:58 +01:00
d22532d8d3 Merge pull request #1340 from AFLplusplus/dev
Dev
2022-02-28 17:42:40 +01:00
cd02f635db remove file 2022-02-28 17:42:11 +01:00
819a1539a6 Merge pull request #1337 from devnexen/llvm_13_plus_fix
Fix build for the LLVM pass for LLVM >= 13
2022-02-27 17:25:42 +01:00
ba7ec51232 Merge pull request #1339 from adamdoupe/dev
Clarify in docs that AFL_TARGET_ENV will apply to QEMU in QEMU mode.
2022-02-27 17:25:02 +01:00
1840c27b6f Clarify in docs that AFL_TARGET_ENV will apply to QEMU in QEMU mode, and note that QEMU_SET_ENV should be used instead in QEMU mode. Closes #1328 2022-02-26 22:20:58 +00:00
e996112fbc Fix build for the LLVM pass for LLVM >= 13
Due to change of inheritance for more modern LLVM versions, the overridable
members are not the same.
2022-02-24 14:50:44 +00:00
9b799aeddd Merge pull request #1335 from AFLplusplus/dev
Dev
2022-02-22 13:59:04 +01:00
fee1acf7e6 Merge branch 'newpm2' into dev 2022-02-22 13:58:49 +01:00
675d17d737 Merge pull request #1334 from Teemperor/llvm14
Fix compilation against LLVM 14
2022-02-22 13:51:39 +01:00
05119990b6 LLVM 14 fixes 2022-02-22 11:13:00 +01:00
914eb79cbc todo list 2022-02-21 10:32:43 +01:00
92db443635 Revert "remove new llvm pass manager :("
This reverts commit 55ed2a443c.
2022-02-20 19:51:43 +01:00
852c036cae Add global caching of block translation to instrumentation 2022-02-18 17:39:21 +00:00
a5943dc782 Merge pull request #1332 from WorksButNotTested/module
Module
2022-02-18 11:04:45 +01:00
fc7bf33fb1 Reserved used address space on dlclose to prevent re-use 2022-02-18 08:21:36 +00:00
fcd06fa99c Added test for running python 2022-02-18 08:20:51 +00:00
5f45f380c3 Changes to default CMOV instrumentation to off 2022-02-18 08:10:19 +00:00
cb1256499f Added instrumentation for CMOV instructions 2022-02-18 08:01:34 +00:00
dd8ad4dfa3 Changes to simplify coverage code 2022-02-18 07:55:26 +00:00
8fc249d210 Fix sample script for Unicornafl2 (#1329)
* Fix the sample script for Unicornafl2

* Make it compatible with unicornafl1

* Sync to the latest unicornafl

* Update UNICORNAFL_VERSION

* Sync to latest unicornafl to resolve linkage problem

* Switch to ucafl2
2022-02-14 18:01:37 +01:00
1d4f1e4879 Merge pull request #1326 from AFLplusplus/dev
push to stable
2022-02-10 12:12:02 +01:00
de7058b75b typo 2022-02-10 10:40:11 +01:00
5e8da2b85c Adapt to my MacOS 2022-02-09 20:36:16 +01:00
056ebbff15 add AFL_EARLY_FORKSERVER support 2022-02-08 20:36:06 +01:00
cf853fb249 reintroduce AFL_PERSISTENT and AFL_DEFER_FORKSRV 2022-02-08 20:15:48 +01:00
fa628865c1 remove debug msg 2022-02-08 18:43:23 +01:00
05a36f10ba import mozilla afl-cc patch 2022-02-08 18:33:59 +01:00
cbf3d1bdee Merge pull request #1325 from devnexen/openbsd_sysconf_upd
afl-system-config update proposal for OpenBSD.
2022-02-08 13:40:21 +01:00
64cc345ec2 afl-system-config update proposal for OpenBSD.
The vast majority of security features can t be disabled but we can
act of allocation config.
2022-02-08 11:25:19 +00:00
8dbc4a1423 Merge pull request #1324 from WorksButNotTested/compile
Fix initialization in non-persistent mode
2022-02-08 12:17:20 +01:00
452eb9f75b Fix initialization in non-persistent mode 2022-02-08 08:58:35 +00:00
a5dc067331 nits 2022-02-07 12:22:57 +01:00
27dc0e09e0 Merge pull request #1323 from yuawn/dev
Add GCC hot attribute to hot functions
2022-02-06 11:51:54 +01:00
bcd802e6fd code format 2022-02-06 08:54:30 +00:00
958a059477 add GCC hot attribute to hot functions 2022-02-06 08:54:14 +00:00
c8bfce21ab Merge pull request #1322 from yuawn/dev
fix -G description
2022-02-06 09:13:40 +01:00
d178b325ab fix -G description 2022-02-06 05:34:44 +00:00
077a3e32e0 fix accidental broken frida mode 2022-02-05 10:57:58 +01:00
fa3c0d8a37 change -y to -g/-G and add env var alternatives 2022-02-05 10:36:37 +01:00
d5b9cd4b73 add afl-fuzz -y fuzz length support 2022-02-05 08:27:17 +01:00
ce5032cc29 debug CI 2022-02-05 07:32:20 +01:00
04d693721b force persistent and deferred also for tools 2022-02-05 07:25:12 +01:00
9eb66cccf4 typo 2022-02-04 15:06:53 +01:00
9b72fe4880 typo 2022-02-04 13:59:11 +01:00
1a89d428c9 same for defered forkserver 2022-02-04 12:12:23 +01:00
d4c01c057b test support for forced persistent mode 2022-02-04 12:09:07 +01:00
80543a809e small doc update 2022-02-01 20:15:45 +01:00
104c0e29e9 small doc update 2022-02-01 20:14:41 +01:00
7d36609722 libafl custom mut readme 2022-02-01 15:53:05 +01:00
119a0e0dce fix build scripts 2022-02-01 14:16:49 +01:00
f336aa463b Merge pull request #1307 from WorksButNotTested/arm64
ARM64
2022-02-01 11:09:39 +01:00
5f6bbc7dea Changes to fix persistent_ret demo 2022-02-01 08:13:28 +00:00
17fc44d995 Fix libunwind libraries when building from source 2022-02-01 08:13:28 +00:00
jon
055af82026 Make default coverage code branchless 2022-02-01 08:13:28 +00:00
e2f76dd41e AARCH64 branch suppression 2022-02-01 08:13:28 +00:00
1c79b82ab8 Add AARCH64 support for setting ic_entries 2022-02-01 08:13:28 +00:00
jon
c38b05c80a Fixed build from source on OSX 2022-02-01 08:13:28 +00:00
bb186a2ece Bump FRIDA version 2022-02-01 08:13:18 +00:00
60e126c615 mention arm64 docker image 2022-01-31 09:24:04 +01:00
dd9003e59b nits for nyx build script 2022-01-31 09:00:01 +01:00
2d9325aed9 Merge pull request #1319 from AFLplusplus/dev
push to stable
2022-01-30 20:59:24 +01:00
53eb5ba2fb update changelog 2022-01-30 20:59:00 +01:00
267dd634f1 Merge pull request #1318 from moyix/stable
Build docker images for arm64 as well as x86.
2022-01-30 20:55:55 +01:00
7ab7862e4d Build docker images for arm64 as well as x86.
This involves:

* A small change to the Dockerfile, so that it checks the target
  architecture and only installs gcc-multilib on x86_64.
* Updates to the GitHub Actions workflow build_aflplusplus_docker.yaml
  to build for both linux/amd64 and linux/arm64.

These changes should allow Mac M1 users to get a working version of
AFL++ by doing "docker pull aflplusplus/aflplusplus".
2022-01-30 14:20:30 -05:00
59a7337bf1 fix ci for mac 2022-01-30 18:02:09 +01:00
c75124aefa debug ci 2022-01-30 17:53:28 +01:00
2861f695ba debug ci 2022-01-30 17:19:22 +01:00
43a7c0d601 make build_... scripts work without afl++ git checkout 2022-01-30 14:50:15 +01:00
311649f458 make fPIC default 2022-01-29 22:16:16 +01:00
a5eafbff6c Merge pull request #1315 from devnexen/afl_fuzz_non_linux
afl fuzz enable getpgid on other platforms.
2022-01-29 21:43:53 +01:00
1d339527bb afl fuzz enable getpgid on other platforms. 2022-01-29 19:32:36 +00:00
707b1701c3 Add cmake in installation instructions (#1313) 2022-01-29 16:32:55 +01:00
b2465a05eb Merge pull request #1311 from AFLplusplus/libafl_mutator
LibAFL basic (just havoc + tokens) custom mutator
2022-01-27 09:00:57 +01:00
aa5f59b501 libafl_base custom mutator 2022-01-26 21:45:30 +01:00
08c39c1552 fix cfg in macro_rules in rust custom mutator 2022-01-26 21:44:07 +01:00
f75535807a 4.01a init 2022-01-26 11:11:42 +01:00
237 changed files with 9866 additions and 4229 deletions

View File

@ -19,40 +19,22 @@ import subprocess
import sys
import os
import re
import shutil
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use
with open(".clang-format") as f:
fmt = f.read()
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
if CLANG_FORMAT_BIN is None:
o = 0
try:
p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
o, _ = p.communicate()
o = str(o, "utf-8")
o = re.sub(r".*ersion ", "", o)
# o = o[len("clang-format version "):].strip()
o = o[: o.find(".")]
o = int(o)
except:
print("clang-format-11 is needed. Aborted.")
exit(1)
# if o < 7:
# if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
# CLANG_FORMAT_BIN = 'clang-format-7'
# elif subprocess.call(['which', 'clang-format-8'], stdout=subprocess.PIPE) == 0:
# CLANG_FORMAT_BIN = 'clang-format-8'
# elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0:
# CLANG_FORMAT_BIN = 'clang-format-9'
# elif subprocess.call(['which', 'clang-format-11'], stdout=subprocess.PIPE) == 0:
# CLANG_FORMAT_BIN = 'clang-format-11'
# else:
# print ("clang-format 7 or above is needed. Aborted.")
# exit(1)
else:
CLANG_FORMAT_BIN = "clang-format-11"
CURRENT_LLVM = os.getenv('LLVM_VERSION', 14)
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
if shutil.which(CLANG_FORMAT_BIN) is None:
CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}"
if shutil.which(CLANG_FORMAT_BIN) is None:
print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.")
exit(1)
COLUMN_LIMIT = 80
for line in fmt.split("\n"):

View File

@ -1,65 +1,75 @@
!/coresight_mode
*.dSYM
*.o
*.pyc
*.so
.sync_tmp
.test
.test2
.sync_tmp
*.o
*.so
*.pyc
*.dSYM
as
ld
in
out
core*
.git
.dockerignore
.github
CITATION.cff
CONTRIBUTING.md
Changelog.md
Dockerfile
LICENSE
TODO.md
afl-analyze
afl-as
afl-clang
afl-clang\+\+
afl-clang-fast
afl-clang-fast\+\+
afl-clang-lto
afl-clang-lto\+\+
afl-fuzz
afl-g\+\+
afl-gcc
afl-gcc-fast
afl-g\+\+-fast
afl-gotcpu
afl-ld
afl-ld-lto
afl-qemu-trace
afl-showmap
afl-tmin
afl-analyze.8
afl-as
afl-as.8
afl-clang-fast\+\+.8
afl-clang
afl-clang-fast
afl-clang-fast.8
afl-clang-fast\+\+
afl-clang-fast\+\+.8
afl-clang-lto
afl-clang-lto.8
afl-clang-lto\+\+
afl-clang-lto\+\+.8
afl-clang\+\+
afl-cmin.8
afl-cmin.bash.8
afl-fuzz
afl-fuzz.8
afl-gcc.8
afl-gcc-fast.8
afl-g\+\+
afl-g\+\+-fast
afl-g\+\+-fast.8
afl-gcc
afl-gcc-fast
afl-gcc-fast.8
afl-gcc.8
afl-gotcpu
afl-gotcpu.8
afl-ld
afl-ld-lto
afl-plot.8
afl-qemu-trace
afl-showmap
afl-showmap.8
afl-system-config.8
afl-tmin
afl-tmin.8
afl-whatsup.8
as
core*
examples/afl_frida/afl-frida
examples/afl_frida/frida-gum-example.c
examples/afl_frida/frida-gum.h
examples/afl_frida/libtestinstr.so
examples/afl_network_proxy/afl-network-client
examples/afl_network_proxy/afl-network-server
in
ld
out
qemu_mode/libcompcov/compcovtest
qemu_mode/qemu-*
test/unittests/unit_hash
test/unittests/unit_list
test/unittests/unit_maybe_alloc
test/unittests/unit_preallocable
test/unittests/unit_rand
unicorn_mode/samples/*/\.test-*
unicorn_mode/samples/*/output
unicorn_mode/unicornafl
test/unittests/unit_maybe_alloc
test/unittests/unit_preallocable
test/unittests/unit_list
test/unittests/unit_rand
test/unittests/unit_hash
examples/afl_network_proxy/afl-network-server
examples/afl_network_proxy/afl-network-client
examples/afl_frida/afl-frida
examples/afl_frida/libtestinstr.so
examples/afl_frida/frida-gum-example.c
examples/afl_frida/frida-gum.h

View File

@ -1,25 +0,0 @@
name: Publish Docker Images
on:
push:
branches: [ stable ]
# paths:
# - Dockerfile
jobs:
push_to_registry:
name: Push Docker images to Dockerhub
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Publish aflpp to Registry
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: aflplusplus/aflplusplus:latest

View File

@ -2,21 +2,24 @@ name: CI
on:
push:
branches: [ stable, dev ]
branches:
- stable
- dev
pull_request:
branches: [ stable, dev ]
branches:
- dev # No need for stable-pull-request, as that equals dev-push
jobs:
linux:
runs-on: '${{ matrix.os }}'
runs-on: "${{ matrix.os }}"
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
env:
AFL_SKIP_CPUFREQ: 1
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: debug
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
- name: update
@ -38,9 +41,9 @@ jobs:
AFL_SKIP_CPUFREQ: 1
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: install
run: brew install make gcc
run: brew install make gcc llvm
- name: fix install
run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
- name: build

33
.github/workflows/code-format.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Formatting
on:
push:
branches:
- stable
- dev
pull_request:
branches:
- dev # No need for stable-pull-request, as that equals dev-push
jobs:
code-format-check:
name: Check code format
if: ${{ 'false' == 'true' }} # Disable the job
runs-on: ubuntu-22.04
container: docker.io/aflplusplus/aflplusplus:dev
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Format
run: |
git config --global --add safe.directory /__w/AFLplusplus/AFLplusplus
apt-get update
apt-get install -y clang-format-${LLVM_VERSION}
make code-format
- name: Check if code needed formatting
run: |
git --no-pager -c color.ui=always diff HEAD
if ! git diff HEAD --quiet; then
echo "[!] Please run 'make code-format' and push its changes."
exit 1
fi

View File

@ -2,31 +2,32 @@ name: "CodeQL"
on:
push:
branches: [ stable, dev ]
branches:
- stable
- dev
pull_request:
branches: [ stable, dev ]
branches:
- dev # No need for stable-pull-request, as that equals dev-push
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
container: # We use a previous image as it's expected to have all the dependencies
image: docker.io/aflplusplus/aflplusplus:dev
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Fix for using external repo in container build # https://github.com/actions/checkout/issues/760
run: git config --global --add safe.directory /__w/AFLplusplus/AFLplusplus
- name: Checkout
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: cpp, python
- name: Build AFLplusplus # Rebuild because CodeQL needs to monitor the build process
env:
CC: gcc # These are symlinked to the version used in the container build
CXX: g++
run: make -i all # Best effort using -i
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

75
.github/workflows/container.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: Container
on:
push:
branches:
- stable
- dev
tags:
- "*"
pull_request:
branches:
- dev # No need for stable-pull-request, as that equals dev-push
jobs:
build-and-test-amd64:
name: Test amd64 image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build amd64
uses: docker/build-push-action@v3
with:
context: .
tags: aflplusplus:test-amd64
load: true
cache-to: type=gha,mode=max
build-args: |
TEST_BUILD=1
- name: Test amd64
run: >
docker run --rm aflplusplus:test-amd64 bash -c "
apt-get update &&
apt-get install -y libcmocka-dev &&
make -i tests
"
push:
name: Push amd64 and arm64 images
runs-on: ubuntu-latest
needs:
- build-and-test-amd64
if: ${{ github.event_name == 'push' && github.repository == 'AFLplusplus/AFLplusplus' }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to docker.io
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Set tags to push
id: push-tags
run: |
PUSH_TAGS=docker.io/aflplusplus/aflplusplus:${GITHUB_REF_NAME}
if [ "${GITHUB_REF_NAME}" = "stable" ]; then
PUSH_TAGS=${PUSH_TAGS},docker.io/aflplusplus/aflplusplus:latest
fi
export PUSH_TAGS
echo "::set-output name=PUSH_TAGS::${PUSH_TAGS}"
- name: Push to docker.io registry
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.push-tags.outputs.PUSH_TAGS }}
cache-from: type=gha

View File

@ -2,9 +2,12 @@ name: Rust Custom Mutators
on:
push:
branches: [ stable, dev ]
branches:
- stable
- dev
pull_request:
branches: [ stable, dev ]
branches:
- dev # No need for stable-pull-request, as that equals dev-push
jobs:
test:
@ -15,9 +18,9 @@ jobs:
working-directory: custom_mutators/rust
strategy:
matrix:
os: [ubuntu-20.04]
os: [ubuntu-22.04, ubuntu-20.04]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Rust Toolchain
uses: actions-rs/toolchain@v1
with:
@ -27,4 +30,4 @@ jobs:
- name: Run General Tests
run: cargo test
- name: Run Tests for afl_internals feature flag
run: cd custom_mutator && cargo test --features=afl_internals
run: cd custom_mutator && cargo test --features=afl_internals

1
.gitignore vendored
View File

@ -97,3 +97,4 @@ utils/persistent_mode/persistent_demo_new
utils/persistent_mode/test-instr
!coresight_mode
!coresight_mode/coresight-trace
vuln_prog

3
.gitmodules vendored
View File

@ -10,9 +10,6 @@
[submodule "custom_mutators/gramatron/json-c"]
path = custom_mutators/gramatron/json-c
url = https://github.com/json-c/json-c
[submodule "utils/optimin/EvalMaxSAT"]
path = utils/optimin/EvalMaxSAT
url = https://github.com/FlorentAvellaneda/EvalMaxSAT
[submodule "coresight_mode/patchelf"]
path = coresight_mode/patchelf
url = https://github.com/NixOS/patchelf.git

View File

@ -76,6 +76,7 @@ cc_binary {
srcs: [
"src/afl-fuzz*.c",
"src/afl-common.c",
"src/afl-forkserver.c",
"src/afl-sharedmem.c",
"src/afl-forkserver.c",
"src/afl-performance.c",

View File

@ -11,12 +11,12 @@ authors:
family-names: Fioraldi
email: andreafioraldi@gmail.com
- given-names: Dominik
family-names: Meier
family-names: Maier
email: mail@dmnk.co
title: "AFL++"
version: 3.14
version: 4.00c
type: software
date-released: 2021-07-19
date-released: 2022-01-26
url: "https://github.com/AFLplusplus/AFLplusplus"
keywords:
- fuzzing

View File

@ -1,75 +1,95 @@
#
# This Dockerfile for AFLplusplus uses Ubuntu 20.04 focal and
# installs LLVM 11 from llvm.org for afl-clang-lto support :-)
# It also installs gcc/g++ 10 from the Ubuntu development platform
# since focal has gcc-10 but not g++-10 ...
# This Dockerfile for AFLplusplus uses Ubuntu 22.04 jammy and
# installs LLVM 14 for afl-clang-lto support.
#
# GCC 11 is used instead of 12 because genhtml for afl-cov doesn't like it.
#
FROM ubuntu:20.04 AS aflplusplus
FROM ubuntu:22.04 AS aflplusplus
LABEL "maintainer"="afl++ team <afl@aflplus.plus>"
LABEL "about"="AFLplusplus docker image"
LABEL "about"="AFLplusplus container image"
### Comment out to enable these features
# Only available on specific ARM64 boards
ENV NO_CORESIGHT=1
# Possible but unlikely in a docker container
ENV NO_NYX=1
### Only change these if you know what you are doing:
# LLVM 15 does not look good so we stay at 14 to still have LTO
ENV LLVM_VERSION=14
# GCC 12 is producing compile errors for some targets so we stay at GCC 11
ENV GCC_VERSION=11
### No changes beyond the point unless you know what you are doing :)
ARG DEBIAN_FRONTEND=noninteractive
env NO_ARCH_OPT 1
RUN apt-get update && \
apt-get -y install --no-install-suggests --no-install-recommends \
automake \
cmake \
meson \
ninja-build \
bison flex \
build-essential \
git \
python3 python3-dev python3-setuptools python-is-python3 \
libtool libtool-bin \
libglib2.0-dev \
wget vim jupp nano bash-completion less \
apt-utils apt-transport-https ca-certificates gnupg dialog \
libpixman-1-dev \
gnuplot-nox \
&& rm -rf /var/lib/apt/lists/*
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main" >> /etc/apt/sources.list && \
wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu focal main" >> /etc/apt/sources.list && \
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 1E9377A2BA9EF27F
ENV NO_ARCH_OPT=1
ENV IS_DOCKER=1
RUN apt-get update && apt-get full-upgrade -y && \
apt-get -y install --no-install-suggests --no-install-recommends \
gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib gcc-multilib gdb lcov \
clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools \
&& rm -rf /var/lib/apt/lists/*
apt-get install -y --no-install-recommends wget ca-certificates apt-utils && \
rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 0
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
RUN echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg.key] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION} main" > /etc/apt/sources.list.d/llvm.list && \
wget -qO /etc/apt/keyrings/llvm-snapshot.gpg.key https://apt.llvm.org/llvm-snapshot.gpg.key
ENV LLVM_CONFIG=llvm-config-12
RUN apt-get update && \
apt-get -y install --no-install-recommends \
make cmake automake meson ninja-build bison flex \
git xz-utils bzip2 wget jupp nano bash-completion less vim joe ssh psmisc \
python3 python3-dev python3-setuptools python-is-python3 \
libtool libtool-bin libglib2.0-dev \
apt-transport-https gnupg dialog \
gnuplot-nox libpixman-1-dev \
gcc-${GCC_VERSION} g++-${GCC_VERSION} gcc-${GCC_VERSION}-plugin-dev gdb lcov \
clang-${LLVM_VERSION} clang-tools-${LLVM_VERSION} libc++1-${LLVM_VERSION} \
libc++-${LLVM_VERSION}-dev libc++abi1-${LLVM_VERSION} libc++abi-${LLVM_VERSION}-dev \
libclang1-${LLVM_VERSION} libclang-${LLVM_VERSION}-dev \
libclang-common-${LLVM_VERSION}-dev libclang-cpp${LLVM_VERSION} \
libclang-cpp${LLVM_VERSION}-dev liblld-${LLVM_VERSION} \
liblld-${LLVM_VERSION}-dev liblldb-${LLVM_VERSION} liblldb-${LLVM_VERSION}-dev \
libllvm${LLVM_VERSION} libomp-${LLVM_VERSION}-dev libomp5-${LLVM_VERSION} \
lld-${LLVM_VERSION} lldb-${LLVM_VERSION} llvm-${LLVM_VERSION} \
llvm-${LLVM_VERSION}-dev llvm-${LLVM_VERSION}-runtime llvm-${LLVM_VERSION}-tools \
$([ "$(dpkg --print-architecture)" = "amd64" ] && echo gcc-${GCC_VERSION}-multilib gcc-multilib) \
$([ "$(dpkg --print-architecture)" = "arm64" ] && echo libcapstone-dev) && \
rm -rf /var/lib/apt/lists/*
# gcc-multilib is only used for -m32 support on x86
# libcapstone-dev is used for coresight_mode on arm64
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 0
RUN wget -qO- https://sh.rustup.rs | CARGO_HOME=/etc/cargo sh -s -- -y -q --no-modify-path
ENV PATH=$PATH:/etc/cargo/bin
ENV LLVM_CONFIG=llvm-config-${LLVM_VERSION}
ENV AFL_SKIP_CPUFREQ=1
ENV AFL_TRY_AFFINITY=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov /afl-cov
RUN cd /afl-cov && make install && cd ..
RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov && \
(cd afl-cov && make install) && rm -rf afl-cov
COPY . /AFLplusplus
WORKDIR /AFLplusplus
COPY . .
RUN export CC=gcc-10 && export CXX=g++-10 && make clean && \
make distrib && make install && make clean
ARG CC=gcc-$GCC_VERSION
ARG CXX=g++-$GCC_VERSION
RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc'
RUN echo '. /etc/bash_completion' >> ~/.bashrc
RUN echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc
RUN echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc
ENV IS_DOCKER="1"
# Used in CI to prevent a 'make clean' which would remove the binaries to be tested
ARG TEST_BUILD
# Disabled until we have the container ready
#COPY --from=aflplusplus/afl-dyninst /usr/local/lib/libdyninstAPI_RT.so /usr/local/lib/libdyninstAPI_RT.so
#COPY --from=aflplusplus/afl-dyninst /afl-dyninst/libAflDyninst.so /usr/local/lib/libAflDyninst.so
RUN sed -i.bak 's/^ -/ /g' GNUmakefile && \
make clean && make distrib && \
([ "${TEST_BUILD}" ] || (make install && make clean)) && \
mv GNUmakefile.bak GNUmakefile
RUN echo "set encoding=utf-8" > /root/.vimrc && \
echo ". /etc/bash_completion" >> ~/.bashrc && \
echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc && \
echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc

View File

@ -76,9 +76,9 @@ else
endif
endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
endif
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
#endif
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
# ifndef SOURCE_DATE_EPOCH
@ -92,9 +92,13 @@ ifneq "$(SYS)" "Darwin"
# SPECIAL_PERFORMANCE += -march=native
#endif
# OS X does not like _FORTIFY_SOURCE=2
ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif
ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif
else
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
LDFLAGS += $(SDK_LD)
endif
ifeq "$(SYS)" "SunOS"
@ -138,12 +142,13 @@ ifdef DEBUG
$(info Compiling DEBUG version of binaries)
override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
else
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
endif
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wno-pointer-arith \
-fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
# -fstack-protector
ifeq "$(SYS)" "FreeBSD"
override CFLAGS += -I /usr/local/include/
@ -167,9 +172,9 @@ endif
ifeq "$(SYS)" "Haiku"
SHMAT_OK=0
override CFLAGS += -DUSEMMAP=1 -Wno-error=format -fPIC
override CFLAGS += -DUSEMMAP=1 -Wno-error=format
override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
SPECIAL_PERFORMANCE += -DUSEMMAP=1
#SPECIAL_PERFORMANCE += -DUSEMMAP=1
endif
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
@ -241,9 +246,6 @@ else
endif
ifneq "$(filter Linux GNU%,$(SYS))" ""
ifndef DEBUG
override CFLAGS += -D_FORTIFY_SOURCE=2
endif
override LDFLAGS += -ldl -lrt -lm
endif
@ -307,10 +309,21 @@ endif
.PHONY: all
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
-$(MAKE) -C utils/aflpp_driver
@echo
@echo
@echo Build Summary:
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be build, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
ifneq "$(SYS)" "Darwin"
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif
@echo
.PHONY: llvm
llvm:
-$(MAKE) -j4 -f GNUmakefile.llvm
-$(MAKE) -j$(nproc) -f GNUmakefile.llvm
@test -e afl-cc || { echo "[-] Compiling afl-cc failed. You seem not to have a working compiler." ; exit 1; }
.PHONY: gcc_plugin
@ -365,14 +378,18 @@ help:
@echo Known build environment options:
@echo "=========================================="
@echo STATIC - compile AFL++ static
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
@echo UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
@echo PROFILING - compile afl-fuzz with profiling information
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
@echo NO_PYTHON - disable python support
@echo NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
@echo NO_NYX - disable building nyx mode dependencies
@echo "NO_CORESIGHT - disable building coresight (arm64 only)"
@echo NO_UNICORN_ARM64 - disable building unicorn on arm64
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
@echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g. Debian)"
@echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)"
@echo "=========================================="
@echo e.g.: make ASAN_BUILD=1
@ -384,7 +401,7 @@ test_x86:
@echo "[*] Testing the PATH environment variable..."
@test "$${PATH}" != "$${PATH#.:}" && { echo "Please remove current directory '.' from PATH to avoid recursion of 'as', thanks!"; echo; exit 1; } || :
@echo "[*] Checking for the ability to compile x86 code..."
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
@echo 'int main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) $(LDFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
@rm -f .test1
else
test_x86:
@ -420,7 +437,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
@ln -sf afl-as as
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
$(CC) $(CFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
@ -528,7 +545,7 @@ code-format:
ifndef AFL_NO_X86
test_build: afl-cc afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@ -564,17 +581,18 @@ all_done: test_build
.PHONY: clean
clean:
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
-$(MAKE) -f GNUmakefile.llvm clean
-$(MAKE) -f GNUmakefile.gcc_plugin clean
-$(MAKE) -C utils/libdislocator clean
-$(MAKE) -C utils/libtokencap clean
$(MAKE) -C utils/aflpp_driver clean
-$(MAKE) -C utils/aflpp_driver clean
-$(MAKE) -C utils/afl_network_proxy clean
-$(MAKE) -C utils/socket_fuzzing clean
-$(MAKE) -C utils/argv_fuzzing clean
-$(MAKE) -C utils/plot_ui clean
-$(MAKE) -C qemu_mode/unsigaction clean
-$(MAKE) -C qemu_mode/fastexit clean
-$(MAKE) -C qemu_mode/libcompcov clean
-$(MAKE) -C qemu_mode/libqasan clean
-$(MAKE) -C frida_mode clean
@ -607,7 +625,7 @@ endif
.PHONY: distrib
distrib: all
-$(MAKE) -j4 -f GNUmakefile.llvm
-$(MAKE) -j$(nproc) -f GNUmakefile.llvm
ifneq "$(SYS)" "Darwin"
-$(MAKE) -f GNUmakefile.gcc_plugin
endif
@ -620,13 +638,23 @@ endif
-$(MAKE) -C frida_mode
ifneq "$(SYS)" "Darwin"
ifeq "$(ARCH)" "aarch64"
ifndef NO_CORESIGHT
-$(MAKE) -C coresight_mode
endif
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX
-cd nyx_mode && ./build_nyx_support.sh
endif
endif
-cd qemu_mode && sh ./build_qemu_support.sh
ifeq "$(ARCH)" "aarch64"
ifndef NO_UNICORN_ARM64
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif
else
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif
endif
.PHONY: binary-only
@ -640,18 +668,53 @@ binary-only: test_shm test_python ready $(PROGS)
-$(MAKE) -C frida_mode
ifneq "$(SYS)" "Darwin"
ifeq "$(ARCH)" "aarch64"
ifndef NO_CORESIGHT
-$(MAKE) -C coresight_mode
endif
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX
-cd nyx_mode && ./build_nyx_support.sh
endif
-cd qemu_mode && sh ./build_qemu_support.sh
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif
-cd qemu_mode && sh ./build_qemu_support.sh
ifeq "$(ARCH)" "aarch64"
ifndef NO_UNICORN_ARM64
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif
else
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif
endif
@echo
@echo
@echo Build Summary:
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
ifneq "$(SYS)" "Darwin"
ifeq "$(ARCH)" "aarch64"
ifndef NO_CORESIGHT
@test -e afl-cs-proxy && echo "[+] coresight_mode successfully built" || echo "[-] coresight_mode could not be built, it is optional and experimental, see coresight_mode/README.md for what is needed"
endif
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX
@test -e libnyx.so && echo "[+] nyx_mode successfully built" || echo "[-] nyx_mode could not be built, it is optional, see nyx_mode/README.md for what is needed"
endif
endif
@test -e afl-qemu-trace && echo "[+] qemu_mode successfully built" || echo "[-] qemu_mode could not be built, see docs/INSTALL.md for what is needed"
ifeq "$(ARCH)" "aarch64"
ifndef NO_UNICORN_ARM64
@test -e unicorn_mode/unicornafl/build_python/libunicornafl.so && echo "[+] unicorn_mode successfully built" || echo "[-] unicorn_mode could not be built, it is optional, see unicorn_mode/README.md for what is needed"
endif
else
@test -e unicorn_mode/unicornafl/build_python/libunicornafl.so && echo "[+] unicorn_mode successfully built" || echo "[-] unicorn_mode could not be built, it is optional, see unicorn_mode/README.md for what is needed"
endif
endif
@echo
.PHONY: source-only
source-only: all
-$(MAKE) -j4 -f GNUmakefile.llvm
-$(MAKE) -j$(nproc) -f GNUmakefile.llvm
ifneq "$(SYS)" "Darwin"
-$(MAKE) -f GNUmakefile.gcc_plugin
endif
@ -659,8 +722,26 @@ endif
-$(MAKE) -C utils/libtokencap
# -$(MAKE) -C utils/plot_ui
ifeq "$(SYS)" "Linux"
ifndef NO_NYX
-cd nyx_mode && ./build_nyx_support.sh
endif
endif
@echo
@echo
@echo Build Summary:
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be build, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
ifneq "$(SYS)" "Darwin"
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX
@test -e libnyx.so && echo "[+] nyx_mode successfully built" || echo "[-] nyx_mode could not be built, it is optional, see nyx_mode/README.md for what is needed"
endif
endif
@echo
%.8: %
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@ -687,6 +768,7 @@ install: all $(MANPAGES)
@rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
@rm -f $${DESTDIR}$(BIN_PATH)/afl-as
@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
@for i in afl-llvm-dict2file.so afl-llvm-lto-instrumentlist.so afl-llvm-pass.so cmplog-instructions-pass.so cmplog-routines-pass.so cmplog-switches-pass.so compare-transform-pass.so libcompcov.so libdislocator.so libnyx.so libqasan.so libtokencap.so SanitizerCoverageLTO.so SanitizerCoveragePCGUARD.so split-compares-pass.so split-switches-pass.so; do echo rm -fv $${DESTDIR}$(HELPER_PATH)/$${i}; done
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
@if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
@if [ -f utils/plot_ui/afl-plot-ui ]; then install -m 755 utils/plot_ui/afl-plot-ui $${DESTDIR}$(BIN_PATH); fi

View File

@ -100,7 +100,9 @@ ifeq "$(SYS)" "SunOS"
endif
PROGS = ./afl-gcc-pass.so ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
PASSES = ./afl-gcc-pass.so ./afl-gcc-cmplog-pass.so ./afl-gcc-cmptrs-pass.so
PROGS = $(PASSES) ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
.PHONY: all
all: test_shm test_deps $(PROGS) test_build all_done
@ -135,11 +137,13 @@ afl-common.o: ./src/afl-common.c
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
$(PASSES): instrumentation/afl-gcc-common.h
./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
@ -148,6 +152,12 @@ afl-common.o: ./src/afl-common.c
ln -sf afl-cc.8 afl-gcc-fast.8
ln -sf afl-cc.8 afl-g++-fast.8
./afl-gcc-cmplog-pass.so: instrumentation/afl-gcc-cmplog-pass.so.cc | test_deps
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
./afl-gcc-cmptrs-pass.so: instrumentation/afl-gcc-cmptrs-pass.so.cc | test_deps
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
.PHONY: test_build
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
@ -190,6 +200,8 @@ install: all
ln -sf afl-c++ $${DESTDIR}$(BIN_PATH)/afl-g++-fast
ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
install -m 755 ./afl-gcc-pass.so $${DESTDIR}$(HELPER_PATH)
install -m 755 ./afl-gcc-cmplog-pass.so $${DESTDIR}$(HELPER_PATH)
install -m 755 ./afl-gcc-cmptrs-pass.so $${DESTDIR}$(HELPER_PATH)
install -m 644 -T instrumentation/README.gcc_plugin.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
.PHONY: clean

View File

@ -45,11 +45,11 @@ 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/ .*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[4-9]' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]' && echo 1 || echo 0 )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && 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_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-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
@ -214,6 +214,17 @@ ifeq "$(LLVM_LTO)" "1"
ifeq "$(AFL_REAL_LD)" ""
ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" ""
AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld
else ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
AFL_REAL_LD = $(shell command -v ld.lld)
TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }')
ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)"
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
else
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode)
AFL_REAL_LD=
LLVM_LTO = 0
endif
undefine TMP_LDLDD_VERSION
else
$(warning ld.lld not found, cannot enable LTO mode)
LLVM_LTO = 0
@ -229,7 +240,7 @@ 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"
AFL_CLANG_FUSELD=1
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(LLVM_BINDIR)/ld.lld -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=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_LDPATH=1
endif
else
@ -394,7 +405,7 @@ endif
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_10_OK)" "1"
-$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
endif
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
@ -407,7 +418,7 @@ ifeq "$(LLVM_LTO)" "1"
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
endif
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
ifeq "$(LLVM_LTO)" "1"
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
@ -447,11 +458,11 @@ document:
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
.PHONY: test_build
test_build: $(PROGS)
@ -474,11 +485,11 @@ install: all
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
@if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi
@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o ;fi
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o ;fi
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o ; fi
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
@if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi
@if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi
@ -520,4 +531,4 @@ endif
.PHONY: clean
clean:
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-llvm-rt*.o instrumentation/*.o
rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-compiler-rt*.o ./afl-llvm-rt*.o instrumentation/*.o

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/master/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
Release version: [4.00c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.04c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.00c
GitHub version: 4.04a
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -50,18 +50,21 @@ Here is some information to get you started:
## Building and installing AFL++
To have AFL++ easily available with everything compiled, pull the image directly
from the Docker Hub:
from the Docker Hub (available for both x86_64 and arm64):
```shell
docker pull aflplusplus/aflplusplus
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
```
This image is automatically generated when a push to the stable repo happens
(see [branches](#branches)). You will find your target source code in `/src` in
the container.
This image is automatically published when a push to the stable branch happens
(see [branches](#branches)). If you use the command above, you will find your
target source code in `/src` in the container.
To build AFL++ yourself - which we recommend - continue at
Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current
development state of AFL++.
To build AFL++ yourself - *which we recommend* - continue at
[docs/INSTALL.md](docs/INSTALL.md).
## Quick start: Fuzzing with AFL++
@ -112,7 +115,7 @@ Step-by-step quick start:
5. You will find found crashes and hangs in the subdirectories `crashes/` and
`hangs/` in the `-o output_dir` directory. You can replay the crashes by
feeding them to the target, e.g.:
feeding them to the target, e.g. if your target is using stdin:
```
cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]

View File

@ -2,6 +2,7 @@
## Should
- better documentation for custom mutators
- better autodetection of shifting runtime timeout values
- Update afl->pending_not_fuzzed for MOpt
- afl-plot to support multiple plot_data
@ -10,6 +11,8 @@
## Maybe
- forkserver tells afl-fuzz if cmplog is supported and if so enable
it by default, with AFL_CMPLOG_NO=1 (?) set to skip?
- afl_custom_fuzz_splice_optin()
- afl_custom_splice()
- cmdline option from-to range for mutations
@ -29,4 +32,4 @@ QEMU mode/FRIDA mode:
using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow up
edge numbers that both following cmp paths have been found and then disable
working on this edge id -> cmplog_intelligence branch
- use cmplog colorization taint result for havoc locations?
- use cmplog colorization taint result for havoc locations?

View File

@ -105,12 +105,13 @@ function usage() {
"Execution control settings:\n" \
" -f file - location read by the fuzzed program (stdin)\n" \
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
" -t msec - run time limit for child process (none)\n" \
" -t msec - run time limit for child process (default: none)\n" \
" -O - use binary-only instrumentation (FRIDA mode)\n" \
" -Q - use binary-only instrumentation (QEMU mode)\n" \
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
"\n" \
"Minimization settings:\n" \
" -A - allow crashes and timeouts (not recommended)\n" \
" -C - keep crashing inputs, reject everything else\n" \
" -e - solve for edge coverage only, ignore hit counts\n" \
"\n" \
@ -123,6 +124,7 @@ function usage() {
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
"AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" \
"AFL_CMIN_ALLOW_ANY: write tuples for crashing inputs also\n" \
"AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \
"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
"printed to stdout\n" \
@ -135,16 +137,23 @@ function exists_and_is_executable(binarypath) {
}
BEGIN {
if (0 != system( "test -t 1")) {
redirected = 1
} else {
redirected = 0
}
print "corpus minimization tool for afl++ (awk version)\n"
# defaults
extra_par = ""
AFL_CMIN_CRASHES_ONLY = ""
AFL_CMIN_ALLOW_ANY = ""
# process options
Opterr = 1 # default is to diagnose
Optind = 1 # skip ARGV[0]
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCOQU?")) != -1) {
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQU?")) != -1) {
if (_go_c == "i") {
if (!Optarg) usage()
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@ -180,6 +189,10 @@ BEGIN {
AFL_CMIN_CRASHES_ONLY = "AFL_CMIN_CRASHES_ONLY=1 "
continue
} else
if (_go_c == "A") {
AFL_CMIN_ALLOW_ANY = "AFL_CMIN_ALLOW_ANY=1 "
continue
} else
if (_go_c == "e") {
extra_par = extra_par " -e"
continue
@ -217,7 +230,7 @@ BEGIN {
for (; Optind < ARGC; Optind++) {
prog_args[i++] = ARGV[Optind]
if (i > 1)
prog_args_string = prog_args_string" "ARGV[Optind]
prog_args_string = prog_args_string" '"ARGV[Optind]"'"
}
# sanity checks
@ -285,6 +298,16 @@ BEGIN {
target_bin = tnew
}
if (0 == system ( "grep -aq AFL_DUMP_MAP_SIZE " target_bin )) {
echo "[!] Trying to obtain the map size of the target ..."
get_map_size = "AFL_DUMP_MAP_SIZE=1 " target_bin
get_map_size | getline mapsize
if (mapsize && mapsize > 65535 && mapsize < 100000000) {
AFL_MAP_SIZE = "AFL_MAP_SIZE="mapsize" "
print "[+] Setting "AFL_MAP_SIZE
}
}
if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
@ -393,10 +416,10 @@ BEGIN {
print "[*] Testing the target binary..."
if (!stdin_file) {
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
system(AFL_MAP_SIZE "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
} else {
system("cp \""in_dir"/"first_file"\" "stdin_file)
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
system(AFL_MAP_SIZE "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
}
first_count = 0
@ -429,15 +452,15 @@ BEGIN {
if (!stdin_file) {
print " Processing "in_count" files (forkserver mode)..."
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
} else {
print " Processing "in_count" files (forkserver mode)..."
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null"
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
}
if (retval && !AFL_CMIN_CRASHES_ONLY) {
print "[!] Exit code "retval" != 0 received from afl-showmap, terminating..."
if (retval && (!AFL_CMIN_CRASHES_ONLY && !AFL_CMIN_ALLOW_ANY)) {
print "[!] Exit code "retval" != 0 received from afl-showmap (this means a crashing or timeout input is likely present), terminating..."
if (!ENVIRON["AFL_KEEP_TRACES"]) {
system("rm -rf "trace_dir" 2>/dev/null")
@ -463,7 +486,8 @@ BEGIN {
while (cur < in_count) {
fn = infilesSmallToBig[cur]
++cur
printf "\r Processing file "cur"/"in_count
if (redirected == 0) { printf "\r Processing file "cur"/"in_count }
else { print " Processing file "cur"/"in_count }
# create path for the trace file from afl-showmap
tracefile_path = trace_dir"/"fn
# gather all keys, and count them
@ -502,7 +526,9 @@ BEGIN {
key = field[nrFields]
++tcnt;
printf "\r Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..."
if (redirected == 0) { printf "\r Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
else { print " Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
if (key in keyAlreadyKnown) {
continue
}
@ -525,7 +551,6 @@ BEGIN {
}
}
close(sortedKeys)
print ""
print "[+] Found "tuple_count" unique tuples across "in_count" files."
if (out_count == 1) {

View File

@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
export AFL_QUIET=1
while getopts "+i:o:f:m:t:eOQUCh" opt; do
while getopts "+i:o:f:m:t:eOQUACh" opt; do
case "$opt" in
@ -80,6 +80,9 @@ while getopts "+i:o:f:m:t:eOQUCh" opt; do
"e")
EXTRA_PAR="$EXTRA_PAR -e"
;;
"A")
export AFL_CMIN_ALLOW_ANY=1
;;
"C")
export AFL_CMIN_CRASHES_ONLY=1
;;
@ -128,6 +131,7 @@ Execution control settings:
Minimization settings:
-A - allow crashing and timeout inputs
-C - keep crashing inputs, reject everything else
-e - solve for edge coverage only, ignore hit counts
@ -215,6 +219,15 @@ if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
fi
grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && {
echo "[!] Trying to obtain the map size of the target ..."
MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null`
test -n "$MAPSIZE" && {
export AFL_MAP_SIZE=$MAPSIZE
echo "[+] Setting AFL_MAP_SIZE=$MAPSIZE"
}
}
if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then

View File

@ -111,12 +111,12 @@ kernel.sched_latency_ns=250000000
EOF
}
egrep -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
egrep -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
egrep '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | egrep -q hardened_usercopy=off || {
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
echo "Configuring performance boot options"
LINE=`egrep '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
}

View File

@ -47,9 +47,9 @@ if [ "$PLATFORM" = "Linux" ] ; then
} > /dev/null
echo Settings applied.
echo
dmesg | egrep -q 'nospectre_v2|spectre_v2=off' || {
dmesg | grep -E -q 'noibrs pcid nopti' || {
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
echo
}
echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.
@ -76,6 +76,9 @@ EOF
DONE=1
fi
if [ "$PLATFORM" = "OpenBSD" ] ; then
doas sysctl vm.malloc_conf=
echo 'Freecheck on allocation in particular can be detrimental to performance.'
echo 'Also we might not want necessarily to abort at any allocation failure.'
echo 'System security features cannot be disabled on OpenBSD.'
echo
DONE=1
@ -115,7 +118,7 @@ if [ "$PLATFORM" = "Darwin" ] ; then
sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1
echo
fi
echo It is recommended to disable System Integration Protection for increased performance.
echo It is recommended to disable System Integrity Protection for increased performance.
echo
DONE=1
fi

View File

@ -54,7 +54,7 @@ $(GLIBC_LDSO): | $(GLIBC_NAME).tar.xz
$(MAKE) install
$(GLIBC_NAME).tar.xz:
wget -O $@ $(GLIBC_URL_BASE)/$@
wget -qO $@ $(GLIBC_URL_BASE)/$@
clean:
$(MAKE) -C $(CS_TRACE) clean

View File

@ -352,7 +352,7 @@ uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
* @return if the file contents was modified return 1 (True), 0 (False)
* otherwise
*/
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) {

View File

@ -72,6 +72,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-inl.h"
/* Header that must be present at the beginning of every test case: */
@ -127,9 +128,11 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
}
/* Allocate memory for new buffer, reusing previous allocation if
possible. */
possible. Note we have to use afl-fuzz's own realloc!
Note that you should only do this if you need to grow the buffer,
otherwise work with in_buf, and assign it to *out_buf instead. */
*out_buf = realloc(data->buf, len);
*out_buf = afl_realloc(out_buf, len);
/* If we're out of memory, the most graceful thing to do is to return the
original buffer and give up on modifying it. Let AFL handle OOM on its
@ -142,9 +145,9 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
}
/* Copy the original data to the new location. */
memcpy(*out_buf, in_buf, len);
if (len > strlen(HEADER))
memcpy(*out_buf + strlen(HEADER), in_buf + strlen(HEADER),
len - strlen(HEADER));
/* Insert the new header. */

View File

@ -29,8 +29,8 @@
#include <stdint.h>
#include <string.h>
#include <zlib.h>
#include <arpa/inet.h>
#include "alloc-inl.h"
/* A macro to round an integer up to 4 kB. */
@ -70,9 +70,6 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
unsigned int len,
const unsigned char **out_buf) {
unsigned char *new_buf = (unsigned char *)in_buf;
unsigned int pos = 8;
/* Don't do anything if there's not enough room for the PNG header
(8 bytes). */
@ -83,6 +80,22 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
}
/* This is not a good way to do it, if you do not need to grow the buffer
then just work with in_buf instead for speed reasons.
But we want to show how to grow a buffer, so this is how it's done: */
unsigned int pos = 8;
unsigned char *new_buf = afl_realloc(out_buf, UP4K(len));
if (!new_buf) {
*out_buf = in_buf;
return len;
}
memcpy(new_buf, in_buf, len);
/* Minimum size of a zero-length PNG chunk is 12 bytes; if we
don't have that, we can bail out. */
@ -111,33 +124,6 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
if (real_cksum != file_cksum) {
/* First modification? Make a copy of the input buffer. Round size
up to 4 kB to minimize the number of reallocs needed. */
if (new_buf == in_buf) {
if (len <= data->size) {
new_buf = data->buf;
} else {
new_buf = realloc(data->buf, UP4K(len));
if (!new_buf) {
*out_buf = in_buf;
return len;
}
data->buf = new_buf;
data->size = UP4K(len);
memcpy(new_buf, in_buf, len);
}
}
*(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum;
}

View File

@ -115,9 +115,9 @@ if [ $? -eq 0 ]; then
git submodule update ./json-c 2>/dev/null # ignore errors
else
echo "[*] cloning json-c"
test -d json-c || {
test -d json-c/.git || {
CNT=1
while [ '!' -d json-c -a "$CNT" -lt 4 ]; do
while [ '!' -d json-c/.git -a "$CNT" -lt 4 ]; do
echo "Trying to clone json-c (attempt $CNT/3)"
git clone "$JSONC_REPO"
CNT=`expr "$CNT" + 1`
@ -125,7 +125,7 @@ else
}
fi
test -d json-c || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
test -e json-c/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
echo "[+] Got json-c."
test -e json-c/.libs/libjson-c.a || {

View File

@ -1 +1 @@
cbe5e32
ff4e5a2

View File

@ -109,9 +109,9 @@ if [ $? -eq 0 ]; then
git submodule update ./grammar_mutator 2>/dev/null # ignore errors
else
echo "[*] cloning grammar mutator"
test -d grammar_mutator || {
test -d grammar_mutator/.git || {
CNT=1
while [ '!' -d grammar_mutator -a "$CNT" -lt 4 ]; do
while [ '!' -d grammar_mutator/.git -a "$CNT" -lt 4 ]; do
echo "Trying to clone grammar_mutator (attempt $CNT/3)"
git clone "$GRAMMAR_REPO"
CNT=`expr "$CNT" + 1`
@ -119,15 +119,16 @@ else
}
fi
test -d grammar_mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
test -e grammar_mutator/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
echo "[+] Got grammar mutator."
cd "grammar_mutator" || exit 1
echo "[*] Checking out $GRAMMAR_VERSION"
git pull >/dev/null 2>&1
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
git checkout "$GRAMMAR_VERSION" || exit 1
echo "[*] Downloading antlr..."
wget -c https://www.antlr.org/download/antlr-4.8-complete.jar
wget -q https://www.antlr.org/download/antlr-4.8-complete.jar
cd ..
echo

10
custom_mutators/libafl_base/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

View File

@ -0,0 +1,14 @@
[package]
name = "libafl_base"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libafl = { git = "https://github.com/AFLplusplus/LibAFL.git", rev = "62614ce1016c86e3f00f35b56399292ceabd486b" }
custom_mutator = { path = "../rust/custom_mutator", features = ["afl_internals"] }
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
[lib]
crate-type = ["cdylib"]

View File

@ -0,0 +1,9 @@
all: target/release/liblibafl_base.so
cp target/release/liblibafl_base.so libafl_base.so
target/release/liblibafl_base.so: src/lib.rs
cargo build --release
clean:
cargo clean
rm -f libafl_base.so

View File

@ -0,0 +1,11 @@
# libafl basic havoc + token mutator
This uses the [libafl](https://github.com/AFLplusplus/libafl) StdScheduledMutator with `havoc_mutations` and `token_mutations`.
Make sure to have [cargo installed](https://rustup.rs/) and just type `make` to build.
Run with:
```
AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/libafl_base/libafl_base.so AFL_CUSTOM_MUTATOR_ONLY=1 afl-fuzz ...
```

View File

@ -0,0 +1,238 @@
#![cfg(unix)]
#![allow(unused_variables)]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
cell::{RefCell, UnsafeCell},
collections::HashMap,
ffi::CStr,
};
use custom_mutator::{afl_state, export_mutator, CustomMutator};
use libafl::{
bolts::{rands::StdRand, serdeany::SerdeAnyMap, tuples::Merge},
corpus::{Corpus, Testcase},
inputs::{BytesInput, HasBytesVec},
mutators::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
Mutator,
},
state::{HasCorpus, HasMaxSize, HasMetadata, HasRand, State},
Error,
};
const MAX_FILE: usize = 1 * 1024 * 1024;
static mut AFL: Option<&'static afl_state> = None;
static mut CURRENT_ENTRY: Option<usize> = None;
fn afl() -> &'static afl_state {
unsafe { AFL.unwrap() }
}
#[derive(Default, Debug)]
pub struct AFLCorpus {
entries: UnsafeCell<HashMap<usize, RefCell<Testcase<BytesInput>>>>,
}
impl Clone for AFLCorpus {
fn clone(&self) -> Self {
unsafe {
Self {
entries: UnsafeCell::new(self.entries.get().as_ref().unwrap().clone()),
}
}
}
}
impl Serialize for AFLCorpus {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
unimplemented!();
}
}
impl<'de> Deserialize<'de> for AFLCorpus {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!();
}
}
impl Corpus<BytesInput> for AFLCorpus {
#[inline]
fn count(&self) -> usize {
afl().queued_items as usize
}
#[inline]
fn add(&mut self, testcase: Testcase<BytesInput>) -> Result<usize, Error> {
unimplemented!();
}
#[inline]
fn replace(&mut self, idx: usize, testcase: Testcase<BytesInput>) -> Result<(), Error> {
unimplemented!();
}
#[inline]
fn remove(&mut self, idx: usize) -> Result<Option<Testcase<BytesInput>>, Error> {
unimplemented!();
}
#[inline]
fn get(&self, idx: usize) -> Result<&RefCell<Testcase<BytesInput>>, Error> {
unsafe {
let entries = self.entries.get().as_mut().unwrap();
entries.entry(idx).or_insert_with(|| {
let queue_buf = std::slice::from_raw_parts_mut(afl().queue_buf, self.count());
let entry = queue_buf[idx].as_mut().unwrap();
let fname = CStr::from_ptr((entry.fname as *mut i8).as_ref().unwrap())
.to_str()
.unwrap()
.to_owned();
let mut testcase = Testcase::with_filename(BytesInput::new(vec![]), fname);
*testcase.input_mut() = None;
RefCell::new(testcase)
});
Ok(&self.entries.get().as_ref().unwrap()[&idx])
}
}
#[inline]
fn current(&self) -> &Option<usize> {
unsafe {
CURRENT_ENTRY = Some(afl().current_entry as usize);
&CURRENT_ENTRY
}
}
#[inline]
fn current_mut(&mut self) -> &mut Option<usize> {
unimplemented!();
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AFLState {
rand: StdRand,
corpus: AFLCorpus,
metadata: SerdeAnyMap,
max_size: usize,
}
impl AFLState {
pub fn new(seed: u32) -> Self {
Self {
rand: StdRand::with_seed(seed as u64),
corpus: AFLCorpus::default(),
metadata: SerdeAnyMap::new(),
max_size: MAX_FILE,
}
}
}
impl State for AFLState {}
impl HasRand for AFLState {
type Rand = StdRand;
#[inline]
fn rand(&self) -> &Self::Rand {
&self.rand
}
#[inline]
fn rand_mut(&mut self) -> &mut Self::Rand {
&mut self.rand
}
}
impl HasCorpus<BytesInput> for AFLState {
type Corpus = AFLCorpus;
#[inline]
fn corpus(&self) -> &Self::Corpus {
&self.corpus
}
#[inline]
fn corpus_mut(&mut self) -> &mut Self::Corpus {
&mut self.corpus
}
}
impl HasMetadata for AFLState {
#[inline]
fn metadata(&self) -> &SerdeAnyMap {
&self.metadata
}
#[inline]
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl HasMaxSize for AFLState {
fn max_size(&self) -> usize {
self.max_size
}
fn set_max_size(&mut self, max_size: usize) {
self.max_size = max_size;
}
}
struct LibAFLBaseCustomMutator {
state: AFLState,
input: BytesInput,
}
impl CustomMutator for LibAFLBaseCustomMutator {
type Error = libafl::Error;
fn init(afl: &'static afl_state, seed: u32) -> Result<Self, Self::Error> {
unsafe {
AFL = Some(afl);
let mut state = AFLState::new(seed);
let extras = std::slice::from_raw_parts(afl.extras, afl.extras_cnt as usize);
let mut tokens = vec![];
for extra in extras {
let data = std::slice::from_raw_parts(extra.data, extra.len as usize);
tokens.push(data.to_vec());
}
if !tokens.is_empty() {
state.add_metadata(Tokens::new(tokens));
}
Ok(Self {
state,
input: BytesInput::new(vec![]),
})
}
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, Self::Error> {
self.state.set_max_size(max_size);
// TODO avoid copy
self.input.bytes_mut().clear();
self.input.bytes_mut().extend_from_slice(buffer);
let mut mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
mutator.mutate(&mut self.state, &mut self.input, 0)?;
Ok(Some(self.input.bytes()))
}
}
export_mutator!(LibAFLBaseCustomMutator);

View File

@ -358,6 +358,36 @@ pub mod wrappers {
}
}
/// An exported macro to defined afl_custom_init meant for insternal usage
#[cfg(feature = "afl_internals")]
#[macro_export]
macro_rules! _define_afl_custom_init {
($mutator_type:ty) => {
#[no_mangle]
pub extern "C" fn afl_custom_init(
afl: ::std::option::Option<&'static $crate::afl_state>,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed as u32)
}
};
}
/// An exported macro to defined afl_custom_init meant for insternal usage
#[cfg(not(feature = "afl_internals"))]
#[macro_export]
macro_rules! _define_afl_custom_init {
($mutator_type:ty) => {
#[no_mangle]
pub extern "C" fn afl_custom_init(
_afl: *const ::std::os::raw::c_void,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(seed as u32)
}
};
}
/// exports the given Mutator as a custom mutator as the C interface that AFL++ expects.
/// It is not possible to call this macro multiple times, because it would define the custom mutator symbols multiple times.
/// # Example
@ -381,23 +411,7 @@ pub mod wrappers {
#[macro_export]
macro_rules! export_mutator {
($mutator_type:ty) => {
#[cfg(feature = "afl_internals")]
#[no_mangle]
pub extern "C" fn afl_custom_init(
afl: ::std::option::Option<&'static $crate::afl_state>,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed as u32)
}
#[cfg(not(feature = "afl_internals"))]
#[no_mangle]
pub extern "C" fn afl_custom_init(
_afl: *const ::std::os::raw::c_void,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(seed as u32)
}
$crate::_define_afl_custom_init!($mutator_type);
#[no_mangle]
pub unsafe extern "C" fn afl_custom_fuzz_count(

View File

@ -1,6 +1,9 @@
# custum mutator: symcc
This uses the excellent symcc to find new paths into the target.
This uses the symcc to find new paths into the target.
Note that this is a just a proof of concept example! It is better to use
the fuzzing helpers of symcc, symqemu, Fuzzolic, etc. rather than this.
To use this custom mutator follow the steps in the symcc repository
[https://github.com/eurecom-s3/symcc/](https://github.com/eurecom-s3/symcc/)

View File

@ -3,10 +3,111 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
## Staying informed
Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++4.04c (release)
- fix gramatron and grammar_mutator build scripts
- enhancements to the afl-persistent-config and afl-system-config
scripts
- afl-fuzz:
- force writing all stats on exit
- afl-cc:
- make gcc_mode (afl-gcc-fast) work with gcc down to version 3.6
- qemu_mode:
- fixed 10x speed degredation in v4.03c, thanks to @ele7enxxh for
reporting!
- added qemu_mode/fastexit helper library
- unicorn_mode:
- Enabled tricore arch (by @jma-qb)
- Updated Capstone version in Rust bindings
- llvm-mode:
- AFL runtime will always pass inputs via shared memory, when possible,
ignoring the command line.
### Version ++4.03c (release)
- Building now gives a build summary what succeeded and what not
- afl-fuzz:
- added AFL_NO_STARTUP_CALIBRATION to start fuzzing at once instead
of calibrating all initial seeds first. Good for large queues
and long execution times, especially in CIs.
- default calibration cycles set to 7 from 8, and only add 5 cycles
to variables queue items instead of 12.
- afl-cc:
- fixed off-by-one bug in our pcguard implemenation, thanks for
@tokatoka for reporting
- fix for llvm 15 and reenabling LTO, thanks to nikic for the PR!
- better handling of -fsanitize=..,...,.. lists
- support added for LLVMFuzzerRunDriver()
- fix gcc_mode cmplog
- obtain the map size of a target with setting AFL_DUMP_MAP_SIZE=1
note that this will exit the target before main()
- qemu_mode:
- added AFL_QEMU_TRACK_UNSTABLE to log the addresses of unstable
edges (together with AFL_DEBUG=1 afl-fuzz). thanks to
worksbutnottested!
- afl-analyze broke at some point, fix by CodeLogicError, thank you!
- afl-cmin/afl-cmin.bash now have an -A option to allow also crashing
and timeout inputs
- unicorn_mode:
- updated upstream unicorn version
- fixed builds for aarch64
- build now uses all available cores
### Version ++4.02c (release)
- afl-cc:
- important fix for the default pcguard mode when LLVM IR vector
selects are produced, thanks to @juppytt for reporting!
- gcc_plugin:
- Adacore submitted CMPLOG support to the gcc_plugin! :-)
- llvm_mode:
- laf cmp splitting fixed for more comparison types
- frida_mode:
- now works on Android!
- afl-fuzz:
- change post_process hook to allow returning NULL and 0 length to
tell afl-fuzz to skip this mutated input
### Version ++4.01c (release)
- fixed */build_...sh scripts to work outside of git
- new custom_mutator: libafl with token fuzzing :)
- afl-fuzz:
- when you just want to compile once and set CMPLOG, then just
set -c 0 to tell afl-fuzz that the fuzzing binary is also for
CMPLOG.
- new commandline options -g/G to set min/max length of generated
fuzz inputs
- you can set the time for syncing to other fuzzer now with
AFL_SYNC_TIME
- reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow
persistent mode and manual forkserver support if these are not
in the target binary (e.g. are in a shared library)
- add AFL_EARLY_FORKSERVER to install the forkserver as earliest as
possible in the target (for afl-gcc-fast/afl-clang-fast/
afl-clang-lto)
- "saved timeouts" was wrong information, timeouts are still thrown
away by default even if they have new coverage (hangs are always
kept), unless AFL_KEEP_TIMEOUTS are set
- AFL never implemented auto token inserts (but user token inserts,
user token overwrite and auto token overwrite), added now!
- fixed a mutation type in havoc mode
- Mopt fix to always select the correct algorithm
- fix effector map calculation (deterministic mode)
- fix custom mutator post_process functionality
- document and auto-activate pizza mode on condition
- afl-cc:
- due a bug in lld of llvm 15 LTO instrumentation wont work atm :-(
- converted all passed to use the new llvm pass manager for llvm 11+
- AFL++ PCGUARD mode is not available for 10.0.1 anymore (11+ only)
- trying to stay on top on all these #$&§!! changes in llvm 15 ...
- frida_mode:
- update to new frida release, handles now c++ throw/catch
- unicorn_mode:
- update unicorn engine, fix C example
- utils:
- removed optimin because it looses coverage due to a bug and is
unmaintained :-(
### Version ++4.00c (release)
- complete documentation restructuring, made possible by Google Season
@ -53,7 +154,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix bug where targets are not killed on timeouts
- moved hidden afl-showmap -A option to -H to be used for
coresight_mode
- Prevent accidentaly killing non-afl/fuzz services when aborting
- Prevent accidentally killing non-afl/fuzz services when aborting
afl-showmap and other tools.
- afl-cc:
- detect overflow reads on initial input buffer for asan

View File

@ -255,3 +255,18 @@ If you find an interesting or important question missing, submit it via
Solution: `git pull ; make clean install` of AFL++.
</p></details>
<details>
<summary id="afl-map-size-warning">AFL++ map size warning.</summary><p>
When you run a large instrumented program stand-alone or via afl-showmap
you might see a warning like the following:
```
Warning: AFL++ tools might need to set AFL_MAP_SIZE to 223723 to be able to run this instrumented program if this crashes!
```
Depending how the target works it might also crash afterwards.
Solution: just do an `export AFL_MAP_SIZE=(the value in the warning)`.
</p></details>

View File

@ -3,26 +3,33 @@
## Linux on x86
An easy way to install AFL++ with everything compiled is available via docker:
You can use the [Dockerfile](../Dockerfile) (which has gcc-10 and clang-11 -
hence afl-clang-lto is available!) or just pull directly from the Docker Hub:
You can use the [Dockerfile](../Dockerfile) (which has gcc-10 and clang-12 -
hence afl-clang-lto is available) or just pull directly from the Docker Hub
(for x86_64 and arm64):
```shell
docker pull aflplusplus/aflplusplus
docker pull aflplusplus/aflplusplus:
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
```
This image is automatically generated when a push to the stable repo happens.
This image is automatically generated when a push to the stable branch happens.
You will find your target source code in `/src` in the container.
Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current
development state of AFL++.
If you want to build AFL++ yourself, you have many options. The easiest choice
is to build and install everything:
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-12` with
whatever llvm version is available. We recommend llvm 12, 13 or 14.
```shell
sudo apt-get update
sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
# try to install llvm 11 and install the distro default if that fails
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools cargo libgtk-3-dev
# try to install llvm 12 and install the distro default if that fails
sudo apt-get install -y lld-12 llvm-12 llvm-12-dev clang-12 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
sudo apt-get install -y ninja-build # for QEMU mode
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
@ -72,18 +79,23 @@ make STATIC=1
These build options exist:
* STATIC - compile AFL++ static
* ASAN_BUILD - compiles with memory sanitizer for debug purposes
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for
debug purposes
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
* PROFILING - compile with profiling information (gprof)
* PROFILING - compile afl-fuzz with profiling information
* INTROSPECTION - compile afl-fuzz with mutation introspection
* NO_PYTHON - disable python support
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for
normal fuzzing
* NO_NYX - disable building nyx mode dependencies
* NO_CORESIGHT - disable building coresight (arm64 only)
* NO_UNICORN_ARM64 - disable building unicorn on arm64
* AFL_NO_X86 - if compiling on non-intel/amd platforms
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config
(e.g., Debian)
e.g.: `make ASAN_BUILD=1`
e.g.: `make LLVM_CONFIG=llvm-config-14`
## MacOS X on x86 and arm64 (M1)
@ -140,7 +152,7 @@ and definitely don't look POSIX-compliant. This means two things:
environment before starting afl-fuzz.
User emulation mode of QEMU does not appear to be supported on MacOS X, so
black-box instrumentation mode (`-Q`) will not work. However, Frida mode (`-O`)
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
works on both x86 and arm64 MacOS boxes.
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the

View File

@ -38,6 +38,11 @@ performed with the custom mutator.
## 2) APIs
**IMPORTANT NOTE**: If you use our C/C++ API and you want to increase the size
of an **out_buf buffer, you have to use `afl_realloc()` for this, so include
`include/alloc-inl.h` - otherwise afl-fuzz will crash when trying to free
your buffers.
C/C++:
```c
@ -63,7 +68,7 @@ Python:
def init(seed):
pass
def fuzz_count(buf, add_buf, max_size):
def fuzz_count(buf):
return cnt
def fuzz(buf, add_buf, max_size):
@ -159,6 +164,10 @@ def deinit(): # optional for Python
This can return any python object that implements the buffer protocol and
supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
You can decide in the post_process mutator to not send the mutated data
to the target, e.g. if it is too short, too corrupted, etc. If so,
return a NULL buffer and zero length (or a 0 length string in Python).
- `queue_new_entry` (optional):
This methods is called after adding a new test case to the queue. If the

View File

@ -160,6 +160,8 @@ Available options:
Setting `AFL_LLVM_CMPLOG=1` during compilation will tell afl-clang-fast to
produce a CmpLog binary.
For afl-gcc-fast, set `AFL_GCC_CMPLOG=1` instead.
For more information, see
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
@ -349,6 +351,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_KEEP_TIMEOUTS` will keep longer running inputs if they reach
new coverage
- `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behavior which
does not allow crashes or timeout seeds in the initial -i corpus.
@ -400,6 +405,10 @@ checks or alter some of the more exotic semantics of the tool:
This makes the "own finds" counter in the UI more accurate. Beyond counter
aesthetics, not much else should change.
- Setting `AFL_INPUT_LEN_MIN` and `AFL_INPUT_LEN_MAX` are an alternative to
the afl-fuzz -g/-G command line option to control the minimum/maximum
of fuzzing input generated.
- `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on
timeout. Unless you implement your own targets or instrumentation, you
likely don't have to set it. By default, on timeout and on exit, `SIGKILL`
@ -446,14 +455,17 @@ checks or alter some of the more exotic semantics of the tool:
normally done when starting up the forkserver and causes a pretty
significant performance drop.
- `AFL_NO_SNAPSHOT` will advice afl-fuzz not to use the snapshot feature if
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
the snapshot lkm is loaded.
- 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.
- In QEMU mode (-Q) and Frida mode (-O), `AFL_PATH` will be searched for
- Setting `AFL_NO_STARTUP_CALIBRATION` will skip the initial calibration
of all starting seeds, and start fuzzing at once.
- In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for
afl-qemu-trace and afl-frida-trace.so.
- If you are using persistent mode (you should, see
@ -461,7 +473,7 @@ checks or alter some of the more exotic semantics of the tool:
some targets keep inherent state due which a detected crash test case does
not crash the target again when the test case is given. To be able to still
re-trigger these crashes, you can use the `AFL_PERSISTENT_RECORD` variable
with a value of how many previous fuzz cases to keep prio a crash. If set to
with a value of how many previous fuzz cases to keep prior a crash. If set to
e.g., 10, then the 9 previous inputs are written to out/default/crashes as
RECORD:000000,cnt:000000 to RECORD:000000,cnt:000008 and
RECORD:000000,cnt:000009 being the crash case. NOTE: This option needs to be
@ -510,11 +522,20 @@ checks or alter some of the more exotic semantics of the tool:
(empty/non present) will add no tags to the metrics. For more information,
see [rpc_statsd.md](rpc_statsd.md).
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes)
between fuzzing instances synchronization. Default sync time is 30 minutes,
note that time is halved for -M main nodes.
- 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
theoretically allow fuzzing of AFL++ itself (with 'target' AFL++ using some
AFL_ vars that would disrupt work of 'fuzzer' AFL++).
AFL_ vars that would disrupt work of 'fuzzer' AFL++). Note that when using
QEMU mode, the `AFL_TARGET_ENV` environment variables will apply to QEMU, as
well as the target binary. Therefore, in this case, you might want to use
QEMU's `QEMU_SET_ENV` environment variable (see QEMU's documentation because
the format is different from `AFL_TARGET_ENV`) to apply the environment
variables to the target and not QEMU.
- `AFL_TESTCACHE_SIZE` allows you to override the size of `#define
TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if
@ -528,9 +549,20 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_TRY_AFFINITY` tries to attempt binding to a specific CPU core
on Linux systems, but will not terminate if that fails.
- Outdated environment variables that are not supported anymore:
- `AFL_DEFER_FORKSRV`
- `AFL_PERSISTENT`
- The following environment variables are only needed if you implemented
your own forkserver or persistent mode, or if __AFL_LOOP or __AFL_INIT
are in a shared library and not the main binary:
- `AFL_DEFER_FORKSRV` enforces a deferred forkserver even if none was
detected in the target binary
- `AFL_PERSISTENT` enforces persistent mode even if none was detected
in the target binary
- If you need an early forkserver in your target because of early
constructors in your target, you can set `AFL_EARLY_FORKSERVER`.
Note that this is not a compile time option but a runtime option :-)
- Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to 0
to disable although it is 1st of April.
## 5) Settings for afl-qemu-trace
@ -592,6 +624,10 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
emulation" variables (e.g., `QEMU_STACK_SIZE`), but there should be no
reason to touch them.
- Normally a `README.txt` is written to the `crashes/` directory when a first
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
The FRIDA wrapper used to instrument binary-only code supports many of the same
@ -658,8 +694,8 @@ support.
* `AFL_FRIDA_STALKER_ADJACENT_BLOCKS` - Configure the number of adjacent blocks
to fetch when generating instrumented code. By fetching blocks in the same
order they appear in the original program, rather than the order of execution
should help reduce locallity and adjacency. This includes allowing us to
vector between adjancent blocks using a NOP slide rather than an immediate
should help reduce locality and adjacency. This includes allowing us to
vector between adjacent blocks using a NOP slide rather than an immediate
branch.
* `AFL_FRIDA_STALKER_IC_ENTRIES` - Configure the number of inline cache entries
stored along-side branch instructions which provide a cache to avoid having to

View File

@ -12,7 +12,7 @@ QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | |
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
| CmpLog [E] | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
| CmpLog [E] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
| Selective Instrumentation [F] | | x | x | x | x | | | |
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | |
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | |

View File

@ -48,11 +48,12 @@ The following setup to use QEMU mode is recommended:
Then run as many instances as you have cores left with either -Q mode or - even
better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
The binary rewriters all have their own advantages and caveats.
ZAFL is the best but cannot be used in a business/commercial context.
If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your
binary, then you can use afl-fuzz normally and it will have twice the speed
compared to QEMU mode (but slower than QEMU persistent mode). Note that several
other binary rewriters exist, all with their advantages and caveats.
If a binary rewriter works for your target then you can use afl-fuzz normally
and it will have twice the speed compared to QEMU mode (but slower than QEMU
persistent mode).
The speed decrease of QEMU mode is at about 50%. However, various options exist
to increase the speed:
@ -290,7 +291,7 @@ its IPT performance is just 6%!
There are many binary-only fuzzing frameworks. Some are great for CTFs but don't
work with large binaries, others are very slow but have good path discovery,
some are very hard to set-up...
some are very hard to set up...
* Jackalope:
[https://github.com/googleprojectzero/Jackalope](https://github.com/googleprojectzero/Jackalope)

View File

@ -333,6 +333,27 @@ is a non-standard way to set this, otherwise set up the build normally and edit
the generated build environment afterwards manually to point it to the right
compiler (and/or `RANLIB` and `AR`).
In complex, weird, alien build systems you can try this neat project:
[https://github.com/fuzzah/exeptor](https://github.com/fuzzah/exeptor)
#### Linker scripts
If the project uses linker scripts to hide the symbols exported by the
binary, then you may see errors such as:
```
undefined symbol: __afl_area_ptr
```
The solution is to modify the linker script to add:
```
{
global:
__afl_*;
}
```
### f) Better instrumentation
If you just fuzz a target program as-is, you are wasting a great opportunity for
@ -502,7 +523,7 @@ mode!) and switch the input directory with a dash (`-`):
afl-fuzz -i - -o output -- bin/target -someopt @@
```
Adding a dictionary is helpful. You have to following options:
Adding a dictionary is helpful. You have the following options:
* See the directory
[dictionaries/](../dictionaries/), if something is already included for your
@ -605,6 +626,9 @@ from other fuzzers in the campaign first.
If you have a large corpus, a corpus from a previous run or are fuzzing in a CI,
then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.
If the queue in the CI is huge and/or the execution time is slow then you can
also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration
phase and start fuzzing at once.
You can also use different fuzzers. If you are using AFL spinoffs or AFL
conforming fuzzers, then just use the same -o directory and give it a unique
@ -648,7 +672,7 @@ The syncing process itself is very simple. As the `-M main-$HOSTNAME` instance
syncs to all `-S` secondaries as well as to other fuzzers, you have to copy only
this directory to the other machines.
Lets say all servers have the `-o out` directory in /target/foo/out, and you
Let's say all servers have the `-o out` directory in /target/foo/out, and you
created a file `servers.txt` which contains the hostnames of all participating
servers, plus you have an ssh key deployed to all of them, then run:
@ -817,9 +841,10 @@ Here are some of the most important caveats for AFL++:
- There is no direct support for fuzzing network services, background daemons,
or interactive apps that require UI interaction to work. You may need to make
simple code changes to make them behave in a more traditional way. Preeny may
offer a relatively simple option, too - see:
[https://github.com/zardus/preeny](https://github.com/zardus/preeny)
simple code changes to make them behave in a more traditional way. Preeny or
libdesock may offer a relatively simple option, too - see:
[https://github.com/zardus/preeny](https://github.com/zardus/preeny) or
[https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
Some useful tips for modifying network-based services can be also found at:
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
@ -880,6 +905,10 @@ complex file formats.
Some notes on continuous integration (CI) fuzzing - this fuzzing is different to
normal fuzzing campaigns as these are much shorter runnings.
If the queue in the CI is huge and/or the execution time is slow then you can
also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration
phase and start fuzzing at once.
1. Always:
* LTO has a much longer compile time which is diametrical to short fuzzing -
hence use afl-clang-fast instead.
@ -893,16 +922,17 @@ normal fuzzing campaigns as these are much shorter runnings.
* Keep the generated corpus, use afl-cmin and reuse it every time!
2. Additionally randomize the AFL++ compilation options, e.g.:
* 40% for `AFL_LLVM_CMPLOG`
* 10% for `AFL_LLVM_LAF_ALL`
* 30% for `AFL_LLVM_CMPLOG`
* 5% for `AFL_LLVM_LAF_ALL`
3. Also randomize the afl-fuzz runtime options, e.g.:
* 65% for `AFL_DISABLE_TRIM`
* 50% for `AFL_KEEP_TIMEOUTS`
* 50% use a dictionary generated by `AFL_LLVM_DICT2FILE`
* 40% use MOpt (`-L 0`)
* 40% for `AFL_EXPAND_HAVOC_NOW`
* 20% for old queue processing (`-Z`)
* for CMPLOG targets, 60% for `-l 2`, 40% for `-l 3`
* for CMPLOG targets, 70% for `-l 2`, 10% for `-l 3`, 20% for `-l 2AT`
4. Do *not* run any `-M` modes, just running `-S` modes is better for CI
fuzzing. `-M` enables old queue handling etc. which is good for a fuzzing

View File

@ -19,18 +19,18 @@ Mentor: vanhauser-thc
## WASM Instrumentation
Currently, AFL++ can be used for source code fuzzing and traditional binaries.
With the rise of WASM as a compile target, however, a novel way of instrumentation
needs to be implemented for binaries compiled to Webassembly. This can either be
done by inserting instrumentation directly into the WASM AST, or by patching
feedback into a WASM VM of choice, similar to the current Unicorn
With the rise of WASM as a compile target, however, a novel way of
instrumentation needs to be implemented for binaries compiled to Webassembly.
This can either be done by inserting instrumentation directly into the WASM AST,
or by patching feedback into a WASM VM of choice, similar to the current Unicorn
instrumentation.
Mentor: any
## Support other programming languages
Other programming languages also use llvm hence they could be (easily?) supported
for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ...
Other programming languages also use llvm hence they could be (easily?)
supported for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ...
GCC also supports: Objective-C, Fortran, Ada, Go, and D (according to
[Gcc homepage](https://gcc.gnu.org/))

View File

@ -1,11 +1,13 @@
# Tools that help fuzzing with AFL++
Speeding up fuzzing:
## Speeding up fuzzing
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
function you want to fuzz requires loading a file, this allows using the
shared memory test case feature :-) - recommended.
Minimization of test cases:
## Minimization of test cases
* [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin
that tries to speed up the process of minimization of a single test case by
using many CPU cores.
@ -14,7 +16,8 @@ Minimization of test cases:
* [halfempty](https://github.com/googleprojectzero/halfempty) - is a fast
utility for minimizing test cases by Tavis Ormandy based on parallelization.
Distributed execution:
## Distributed execution
* [disfuzz-afl](https://github.com/MartijnB/disfuzz-afl) - distributed fuzzing
for AFL.
* [AFLDFF](https://github.com/quantumvm/AFLDFF) - AFL distributed fuzzing
@ -26,7 +29,8 @@ Distributed execution:
* [afl-in-the-cloud](https://github.com/abhisek/afl-in-the-cloud) - another
script for running AFL in AWS.
Deployment, management, monitoring, reporting
## Deployment, management, monitoring, reporting
* [afl-utils](https://gitlab.com/rc0r/afl-utils) - a set of utilities for
automatic processing/analysis of crashes and reducing the number of test
cases.
@ -44,7 +48,8 @@ Deployment, management, monitoring, reporting
* [afl-extras](https://github.com/fekir/afl-extras) - shell scripts to
parallelize afl-tmin, startup, and data collection.
Crash processing
## Crash processing
* [AFLTriage](https://github.com/quic/AFLTriage) -
triage crashing input files using gdb.
* [afl-crash-analyzer](https://github.com/floyd-fuh/afl-crash-analyzer) -

View File

@ -1,5 +1,9 @@
# Tutorials
If you are a total newbie, try this guide:
* [https://github.com/alex-maleno/Fuzzing-Module](https://github.com/alex-maleno/Fuzzing-Module)
Here are some good write-ups to show how to effectively use AFL++:
* [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
@ -17,7 +21,7 @@ training, then we can highly recommend the following:
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
If you are interested in fuzzing structured data (where you define what the
structure is), these links have you covered:
structure is), these links have you covered (some are outdated though):
* libprotobuf for AFL++:
[https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
@ -29,6 +33,7 @@ structure is), these links have you covered:
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
## Video Tutorials
* [Install AFL++ Ubuntu](https://www.youtube.com/watch?v=5dCvhkbi3RA)
* [[Fuzzing with AFLplusplus] Installing AFLPlusplus and fuzzing a simple C program](https://www.youtube.com/watch?v=9wRVo0kYSlc)
* [[Fuzzing with AFLplusplus] How to fuzz a binary with no source code on Linux in persistent mode](https://www.youtube.com/watch?v=LGPJdEO02p4)

View File

@ -13,6 +13,16 @@ JS_SRC:=$(BUILD_DIR)api.c
JS_OBJ:=$(BUILD_DIR)api.o
SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))
TARGET_CC?=$(CC)
TARGET_CXX?=$(CXX)
HOST_CC?=$(CC)
HOST_CXX?=$(CXX)
IS_ANDROID:=$(findstring android, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_x86:=$(findstring i686, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_x86_64:=$(findstring x86_64, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_ARM:=$(findstring arm, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_ARM64:=$(findstring aarch64, $(shell $(TARGET_CC) --version 2>/dev/null))
CFLAGS+=-fPIC \
-D_GNU_SOURCE \
-D_FORTIFY_SOURCE=2 \
@ -21,6 +31,10 @@ CFLAGS+=-fPIC \
-funroll-loops \
-ffunction-sections \
ifdef IS_ANDROID
CFLAGS+=-DANDROID
endif
AFL_CFLAGS:=-Wno-unused-parameter \
-Wno-sign-compare \
-Wno-unused-function \
@ -28,9 +42,16 @@ AFL_CFLAGS:=-Wno-unused-parameter \
-Wno-int-to-pointer-cast \
-Wno-pointer-sign
ifdef IS_ANDROID
LDFLAGS+= -static-libstdc++ \
-DANDROID \
-llog \
-shared
else
LDFLAGS+=-shared \
-lpthread \
-lresolv
endif
ifdef DEBUG
CFLAGS+=-Werror \
@ -43,10 +64,12 @@ endif
FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so
FRIDA_TRACE_LIB:=$(BUILD_DIR)libafl-frida-trace.a
FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded
TARGET_CC?=$(CC)
TARGET_CXX?=$(CXX)
TARGET_AR?=$(AR)
HOST_CC?=$(CC)
HOST_CXX?=$(CXX)
@ -66,18 +89,21 @@ ifeq "$(ARCH)" "i686"
endif
endif
GUM_ARCH="-$(ARCH)"
ifeq "$(shell uname)" "Darwin"
OS:=macos
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
GUM_ARCH:=""
else
ifdef DEBUG
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor
endif
LDFLAGS+= -z noexecstack \
-Wl,--gc-sections \
-Wl,--exclude-libs,ALL \
-ldl \
-lrt
-ldl
LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
endif
@ -88,38 +114,41 @@ ifeq "$(shell uname)" "Linux"
endif
endif
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
ifdef IS_ANDROID
OS:=android
ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=arm64
ifdef IS_x86
ARCH:=x86
endif
ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" ""
ifdef IS_x86
ARCH:=x86_64
endif
ifdef IS_ARM
ARCH:=arm
endif
ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86_64
endif
ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86
ifdef IS_ARM64
ARCH:=arm64
endif
endif
ifeq "$(ARCH)" "armhf"
TARGET_CC:=arm-linux-gnueabihf-gcc
TARGET_CXX:=arm-linux-gnueabihf-g++
TARGET_AR:=arm-linux-gnueabihf-ar
endif
ifndef OS
$(error "Operating system unsupported")
endif
GUM_DEVKIT_VERSION=15.1.13
GUM_DEVKIT_VERSION=15.2.1
GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
ifdef FRIDA_SOURCE
GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gumjs-1.0.a
GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gumjs-1.0.a
else
GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a
endif
@ -154,7 +183,7 @@ BIN2C_SRC:=$(PWD)util/bin2c.c
############################## ALL #############################################
all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN)
all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN)
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
@ -177,7 +206,7 @@ $(FRIDA_MAKEFILE): | $(BUILD_DIR)
.PHONY: $(GUM_DEVIT_LIBRARY)
$(GUM_DEVIT_LIBRARY): $(FRIDA_MAKEFILE)
cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
cd $(FRIDA_DIR) && make gum-$(OS)$(GUM_ARCH)
$(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
echo "#include <stdio.h>" > $@
@ -189,65 +218,99 @@ $(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
echo "#include <gum/gumlibc.h>" >> $@
echo "#include <gumjs/gumscriptbackend.h>" >> $@
ifeq "$(ARCH)" "arm64"
ifeq "$(OS)" "macos"
CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-linux-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/json-glib-1.0/ \
CFLAGS+=-I $(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsqlite3.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libtcc.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libquickjs.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libcapstone.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind-*.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libffi.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libdwarf.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libelf.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgio-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libglib-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/liblzma.a \
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libz.a \
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libtcc.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libffi.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/liblzma.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libz.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libiconv.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libv8-8.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgmodule-2.0.a \
else ifeq "$(ARCH)" "arm64"
CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-$(OS)-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
ifeq "$(OS)" "android"
CFLAGS += -static-libstdc++
endif
else
CFLAGS+=-I $(FRIDA_DIR)build/frida-linux-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/json-glib-1.0/ \
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsqlite3.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libtcc.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libquickjs.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libcapstone.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind-*.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libffi.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libdwarf.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libelf.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgio-2.0.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libglib-2.0.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/liblzma.a \
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libz.a \
CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-$(OS)-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
endif
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libtcc.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libunwind.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libffi.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libdwarf.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libelf.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/liblzma.a \
$(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libz.a \
CFLAGS+=-I $(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/include/frida-1.0 \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/capstone/ \
-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/
ifeq "$(OS)" "android"
CFLAGS += -static-libstdc++
endif
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libtcc.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libunwind.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libffi.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libdwarf.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libelf.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/liblzma.a \
$(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libz.a \
else
$(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
wget -O $@ $(GUM_DEVKIT_URL) || curl -L -o $@ $(GUM_DEVKIT_URL)
wget -qO $@ $(GUM_DEVKIT_URL) || curl -L -o $@ $(GUM_DEVKIT_URL)
$(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL)
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
@ -325,6 +388,15 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL
cp -v $(FRIDA_TRACE) $(ROOT)
$(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) $(AFL_PERFORMANCE_OBJ) GNUmakefile | $(BUILD_DIR)
$(TARGET_AR) \
-rcs \
$@ \
$(OBJS) \
$(JS_OBJ) \
$(AFL_COMPILER_RT_OBJ) \
$(AFL_PERFORMANCE_OBJ) \
############################# HOOK #############################################
$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR)
@ -336,6 +408,7 @@ $(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR)
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
############################# ADDR #############################################
ifneq "$(OS)" "android"
$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR)
-$(TARGET_CC) \
$(CFLAGS) \
@ -349,7 +422,20 @@ $(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR)
-ldl \
-lrt \
$< -o $@
else
$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR)
-$(TARGET_CC) \
$(CFLAGS) \
-Werror \
-Wall \
-Wextra \
-Wpointer-arith \
-z noexecstack \
-Wl,--gc-sections \
-Wl,--exclude-libs,ALL \
-ldl \
$< -o $@
endif
addr: $(ADDR_BIN)
############################# CLEAN ############################################

View File

@ -86,7 +86,7 @@ To enable the powerful CMPLOG mechanism, set `-c 0` for `afl-fuzz`.
## Scripting
One of the more powerful features of FRIDA mode is it's support for
One of the more powerful features of FRIDA mode is its support for
configuration by JavaScript, rather than using environment variables. For
details of how this works, see [Scripting.md](Scripting.md).
@ -146,36 +146,45 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
QEMU driver to provide a `main` loop for a user provided
`LLVMFuzzerTestOneInput`, this option configures the driver to read input from
`stdin` rather than using in-memory test cases.
* `AFL_FRIDA_INST_COVERAGE_ABSOLUTE` - Generate coverage files using absolute
virtual addresses rather than relative virtual addresses.
* `AFL_FRIDA_INST_COVERAGE_FILE` - File to write DynamoRIO format coverage
information (e.g., to be loaded within IDA lighthouse).
* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
and their instrumented counterparts during block compilation.
```
***
```
Creating block for 0x7ffff7953313:
0x7ffff7953313 mov qword ptr [rax], 0
0x7ffff795331a add rsp, 8
0x7ffff795331e ret
Creating block for 0x7ffff7953313:
0x7ffff7953313 mov qword ptr [rax], 0
0x7ffff795331a add rsp, 8
0x7ffff795331e ret
Generated block 0x7ffff75e98e2
0x7ffff75e98e2 mov qword ptr [rax], 0
0x7ffff75e98e9 add rsp, 8
0x7ffff75e98ed lea rsp, [rsp - 0x80]
0x7ffff75e98f5 push rcx
0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
0x7ffff75e9900 jmp 0x7ffff75e9384
Generated block 0x7ffff75e98e2
0x7ffff75e98e2 mov qword ptr [rax], 0
0x7ffff75e98e9 add rsp, 8
0x7ffff75e98ed lea rsp, [rsp - 0x80]
0x7ffff75e98f5 push rcx
0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
0x7ffff75e9900 jmp 0x7ffff75e9384
***
```
```
* `AFL_FRIDA_INST_CACHE_SIZE` - Set the size of the instrumentation cache used
as a look-up table to cache real to instrumented address block translations.
Default is 256Mb.
* `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional
instructions (e.g. `CMOV` instructions on x64).
* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
code. Code is considered to be JIT if the executable segment is not backed by
a file.
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use
* `AFL_FRIDA_INST_REGS_FILE` - File to write raw register contents at the start
of each block.
`AFL_FRIDA_INST_TRACE`.
* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to
instrumented address block translations.
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will
report instrumented blocks back to the parent so that it can also instrument
them and they be inherited by the next child on fork, implies

View File

@ -2,7 +2,7 @@
FRIDA now supports the ability to configure itself using JavaScript. This allows
the user to make use of the convenience of FRIDA's scripting engine (along with
it's support for debug symbols and exports) to configure all of the things which
its support for debug symbols and exports) to configure all of the things which
were traditionally configured using environment variables.
By default, FRIDA mode will look for the file `afl.js` in the current working
@ -95,7 +95,7 @@ Afl.print("done");
## Stripped binaries
Lastly, if the binary you attempting to fuzz has no symbol information and no
Lastly, if the binary you're attempting to fuzz has no symbol information and no
exports, then the following approach can be used.
```js
@ -850,6 +850,14 @@ class Afl {
static setInstrumentNoOptimize() {
Afl.jsApiSetInstrumentNoOptimize();
}
/**
* See `AFL_FRIDA_INST_REGS_FILE`. This function takes a single `string` as
* an argument.
*/
public static setInstrumentRegsFile(file: string): void {
const buf = Memory.allocUtf8String(file);
Afl.jsApiSetInstrumentRegsFile(buf);
}
/*
* See `AFL_FRIDA_INST_SEED`
*/

View File

@ -9,13 +9,18 @@
js_api_done;
js_api_error;
js_api_set_backpatch_disable;
js_api_set_cache_disable;
js_api_set_debug_maps;
js_api_set_entrypoint;
js_api_set_instrument_cache_size;
js_api_set_instrument_coverage_absolute;
js_api_set_instrument_coverage_file;
js_api_set_instrument_debug_file;
js_api_set_instrument_jit;
js_api_set_instrument_libraries;
js_api_set_instrument_instructions;
js_api_set_instrument_no_optimize;
js_api_set_instrument_regs_file;
js_api_set_instrument_seed;
js_api_set_instrument_trace;
js_api_set_instrument_trace_unique;

View File

@ -31,7 +31,7 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
// do a length check matching the target!
void **esp = (void **)regs->esp;
void * arg1 = esp[0];
void *arg1 = esp[0];
void **arg2 = &esp[1];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;
@ -50,6 +50,16 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
}
#elif defined(__arm__)
__attribute__((visibility("default"))) void afl_persistent_hook(
GumCpuContext *regs, uint8_t *input_buf, uint32_t input_buf_len) {
// do a length check matching the target!
memcpy((void *)regs->r[0], input_buf, input_buf_len);
regs->r[1] = input_buf_len;
}
#else
#pragma error "Unsupported architecture"
#endif

View File

@ -5,13 +5,16 @@
#include "config.h"
extern char * instrument_debug_filename;
extern char * instrument_coverage_filename;
extern char *instrument_debug_filename;
extern char *instrument_coverage_filename;
extern bool instrument_coverage_absolute;
extern gboolean instrument_tracing;
extern gboolean instrument_optimize;
extern gboolean instrument_unique;
extern guint64 instrument_hash_zero;
extern char * instrument_coverage_unstable_filename;
extern char *instrument_coverage_unstable_filename;
extern gboolean instrument_coverage_insn;
extern char *instrument_regs_filename;
extern gboolean instrument_use_fixed_seed;
extern guint64 instrument_fixed_seed;
@ -21,6 +24,9 @@ extern uint32_t __afl_map_size;
extern __thread guint64 *instrument_previous_pc_addr;
extern gboolean instrument_cache_enabled;
extern gsize instrument_cache_size;
void instrument_config(void);
void instrument_init(void);
@ -31,8 +37,10 @@ GumStalkerTransformer *instrument_get_transformer(void);
gboolean instrument_is_coverage_optimize_supported(void);
void instrument_coverage_optimize_init(void);
void instrument_coverage_optimize(const cs_insn * instr,
void instrument_coverage_optimize(const cs_insn *instr,
GumStalkerOutput *output);
void instrument_coverage_optimize_insn(const cs_insn *instr,
GumStalkerOutput *output);
void instrument_debug_config(void);
void instrument_debug_init(void);
@ -56,5 +64,12 @@ void instrument_on_fork(void);
guint64 instrument_get_offset_hash(GumAddress current_rip);
void instrument_cache_config(void);
void instrument_cache_init(void);
void instrument_cache_insert(gpointer real_address, gpointer code_address);
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, ...);
#endif

View File

@ -0,0 +1,11 @@
#ifndef _MODULE_H
#define _MODULE_H
#include "frida-gumjs.h"
void module_config(void);
void module_init(void);
#endif

View File

@ -13,7 +13,7 @@ typedef void (*afl_persistent_hook_fn)(api_regs *regs, uint64_t guest_base,
extern int __afl_persistent_loop(unsigned int max_cnt);
extern unsigned int * __afl_fuzz_len;
extern unsigned int *__afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr;
extern guint64 persistent_start;

View File

@ -1,7 +1,7 @@
#ifndef _SECCOMP_H
#define _SECCOMP_H
#ifndef __APPLE__
#if !defined(__APPLE__) && !defined(__ANDROID__)
#include <stdint.h>
#include <linux/filter.h>
@ -401,9 +401,9 @@ enum {
typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
typedef void (*seccomp_filter_callback_t)(struct seccomp_notif * req,
typedef void (*seccomp_filter_callback_t)(struct seccomp_notif *req,
struct seccomp_notif_resp *resp,
GumReturnAddressArray * frames);
GumReturnAddressArray *frames);
void seccomp_atomic_set(volatile bool *ptr, bool val);
bool seccomp_atomic_try_set(volatile bool *ptr, bool val);

9
frida_mode/include/shm.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _SHM_H
#define _SHM_H
#include <stddef.h>
void *shm_create(size_t size);
#endif

View File

@ -43,7 +43,7 @@ typedef struct {
G_DECLARE_FINAL_TYPE(GumAflStalkerStats, gum_afl_stalker_stats, GUM,
AFL_STALKER_STATS, GObject)
extern char * stats_filename;
extern char *stats_filename;
extern guint64 stats_interval;
void stats_config(void);

View File

@ -5,6 +5,14 @@
#include "debug.h"
#ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
#else
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif
#endif
#define UNUSED_PARAMETER(x) (void)(x)
#define IGNORED_RETURN(x) (void)!(x)

View File

@ -30,12 +30,21 @@ void asan_init(void) {
static gboolean asan_exclude_module(const GumModuleDetails *details,
gpointer user_data) {
gchar * symbol_name = (gchar *)user_data;
gchar *symbol_name = (gchar *)user_data;
GumAddress address;
address = gum_module_find_export_by_name(details->name, symbol_name);
if (address == 0) { return TRUE; }
/* If the reported address of the symbol is outside of the range of the module
* then ignore it */
if (address < details->range->base_address) { return TRUE; }
if (address > (details->range->base_address + details->range->size)) {
return TRUE;
}
ranges_add_exclude((GumMemoryRange *)details->range);
return FALSE;

View File

@ -22,8 +22,8 @@ asan_storeN_t asan_storeN = NULL;
static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
asan_ctx_t * asan_ctx = (asan_ctx_t *)user_data;
cs_arm64_op * operand = &asan_ctx->operand;
asan_ctx_t *asan_ctx = (asan_ctx_t *)user_data;
cs_arm64_op *operand = &asan_ctx->operand;
arm64_op_mem *mem = &operand->mem;
gsize base = 0;
gsize index = 0;
@ -59,7 +59,7 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
cs_arm64 arm64 = instr->detail->arm64;
cs_arm64_op *operand;
asan_ctx_t * ctx;
asan_ctx_t *ctx;
if (!asan_initialized) return;

View File

@ -17,7 +17,7 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
UNUSED_PARAMETER(user_data);
cs_x86_op * operand = (cs_x86_op *)user_data;
cs_x86_op *operand = (cs_x86_op *)user_data;
x86_op_mem *mem = &operand->mem;
gsize base = 0;
gsize index = 0;
@ -48,9 +48,9 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(iterator);
cs_x86 x86 = instr->detail->x86;
cs_x86_op * operand;
cs_x86_op *operand;
x86_op_mem *mem;
cs_x86_op * ctx;
cs_x86_op *ctx;
if (!asan_initialized) return;

View File

@ -17,7 +17,7 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
UNUSED_PARAMETER(user_data);
cs_x86_op * operand = (cs_x86_op *)user_data;
cs_x86_op *operand = (cs_x86_op *)user_data;
x86_op_mem *mem = &operand->mem;
gsize base = 0;
gsize index = 0;
@ -48,9 +48,9 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(iterator);
cs_x86 x86 = instr->detail->x86;
cs_x86_op * operand;
cs_x86_op *operand;
x86_op_mem *mem;
cs_x86_op * ctx;
cs_x86_op *ctx;
if (!asan_initialized) return;

View File

@ -13,9 +13,9 @@
#define MAX_MEMFD_SIZE (64UL << 10)
extern struct cmp_map *__afl_cmp_map;
static GArray * cmplog_ranges = NULL;
static GHashTable * hash_yes = NULL;
static GHashTable * hash_no = NULL;
static GArray *cmplog_ranges = NULL;
static GHashTable *hash_yes = NULL;
static GHashTable *hash_no = NULL;
static long page_size = 0;
static long page_offset_mask = 0;
@ -24,7 +24,7 @@ static long page_mask = 0;
static gboolean cmplog_range(const GumRangeDetails *details,
gpointer user_data) {
GArray * cmplog_ranges = (GArray *)user_data;
GArray *cmplog_ranges = (GArray *)user_data;
GumMemoryRange range = *details->range;
g_array_append_val(cmplog_ranges, range);
return TRUE;
@ -118,7 +118,7 @@ gboolean cmplog_test_addr(guint64 addr, size_t size) {
if (g_hash_table_contains(hash_yes, GSIZE_TO_POINTER(addr))) { return true; }
if (g_hash_table_contains(hash_no, GSIZE_TO_POINTER(addr))) { return false; }
void * page_addr = GSIZE_TO_POINTER(addr & page_mask);
void *page_addr = GSIZE_TO_POINTER(addr & page_mask);
size_t page_offset = addr & page_offset_mask;
/* If it spans a page, then bail */

View File

@ -148,7 +148,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
cs_arm64_op * operand) {
cs_arm64_op *operand) {
ctx->type = operand->type;
switch (operand->type) {
@ -169,7 +169,7 @@ static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
}
static void cmplog_instrument_call(const cs_insn * instr,
static void cmplog_instrument_call(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_arm64 arm64 = instr->detail->arm64;
@ -247,8 +247,8 @@ static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
cs_arm64_op * operand1,
cs_arm64_op * operand2,
cs_arm64_op *operand1,
cs_arm64_op *operand2,
size_t size) {
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
@ -263,7 +263,7 @@ static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
}
static void cmplog_instrument_cmp_sub(const cs_insn * instr,
static void cmplog_instrument_cmp_sub(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_arm64 arm64 = instr->detail->arm64;

View File

@ -141,7 +141,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
cs_x86_op * operand) {
cs_x86_op *operand) {
ctx->type = operand->type;
ctx->size = operand->size;
@ -163,7 +163,7 @@ static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
}
static void cmplog_instrument_call(const cs_insn * instr,
static void cmplog_instrument_call(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;
@ -230,7 +230,7 @@ static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
cs_x86_op * operand1,
cs_x86_op *operand1,
cs_x86_op *operand2) {
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
@ -244,7 +244,7 @@ static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
}
static void cmplog_instrument_cmp_sub(const cs_insn * instr,
static void cmplog_instrument_cmp_sub(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;

View File

@ -146,7 +146,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
cs_x86_op * operand) {
cs_x86_op *operand) {
ctx->type = operand->type;
ctx->size = operand->size;
@ -168,7 +168,7 @@ static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
}
static void cmplog_instrument_call(const cs_insn * instr,
static void cmplog_instrument_call(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;
@ -238,7 +238,7 @@ static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
}
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
cs_x86_op * operand1,
cs_x86_op *operand1,
cs_x86_op *operand2) {
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
@ -252,7 +252,7 @@ static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
}
static void cmplog_instrument_cmp_sub(const cs_insn * instr,
static void cmplog_instrument_cmp_sub(const cs_insn *instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;

View File

@ -78,6 +78,13 @@ void entry_init(void) {
void entry_start(void) {
if (persistent_start == 0) {
ranges_exclude();
stalker_trust();
}
if (entry_point == 0) { entry_launch(); }
}

View File

@ -1,6 +1,5 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include "frida-gumjs.h"
@ -16,10 +15,13 @@
#include "persistent.h"
#include "prefetch.h"
#include "ranges.h"
#include "shm.h"
#include "stalker.h"
#include "stats.h"
#include "util.h"
#define FRIDA_DEFAULT_MAP_SIZE (64UL << 10)
gboolean instrument_tracing = false;
gboolean instrument_optimize = false;
gboolean instrument_unique = false;
@ -28,13 +30,17 @@ guint64 instrument_hash_seed = 0;
gboolean instrument_use_fixed_seed = FALSE;
guint64 instrument_fixed_seed = 0;
char * instrument_coverage_unstable_filename = NULL;
char *instrument_coverage_unstable_filename = NULL;
gboolean instrument_coverage_insn = FALSE;
char *instrument_regs_filename = NULL;
static GumStalkerTransformer *transformer = NULL;
static GumAddress previous_rip = 0;
static GumAddress previous_end = 0;
static u8 * edges_notified = NULL;
static u8 *edges_notified = NULL;
static int regs_fd = -1;
__thread guint64 instrument_previous_pc;
__thread guint64 *instrument_previous_pc_addr = NULL;
@ -148,7 +154,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
static void instrument_basic_block(GumStalkerIterator *iterator,
GumStalkerOutput * output,
GumStalkerOutput *output,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
@ -156,7 +162,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
const cs_insn *instr;
gboolean begin = TRUE;
gboolean excluded;
block_ctx_t * ctx = NULL;
block_ctx_t *ctx = NULL;
while (gum_stalker_iterator_next(iterator, &instr)) {
@ -229,11 +235,22 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
}
if (unlikely(instrument_regs_filename != NULL)) {
gum_stalker_iterator_put_callout(iterator, instrument_write_regs,
(void *)(size_t)regs_fd, NULL);
}
}
}
instrument_debug_instruction(instr->address, instr->size, output);
if (instrument_coverage_insn) {
instrument_coverage_optimize_insn(instr, output);
}
if (likely(!excluded)) {
@ -242,6 +259,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
}
instrument_cache(instr, output);
if (js_stalker_callback(instr, begin, excluded, output)) {
gum_stalker_iterator_keep(iterator);
@ -269,16 +288,21 @@ void instrument_config(void) {
instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0);
instrument_coverage_unstable_filename =
(getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE"));
instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL);
instrument_regs_filename = getenv("AFL_FRIDA_INST_REGS_FILE");
instrument_debug_config();
instrument_coverage_config();
asan_config();
cmplog_config();
instrument_cache_config();
}
void instrument_init(void) {
if (__afl_map_size == MAP_SIZE) __afl_map_size = FRIDA_DEFAULT_MAP_SIZE;
if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false;
FOKF(cBLU "Instrumentation" cRST " - " cGRN "optimize:" cYEL " [%c]",
@ -294,6 +318,8 @@ void instrument_init(void) {
instrument_coverage_unstable_filename == NULL
? " "
: instrument_coverage_unstable_filename);
FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]",
instrument_coverage_insn ? 'X' : ' ');
if (instrument_tracing && instrument_optimize) {
@ -321,29 +347,7 @@ void instrument_init(void) {
transformer = gum_stalker_transformer_make_from_callback(
instrument_basic_block, NULL, NULL);
if (instrument_unique) {
int shm_id =
shmget(IPC_PRIVATE, __afl_map_size, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); }
edges_notified = shmat(shm_id, NULL, 0);
g_assert(edges_notified != MAP_FAILED);
/*
* Configure the shared memory region to be removed once the process
* dies.
*/
if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
}
/* Clear it, not sure it's necessary, just seems like good practice */
memset(edges_notified, '\0', __afl_map_size);
}
if (instrument_unique) { edges_notified = shm_create(__afl_map_size); }
if (instrument_use_fixed_seed) {
@ -377,11 +381,31 @@ void instrument_init(void) {
instrument_hash_seed);
instrument_hash_zero = instrument_get_offset_hash(0);
FOKF(cBLU "Instrumentation" cRST " - " cGRN "regs:" cYEL " [%s]",
instrument_regs_filename == NULL ? " " : instrument_regs_filename);
if (instrument_regs_filename != NULL) {
char *path =
g_canonicalize_filename(instrument_regs_filename, g_get_current_dir());
FOKF(cBLU "Instrumentation" cRST " - " cGRN "path:" cYEL " [%s]", path);
regs_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (regs_fd < 0) { FFATAL("Failed to open regs file '%s'", path); }
g_free(path);
}
asan_init();
cmplog_init();
instrument_coverage_init();
instrument_coverage_optimize_init();
instrument_debug_init();
instrument_cache_init();
}
@ -402,3 +426,22 @@ void instrument_on_fork() {
}
void instrument_regs_format(int fd, char *format, ...) {
va_list ap;
char buffer[4096] = {0};
int ret;
int len;
va_start(ap, format);
ret = vsnprintf(buffer, sizeof(buffer) - 1, format, ap);
va_end(ap);
if (ret < 0) { return; }
len = strnlen(buffer, sizeof(buffer));
IGNORED_RETURN(write(fd, buffer, len));
}

View File

@ -5,24 +5,193 @@
#if defined(__arm__)
gboolean instrument_is_coverage_optimize_supported(void) {
#define PAGE_MASK (~(GUM_ADDRESS(0xfff)))
#define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x))
return false;
gboolean instrument_cache_enabled = FALSE;
gsize instrument_cache_size = 0;
extern __thread guint64 instrument_previous_pc;
__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
#pragma pack(push, 1)
typedef struct {
// cur_location = (block_address >> 4) ^ (block_address << 8);
// shared_mem[cur_location ^ prev_location]++;
// prev_location = cur_location >> 1;
/* We can remove this branch when we add support for branch suppression */
uint32_t b_code; /* b imm */
uint8_t *shared_mem;
uint64_t *prev_location;
/* code */
/* save regs */
uint32_t str_r0_sp_rz; /* str r0, [sp - RED_ZONE] */
uint32_t str_r1_sp_rz_4; /* str r1, [sp - (RED_ZONE + 4)] */
/* load prev */
uint32_t ldr_r0_pprev; /* ldr r0, [pc-x] */
uint32_t ldrh_r1_r0; /* ldrh r1, [r0] */
/* load curr */
uint32_t mov_r0_block_id; /* mov r0, #imm16 */
/* calculate new */
uint32_t eor_r0_r0_r1; /* eor r0, r0, r1 */
/* load map */
uint32_t ldr_r1_pmap; /* ldr r1, [pc-x] */
/* calculate offset */
uint32_t add_r1_r1_r0; /* add r1, r1, r0 */
/* Load the value */
uint32_t ldrb_r0_r1; /* ldrb r0, [r1] */
/* Increment the value */
uint32_t add_r0_r0_1; /* add r0, r0, #1 */
uint32_t add_r0_r0_r0_lsr_8; /* add r0, r0, r0, lsr #8 */
/* Save the value */
uint32_t strb_r0_r1; /* strb r0, [r1] */
/* load curr shifted */
uint32_t mov_r0_block_id_shr_1; /* mov r0, #imm16 >> 1*/
/* Update prev */
uint32_t ldr_r1_pprev; /* ldr r1, [pc-x] */
uint32_t strh_r0_r1; /* strh r0, [r1] */
/* restore regs */
uint32_t ldr_r1_sp_rz_4; /* ldr r1, [sp - (RED_ZONE + 4)] */
uint32_t ldr_r0_sp_rz; /* ldr r0, [sp - RED_ZONE] */
} afl_log_code_asm_t;
typedef union {
afl_log_code_asm_t code;
uint8_t bytes[0];
} afl_log_code;
#pragma pack(pop)
static const afl_log_code_asm_t template =
{
.b_code = GUINT32_TO_LE(0xea000001),
.shared_mem = (uint8_t *)GUINT32_TO_LE(0xcefaadde),
.prev_location = (uint64_t *)GUINT32_TO_LE(0xadba0df0),
.str_r0_sp_rz = GUINT32_TO_LE(0xe50d0080),
.str_r1_sp_rz_4 = GUINT32_TO_LE(0xe50d1084),
.ldr_r0_pprev = GUINT32_TO_LE(0xe51f0014),
.ldrh_r1_r0 = GUINT32_TO_LE(0xe1d010b0),
.mov_r0_block_id = GUINT32_TO_LE(0xe3000000),
.eor_r0_r0_r1 = GUINT32_TO_LE(0xe0200001),
.ldr_r1_pmap = GUINT32_TO_LE(0xe51f1028),
.add_r1_r1_r0 = GUINT32_TO_LE(0xe0811000),
.ldrb_r0_r1 = GUINT32_TO_LE(0xe5d10000),
.add_r0_r0_1 = GUINT32_TO_LE(0xe2800001),
.add_r0_r0_r0_lsr_8 = GUINT32_TO_LE(0xe0800420),
.strb_r0_r1 = GUINT32_TO_LE(0xe5c10000),
.mov_r0_block_id_shr_1 = GUINT32_TO_LE(0xe3000000),
.ldr_r1_pprev = GUINT32_TO_LE(0xe51f1040),
.strh_r0_r1 = GUINT32_TO_LE(0xe1c100b0),
.ldr_r1_sp_rz_4 = GUINT32_TO_LE(0xe51d1084),
.ldr_r0_sp_rz = GUINT32_TO_LE(0xe51d0080),
}
void instrument_coverage_optimize(const cs_insn * instr,
;
gboolean instrument_is_coverage_optimize_supported(void) {
return true;
}
static void patch_t3_insn(uint32_t *insn, uint16_t val) {
uint32_t orig = GUINT32_FROM_LE(*insn);
uint32_t imm12 = (val & 0xfff);
uint32_t imm4 = (val >> 12);
orig |= imm12;
orig |= (imm4 << 16);
*insn = GUINT32_TO_LE(orig);
}
void instrument_coverage_optimize(const cs_insn *instr,
GumStalkerOutput *output) {
afl_log_code code = {0};
GumArmWriter *cw = output->writer.arm;
gpointer block_start;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
gsize map_size_pow2;
gsize area_offset_ror;
GumAddress code_addr = 0;
// gum_arm64_writer_put_brk_imm(cw, 0x0);
code_addr = cw->pc;
block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code));
code.code = template;
g_assert(PAGE_ALIGNED(__afl_area_ptr));
map_size_pow2 = util_log2(__afl_map_size);
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
code.code.shared_mem = __afl_area_ptr;
code.code.prev_location = instrument_previous_pc_addr;
patch_t3_insn(&code.code.mov_r0_block_id, (uint16_t)area_offset);
patch_t3_insn(&code.code.mov_r0_block_id_shr_1, (uint16_t)area_offset_ror);
// gum_arm_writer_put_breakpoint(cw);
gum_arm_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
}
void instrument_coverage_optimize_insn(const cs_insn *instr,
GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
FFATAL("Optimized coverage not supported on this architecture");
}
void instrument_coverage_optimize_init(void) {
FWARNF("Optimized coverage not supported on this architecture");
char *shm_env = getenv(SHM_ENV_VAR);
FVERBOSE("SHM_ENV_VAR: %s", shm_env);
if (shm_env == NULL) {
FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes");
__afl_area_ptr = area_ptr_dummy;
memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy));
}
FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
if (instrument_previous_pc_addr == NULL) {
instrument_previous_pc_addr = &instrument_previous_pc;
*instrument_previous_pc_addr = instrument_hash_zero;
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
}
}
@ -46,5 +215,48 @@ gpointer instrument_cur(GumStalkerOutput *output) {
}
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) {
int fd = (int)user_data;
instrument_regs_format(fd,
"r0 : 0x%08x, r1 : 0x%08x, r2 : 0x%08x, r3 : 0x%08x\n",
cpu_context->r[0], cpu_context->r[2],
cpu_context->r[1], cpu_context->r[3]);
instrument_regs_format(fd,
"r4 : 0x%08x, r5 : 0x%08x, r6 : 0x%08x, r7 : 0x%08x\n",
cpu_context->r[4], cpu_context->r[5],
cpu_context->r[6], cpu_context->r[7]);
instrument_regs_format(
fd, "r8 : 0x%08x, r9 : 0x%08x, r10: 0x%08x, r11: 0x%08x\n",
cpu_context->r8, cpu_context->r9, cpu_context->r10, cpu_context->r11);
instrument_regs_format(
fd, "r12: 0x%08x, sp : 0x%08x, lr : 0x%08x, pc : 0x%08x\n",
cpu_context->r12, cpu_context->sp, cpu_context->lr, cpu_context->pc);
instrument_regs_format(fd, "cpsr: 0x%08x\n\n", cpu_context->cpsr);
}
#endif

View File

@ -14,9 +14,14 @@
#define PAGE_MASK (~(GUM_ADDRESS(0xfff)))
#define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x))
#define GUM_RESTORATION_PROLOG_SIZE 4
#if defined(__aarch64__)
gboolean instrument_cache_enabled = FALSE;
gsize instrument_cache_size = 0;
static GHashTable *coverage_blocks = NULL;
__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
#pragma pack(push, 1)
@ -44,6 +49,9 @@ typedef struct {
// b 0x7fb6f0dee4
// ldp x16, x17, [sp], #144
uint32_t b_imm8; /* br #68 */
uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */
uint32_t stp_x0_x1; /* stp x0, x1, [sp, #-0xa0] */
uint32_t adrp_x0_prev_loc1; /* adrp x0, #0xXXXX */
@ -66,9 +74,6 @@ typedef struct {
uint32_t ldp_x0_x1; /* ldp x0, x1, [sp, #-0xa0] */
uint32_t b_imm8; /* br #8 */
uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */
} afl_log_code_asm_t;
#pragma pack(pop)
@ -83,6 +88,9 @@ typedef union {
static const afl_log_code_asm_t template =
{
.b_imm8 = 0x14000011,
.restoration_prolog = 0xa8c947f0,
.stp_x0_x1 = 0xa93607e0,
.adrp_x0_prev_loc1 = 0x90000000,
@ -107,9 +115,6 @@ static const afl_log_code_asm_t template =
.ldp_x0_x1 = 0xa97607e0,
.b_imm8 = 0x14000002,
.restoration_prolog = 0xa8c947f0,
}
;
@ -120,6 +125,112 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
static gboolean instrument_is_deterministic(const cs_insn *from_insn) {
cs_arm64 *arm64;
arm64_cc cc;
if (from_insn == NULL) { return FALSE; }
arm64 = &from_insn->detail->arm64;
cc = arm64->cc;
switch (from_insn->id) {
case ARM64_INS_B:
case ARM64_INS_BL:
if (cc == ARM64_CC_INVALID) { return TRUE; }
break;
case ARM64_INS_RET:
case ARM64_INS_RETAA:
case ARM64_INS_RETAB:
if (arm64->op_count == 0) { return TRUE; }
break;
default:
return FALSE;
}
return FALSE;
}
static void instrument_coverage_switch(GumStalkerObserver *self,
gpointer from_address,
gpointer start_address,
const cs_insn *from_insn,
gpointer *target) {
UNUSED_PARAMETER(self);
UNUSED_PARAMETER(from_address);
UNUSED_PARAMETER(start_address);
gsize fixup_offset;
if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target)) &&
!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target + 4))) {
return;
}
if (instrument_is_deterministic(from_insn)) { return; }
/*
* Since each block is prefixed with a restoration prologue, we need to be
* able to begin execution at an offset into the block and execute both this
* restoration prologue and the instrumented block without the coverage code.
* We therefore layout our block as follows:
*
* +-----+------------------+-----+--------------------------+-------------+
* | LDP | BR <TARGET CODE> | LDP | COVERAGE INSTRUMENTATION | TARGET CODE |
* +-----+------------------+-----+--------------------------+-------------+
*
* ^ ^ ^ ^
* | | | |
* A B C D
*
* Without instrumentation suppression, the block is either executed at point
* (C) if it is reached by an indirect branch (and registers need to be
* restored) or point (D) if it is reached by an direct branch (and hence the
* registers don't need restoration). Similarly, we can start execution of the
* block at points (A) or (B) to achieve the same functionality, but without
* executing the coverage instrumentation.
*
* In either case, Stalker will call us back with the address of the target
* block to be executed as the destination. We can then check if the branch is
* a deterministic one and if so branch to point (C) or (D) rather than (A)
* or (B). We lay the code out in this fashion so that in the event we can't
* suppress coverage (the most likely), we can vector directly to the coverage
* instrumentation code and execute entirely without any branches. If we
* suppress the coverage, we simply branch beyond it instead.
*/
fixup_offset = GUM_RESTORATION_PROLOG_SIZE +
G_STRUCT_OFFSET(afl_log_code_asm_t, restoration_prolog);
*target += fixup_offset;
}
static void instrument_coverage_suppress_init(void) {
static gboolean initialized = false;
if (initialized) { return; }
initialized = true;
GumStalkerObserver *observer = stalker_get_observer();
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
iface->switch_callback = instrument_coverage_switch;
coverage_blocks = g_hash_table_new(g_direct_hash, g_direct_equal);
if (coverage_blocks == NULL) {
FATAL("Failed to g_hash_table_new, errno: %d", errno);
}
}
static gboolean instrument_coverage_in_range(gssize offset) {
return (offset >= G_MININT33 && offset <= G_MAXINT33);
@ -146,11 +257,12 @@ static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
}
void instrument_coverage_optimize(const cs_insn * instr,
void instrument_coverage_optimize(const cs_insn *instr,
GumStalkerOutput *output) {
afl_log_code code = {0};
GumArm64Writer *cw = output->writer.arm64;
gpointer block_start;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
gsize map_size_pow2;
gsize area_offset_ror;
@ -160,9 +272,10 @@ void instrument_coverage_optimize(const cs_insn * instr,
GumAddressSpec spec = {.near_address = cw->code,
.max_distance = 1ULL << 30};
guint page_size = gum_query_page_size();
instrument_previous_pc_addr = gum_memory_allocate_near(
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
&spec, sizeof(guint64), page_size, GUM_PAGE_READ | GUM_PAGE_WRITE);
*instrument_previous_pc_addr = instrument_hash_zero;
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
FVERBOSE("code_addr: %p", cw->code);
@ -171,8 +284,32 @@ void instrument_coverage_optimize(const cs_insn * instr,
// gum_arm64_writer_put_brk_imm(cw, 0x0);
instrument_coverage_suppress_init();
code_addr = cw->pc;
/*
* On AARCH64, immediate branches can only be encoded with a 28-bit offset. To
* make a longer branch, it is necessary to load a register with the target
* address, this register must be saved beyond the red-zone before the branch
* is taken. To restore this register each block is prefixed by Stalker with
* an instruction to load x16,x17 from beyond the red-zone on the stack. A
* pair of registers are saved/restored because on AARCH64, the stack pointer
* must be 16 byte aligned. This instruction is emitted into the block before
* the tranformer (from which we are called) is executed. If is is possible
* for Stalker to make a direct branch (the target block is close enough), it
* can forego pushing the registers and instead branch at an offset into the
* block to skip this restoration prolog.
*/
block_start =
GSIZE_TO_POINTER(GUM_ADDRESS(cw->code) - GUM_RESTORATION_PROLOG_SIZE);
if (!g_hash_table_add(coverage_blocks, block_start)) {
FATAL("Failed - g_hash_table_add");
}
code.code = template;
/*
@ -209,6 +346,14 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
void instrument_coverage_optimize_insn(const cs_insn *instr,
GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
void instrument_coverage_optimize_init(void) {
char *shm_env = getenv(SHM_ENV_VAR);
@ -239,5 +384,65 @@ gpointer instrument_cur(GumStalkerOutput *output) {
}
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) {
int fd = (int)(size_t)user_data;
instrument_regs_format(
fd, "x0 : 0x%016x, x1 : 0x%016x, x2 : 0x%016x, x3 : 0x%016x\n",
cpu_context->x[0], cpu_context->x[1], cpu_context->x[2],
cpu_context->x[3]);
instrument_regs_format(
fd, "x4 : 0x%016x, x5 : 0x%016x, x6 : 0x%016x, x7 : 0x%016x\n",
cpu_context->x[4], cpu_context->x[5], cpu_context->x[6],
cpu_context->x[7]);
instrument_regs_format(
fd, "x8 : 0x%016x, x9 : 0x%016x, x10: 0x%016x, x11: 0x%016x\n",
cpu_context->x[8], cpu_context->x[9], cpu_context->x[10],
cpu_context->x[11]);
instrument_regs_format(
fd, "x12: 0x%016x, x13: 0x%016x, x14: 0x%016x, x15: 0x%016x\n",
cpu_context->x[12], cpu_context->x[13], cpu_context->x[14],
cpu_context->x[15]);
instrument_regs_format(
fd, "x16: 0x%016x, x17: 0x%016x, x18: 0x%016x, x19: 0x%016x\n",
cpu_context->x[16], cpu_context->x[17], cpu_context->x[18],
cpu_context->x[19]);
instrument_regs_format(
fd, "x20: 0x%016x, x21: 0x%016x, x22: 0x%016x, x23: 0x%016x\n",
cpu_context->x[20], cpu_context->x[21], cpu_context->x[22],
cpu_context->x[23]);
instrument_regs_format(
fd, "x24: 0x%016x, x25: 0x%016x, x26: 0x%016x, x27: 0x%016x\n",
cpu_context->x[24], cpu_context->x[25], cpu_context->x[26],
cpu_context->x[27]);
instrument_regs_format(
fd, "x28: 0x%016x, fp : 0x%016x, lr : 0x%016x, sp : 0x%016x\n",
cpu_context->x[28], cpu_context->fp, cpu_context->lr, cpu_context->sp);
instrument_regs_format(fd, "pc : 0x%016x\n\n", cpu_context->pc);
}
#endif

View File

@ -9,6 +9,7 @@
#include "util.h"
char *instrument_coverage_filename = NULL;
bool instrument_coverage_absolute = false;
static int normal_coverage_fd = -1;
static int normal_coverage_pipes[2] = {-1, -1};
@ -17,7 +18,7 @@ static int unstable_coverage_fd = -1;
static int unstable_coverage_pipes[2] = {-1, -1};
static uint64_t normal_coverage_last_start = 0;
static gchar * unstable_coverage_fuzzer_stats = NULL;
static gchar *unstable_coverage_fuzzer_stats = NULL;
typedef struct {
@ -68,7 +69,7 @@ typedef struct {
static gboolean coverage_range(const GumRangeDetails *details,
gpointer user_data) {
GArray * coverage_ranges = (GArray *)user_data;
GArray *coverage_ranges = (GArray *)user_data;
coverage_range_t coverage = {0};
if (details->file == NULL) { return TRUE; }
@ -210,8 +211,8 @@ static GArray *coverage_get_modules(void) {
static void instrument_coverage_mark(void *key, void *value, void *user_data) {
UNUSED_PARAMETER(key);
coverage_mark_ctx_t * ctx = (coverage_mark_ctx_t *)user_data;
GArray * coverage_modules = ctx->modules;
coverage_mark_ctx_t *ctx = (coverage_mark_ctx_t *)user_data;
GArray *coverage_modules = ctx->modules;
normal_coverage_data_t *val = (normal_coverage_data_t *)value;
guint i;
@ -237,6 +238,18 @@ static void instrument_coverage_mark(void *key, void *value, void *user_data) {
}
static void instrument_coverage_mark_first(void *key, void *value,
void *user_data) {
UNUSED_PARAMETER(key);
coverage_range_t *module = (coverage_range_t *)user_data;
normal_coverage_data_t *val = (normal_coverage_data_t *)value;
val->module = module;
module->count++;
}
static void coverage_write(int fd, void *data, size_t size) {
ssize_t written;
@ -289,9 +302,9 @@ static void coverage_write_modules(int fd, GArray *coverage_modules) {
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->base_address);
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->limit);
/* entry */
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0);
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0UL);
/* checksum */
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0);
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0UL);
/* timestamp */
coverage_format(fd, "%08" G_GINT32_MODIFIER "X, ", 0);
coverage_format(fd, "%s\n", module->path);
@ -317,6 +330,12 @@ static void coverage_write_events(void *key, void *value, void *user_data) {
};
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
evt.offset = __builtin_bswap32(evt.offset);
evt.length = __builtin_bswap16(evt.length);
evt.module = __builtin_bswap16(evt.module);
#endif
coverage_write(fd, &evt, sizeof(coverage_event_t));
}
@ -398,35 +417,76 @@ static void instrument_coverage_normal_run() {
instrument_coverage_print("Coverage - Preparing\n");
GArray *coverage_modules = coverage_get_modules();
if (instrument_coverage_absolute) {
guint size = g_hash_table_size(coverage_hash);
instrument_coverage_print("Coverage - Total Entries: %u\n", size);
guint size = g_hash_table_size(coverage_hash);
instrument_coverage_print("Coverage - Total Entries: %u\n", size);
coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0};
coverage_range_t module = {
g_hash_table_foreach(coverage_hash, instrument_coverage_mark, &ctx);
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
.base_address = GUM_ADDRESS(0),
.limit = GUM_ADDRESS(-1),
.size = GUM_ADDRESS(-1),
.path = "absolute",
.offset = 0,
.is_executable = true,
.count = size,
.id = 0,
guint coverage_marked_modules = coverage_mark_modules(coverage_modules);
instrument_coverage_print("Coverage - Marked Modules: %u\n",
coverage_marked_modules);
};
coverage_write_header(normal_coverage_fd, coverage_marked_modules);
coverage_write_modules(normal_coverage_fd, coverage_modules);
coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", ctx.count);
g_hash_table_foreach(coverage_hash, coverage_write_events,
&normal_coverage_fd);
instrument_coverage_print("Coverage Module - 0x%016" G_GINT64_MODIFIER
"X - 0x%016" G_GINT64_MODIFIER "X (%s)\n",
module.base_address, module.limit, module.path);
GArray *coverage_modules =
g_array_sized_new(false, false, sizeof(coverage_range_t), 1);
g_array_append_val(coverage_modules, module);
g_hash_table_foreach(coverage_hash, instrument_coverage_mark_first,
&module);
coverage_write_header(normal_coverage_fd, 1);
coverage_write_modules(normal_coverage_fd, coverage_modules);
coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", size);
g_hash_table_foreach(coverage_hash, coverage_write_events,
&normal_coverage_fd);
} else {
GArray *coverage_modules = coverage_get_modules();
guint size = g_hash_table_size(coverage_hash);
instrument_coverage_print("Coverage - Total Entries: %u\n", size);
coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0};
/* For each coverage event in the hashtable associate it with a module and
* count the number of entries per module */
g_hash_table_foreach(coverage_hash, instrument_coverage_mark, &ctx);
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
/* For each module with coverage events assign it an incrementing number */
guint coverage_marked_modules = coverage_mark_modules(coverage_modules);
instrument_coverage_print("Coverage - Marked Modules: %u\n",
coverage_marked_modules);
coverage_write_header(normal_coverage_fd, coverage_marked_modules);
coverage_write_modules(normal_coverage_fd, coverage_modules);
coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", ctx.count);
g_hash_table_foreach(coverage_hash, coverage_write_events,
&normal_coverage_fd);
}
g_hash_table_unref(coverage_hash);
instrument_coverage_print("Coverage - Completed\n");
}
static GArray *instrument_coverage_unstable_read_unstable_ids(void) {
gchar * contents = NULL;
gchar *contents = NULL;
gsize length = 0;
GArray *unstable_edge_ids =
g_array_sized_new(false, false, sizeof(gpointer), 100);
@ -533,7 +593,7 @@ static GHashTable *instrument_collect_unstable_blocks(
while (g_hash_table_iter_next(&iter, NULL, &value)) {
unstable_coverage_data_t *unstable = (unstable_coverage_data_t *)value;
normal_coverage_data_t * from =
normal_coverage_data_t *from =
gum_malloc0(sizeof(normal_coverage_data_t));
normal_coverage_data_t *to = gum_malloc0(sizeof(normal_coverage_data_t));
from->start = unstable->from;
@ -616,8 +676,6 @@ static void instrument_coverage_unstable_run(void) {
instrument_coverage_print("Coverage - Preparing\n");
GArray *coverage_modules = coverage_get_modules();
instrument_coverage_print("Found edges: %u\n", edges);
GArray *unstable_edge_ids = instrument_coverage_unstable_read_unstable_ids();
@ -628,20 +686,60 @@ static void instrument_coverage_unstable_run(void) {
guint size = g_hash_table_size(unstable_blocks);
instrument_coverage_print("Unstable blocks: %u\n", size);
coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0};
if (instrument_coverage_absolute) {
g_hash_table_foreach(unstable_blocks, instrument_coverage_mark, &ctx);
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
instrument_coverage_print("Coverage - Total Entries: %u\n", size);
guint coverage_marked_modules = coverage_mark_modules(coverage_modules);
instrument_coverage_print("Coverage - Marked Modules: %u\n",
coverage_marked_modules);
coverage_range_t module = {
coverage_write_header(unstable_coverage_fd, coverage_marked_modules);
coverage_write_modules(unstable_coverage_fd, coverage_modules);
coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", ctx.count);
g_hash_table_foreach(unstable_blocks, coverage_write_events,
&unstable_coverage_fd);
.base_address = GUM_ADDRESS(0),
.limit = GUM_ADDRESS(-1),
.size = GUM_ADDRESS(-1),
.path = "absolute",
.offset = 0,
.is_executable = true,
.count = size,
.id = 0,
};
instrument_coverage_print("Coverage Module - 0x%016" G_GINT64_MODIFIER
"X - 0x%016" G_GINT64_MODIFIER "X (%s)\n",
module.base_address, module.limit, module.path);
GArray *coverage_modules =
g_array_sized_new(false, false, sizeof(coverage_range_t), 1);
g_array_append_val(coverage_modules, module);
g_hash_table_foreach(unstable_blocks, instrument_coverage_mark_first,
&module);
coverage_write_header(unstable_coverage_fd, 1);
coverage_write_modules(unstable_coverage_fd, coverage_modules);
coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", size);
g_hash_table_foreach(unstable_blocks, coverage_write_events,
&unstable_coverage_fd);
} else {
GArray *coverage_modules = coverage_get_modules();
coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0};
g_hash_table_foreach(unstable_blocks, instrument_coverage_mark, &ctx);
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
guint coverage_marked_modules = coverage_mark_modules(coverage_modules);
instrument_coverage_print("Coverage - Marked Modules: %u\n",
coverage_marked_modules);
coverage_write_header(unstable_coverage_fd, coverage_marked_modules);
coverage_write_modules(unstable_coverage_fd, coverage_modules);
coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", ctx.count);
g_hash_table_foreach(unstable_blocks, coverage_write_events,
&unstable_coverage_fd);
}
g_hash_table_unref(unstable_blocks);
g_array_free(unstable_edge_ids, TRUE);
@ -654,6 +752,8 @@ static void instrument_coverage_unstable_run(void) {
void instrument_coverage_config(void) {
instrument_coverage_filename = getenv("AFL_FRIDA_INST_COVERAGE_FILE");
instrument_coverage_absolute =
(getenv("AFL_FRIDA_INST_COVERAGE_ABSOLUTE") != NULL);
}

View File

@ -66,7 +66,7 @@ static void instrument_disasm(guint8 *start, guint8 *end,
instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t* 0x%016" G_GSIZE_MODIFIER
"x\n",
curr, *(size_t *)curr);
(uint64_t)(size_t)curr, *(size_t *)curr);
len += sizeof(size_t);
continue;

View File

@ -23,13 +23,39 @@
#if defined(__x86_64__)
#ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
#else
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif
#endif
enum jcc_opcodes {
OPC_JO = 0x70,
OPC_JNO = 0x71,
OPC_JB = 0x72,
OPC_JAE = 0x73,
OPC_JE = 0x74,
OPC_JNE = 0x75,
OPC_JBE = 0x76,
OPC_JA = 0x77,
OPC_JS = 0x78,
OPC_JNS = 0x79,
OPC_JP = 0x7a,
OPC_JNP = 0x7b,
OPC_JL = 0x7c,
OPC_JGE = 0x7d,
OPC_JLE = 0x7e,
OPC_JG = 0x7f,
};
typedef union {
struct {
uint8_t opcode;
uint8_t distance;
};
uint8_t bytes[0];
} jcc_insn;
static GHashTable *coverage_blocks = NULL;
@ -45,8 +71,7 @@ static gboolean instrument_coverage_in_range(gssize offset) {
}
#ifdef __APPLE__
#pragma pack(push, 1)
#pragma pack(push, 1)
typedef struct {
@ -54,21 +79,28 @@ typedef struct {
// shared_mem[cur_location ^ prev_location]++;
// prev_location = cur_location >> 1;
// mov QWORD PTR [rsp-0x80],rax
// lahf
// mov QWORD PTR [rsp-0x88],rax
// mov QWORD PTR [rsp-0x90],rbx
// mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740
// mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740
// lea rax,[rip + 0x103f77]
// mov bl,BYTE PTR [rax]
// add bl,0x1
// adc bl,0x0
// mov BYTE PTR [rax],bl
// mov rbx,QWORD PTR [rsp-0x90]
// mov rax,QWORD PTR [rsp-0x88]
// sahf
// mov rax,QWORD PTR [rsp-0x80]
// mov QWORD PTR [rsp-0x88],rax
// lahf
// mov QWORD PTR [rsp-0x90],rax
// mov QWORD PTR [rsp-0x98],rbx
// mov eax,DWORD PTR [rip+0x1312334]
// xor eax,0x3f77
// lea rbx,[rip+0x132338]
// add rax,rbx
// mov bl,BYTE PTR [rax]
// add bl,0x1
// adc bl,0x0
// mov BYTE PTR [rax],bl
// mov rbx,QWORD PTR [rsp-0x98]
// mov rax,QWORD PTR [rsp-0x90]
// sahf
// mov rax,QWORD PTR [rsp-0x88]
// mov DWORD PTR [rip+0x13122f8],0x9fbb
uint8_t mov_rax_rsp_88[8];
uint8_t lahf;
@ -76,84 +108,11 @@ typedef struct {
uint8_t mov_rbx_rsp_98[8];
uint8_t mov_eax_prev_loc[6];
uint8_t mov_prev_loc_curr_loc_shr1[10];
uint8_t leax_eax_curr_loc[7];
uint8_t mov_rbx_ptr_rax[2];
uint8_t add_bl_1[3];
uint8_t adc_bl_0[3];
uint8_t mov_ptr_rax_rbx[2];
uint8_t mov_rsp_98_rbx[8];
uint8_t mov_rsp_90_rax[8];
uint8_t sahf;
uint8_t mov_rsp_88_rax[8];
} afl_log_code_asm_t;
#pragma pack(pop)
static const afl_log_code_asm_t template =
{
.mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
.lahf = 0x9f,
.mov_rax_rsp_90 = {0x48, 0x89, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
.mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
.mov_eax_prev_loc = {0x8b, 0x05},
.mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
.leax_eax_curr_loc = {0x48, 0x8d, 0x05},
.mov_rbx_ptr_rax = {0x8a, 0x18},
.add_bl_1 = {0x80, 0xc3, 0x01},
.adc_bl_0 = {0x80, 0xd3, 0x00},
.mov_ptr_rax_rbx = {0x88, 0x18},
.mov_rsp_98_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
.mov_rsp_90_rax = {0x48, 0x8B, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
.sahf = 0x9e,
.mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
}
;
#else
#pragma pack(push, 1)
typedef struct {
// cur_location = (block_address >> 4) ^ (block_address << 8);
// shared_mem[cur_location ^ prev_location]++;
// prev_location = cur_location >> 1;
// mov QWORD PTR [rsp-0x80],rax
// lahf
// mov QWORD PTR [rsp-0x88],rax
// mov QWORD PTR [rsp-0x90],rbx
// mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740
// mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740
// xor eax,0x103f77
// mov bl,BYTE PTR [rax]
// add bl,0x1
// adc bl,0x0
// mov BYTE PTR [rax],bl
// mov rbx,QWORD PTR [rsp-0x90]
// mov rax,QWORD PTR [rsp-0x88]
// sahf
// mov rax,QWORD PTR [rsp-0x80]
uint8_t mov_rax_rsp_88[8];
uint8_t lahf;
uint8_t mov_rax_rsp_90[8];
uint8_t mov_rbx_rsp_98[8];
uint8_t mov_eax_prev_loc[6];
uint8_t mov_prev_loc_curr_loc_shr1[10];
uint8_t xor_eax_curr_loc[5];
uint8_t lea_rbx_area_ptr[7];
uint8_t add_rax_rbx[3];
uint8_t mov_rbx_ptr_rax[2];
uint8_t add_bl_1[3];
uint8_t adc_bl_0[3];
@ -164,9 +123,11 @@ typedef struct {
uint8_t sahf;
uint8_t mov_rsp_88_rax[8];
uint8_t mov_prev_loc_curr_loc_shr1[10];
} afl_log_code_asm_t;
#pragma pack(pop)
#pragma pack(pop)
static const afl_log_code_asm_t template =
{
@ -177,9 +138,10 @@ static const afl_log_code_asm_t template =
.mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
.mov_eax_prev_loc = {0x8b, 0x05},
.mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
.xor_eax_curr_loc = {0x35},
.lea_rbx_area_ptr = {0x48, 0x8d, 0x1d},
.add_rax_rbx = {0x48, 0x01, 0xd8},
.mov_rbx_ptr_rax = {0x8a, 0x18},
.add_bl_1 = {0x80, 0xc3, 0x01},
.adc_bl_0 = {0x80, 0xd3, 0x00},
@ -190,10 +152,11 @@ static const afl_log_code_asm_t template =
.sahf = 0x9e,
.mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
.mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
}
;
#endif
typedef union {
@ -202,180 +165,22 @@ typedef union {
} afl_log_code;
#ifdef __APPLE__
void instrument_coverage_optimize_init(void) {
}
#else
static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
gpointer user_data) {
static GumAddress last_limit = (64ULL << 10);
gpointer * address = (gpointer *)user_data;
last_limit = GUM_ALIGN_SIZE(last_limit, __afl_map_size);
if ((details->range->base_address - last_limit) > __afl_map_size) {
*address = GSIZE_TO_POINTER(last_limit);
return FALSE;
}
if (details->range->base_address > ((2ULL << 30) - __afl_map_size)) {
return FALSE;
}
/*
* Align our buffer on a 64k boundary so that the low 16-bits of the address
* are zero, then we can just XOR the base address in, when we XOR with the
* current block ID.
*/
last_limit = GUM_ALIGN_SIZE(
details->range->base_address + details->range->size, __afl_map_size);
return TRUE;
}
static void instrument_coverage_optimize_map_mmap_anon(gpointer address) {
__afl_area_ptr =
mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
}
static void instrument_coverage_optimize_map_mmap(char * shm_file_path,
gpointer address) {
int shm_fd = -1;
if (munmap(__afl_area_ptr, __afl_map_size) != 0) {
FATAL("Failed to unmap previous __afl_area_ptr");
}
__afl_area_ptr = NULL;
#if !defined(__ANDROID__)
shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { FATAL("shm_open() failed\n"); }
#else
shm_fd = open("/dev/ashmem", O_RDWR);
if (shm_fd == -1) { FATAL("open() failed\n"); }
if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) {
FATAL("ioctl(ASHMEM_SET_NAME) failed");
}
if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) {
FATAL("ioctl(ASHMEM_SET_SIZE) failed");
}
#endif
__afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); }
}
static void instrument_coverage_optimize_map_shm(guint64 shm_env_val,
gpointer address) {
if (shmdt(__afl_area_ptr) != 0) {
FATAL("Failed to detach previous __afl_area_ptr");
}
__afl_area_ptr = shmat(shm_env_val, address, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map shm __afl_area_ptr: %d", errno);
}
}
void instrument_coverage_optimize_init(void) {
gpointer low_address = NULL;
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
&low_address);
FVERBOSE("Low address: %p", low_address);
if (low_address == 0 ||
GPOINTER_TO_SIZE(low_address) > ((2UL << 30) - __afl_map_size)) {
FATAL("Invalid low_address: %p", low_address);
}
ranges_print_debug_maps();
char *shm_env = getenv(SHM_ENV_VAR);
FVERBOSE("SHM_ENV_VAR: %s", shm_env);
if (shm_env == NULL) {
FWARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes");
instrument_coverage_optimize_map_mmap_anon(low_address);
} else {
guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10);
if (shm_env_val == 0) {
instrument_coverage_optimize_map_mmap(shm_env, low_address);
} else {
instrument_coverage_optimize_map_shm(shm_env_val, low_address);
}
}
FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
}
#endif
static void instrument_coverage_switch(GumStalkerObserver *self,
gpointer from_address,
gpointer start_address,
const cs_insn * from_insn,
gpointer * target) {
const cs_insn *from_insn,
gpointer *target) {
UNUSED_PARAMETER(self);
UNUSED_PARAMETER(start_address);
UNUSED_PARAMETER(from_address);
cs_x86 * x86;
cs_x86 *x86;
cs_x86_op *op;
if (from_insn == NULL) { return; }
@ -398,10 +203,17 @@ static void instrument_coverage_switch(GumStalkerObserver *self,
}
if (op[0].type != X86_OP_IMM) { return; }
if (op[0].type != X86_OP_IMM) {
instrument_cache_insert(start_address, *target);
return;
}
break;
case X86_INS_RET:
instrument_cache_insert(start_address,
(guint8 *)*target + sizeof(afl_log_code));
break;
default:
return;
@ -418,7 +230,7 @@ static void instrument_coverage_suppress_init(void) {
if (initialized) { return; }
initialized = true;
GumStalkerObserver * observer = stalker_get_observer();
GumStalkerObserver *observer = stalker_get_observer();
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
iface->switch_callback = instrument_coverage_switch;
@ -431,48 +243,19 @@ static void instrument_coverage_suppress_init(void) {
}
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) {
static void instrument_coverage_write(GumAddress address,
GumStalkerOutput *output) {
afl_log_code code = {0};
GumX86Writer *cw = output->writer.x86;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
gsize map_size_pow2;
gsize area_offset_ror;
GumAddress code_addr = 0;
if (instrument_previous_pc_addr == NULL) {
GumAddressSpec spec = {.near_address = cw->code,
.max_distance = 1ULL << 30};
instrument_previous_pc_addr = gum_memory_allocate_near(
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
*instrument_previous_pc_addr = instrument_hash_zero;
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
FVERBOSE("code_addr: %p", cw->code);
}
instrument_coverage_suppress_init();
// gum_x86_writer_put_breakpoint(cw);
code_addr = cw->pc;
if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
FATAL("Failed - g_hash_table_add");
}
guint64 area_offset = instrument_get_offset_hash(address);
gsize map_size_pow2;
gsize area_offset_ror;
GumAddress code_addr = cw->pc;
code.code = template;
gssize curr_loc_shr_1_offset =
offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
map_size_pow2 = util_log2(__afl_map_size);
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
*((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
/* mov_prev_loc_curr_loc_shr1 */
gssize prev_loc_value =
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
@ -490,6 +273,8 @@ void instrument_coverage_optimize(const cs_insn * instr,
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
/* mov_eax_prev_loc */
gssize prev_loc_value2 =
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
(code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
@ -505,40 +290,172 @@ void instrument_coverage_optimize(const cs_insn * instr,
*((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2;
#ifdef __APPLE__
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.leax_eax_curr_loc) +
sizeof(code.code.leax_eax_curr_loc) -
sizeof(guint32);
gssize xor_curr_loc_value =
((GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset) -
(code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
sizeof(code.code.mov_eax_prev_loc)));
if (!instrument_coverage_in_range(xor_curr_loc_value)) {
FATAL("Patch out of range (xor_curr_loc_value): 0x%016lX",
xor_curr_loc_value);
}
*((guint32 *)&code.bytes[xor_curr_loc_offset]) = xor_curr_loc_value;
#else
/* xor_eax_curr_loc */
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) +
sizeof(code.code.xor_eax_curr_loc) -
sizeof(guint32);
*((guint32 *)&code.bytes[xor_curr_loc_offset]) =
(guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset);
#endif
*((guint32 *)&code.bytes[xor_curr_loc_offset]) = area_offset;
/* lea_rbx_area_ptr */
gssize lea_rbx_area_ptr_offset =
offsetof(afl_log_code, code.lea_rbx_area_ptr) +
sizeof(code.code.lea_rbx_area_ptr) - sizeof(guint32);
gssize lea_rbx_area_ptr_value =
(GPOINTER_TO_SIZE(__afl_area_ptr) -
(code_addr + offsetof(afl_log_code, code.lea_rbx_area_ptr) +
sizeof(code.code.lea_rbx_area_ptr)));
if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) {
FATAL("Patch out of range (lea_rbx_area_ptr_value): 0x%016lX",
lea_rbx_area_ptr_value);
}
*((guint32 *)&code.bytes[lea_rbx_area_ptr_offset]) = lea_rbx_area_ptr_value;
/* mov_prev_loc_curr_loc_shr1 */
gssize curr_loc_shr_1_offset =
offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
map_size_pow2 = util_log2(__afl_map_size);
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
*((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
}
void instrument_coverage_optimize(const cs_insn *instr,
GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
if (instrument_previous_pc_addr == NULL) {
GumAddressSpec spec = {.near_address = cw->code,
.max_distance = 1ULL << 30};
guint page_size = gum_query_page_size();
instrument_previous_pc_addr = gum_memory_allocate_near(
&spec, sizeof(guint64), page_size, GUM_PAGE_READ | GUM_PAGE_WRITE);
*instrument_previous_pc_addr = instrument_hash_zero;
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
FVERBOSE("code_addr: %p", cw->code);
}
instrument_coverage_suppress_init();
if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
FATAL("Failed - g_hash_table_add");
}
instrument_coverage_write(GUM_ADDRESS(instr->address), output);
}
void instrument_coverage_optimize_insn(const cs_insn *instr,
GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
jcc_insn taken, not_taken;
switch (instr->id) {
case X86_INS_CMOVA:
taken.opcode = OPC_JA;
not_taken.opcode = OPC_JBE;
break;
case X86_INS_CMOVAE:
taken.opcode = OPC_JAE;
not_taken.opcode = OPC_JB;
break;
case X86_INS_CMOVB:
taken.opcode = OPC_JB;
not_taken.opcode = OPC_JAE;
break;
case X86_INS_CMOVBE:
taken.opcode = OPC_JBE;
not_taken.opcode = OPC_JA;
break;
case X86_INS_CMOVE:
taken.opcode = OPC_JE;
not_taken.opcode = OPC_JNE;
break;
case X86_INS_CMOVG:
taken.opcode = OPC_JG;
not_taken.opcode = OPC_JLE;
break;
case X86_INS_CMOVGE:
taken.opcode = OPC_JGE;
not_taken.opcode = OPC_JL;
break;
case X86_INS_CMOVL:
taken.opcode = OPC_JL;
not_taken.opcode = OPC_JGE;
break;
case X86_INS_CMOVLE:
taken.opcode = OPC_JLE;
not_taken.opcode = OPC_JG;
break;
case X86_INS_CMOVNE:
taken.opcode = OPC_JNE;
not_taken.opcode = OPC_JE;
break;
case X86_INS_CMOVNO:
taken.opcode = OPC_JNO;
not_taken.opcode = OPC_JO;
break;
case X86_INS_CMOVNP:
taken.opcode = OPC_JNP;
not_taken.opcode = OPC_JP;
break;
case X86_INS_CMOVNS:
taken.opcode = OPC_JNS;
not_taken.opcode = OPC_JS;
break;
case X86_INS_CMOVO:
taken.opcode = OPC_JO;
not_taken.opcode = OPC_JNO;
break;
case X86_INS_CMOVP:
taken.opcode = OPC_JP;
not_taken.opcode = OPC_JNP;
break;
case X86_INS_CMOVS:
taken.opcode = OPC_JS;
not_taken.opcode = OPC_JNS;
break;
default:
return;
}
taken.distance = sizeof(afl_log_code);
not_taken.distance = sizeof(afl_log_code);
// gum_x86_writer_put_breakpoint(cw);
gum_x86_writer_put_bytes(cw, taken.bytes, sizeof(jcc_insn));
instrument_coverage_write(GUM_ADDRESS(instr->address), output);
gum_x86_writer_put_bytes(cw, not_taken.bytes, sizeof(jcc_insn));
instrument_coverage_write(GUM_ADDRESS(instr->address + instr->size), output);
FVERBOSE("Instrument - 0x%016lx: %s %s", instr->address, instr->mnemonic,
instr->op_str);
}
void instrument_flush(GumStalkerOutput *output) {
gum_x86_writer_flush(output->writer.x86);
@ -551,5 +468,24 @@ gpointer instrument_cur(GumStalkerOutput *output) {
}
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) {
int fd = (int)(size_t)user_data;
instrument_regs_format(
fd, "rax: 0x%016x, rbx: 0x%016x, rcx: 0x%016x, rdx: 0x%016x\n",
cpu_context->rax, cpu_context->rbx, cpu_context->rcx, cpu_context->rdx);
instrument_regs_format(
fd, "rdi: 0x%016x, rsi: 0x%016x, rbp: 0x%016x, rsp: 0x%016x\n",
cpu_context->rdi, cpu_context->rsi, cpu_context->rbp, cpu_context->rsp);
instrument_regs_format(
fd, "r8 : 0x%016x, r9 : 0x%016x, r10: 0x%016x, r11: 0x%016x\n",
cpu_context->r8, cpu_context->r9, cpu_context->r10, cpu_context->r11);
instrument_regs_format(
fd, "r12: 0x%016x, r13: 0x%016x, r14: 0x%016x, r15: 0x%016x\n",
cpu_context->r12, cpu_context->r13, cpu_context->r14, cpu_context->r15);
instrument_regs_format(fd, "rip: 0x%016x\n\n", cpu_context->rip);
}
#endif

View File

@ -0,0 +1,435 @@
#include <sys/mman.h>
#include <sys/resource.h>
#include "instrument.h"
#include "util.h"
#if defined(__x86_64__)
#define INVALID 1
#define DEFAULT_CACHE_SIZE (256ULL << 20)
gboolean instrument_cache_enabled = TRUE;
gsize instrument_cache_size = DEFAULT_CACHE_SIZE;
static gpointer *map_base = MAP_FAILED;
void instrument_cache_config(void) {
instrument_cache_enabled = (getenv("AFL_FRIDA_INST_NO_CACHE") == NULL);
if (getenv("AFL_FRIDA_INST_CACHE_SIZE") != NULL) {
if (!instrument_cache_enabled) {
FFATAL(
"AFL_FRIDA_INST_CACHE_SIZE incomatible with "
"AFL_FRIDA_INST_NO_CACHE");
}
instrument_cache_size =
util_read_address("AFL_FRIDA_INST_CACHE_SIZE", DEFAULT_CACHE_SIZE);
util_log2(instrument_cache_size);
}
}
void instrument_cache_init(void) {
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache:" cYEL " [%c]",
instrument_cache_enabled ? 'X' : ' ');
if (!instrument_cache_enabled) { return; }
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache size:" cYEL " [0x%016lX]",
instrument_cache_size);
const struct rlimit data_limit = {.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY};
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
FFATAL("Failed to setrlimit: %d", 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); }
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
GUM_ADDRESS(map_base));
}
static gpointer *instrument_cache_get_addr(gpointer addr) {
gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
return &map_base[GPOINTER_TO_SIZE(addr) & mask];
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
if (!instrument_cache_enabled) { return; }
gpointer *target = instrument_cache_get_addr(real_address);
if (*target == code_address) {
return;
} else if (*target == NULL) {
*target = code_address;
} else {
*target = GSIZE_TO_POINTER(INVALID);
}
}
static gboolean instrument_cache_relocate(GumAddress old_pc, GumAddress new_pc,
gint32 old_offset,
gint32 *new_offset) {
guint64 old_target = old_pc + old_offset;
gint64 relocated = old_target - new_pc;
if (relocated > G_MAXINT32 || relocated < G_MININT32) { return FALSE; }
*new_offset = relocated;
return TRUE;
}
static void instrument_cache_rewrite_branch_insn(const cs_insn *instr,
GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 *x86 = &instr->detail->x86;
guint8 modified[sizeof(instr->bytes)] = {0};
guint8 offset = 0;
guint8 skip = 0;
g_assert(sizeof(x86->prefix) == 4);
g_assert(sizeof(x86->opcode) == 4);
/*
* If the target is simply RAX, we can skip writing the code to load the
* RIP
*/
if (x86->operands[0].type == X86_OP_REG ||
x86->operands[0].reg == X86_REG_RAX) {
return;
}
/* Write the prefix */
for (gsize i = 0; i < sizeof(x86->prefix); i++) {
if (x86->prefix[i] != 0) {
if (x86->prefix[i] == 0xf2) {
skip++;
} else {
modified[offset++] = x86->prefix[i];
skip++;
}
}
}
/* Write the REX */
if (x86->rex == 0) {
/*
* CALL (near) and JMP (near) default to 64-bit operands, MOV does not,
* write REX.W
*/
modified[offset++] = 0x48;
} else {
if ((x86->rex & 0xF8) != 0x40) {
FATAL("Unexpected REX byte: 0x%02x", x86->rex);
}
modified[offset++] = x86->rex | 0x08;
skip++;
}
/*
* CALL is FF /2, JMP is FF /4. The remaining op-code fields should thus be
* unused
*/
if (x86->opcode[0] != 0xFF || x86->opcode[1] != 0x00 ||
x86->opcode[2] != 0x00 || x86->opcode[3] != 0x00) {
FFATAL("Unexpected Op-code: 0x%02x 0x%02x 0x%02x 0x%02x", x86->opcode[0],
x86->opcode[1], x86->opcode[2], x86->opcode[3]);
}
/* The reg field of the ModRM should be set to 2 for CALL and 4 for JMP */
guint8 reg = (x86->modrm >> 3) & 7;
if (reg != 0x4 && reg != 0x2) {
FFATAL("Unexpected Reg: 0x%02x, ModRM: 0x%02x", reg, x86->modrm);
}
/* MOV */
modified[offset++] = 0x8b;
skip++;
/* Clear the reg field (RAX) */
modified[offset++] = x86->modrm & 0xc7;
skip++;
/* Operands */
guint8 op_len = instr->size - skip;
/* If our branch was RIP relative, we'll need to fix-up the offset */
if (x86->operands[0].type == X86_OP_MEM &&
x86->operands[0].mem.base == X86_REG_RIP) {
/* RIP relative offsets should be 32-bits */
if (op_len != sizeof(gint32)) {
FFATAL("Unexpected operand length: %d\n", op_len);
}
gint32 old_offset = *(gint32 *)&instr->bytes[skip];
gint32 new_offset = 0;
if (instrument_cache_relocate(instr->address, cw->pc, old_offset,
&new_offset)) {
gint32 *output = (gint32 *)&modified[offset];
*output = new_offset;
offset += sizeof(gint32);
} else {
GumAddress target = instr->address + old_offset;
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, target);
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_X86_RAX, GUM_X86_RAX);
return;
}
} else {
for (int i = 0; i < op_len; i++) {
guint8 val = instr->bytes[i + skip];
modified[offset++] = val;
}
}
gum_x86_writer_put_bytes(cw, modified, offset);
}
static void instrument_cache_write_push_frame(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))),
GUM_X86_XAX);
gum_x86_writer_put_lahf(cw);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))),
GUM_X86_XAX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))),
GUM_X86_XBX);
}
static void instrument_cache_write_pop_frame(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_X86_XBX, GUM_X86_XSP,
-(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))));
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_X86_XAX, GUM_X86_XSP,
-(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))));
gum_x86_writer_put_sahf(cw);
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_X86_XAX, GUM_X86_XSP,
-(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
}
static void instrument_cache_write_lookup(GumX86Writer *cw) {
/* &map_base[GPOINTER_TO_SIZE(addr) & MAP_MASK]; */
gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
gum_x86_writer_put_mov_reg_u64(cw, GUM_X86_XBX, mask);
gum_x86_writer_put_and_reg_reg(cw, GUM_X86_XAX, GUM_X86_XBX);
gum_x86_writer_put_shl_reg_u8(cw, GUM_X86_XAX, util_log2(sizeof(gpointer)));
gum_x86_writer_put_mov_reg_u64(cw, GUM_X86_XBX, GPOINTER_TO_SIZE(map_base));
gum_x86_writer_put_add_reg_reg(cw, GUM_X86_XAX, GUM_X86_XBX);
/* Read the return address lookup */
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_X86_XAX, GUM_X86_XAX);
}
void instrument_cache_jmp_call(const cs_insn *instr, GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 *x86 = &instr->detail->x86;
if (x86->op_count != 1) { FFATAL("Unexpected operand count"); }
if (x86->operands[0].type == X86_OP_IMM) { return; }
gconstpointer null = cw->code;
instrument_cache_write_push_frame(cw);
/*
* We are about to re-write the CALL or JMP instruction, but replace the
* op-code with that for a MOV into RAX. Since we are keeping the operand from
* the JMP exactly the same, it is imperative that the target register state
* be exactly the same as how the target left it. Since `LAHF` spoils `RAX` we
* must restore it from the stack. We also must avoid adjusting `RSP`, so we
* use `MOV` instructions to store our context into the stack beyond the
* red-zone.
*/
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_X86_XAX, GUM_X86_XSP,
-(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
instrument_cache_rewrite_branch_insn(instr, output);
instrument_cache_write_lookup(cw);
/* Test if its set*/
gum_x86_writer_put_cmp_reg_i32(cw, GUM_X86_XAX, INVALID);
gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
/* If it's set, then stash the address beyond the red-zone */
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))),
GUM_X86_XAX);
if (instr->id == X86_INS_JMP) {
instrument_cache_write_pop_frame(cw);
gum_x86_writer_put_jmp_reg_offset_ptr(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))));
} else {
gum_x86_writer_put_mov_reg_address(
cw, GUM_X86_XAX, GUM_ADDRESS(instr->address + instr->size));
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_X86_XSP,
-sizeof(gpointer), GUM_X86_XAX);
instrument_cache_write_pop_frame(cw);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_XSP, GUM_X86_XSP,
-sizeof(gpointer));
gum_x86_writer_put_jmp_reg_offset_ptr(
cw, GUM_X86_XSP, -(GUM_RED_ZONE_SIZE + ((4 - 1) * sizeof(gpointer))));
}
/* Tidy up our mess and let FRIDA handle it */
gum_x86_writer_put_label(cw, null);
instrument_cache_write_pop_frame(cw);
}
void instrument_cache_ret(const cs_insn *instr, GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 *x86 = &instr->detail->x86;
guint16 n = 0;
if (x86->op_count != 0) {
if (x86->operands[0].type != X86_OP_IMM) {
FFATAL("Unexpected operand type");
}
n = x86->operands[0].imm;
}
gconstpointer null = cw->code;
instrument_cache_write_push_frame(cw);
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_X86_XAX, GUM_X86_XSP);
instrument_cache_write_lookup(cw);
/* Test if its set*/
gum_x86_writer_put_cmp_reg_i32(cw, GUM_X86_XAX, INVALID);
gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
/* If it's set, then overwrite our return address and return */
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_XSP, GUM_X86_XAX);
instrument_cache_write_pop_frame(cw);
if (n == 0) {
gum_x86_writer_put_ret(cw);
} else {
gum_x86_writer_put_ret_imm(cw, n);
}
/* Tidy up our mess and let FRIDA handle it */
gum_x86_writer_put_label(cw, null);
instrument_cache_write_pop_frame(cw);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
if (!instrument_cache_enabled) { return; }
switch (instr->id) {
case X86_INS_RET:
instrument_cache_ret(instr, output);
break;
case X86_INS_CALL:
case X86_INS_JMP:
instrument_cache_jmp_call(instr, output);
break;
default:
return;
}
}
#endif

View File

@ -6,6 +6,9 @@
#if defined(__i386__)
gboolean instrument_cache_enabled = FALSE;
gsize instrument_cache_size = 0;
static GHashTable *coverage_blocks = NULL;
#pragma pack(push, 1)
@ -81,14 +84,16 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
static void instrument_coverage_switch(GumStalkerObserver *self,
gpointer from_address,
gpointer start_address,
const cs_insn * from_insn,
gpointer * target) {
const cs_insn *from_insn,
gpointer *target) {
UNUSED_PARAMETER(self);
UNUSED_PARAMETER(from_address);
UNUSED_PARAMETER(start_address);
cs_x86 * x86;
cs_x86 *x86;
cs_x86_op *op;
if (from_insn == NULL) { return; }
@ -131,7 +136,7 @@ static void instrument_coverage_suppress_init(void) {
if (initialized) { return; }
initialized = true;
GumStalkerObserver * observer = stalker_get_observer();
GumStalkerObserver *observer = stalker_get_observer();
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
iface->switch_callback = instrument_coverage_switch;
@ -144,7 +149,7 @@ static void instrument_coverage_suppress_init(void) {
}
void instrument_coverage_optimize(const cs_insn * instr,
void instrument_coverage_optimize(const cs_insn *instr,
GumStalkerOutput *output) {
afl_log_code code = {0};
@ -157,9 +162,10 @@ void instrument_coverage_optimize(const cs_insn * instr,
GumAddressSpec spec = {.near_address = cw->code,
.max_distance = 1ULL << 30};
guint page_size = gum_query_page_size();
instrument_previous_pc_addr = gum_memory_allocate_near(
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
&spec, sizeof(guint64), page_size, GUM_PAGE_READ | GUM_PAGE_WRITE);
*instrument_previous_pc_addr = instrument_hash_zero;
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
FVERBOSE("code_addr: %p", cw->code);
@ -218,6 +224,14 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
void instrument_coverage_optimize_insn(const cs_insn *instr,
GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
void instrument_coverage_optimize_init(void) {
}
@ -234,5 +248,40 @@ gpointer instrument_cur(GumStalkerOutput *output) {
}
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) {
int fd = (int)(size_t)user_data;
instrument_regs_format(
fd, "eax: 0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x\n",
cpu_context->eax, cpu_context->ebx, cpu_context->ecx, cpu_context->edx);
instrument_regs_format(
fd, "esi: 0x%08x, edi: 0x%08x, ebp: 0x%08x, esp: 0x%08x\n",
cpu_context->esi, cpu_context->edi, cpu_context->ebp, cpu_context->esp);
instrument_regs_format(fd, "eip: 0x%08x\n\n", cpu_context->eip);
}
#endif

View File

@ -7,8 +7,8 @@ void intercept_hook(void *address, gpointer replacement, gpointer user_data) {
GumInterceptor *interceptor = gum_interceptor_obtain();
gum_interceptor_begin_transaction(interceptor);
GumReplaceReturn ret =
gum_interceptor_replace(interceptor, address, replacement, user_data);
GumReplaceReturn ret = gum_interceptor_replace(interceptor, address,
replacement, user_data, NULL);
if (ret != GUM_REPLACE_OK) { FFATAL("gum_interceptor_attach: %d", ret); }
gum_interceptor_end_transaction(interceptor);

View File

@ -68,6 +68,12 @@ class Afl {
static setBackpatchDisable() {
Afl.jsApiSetBackpatchDisable();
}
/**
* See `AFL_FRIDA_INST_NO_CACHE`.
*/
static setCacheDisable() {
Afl.jsApiSetCacheDisable();
}
/**
* See `AFL_FRIDA_DEBUG_MAPS`.
*/
@ -91,6 +97,19 @@ class Afl {
static setInMemoryFuzzing() {
Afl.jsApiAflSharedMemFuzzing.writeInt(1);
}
/**
* See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number`
* as an argument.
*/
static setInstrumentCacheSize(size) {
Afl.jsApiSetInstrumentCacheSize(size);
}
/**
* See `AFL_FRIDA_INST_COVERAGE_ABSOLUTE`.
*/
static setInstrumentCoverageAbsolute() {
Afl.jsApiSetInstrumentCoverageAbsolute();
}
/**
* See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
* as an argument.
@ -113,6 +132,12 @@ class Afl {
static setInstrumentEnableTracing() {
Afl.jsApiSetInstrumentTrace();
}
/**
* See `AFL_FRIDA_INST_INSN`
*/
static setInstrumentInstructions() {
Afl.jsApiSetInstrumentInstructions();
}
/**
* See `AFL_FRIDA_INST_JIT`.
*/
@ -131,6 +156,14 @@ class Afl {
static setInstrumentNoOptimize() {
Afl.jsApiSetInstrumentNoOptimize();
}
/**
* See `AFL_FRIDA_INST_REGS_FILE`. This function takes a single `string` as
* an argument.
*/
static setInstrumentRegsFile(file) {
const buf = Memory.allocUtf8String(file);
Afl.jsApiSetInstrumentRegsFile(buf);
}
/*
* See `AFL_FRIDA_INST_SEED`
*/
@ -293,13 +326,18 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing");
Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []);
Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []);
Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "void", []);
Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []);
Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]);
Afl.jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction("js_api_set_instrument_cache_size", "void", ["size_t"]);
Afl.jsApiSetInstrumentCoverageAbsolute = Afl.jsApiGetFunction("js_api_set_instrument_coverage_absolute", "void", []);
Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []);
Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []);
Afl.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]);
Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []);
Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []);

View File

@ -7,16 +7,16 @@ gboolean js_done = FALSE;
js_api_stalker_callback_t js_user_callback = NULL;
js_main_hook_t js_main_hook = NULL;
static char * js_script = NULL;
static gchar * filename = "afl.js";
static gchar * contents;
static GumScriptBackend * backend;
static GCancellable * cancellable = NULL;
static GError * error = NULL;
static GumScript * script;
static char *js_script = NULL;
static gchar *filename = "afl.js";
static gchar *contents;
static GumScriptBackend *backend;
static GCancellable *cancellable = NULL;
static GError *error = NULL;
static GumScript *script;
static GumScriptScheduler *scheduler;
static GMainContext * context;
static GMainLoop * main_loop;
static GMainContext *context;
static GMainLoop *main_loop;
static void js_msg(GumScript *script, const gchar *message, GBytes *data,
gpointer user_data) {

View File

@ -115,6 +115,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_libraries() {
}
__attribute__((visibility("default"))) void
js_api_set_instrument_coverage_absolute(void) {
instrument_coverage_absolute = true;
}
__attribute__((visibility("default"))) void js_api_set_instrument_coverage_file(
char *path) {
@ -142,6 +149,13 @@ js_api_set_prefetch_backpatch_disable(void) {
}
__attribute__((visibility("default"))) void js_api_set_instrument_instructions(
void) {
instrument_coverage_insn = TRUE;
}
__attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
void) {
@ -149,6 +163,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
}
__attribute__((visibility("default"))) void js_api_set_instrument_regs_file(
char *path) {
instrument_regs_filename = g_strdup(path);
}
__attribute__((visibility("default"))) void js_api_set_instrument_seed(
guint64 seed) {
@ -255,6 +276,19 @@ __attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks(
}
__attribute__((visibility("default"))) void js_api_set_cache_disable(void) {
instrument_cache_enabled = FALSE;
}
__attribute__((visibility("default"))) void js_api_set_instrument_cache_size(
gsize size) {
instrument_cache_size = size;
}
__attribute__((visibility("default"))) void js_api_set_js_main_hook(
const js_main_hook_t hook) {

View File

@ -69,8 +69,8 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
Elf_Addr preferred_base;
Elf_Shdr *shdr;
Elf_Shdr *shstrtab;
char * shstr;
char * section_name;
char *shstr;
char *section_name;
Elf_Shdr *curr;
char text_name[] = ".text";

View File

@ -16,9 +16,9 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
gpointer user_data) {
GumDarwinModule **ret = (GumDarwinModule **)user_data;
GumDarwinModule * module = gum_darwin_module_new_from_memory(
details->path, mach_task_self(), details->range->base_address,
GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
GumDarwinModule *module = gum_darwin_module_new_from_memory(
details->path, mach_task_self(), details->range->base_address,
GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
FVERBOSE("Found main module: %s", module->name);

View File

@ -21,6 +21,7 @@
#include "intercept.h"
#include "js.h"
#include "lib.h"
#include "module.h"
#include "output.h"
#include "persistent.h"
#include "prefetch.h"
@ -35,6 +36,18 @@
#ifdef __APPLE__
extern mach_port_t mach_task_self();
extern GumAddress gum_darwin_find_entrypoint(mach_port_t task);
#elif defined(__ANDROID__)
typedef struct {
void (**preinit_array)(void);
void (**init_array)(void);
void (**fini_array)(void);
} structors_array_t;
extern void __libc_init(void *raw_args, void (*onexit)(void) __unused,
int (*slingshot)(int, char **, char **),
structors_array_t const *const structors);
#else
extern int __libc_start_main(int (*main)(int, char **, char **), int argc,
char **ubp_av, void (*init)(void),
@ -68,7 +81,11 @@ static void on_main_os(int argc, char **argv, char **envp) {
GumInterceptor *interceptor = gum_interceptor_obtain();
gum_interceptor_begin_transaction(interceptor);
#if defined(__ANDROID__)
gum_interceptor_revert(interceptor, __libc_init);
#else
gum_interceptor_revert(interceptor, __libc_start_main);
#endif
gum_interceptor_end_transaction(interceptor);
gum_interceptor_flush(interceptor);
@ -91,7 +108,7 @@ static void embedded_init(void) {
static void afl_print_cmdline(void) {
#if defined(__linux__)
char * buffer = g_malloc0(PROC_MAX);
char *buffer = g_malloc0(PROC_MAX);
gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
int fd = open(fname, O_RDONLY);
@ -143,7 +160,7 @@ static void afl_print_cmdline(void) {
static void afl_print_env(void) {
char * buffer = g_malloc0(PROC_MAX);
char *buffer = g_malloc0(PROC_MAX);
gchar *fname = g_strdup_printf("/proc/%d/environ", getppid());
int fd = open(fname, O_RDONLY);
@ -197,6 +214,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
instrument_config();
js_config();
lib_config();
module_config();
output_config();
persistent_config();
prefetch_config();
@ -214,6 +232,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
entry_init();
instrument_init();
lib_init();
module_init();
persistent_init();
prefetch_init();
seccomp_init();
@ -274,6 +293,24 @@ static void intercept_main(void) {
}
#elif defined(__ANDROID__)
static void on_libc_init(void *raw_args, void (*onexit)(void) __unused,
int (*slingshot)(int, char **, char **),
structors_array_t const *const structors) {
main_fn = slingshot;
intercept_unhook_self();
intercept_hook(slingshot, on_main, NULL);
return __libc_init(raw_args, onexit, slingshot, structors);
}
static void intercept_main(void) {
intercept_hook(__libc_init, on_libc_init, NULL);
}
#else
static int on_libc_start_main(int (*main)(int, char **, char **), int argc,
char **ubp_av, void (*init)(void),

108
frida_mode/src/module.c Normal file
View File

@ -0,0 +1,108 @@
#include "intercept.h"
#include "module.h"
#include "util.h"
#if defined(__linux__)
#include <dlfcn.h>
#include <link.h>
#endif
static guint page_size = 0;
static gboolean handle_dlclose = FALSE;
void module_config(void) {
#if defined(__linux__)
handle_dlclose = (getenv("AFL_FRIDA_NO_MODULE") == NULL);
#else
FWARNF("AFL_FRIDA_MODULE not supported");
#endif
}
typedef struct {
GumMemoryRange range;
GumPageProtection protection;
GumFileMapping file;
} gum_range_t;
gboolean found_range(const GumRangeDetails *details, gpointer user_data) {
gum_range_t range = {0};
GArray *ranges = (GArray *)user_data;
range.range = *details->range;
range.protection = details->protection;
if (details->file != NULL) { range.file = *details->file; }
g_array_append_val(ranges, range);
return FALSE;
}
#if defined(__linux__) && !defined(__ANDROID__)
static int on_dlclose(void *handle) {
GArray *ranges = NULL;
struct link_map *lm = NULL;
gum_range_t *range = NULL;
GumAddress base;
GumAddress limit;
gpointer mem;
if (dlinfo(handle, RTLD_DI_LINKMAP, &lm) < 0) {
FFATAL("Failed to dlinfo: %s", dlerror());
}
FVERBOSE("on_dlclose: %s", lm->l_name);
ranges = g_array_new(FALSE, TRUE, sizeof(gum_range_t));
gum_module_enumerate_ranges(lm->l_name, GUM_PAGE_EXECUTE, found_range,
ranges);
int ret = dlclose(handle);
if (ret != 0) {
FWARNF("dlclose returned: %d (%s)", ret, dlerror());
return ret;
}
for (guint i = 0; i < ranges->len; i++) {
range = &g_array_index(ranges, gum_range_t, i);
base = range->range.base_address;
limit = base + range->range.size;
FVERBOSE("Reserving range: 0x%016" G_GINT64_MODIFIER
"x, 0x%016" G_GINT64_MODIFIER "X",
base, limit);
mem = gum_memory_allocate(GSIZE_TO_POINTER(base), range->range.size,
page_size, GUM_PAGE_NO_ACCESS);
if (mem == NULL) { FATAL("Failed to allocate %p (%d)", mem, errno); }
}
g_array_free(ranges, TRUE);
return 0;
}
#endif
void module_init(void) {
FOKF(cBLU "Module" cRST " - " cYEL " [%c]", handle_dlclose ? 'X' : ' ');
#if defined(__linux__) && !defined(__ANDROID__)
if (!handle_dlclose) { return; }
page_size = gum_query_page_size();
intercept_hook(dlclose, on_dlclose, NULL);
#endif
}

View File

@ -1,75 +1,294 @@
#include "frida-gumjs.h"
#include "instrument.h"
#include "persistent.h"
#include "util.h"
#if defined(__arm__)
struct arm_regs {
// struct _GumArmCpuContext {
uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
// guint32 pc;
// guint32 sp;
// guint32 cpsr;
union {
// guint32 r8;
// guint32 r9;
// guint32 r10;
// guint32 r11;
// guint32 r12;
uint32_t r11;
uint32_t fp;
// GumArmVectorReg v[16];
};
// guint32 _padding;
union {
// guint32 r[8];
// guint32 lr;
// };
uint32_t r12;
uint32_t ip;
// r11 - fp
// r12 - ip
// r13 - sp
// r14 - lr
// r15 - pc
};
union {
uint32_t r13;
uint32_t sp;
};
union {
uint32_t r14;
uint32_t lr;
};
union {
uint32_t r15;
uint32_t pc;
};
uint32_t cpsr;
uint8_t vfp_zregs[32][16];
uint32_t vfp_xregs[16];
};
typedef struct arm_regs arch_api_regs;
static GumCpuContext saved_regs = {0};
static gpointer saved_lr = NULL;
gboolean persistent_is_supported(void) {
return false;
return true;
}
static void instrument_persitent_save_regs(GumArmWriter *cw,
GumCpuContext *regs) {
/* Save Regs */
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP,
GUM_RED_ZONE_SIZE + sizeof(guint32));
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs));
/* Save r1-r7 */
for (size_t i = ARM_REG_R1; i < ARM_REG_R8; i++) {
gum_arm_writer_put_str_reg_reg_offset(
cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0]));
}
/* Save r8-r12 */
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0,
offsetof(GumCpuContext, r8));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0,
offsetof(GumCpuContext, r9));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0,
offsetof(GumCpuContext, r10));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0,
offsetof(GumCpuContext, r11));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0,
offsetof(GumCpuContext, r12));
/* Save sp & lr */
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0,
offsetof(GumCpuContext, sp));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0,
offsetof(GumCpuContext, lr));
/* Save r0 (load from stack into r1) */
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0,
offsetof(GumCpuContext, r[0]));
/* Save CPSR */
gum_arm_writer_put_mov_reg_cpsr(cw, ARM_REG_R1);
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0,
offsetof(GumCpuContext, cpsr));
/* Save PC */
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1,
GUM_ADDRESS(persistent_start));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0,
offsetof(GumCpuContext, pc));
/* Restore Regs */
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP,
GUM_RED_ZONE_SIZE + sizeof(guint32));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
}
static void instrument_persitent_restore_regs(GumArmWriter *cw,
GumCpuContext *regs) {
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs));
/* Restore CPSR */
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0,
offsetof(GumCpuContext, cpsr));
gum_arm_writer_put_mov_cpsr_reg(cw, ARM_REG_R1);
/* Restore sp & lr */
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0,
offsetof(GumCpuContext, sp));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0,
offsetof(GumCpuContext, lr));
/* Restore r8-r12 */
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0,
offsetof(GumCpuContext, r8));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0,
offsetof(GumCpuContext, r9));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0,
offsetof(GumCpuContext, r10));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0,
offsetof(GumCpuContext, r11));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0,
offsetof(GumCpuContext, r12));
/* Restore r7-r0 */
for (size_t i = ARM_REG_R7; i >= ARM_REG_R0; i--) {
gum_arm_writer_put_ldr_reg_reg_offset(
cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0]));
}
}
static void instrument_exit(GumArmWriter *cw) {
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);
}
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");
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
static void instrument_afl_persistent_loop(GumArmWriter *cw) {
gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
}
static void persistent_prologue_hook(GumArmWriter *cw, GumCpuContext *regs) {
if (persistent_hook == NULL) return;
gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R2,
GUM_ADDRESS(&__afl_fuzz_len));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0);
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0);
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1,
GUM_ADDRESS(&__afl_fuzz_ptr));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R1, 0);
gum_arm_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, GUM_ADDRESS(regs),
GUM_ARG_REGISTER, ARM_REG_R1, GUM_ARG_REGISTER, ARM_REG_R2);
gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
}
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_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,
GUM_RED_ZONE_SIZE);
}
void persistent_prologue_arch(GumStalkerOutput *output) {
UNUSED_PARAMETER(output);
FFATAL("Persistent mode not supported on this architecture");
/*
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* 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");
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_arm_writer_put_label(cw, loop);
/* call instrument_prologue_func */
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);
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); }
}
void persistent_epilogue_arch(GumStalkerOutput *output) {
UNUSED_PARAMETER(output);
FFATAL("Persistent mode not supported on this architecture");
GumArmWriter *cw = output->writer.arm;
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_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);
gum_arm_writer_put_bx_reg(cw, ARM_REG_R0);
}

View File

@ -24,7 +24,7 @@ gboolean persistent_is_supported(void) {
}
static void instrument_persitent_save_regs(GumArm64Writer * cw,
static void instrument_persitent_save_regs(GumArm64Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
@ -105,18 +105,13 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw,
offsetof(persistent_ctx_t, rflags));
/* Q */
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0,
offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0,
offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0,
offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0,
offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET);
for (int i = 0; i < 16; i++) {
gum_arm64_writer_put_stp_reg_reg_reg_offset(
cw, ARM64_REG_Q0 + (i * 2), ARM64_REG_Q0 + (i * 2) + 1, ARM64_REG_X0,
offsetof(GumCpuContext, v[i]), GUM_INDEX_SIGNED_OFFSET);
}
/* x0 & x1 */
gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3,
@ -136,7 +131,7 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw,
}
static void instrument_persitent_restore_regs(GumArm64Writer * cw,
static void instrument_persitent_restore_regs(GumArm64Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
@ -201,18 +196,14 @@ static void instrument_persitent_restore_regs(GumArm64Writer * cw,
offsetof(persistent_ctx_t, rflags));
gum_arm64_writer_put_instruction(cw, msr_nzcv_x1);
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0,
offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0,
offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0,
offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET);
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0,
offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET);
/* Q */
for (int i = 0; i < 16; i++) {
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
cw, ARM64_REG_Q0 + (i * 2), ARM64_REG_Q0 + (i * 2) + 1, ARM64_REG_X0,
offsetof(GumCpuContext, v[i]), GUM_INDEX_SIGNED_OFFSET);
}
/* x2 & x3 */
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
@ -258,7 +249,7 @@ static void instrument_afl_persistent_loop(GumArm64Writer *cw) {
}
static void persistent_prologue_hook(GumArm64Writer * cw,
static void persistent_prologue_hook(GumArm64Writer *cw,
persistent_ctx_t *regs) {
if (persistent_hook == NULL) return;

View File

@ -25,148 +25,148 @@ gboolean persistent_is_supported(void) {
}
static void instrument_persitent_save_regs(GumX86Writer * cw,
static void instrument_persitent_save_regs(GumX86Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
-(GUM_RED_ZONE_SIZE));
/* Should be pushing FPU here, but meh */
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, regs_address);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rbx), GUM_REG_RBX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rbx), GUM_X86_RBX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rcx), GUM_REG_RCX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rcx), GUM_X86_RCX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rdx), GUM_REG_RDX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rdx), GUM_X86_RDX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rdi), GUM_REG_RDI);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rdi), GUM_X86_RDI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rsi), GUM_REG_RSI);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rsi), GUM_X86_RSI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rbp), GUM_REG_RBP);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rbp), GUM_X86_RBP);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r8), GUM_REG_R8);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r8), GUM_X86_R8);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r9), GUM_REG_R9);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r9), GUM_X86_R9);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r10), GUM_REG_R10);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r10), GUM_X86_R10);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r11), GUM_REG_R11);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r11), GUM_X86_R11);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r12), GUM_REG_R12);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r12), GUM_X86_R12);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r13), GUM_REG_R13);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r13), GUM_X86_R13);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r14), GUM_REG_R14);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r14), GUM_X86_R14);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, r15), GUM_REG_R15);
cw, GUM_X86_RAX, offsetof(GumCpuContext, r15), GUM_X86_R15);
/* Store RIP */
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RBX,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RBX,
GUM_ADDRESS(persistent_start));
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rip), GUM_REG_RBX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rip), GUM_X86_RBX);
/* Store adjusted RSP */
gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_RBX, GUM_REG_RSP);
gum_x86_writer_put_mov_reg_reg(cw, GUM_X86_RBX, GUM_X86_RSP);
/* RED_ZONE + Saved flags, RAX, alignment */
gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX,
gum_x86_writer_put_add_reg_imm(cw, GUM_X86_RBX,
GUM_RED_ZONE_SIZE + (0x8 * 2));
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rsp), GUM_REG_RBX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rsp), GUM_X86_RBX);
/* Save the flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x8);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP, 0x8);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(persistent_ctx_t, rflags), GUM_REG_RBX);
cw, GUM_X86_RAX, offsetof(persistent_ctx_t, rflags), GUM_X86_RBX);
/* Save the RAX */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP, 0x0);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_RAX, offsetof(GumCpuContext, rax), GUM_REG_RBX);
cw, GUM_X86_RAX, offsetof(GumCpuContext, rax), GUM_X86_RBX);
/* Pop the saved values */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 0x10);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 0x10);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
}
static void instrument_persitent_restore_regs(GumX86Writer * cw,
static void instrument_persitent_restore_regs(GumX86Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, regs_address);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RCX, GUM_X86_RAX,
offsetof(GumCpuContext, rcx));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RDX, GUM_X86_RAX,
offsetof(GumCpuContext, rdx));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RDI, GUM_X86_RAX,
offsetof(GumCpuContext, rdi));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RSI, GUM_X86_RAX,
offsetof(GumCpuContext, rsi));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBP, GUM_X86_RAX,
offsetof(GumCpuContext, rbp));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R8, GUM_X86_RAX,
offsetof(GumCpuContext, r8));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R9, GUM_X86_RAX,
offsetof(GumCpuContext, r9));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R10, GUM_X86_RAX,
offsetof(GumCpuContext, r10));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R11, GUM_X86_RAX,
offsetof(GumCpuContext, r11));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R12, GUM_X86_RAX,
offsetof(GumCpuContext, r12));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R13, GUM_X86_RAX,
offsetof(GumCpuContext, r13));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R14, GUM_X86_RAX,
offsetof(GumCpuContext, r14));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_R15, GUM_X86_RAX,
offsetof(GumCpuContext, r15));
/* Don't restore RIP */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RSP, GUM_X86_RAX,
offsetof(GumCpuContext, rsp));
/* Restore RBX, RAX & Flags */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RAX,
offsetof(GumCpuContext, rbx));
gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RAX,
offsetof(GumCpuContext, rax));
gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RAX,
offsetof(persistent_ctx_t, rflags));
gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
}
static void instrument_exit(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_RDI, 0);
gum_x86_writer_put_call_reg(cw, GUM_REG_RAX);
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);
}
@ -186,13 +186,13 @@ static int instrument_afl_persistent_loop_func(void) {
static void instrument_afl_persistent_loop(GumX86Writer *cw) {
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
-(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_REG_RAX, GUM_REG_RAX);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
}
@ -200,26 +200,26 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) {
if (persistent_hook == NULL) return;
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RDX,
GUM_ADDRESS(&__afl_fuzz_len));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0);
gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff);
gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RDX, GUM_REG_RDI);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RDX, GUM_X86_RDX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RDX, GUM_X86_RDX, 0);
gum_x86_writer_put_mov_reg_u64(cw, GUM_X86_RDI, 0xffffffff);
gum_x86_writer_put_and_reg_reg(cw, GUM_X86_RDX, GUM_X86_RDI);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RSI,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RSI,
GUM_ADDRESS(&__afl_fuzz_ptr));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RSI, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RSI, GUM_X86_RSI, 0);
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS,
GUM_ADDRESS(&regs->ctx), GUM_ARG_REGISTER, GUM_REG_RSI, GUM_ARG_REGISTER,
GUM_REG_RDX);
GUM_ADDRESS(&regs->ctx), GUM_ARG_REGISTER, GUM_X86_RSI, GUM_ARG_REGISTER,
GUM_X86_RDX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
}
@ -228,23 +228,23 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
/* Stack usage by this function */
gssize offset = GUM_RED_ZONE_SIZE + (3 * 8);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_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_REG_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_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_REG_RAX, GUM_REG_RBX);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
}
@ -278,7 +278,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
instrument_persitent_save_regs(cw, &saved_regs);
@ -326,13 +326,13 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
/* The stack should be aligned when we re-enter our loop */
gconstpointer zero = cw->code + 1;
gum_x86_writer_put_test_reg_u32(cw, GUM_REG_RSP, 0xF);
gum_x86_writer_put_test_reg_u32(cw, GUM_X86_RSP, 0xF);
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, zero, GUM_NO_HINT);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -8);
gum_x86_writer_put_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_REG_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_RAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
}

View File

@ -25,105 +25,105 @@ gboolean persistent_is_supported(void) {
}
static void instrument_persitent_save_regs(GumX86Writer * cw,
static void instrument_persitent_save_regs(GumX86Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
/* Should be pushing FPU here, but meh */
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, regs_address);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, ebx), GUM_REG_EBX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, ebx), GUM_X86_EBX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, ecx), GUM_REG_ECX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, ecx), GUM_X86_ECX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, edx), GUM_REG_EDX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, edx), GUM_X86_EDX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, edi), GUM_REG_EDI);
cw, GUM_X86_EAX, offsetof(GumCpuContext, edi), GUM_X86_EDI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, esi), GUM_REG_ESI);
cw, GUM_X86_EAX, offsetof(GumCpuContext, esi), GUM_X86_ESI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, ebp), GUM_REG_EBP);
cw, GUM_X86_EAX, offsetof(GumCpuContext, ebp), GUM_X86_EBP);
/* Store RIP */
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EBX,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EBX,
GUM_ADDRESS(persistent_start));
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, eip), GUM_REG_EBX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, eip), GUM_X86_EBX);
/* Store adjusted RSP */
gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_EBX, GUM_REG_ESP);
gum_x86_writer_put_mov_reg_reg(cw, GUM_X86_EBX, GUM_X86_ESP);
/* RED_ZONE + Saved flags, RAX */
gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EBX, (0x4 * 2));
gum_x86_writer_put_add_reg_imm(cw, GUM_X86_EBX, (0x4 * 2));
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, esp), GUM_REG_EBX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, esp), GUM_X86_EBX);
/* Save the flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x4);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP, 0x4);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(persistent_ctx_t, eflags), GUM_REG_EBX);
cw, GUM_X86_EAX, offsetof(persistent_ctx_t, eflags), GUM_X86_EBX);
/* Save the RAX */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP, 0x0);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_EAX, offsetof(GumCpuContext, eax), GUM_REG_EBX);
cw, GUM_X86_EAX, offsetof(GumCpuContext, eax), GUM_X86_EBX);
/* Pop the saved values */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 0x8);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 0x8);
}
static void instrument_persitent_restore_regs(GumX86Writer * cw,
static void instrument_persitent_restore_regs(GumX86Writer *cw,
persistent_ctx_t *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, regs_address);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_ECX, GUM_X86_EAX,
offsetof(GumCpuContext, ecx));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EDX, GUM_X86_EAX,
offsetof(GumCpuContext, edx));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EDI, GUM_X86_EAX,
offsetof(GumCpuContext, edi));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_ESI, GUM_X86_EAX,
offsetof(GumCpuContext, esi));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBP, GUM_X86_EAX,
offsetof(GumCpuContext, ebp));
/* Don't restore RIP */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_ESP, GUM_X86_EAX,
offsetof(GumCpuContext, esp));
/* Restore RBX, RAX & Flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_EAX,
offsetof(GumCpuContext, ebx));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_EAX,
offsetof(GumCpuContext, eax));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_EAX,
offsetof(persistent_ctx_t, eflags));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_EBX);
}
static void instrument_exit(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_EDI, 0);
gum_x86_writer_put_push_reg(cw, GUM_REG_EDI);
gum_x86_writer_put_call_reg(cw, GUM_REG_EAX);
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);
}
@ -145,7 +145,7 @@ 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_REG_EAX, GUM_REG_EAX);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
}
@ -153,20 +153,20 @@ static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) {
if (persistent_hook == NULL) return;
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_ECX,
GUM_ADDRESS(&__afl_fuzz_len));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_ECX, GUM_X86_ECX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_ECX, GUM_X86_ECX, 0);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDX,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EDX,
GUM_ADDRESS(&__afl_fuzz_ptr));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EDX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EDX, GUM_X86_EDX, 0);
/* Base address is 64-bits (hence two zero arguments) */
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS,
GUM_ADDRESS(&regs->ctx), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER,
GUM_REG_ECX);
GUM_ADDRESS(&regs->ctx), GUM_ARG_REGISTER, GUM_X86_EDX, GUM_ARG_REGISTER,
GUM_X86_ECX);
}
@ -176,16 +176,16 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gssize offset = (3 * 4);
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_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_REG_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP,
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_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_REG_EAX, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_popfx(cw);
}
@ -219,7 +219,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
instrument_persitent_save_regs(cw, &saved_regs);
@ -263,8 +263,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_EAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
}

View File

@ -1,12 +1,11 @@
#include <errno.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include "frida-gumjs.h"
#include "entry.h"
#include "intercept.h"
#include "prefetch.h"
#include "shm.h"
#include "stalker.h"
#include "util.h"
@ -19,7 +18,7 @@
typedef struct {
size_t count;
void * entry[PREFETCH_ENTRIES];
void *entry[PREFETCH_ENTRIES];
guint8 backpatch_data[BP_SIZE];
gsize backpatch_size;
@ -32,6 +31,8 @@ gboolean prefetch_backpatch = TRUE;
static prefetch_data_t *prefetch_data = NULL;
static int prefetch_shm_id = -1;
static GHashTable *cant_prefetch = NULL;
static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
const GumBackpatch *backpatch,
gsize size) {
@ -40,6 +41,18 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
if (!entry_run) { return; }
gsize remaining =
sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size;
gpointer from = gum_stalker_backpatch_get_from(backpatch);
gpointer to = gum_stalker_backpatch_get_to(backpatch);
/* Stop reporting patches which can't be prefetched */
if (g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(from)) ||
g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(to))) {
return;
}
if (sizeof(gsize) + size > remaining) { return; }
gsize *dst_backpatch_size =
@ -68,6 +81,9 @@ void prefetch_write(void *addr) {
/* Bail if we aren't initialized */
if (prefetch_data == NULL) return;
/* Stop reporting blocks which can't be prefetched */
if (g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(addr))) { return; }
/*
* Our shared memory IPC is large enough for about 1000 entries, we can fine
* tune this if we need to. But if we have more new blocks that this in a
@ -84,6 +100,38 @@ void prefetch_write(void *addr) {
}
typedef struct {
GumAddress address;
gboolean executable;
} check_executable_t;
static gboolean prefetch_find_executable(const GumRangeDetails *details,
gpointer user_data) {
check_executable_t *ctx = (check_executable_t *)user_data;
if (GUM_MEMORY_RANGE_INCLUDES(details->range, ctx->address)) {
ctx->executable = TRUE;
return FALSE;
}
return TRUE;
}
static gboolean prefetch_is_executable(void *address) {
check_executable_t ctx = {.address = GUM_ADDRESS(address),
.executable = FALSE};
gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, prefetch_find_executable,
&ctx);
return ctx.executable;
}
static void prefetch_read_blocks(void) {
GumStalker *stalker = stalker_get();
@ -92,7 +140,24 @@ static void prefetch_read_blocks(void) {
for (size_t i = 0; i < prefetch_data->count; i++) {
void *addr = prefetch_data->entry[i];
gum_stalker_prefetch(stalker, addr, 1);
if (prefetch_is_executable(addr)) {
gum_stalker_prefetch(stalker, addr, 1);
} else {
/*
* If our child process creates a new executable mapping, e.g. by
* dynamically loading a new DSO, then this won't appear in our parent
* process' memory map and hence we can't prefetch it. Add it to a
* hashtable which the child will inherit on the next fork to prevent the
* child from keep reporting it and exhausting the shared memory buffers
* used to pass new blocks from the child back to the parent.
*/
g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(addr));
}
}
@ -107,7 +172,7 @@ static void prefetch_read_blocks(void) {
static void prefetch_read_patches(void) {
gsize offset = 0;
GumStalker * stalker = stalker_get();
GumStalker *stalker = stalker_get();
GumBackpatch *backpatch = NULL;
for (gsize remaining = prefetch_data->backpatch_size - offset;
@ -125,7 +190,36 @@ static void prefetch_read_patches(void) {
}
backpatch = (GumBackpatch *)&prefetch_data->backpatch_data[offset];
gum_stalker_prefetch_backpatch(stalker, backpatch);
gpointer from = gum_stalker_backpatch_get_from(backpatch);
gpointer to = gum_stalker_backpatch_get_to(backpatch);
/*
* If our child process creates a new executable mapping, e.g. by
* dynamically loading a new DSO, then this won't appear in our parent
* process' memory map and hence we can't prefetch it. Add it to a
* hashtable which the child will inherit on the next fork to prevent the
* child from keep reporting it and exhausting the shared memory buffers
* used to pass new blocks from the child back to the parent.
*/
if (!prefetch_is_executable(from)) {
g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(from));
}
if (!prefetch_is_executable(to)) {
g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(to));
}
if (prefetch_is_executable(from) && prefetch_is_executable(to)) {
gum_stalker_prefetch_backpatch(stalker, backpatch);
}
offset += size;
}
@ -190,34 +284,20 @@ void prefetch_init(void) {
* with the coverage bitmap region and fork will take care of ensuring both
* the parent and child see the same consistent memory region.
*/
prefetch_shm_id =
shmget(IPC_PRIVATE, sizeof(prefetch_data_t), IPC_CREAT | IPC_EXCL | 0600);
if (prefetch_shm_id < 0) {
FFATAL("prefetch_shm_id < 0 - errno: %d\n", errno);
}
prefetch_data = shmat(prefetch_shm_id, NULL, 0);
g_assert(prefetch_data != MAP_FAILED);
/*
* Configure the shared memory region to be removed once the process dies.
*/
if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) {
FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
}
/* Clear it, not sure it's necessary, just seems like good practice */
memset(prefetch_data, '\0', sizeof(prefetch_data_t));
prefetch_data = shm_create(sizeof(prefetch_data_t));
prefetch_hook_fork();
cant_prefetch = g_hash_table_new(g_direct_hash, g_direct_equal);
if (cant_prefetch == NULL) {
FFATAL("Failed to g_hash_table_new, errno: %d", errno);
}
if (!prefetch_backpatch) { return; }
GumStalkerObserver * observer = stalker_get_observer();
GumStalkerObserver *observer = stalker_get_observer();
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
iface->notify_backpatch = gum_afl_stalker_backpatcher_notify;

View File

@ -9,7 +9,7 @@
typedef struct {
gchar * suffix;
gchar *suffix;
GumMemoryRange *range;
gboolean done;
@ -135,7 +135,7 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details,
static void convert_name_token(gchar *token, GumMemoryRange *range) {
gchar * suffix = g_strconcat("/", token, NULL);
gchar *suffix = g_strconcat("/", token, NULL);
convert_name_ctx_t ctx = {.suffix = suffix, .range = range, .done = false};
gum_process_enumerate_modules(convert_name_token_for_module, &ctx);
@ -235,7 +235,7 @@ static void print_ranges(char *key, GArray *ranges) {
static gboolean collect_module_ranges_callback(const GumRangeDetails *details,
gpointer user_data) {
GArray * ranges = (GArray *)user_data;
GArray *ranges = (GArray *)user_data;
GumMemoryRange range = *details->range;
g_array_append_val(ranges, range);
return TRUE;
@ -292,12 +292,12 @@ void ranges_add_exclude(GumMemoryRange *range) {
static GArray *collect_ranges(char *env_key) {
char * env_val;
gchar ** tokens;
char *env_val;
gchar **tokens;
int token_count;
GumMemoryRange range;
int i;
GArray * result;
GArray *result;
result = g_array_new(false, false, sizeof(GumMemoryRange));
@ -330,7 +330,7 @@ static GArray *collect_ranges(char *env_key) {
static GArray *collect_libs_ranges(void) {
GArray * result;
GArray *result;
GumMemoryRange range;
result = g_array_new(false, false, sizeof(GumMemoryRange));
@ -422,7 +422,7 @@ static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra,
static GArray *intersect_ranges(GArray *a, GArray *b) {
GArray * result;
GArray *result;
GumMemoryRange *ra;
GumMemoryRange *rb;
GumMemoryRange ri;
@ -452,7 +452,7 @@ static GArray *intersect_ranges(GArray *a, GArray *b) {
static GArray *subtract_ranges(GArray *a, GArray *b) {
GArray * result;
GArray *result;
GumMemoryRange *ra;
GumAddress ral;
GumMemoryRange *rb;
@ -528,7 +528,7 @@ static GArray *subtract_ranges(GArray *a, GArray *b) {
static GArray *merge_ranges(GArray *a) {
GArray * result;
GArray *result;
GumMemoryRange rp;
GumMemoryRange *r;
@ -585,18 +585,16 @@ void ranges_config(void) {
void ranges_init(void) {
GumMemoryRange ri;
GArray * step1;
GArray * step2;
GArray * step3;
GArray * step4;
GArray * step5;
GArray *step1;
GArray *step2;
GArray *step3;
GArray *step4;
GArray *step5;
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument jit:" cYEL " [%c]",
ranges_inst_jit ? 'X' : ' ');
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
ranges_inst_libs ? 'X' : ' ');
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
ranges_inst_libs ? 'X' : ' ');
print_ranges("include", include_ranges);
print_ranges("exclude", exclude_ranges);
@ -671,7 +669,7 @@ gboolean range_is_excluded(GumAddress address) {
void ranges_exclude() {
GumMemoryRange *r;
GumStalker * stalker = stalker_get();
GumStalker *stalker = stalker_get();
FVERBOSE("Excluding ranges");

View File

@ -11,6 +11,8 @@ void seccomp_on_fork(void) {
#ifdef __APPLE__
FFATAL("Seccomp not supported on OSX");
#elif defined(__ANDROID__)
FFATAL("Seccomp not supported on Android");
#else
seccomp_callback_parent();
#endif
@ -32,6 +34,8 @@ void seccomp_init(void) {
#ifdef __APPLE__
FFATAL("Seccomp not supported on OSX");
#elif defined(__ANDROID__)
FFATAL("Seccomp not supported on Android");
#else
seccomp_callback_initialize();
#endif

View File

@ -8,9 +8,9 @@
#include "seccomp.h"
#include "util.h"
static void seccomp_callback_filter(struct seccomp_notif * req,
static void seccomp_callback_filter(struct seccomp_notif *req,
struct seccomp_notif_resp *resp,
GumReturnAddressArray * frames) {
GumReturnAddressArray *frames) {
GumDebugSymbolDetails details = {0};
if (req->data.nr == SYS_OPENAT) {
@ -54,7 +54,7 @@ static void seccomp_callback_filter(struct seccomp_notif * req,
free(syms);
#else
void **syms = (void **)__builtin_frame_address(0);
void * framep = __builtin_frame_address(1);
void *framep = __builtin_frame_address(1);
int i = 0;
syms = framep;

View File

@ -21,7 +21,7 @@ typedef struct {
seccomp_child_func_t func;
int event_fd;
void * ctx;
void *ctx;
} seccomp_child_func_ctx_t;

View File

@ -129,7 +129,7 @@ static volatile bool seccomp_filter_child_done = false;
static pid_t seccomp_filter_child = -1;
static GumCpuContext seccomp_filter_cpu_context = {0};
static GumReturnAddressArray seccomp_filter_frames = {.len = 0, .items = {0}};
static GumBacktracer * seccomp_filter_backtracer = NULL;
static GumBacktracer *seccomp_filter_backtracer = NULL;
static void seccomp_filter_child_handler(int sig, siginfo_t *info,
void *ucontext) {
@ -209,7 +209,7 @@ int seccomp_filter_install(pid_t child) {
void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) {
struct seccomp_notif * req = NULL;
struct seccomp_notif *req = NULL;
struct seccomp_notif_resp *resp = NULL;
struct seccomp_notif_sizes sizes;

View File

@ -59,9 +59,9 @@ void seccomp_socket_send(int sockfd, int fd) {
struct iovec iov = {.iov_base = &data, .iov_len = sizeof(data)};
union cmsg control_msg = {.hdr = {
.cmsg_len = CMSG_LEN(sizeof(int)),
.cmsg_level = SOL_SOCKET,
.cmsg_type = SCM_RIGHTS,
.cmsg_len = CMSG_LEN(sizeof(int)),
.cmsg_level = SOL_SOCKET,
.cmsg_type = SCM_RIGHTS,
}};

87
frida_mode/src/shm.c Normal file
View File

@ -0,0 +1,87 @@
#include "shm.h"
#include "util.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>
#ifdef __ANDROID__
#include <linux/ashmem.h>
#include <sys/ioctl.h>
#endif
#ifdef __ANDROID__
#define ASHMEM_DEVICE "/dev/ashmem"
void *shm_create(size_t size) {
int fd = -1;
char ourkey[11] = {0};
void *addr = MAP_FAILED;
struct ashmem_pin pin = {0, size};
fd = open(ASHMEM_DEVICE, O_RDWR);
if (fd < 0) { FFATAL("Failed open /dev/ashmem: %d", errno); }
if (snprintf(ourkey, sizeof(ourkey) - 1, "%d", IPC_PRIVATE) < 0) {
FFATAL("Failed to generate key: %d", errno);
}
if (ioctl(fd, ASHMEM_SET_NAME, ourkey) < 0) {
FFATAL("ioctl(ASHMEM_SET_NAME) errno: %d\n", errno);
}
if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) {
FFATAL("ioctl(ASHMEM_SET_SIZE) errno: %d\n", errno);
}
addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) { FFATAL("mmap failed: %d\n", errno); }
/* Shared memory pinning has been deprecated. So if the ioctl fails, then
just assume we are running on a version where it has been. Worst case, we
will leak the shared memory region.*/
ioctl(fd, ASHMEM_UNPIN, &pin);
close(fd);
return addr;
}
#else
void *shm_create(size_t size) {
int shm_id =
shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); }
void *addr = shmat(shm_id, NULL, 0);
if (addr == MAP_FAILED) { FFATAL("addr == MAP_FAILED - errno: %d\n", errno); }
/*
* Configure the shared memory region to be removed once the process
* dies.
*/
if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
}
/* Clear it, not sure it's necessary, just seems like good practice */
memset(addr, '\0', size);
return addr;
}
#endif

View File

@ -74,7 +74,7 @@ static gboolean stalker_exclude_self(const GumRangeDetails *details,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
gchar * name;
gchar *name;
gboolean found;
GumStalker *stalker;
if (details->file == NULL) { return TRUE; }
@ -100,7 +100,7 @@ void stalker_init(void) {
FOKF(cBLU "Stalker" cRST " - " cGRN "adjacent_blocks:" cYEL " [%u]",
stalker_adjacent_blocks);
#if !(defined(__x86_64__) || defined(__i386__))
#if !(defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))
if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) {
FFATAL("AFL_FRIDA_STALKER_IC_ENTRIES not supported");
@ -131,9 +131,14 @@ void stalker_init(void) {
}
gum_stalker_activate_experimental_unwind_support();
#if defined(__x86_64__) || defined(__i386__)
stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries,
"adjacent-blocks", stalker_adjacent_blocks, NULL);
#elif defined(__aarch64__)
stalker =
g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, NULL);
#else
stalker = gum_stalker_new();
#endif

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