Compare commits
622 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e2986dd78 | |||
1f06b55a8b | |||
7b6ee28291 | |||
94fe62ad8d | |||
608ea5f8ab | |||
00b5d3792d | |||
e9cb939956 | |||
7b6743f14c | |||
4b9c560b07 | |||
9d5a2d1b8e | |||
1e524d1f43 | |||
7c50ec5d05 | |||
7bdb22c70c | |||
3562de440e | |||
98e8838755 | |||
a2f3c3ee51 | |||
6056d4b140 | |||
d745da0c93 | |||
4fdd64d6d6 | |||
f2b7104cd6 | |||
c6af98bc35 | |||
67fabcb0be | |||
7b7914e1d6 | |||
9551be3f8e | |||
f22d28333b | |||
d8d6ea93cf | |||
0540d30274 | |||
9657b700b1 | |||
6c26434a63 | |||
42c677aa7b | |||
0373628adf | |||
d090232452 | |||
4d20b2d28b | |||
c67f98865e | |||
ca4a8c0f92 | |||
c57988e672 | |||
b847e0f414 | |||
338f1ae2f8 | |||
1f4b45b5bf | |||
30736ab7d6 | |||
46fed1f43f | |||
662662c15d | |||
d088c26045 | |||
3d2a095f2e | |||
9abae56a37 | |||
1f17aa082d | |||
c7c7476453 | |||
b883faa942 | |||
b1e0d6e640 | |||
ada61204f3 | |||
72344a2f5f | |||
0bb8cc46b4 | |||
05080f32ee | |||
32c4be4773 | |||
1759859ae2 | |||
e6f27c2645 | |||
c90dd00fc9 | |||
0da935183f | |||
4848c8d24c | |||
250000ee79 | |||
fc520a2bde | |||
6c9c8fdc65 | |||
24458ae285 | |||
36a0ab1193 | |||
1334851e7c | |||
b077a7963b | |||
3e65e1a029 | |||
e21738a248 | |||
4094750803 | |||
92352951d7 | |||
bb509765df | |||
6705953a49 | |||
b3edb657c2 | |||
a1889db9bf | |||
c83635e1d2 | |||
fd404194f2 | |||
5fa7861149 | |||
e969972c97 | |||
80e829f79d | |||
73db4fe993 | |||
22c3b519fa | |||
88077d4136 | |||
cfb0257c99 | |||
9a93688e3e | |||
48c2d51689 | |||
1dac69b1eb | |||
0da7ddb738 | |||
6e960f78d6 | |||
3282023047 | |||
c7db5b67f9 | |||
fc98d53e27 | |||
a5822c7c2f | |||
01cb84051a | |||
d9c2487c3e | |||
a7f3f87f41 | |||
1a4c0d2ecd | |||
eb37cec76e | |||
5ed993d74e | |||
5d5d1f70fc | |||
85b1ce00a8 | |||
51a88b17b3 | |||
b0e58baca2 | |||
f23cac854a | |||
0c3ba7d227 | |||
605f2bf969 | |||
dc3e2e8200 | |||
47d4f16189 | |||
74f70d0c74 | |||
be79ee7072 | |||
bf6a0159a9 | |||
fc3b483450 | |||
0dd1c39b5a | |||
60702fef7a | |||
a96f9a349a | |||
4fdd1129f0 | |||
4990823840 | |||
3d1a57deed | |||
47d8947471 | |||
80892b8fc5 | |||
ba21e20695 | |||
5b471986b8 | |||
da1b041098 | |||
95aa81045b | |||
b595727f2f | |||
d798a90f04 | |||
35d49c7c5c | |||
83f32c5248 | |||
683dcc4710 | |||
59bb4a6cc4 | |||
6afccdebcd | |||
7413316496 | |||
ad2a1b0574 | |||
942b85bb77 | |||
50c6031cc3 | |||
066d65d846 | |||
1441503c43 | |||
c96238d85f | |||
4103ee43e2 | |||
ba3c7bfe40 | |||
5ad760a77b | |||
6dfc9aaab0 | |||
ffdbe8a2fb | |||
c5083f8982 | |||
ca721404ef | |||
c563faa076 | |||
a2eb1f1412 | |||
c08eeb95ca | |||
7c755a675f | |||
4c0281adc8 | |||
022f364661 | |||
3dc72ffb6b | |||
ca361e1b6a | |||
b36d0adb46 | |||
2a4d77abc6 | |||
dfe03a346a | |||
1605291154 | |||
f180109d1a | |||
927cb770f0 | |||
82c6c8e563 | |||
79099a01f8 | |||
7c8246f18f | |||
51942b605d | |||
47dae21f4a | |||
ba12c7fc09 | |||
229a45c6a6 | |||
45219dee80 | |||
13e0fd3e1a | |||
68e8467859 | |||
293e255734 | |||
0b228fb0f5 | |||
01594dc416 | |||
46d5452c86 | |||
c7bb0a9638 | |||
ee409d18a6 | |||
5d5aa430d2 | |||
5792d492ed | |||
9ac3c53104 | |||
ee50f41d29 | |||
aeeca164b5 | |||
b2c96f66ee | |||
7f26d13345 | |||
5798c686b2 | |||
f53e6a6cf2 | |||
630eb943a5 | |||
4f42ecd815 | |||
1d00bde6c5 | |||
b1da7500b2 | |||
223c52827a | |||
e1c4a4ea7e | |||
b092ee4986 | |||
494c55df15 | |||
35cf1fa906 | |||
6e790552fe | |||
8971c9a5ce | |||
57db3e7f4f | |||
0540382c41 | |||
2263989e12 | |||
6aa470d641 | |||
0db57c3eec | |||
ce1fc4b27d | |||
5d4b0938d5 | |||
c208dcf9c5 | |||
d8317182ef | |||
e9288bcfad | |||
396de6fc9c | |||
891f4d3c8e | |||
9933a6f3ab | |||
3261e86a3a | |||
3ccebbf9c5 | |||
9c2c35b233 | |||
bf5b90f95a | |||
8385bc794a | |||
ac80678592 | |||
3c5edab724 | |||
9887f636ba | |||
fc48951468 | |||
0e9d0ebbfe | |||
84e03e4a4d | |||
044d3e823e | |||
3fc03d4b6b | |||
15b43e6ce1 | |||
d9fa6af1b1 | |||
ef5543680a | |||
881aef21fd | |||
26f3ec28ee | |||
657e4cc812 | |||
29f0bb1c6a | |||
c4363dd8b3 | |||
ff5882f415 | |||
7f56a93f5d | |||
2d7ac5f69c | |||
285a5cb38b | |||
51dbd0e957 | |||
772e33d550 | |||
77a3abfa5e | |||
a436ef47e5 | |||
b34751efbf | |||
d2ea1141eb | |||
3f0d642f9b | |||
7598efb8e6 | |||
0dca6ee038 | |||
a601b56627 | |||
ce0db35f18 | |||
d012358748 | |||
d4734f6d9b | |||
bcf123e1ee | |||
9a87e83bf4 | |||
c2ae24ab96 | |||
13c8a27faa | |||
a133aa9106 | |||
fa2b040476 | |||
69c9a176eb | |||
bdfac291ba | |||
90fd61d14a | |||
3d1be62c96 | |||
d1f59435ca | |||
1bea949f34 | |||
3c11a37757 | |||
e4f201707f | |||
59eaed2f70 | |||
1a65df2bee | |||
c08304ad3d | |||
2b8fea083e | |||
34d7a6357e | |||
ae9897ff7b | |||
d297738255 | |||
981a04eb27 | |||
2a00f32666 | |||
c2229b506e | |||
70cc32dc6d | |||
5385cc7618 | |||
2eeba2dbf0 | |||
09123d8617 | |||
713b069f40 | |||
0f7419fc91 | |||
7c9b7c0bc0 | |||
544b68044a | |||
33e43b11f8 | |||
a2d54218ad | |||
899fa59ab6 | |||
f2831419f5 | |||
d325fa5db8 | |||
7e67545b9d | |||
d84a8da1e9 | |||
f70760896c | |||
c9504867da | |||
744ad172e1 | |||
5e9286b9ea | |||
d22532d8d3 | |||
cd02f635db | |||
819a1539a6 | |||
ba7ec51232 | |||
1840c27b6f | |||
e996112fbc | |||
9b799aeddd | |||
fee1acf7e6 | |||
675d17d737 | |||
05119990b6 | |||
914eb79cbc | |||
92db443635 | |||
852c036cae | |||
a5943dc782 | |||
fc7bf33fb1 | |||
fcd06fa99c | |||
5f45f380c3 | |||
cb1256499f | |||
dd8ad4dfa3 | |||
8fc249d210 | |||
1d4f1e4879 | |||
de7058b75b | |||
5e8da2b85c | |||
056ebbff15 | |||
cf853fb249 | |||
fa628865c1 | |||
05a36f10ba | |||
cbf3d1bdee | |||
64cc345ec2 | |||
8dbc4a1423 | |||
452eb9f75b | |||
a5dc067331 | |||
27dc0e09e0 | |||
bcd802e6fd | |||
958a059477 | |||
c8bfce21ab | |||
d178b325ab | |||
077a3e32e0 | |||
fa3c0d8a37 | |||
d5b9cd4b73 | |||
ce5032cc29 | |||
04d693721b | |||
9eb66cccf4 | |||
9b72fe4880 | |||
1a89d428c9 | |||
d4c01c057b | |||
80543a809e | |||
104c0e29e9 | |||
7d36609722 | |||
119a0e0dce | |||
f336aa463b | |||
5f6bbc7dea | |||
17fc44d995 | |||
055af82026 | |||
e2f76dd41e | |||
1c79b82ab8 | |||
c38b05c80a | |||
bb186a2ece | |||
60e126c615 | |||
dd9003e59b | |||
2d9325aed9 | |||
53eb5ba2fb | |||
267dd634f1 | |||
7ab7862e4d | |||
59a7337bf1 | |||
c75124aefa | |||
2861f695ba | |||
43a7c0d601 | |||
311649f458 | |||
a5eafbff6c | |||
1d339527bb | |||
707b1701c3 | |||
b2465a05eb | |||
aa5f59b501 | |||
08c39c1552 | |||
f75535807a | |||
143c9d175e | |||
b0758ac8db | |||
77c06408c3 | |||
6bf52c1434 | |||
eebc2f4f1e | |||
016bdc36bb | |||
ed72b9ec1d | |||
615a8ff986 | |||
026096ccf3 | |||
87f2789e98 | |||
d9ed784298 | |||
0fd6315dfb | |||
28a1765781 | |||
0b5ad8ee84 | |||
3a78db2ade | |||
605b0e6465 | |||
7270cbe756 | |||
a790bf6cc2 | |||
86983f4060 | |||
319c7457ff | |||
e9be58b69c | |||
61d79f85c5 | |||
9baa402344 | |||
04e3b5a6d3 | |||
227b42b1d0 | |||
ac169c3087 | |||
3609912f41 | |||
6d2b8e3ed2 | |||
06ee6b1986 | |||
0090b3a3f0 | |||
452a4cf5be | |||
f63d2b0f55 | |||
29235a7935 | |||
ac0e855907 | |||
f7a5ea667b | |||
fce512db40 | |||
b427a53a6b | |||
2bb86863e6 | |||
26a3d1b53b | |||
2a0f082723 | |||
22da04f077 | |||
5933e787f9 | |||
6ce736aa91 | |||
830dcacc07 | |||
74d9da7203 | |||
9d3e6a869e | |||
1a15e98fff | |||
a594182314 | |||
9d87f408dd | |||
b4c2fc9416 | |||
ecf8db0014 | |||
ec7b14a3d6 | |||
c74686e20d | |||
4902bb91d2 | |||
237a475d9b | |||
686a595df3 | |||
1529bd070e | |||
29f8040f09 | |||
029bfc386f | |||
88905c65af | |||
492418ebd6 | |||
a9d549ca07 | |||
4721d869ad | |||
7aced239e8 | |||
d1de12d617 | |||
5deae7924f | |||
1d9d5936d9 | |||
7afad147d1 | |||
550ba4d772 | |||
25c8336c0c | |||
4bcb177f62 | |||
409a6517c1 | |||
d9fefafae7 | |||
16bd6aad7c | |||
5b06078a41 | |||
a3cf7c1224 | |||
6de9b37b2a | |||
1e5699ccaa | |||
bdec40ae5d | |||
56ce081ac7 | |||
861bd5e04b | |||
c5117b42ca | |||
0e2c832499 | |||
34caf7d781 | |||
c8061e5b35 | |||
a45cdb240c | |||
2b82492457 | |||
d51ec57d91 | |||
751e09f47b | |||
c1415b816a | |||
4217a6606c | |||
20177151e6 | |||
9a4552d6c4 | |||
8c58bdb504 | |||
f42c0047c8 | |||
1ca3317425 | |||
630ba07054 | |||
27ab84fbf1 | |||
4c07e37eae | |||
8f7e584b82 | |||
f6c08c3a1c | |||
9e38c43686 | |||
c8e6a59e7d | |||
bedd812e7b | |||
110cc27632 | |||
21ebfec79c | |||
8701cdcc2c | |||
e7ddd15fa5 | |||
5e47829462 | |||
e663897a8a | |||
b7ddde636b | |||
8764375357 | |||
657c1e9b9b | |||
0ed1cb4d31 | |||
741dcabd5d | |||
2342c85db4 | |||
091fa09e5e | |||
d8920e31f8 | |||
6a7f184c4e | |||
30666cb81e | |||
9242e0db8a | |||
add85f34d1 | |||
c7dbeb8568 | |||
179b118bc9 | |||
7884e0f449 | |||
10dae419d6 | |||
d2715336a5 | |||
41b07983f1 | |||
ef77d552e9 | |||
85f3ebc714 | |||
b7d741b18e | |||
da5ff0df0a | |||
7ae90a66c4 | |||
ee295801a6 | |||
03ba344e6d | |||
cc94e37ae1 | |||
8c1015ac39 | |||
dc7b607080 | |||
511ffc06d2 | |||
3b96c8ae13 | |||
226450600c | |||
845c32b5fb | |||
ee57053be1 | |||
a010d356de | |||
3b3ba08daa | |||
72cebac42e | |||
e1082f2548 | |||
128413690e | |||
b6b81a687d | |||
b8e61da8ab | |||
cda84594cc | |||
fd9f61a8c5 | |||
8b75680c7a | |||
09c4d9ed75 | |||
02082bcd2e | |||
fa6a0aba61 | |||
dbc62dbe56 | |||
1a25ccb618 | |||
0792cab566 | |||
b5cb99f6fe | |||
0a18bf8db5 | |||
48ad95f0e5 | |||
fd99ddb1d6 | |||
7e8a491500 | |||
8b8aaa93bd | |||
f511ebd125 | |||
83bf876255 | |||
41291d8c72 | |||
f9d4dcdd85 | |||
8a681bc163 | |||
53fa703755 | |||
51d6f863f5 | |||
be00dbc2ac | |||
65ffa4b472 | |||
7bd2899f2e | |||
43b162c222 | |||
5d9134d6ad | |||
6c8a47f7dc | |||
89c4fa3051 | |||
81aae9b54c | |||
54eca027a5 | |||
8fe6282164 | |||
8588becf47 | |||
a91d445b5f | |||
2d9e0f56b0 | |||
146eb32c31 | |||
550dc989b3 | |||
251264fde5 | |||
649076600d | |||
8521eb8413 | |||
699c16c7e0 | |||
6b50a001b0 | |||
24dd35ef96 | |||
8217b5ff81 | |||
7b3b707ae6 | |||
60b0c38022 | |||
17d4ae9a16 | |||
71621bbc52 | |||
ddc90e1176 | |||
47488dcd02 | |||
185d7f2ede | |||
376d1736a8 | |||
edeaf72ea8 | |||
c76dc73c7a | |||
964819d3fc | |||
68436b277b | |||
6106efa301 | |||
d59a76261d | |||
db19116ce6 | |||
a3421f8099 | |||
fd1d162149 | |||
5a28157ffd | |||
e3106e6f52 | |||
b3a0ecfd48 | |||
641a943d95 | |||
74a8f145e0 | |||
3cb7319ccd | |||
5f70bc5404 | |||
ee10461f48 | |||
9f911bf0bd | |||
88814be474 | |||
a2314fc37f | |||
176ede3fc8 | |||
d89fa8c7ad | |||
63087d9bd9 | |||
fad8a3feb8 | |||
02fba1cc7e | |||
2564eb6f8c | |||
495348261d | |||
7a939a6c59 | |||
425cbb9025 | |||
ab699bbeea | |||
bf8e07d168 | |||
ae958acc83 | |||
088aae7c25 | |||
75ac9c013c | |||
22e2362f0f | |||
c6bad07d75 | |||
83487415b1 | |||
9de3de6cdf | |||
aceb1af908 | |||
3a60f6a251 | |||
52dd5d479d | |||
ece717c424 | |||
57bc3c0701 | |||
630272bac5 | |||
5590d1836a | |||
e41ac9564b | |||
2c144e88fb | |||
5c7e84c5c8 | |||
52cae6d132 | |||
6eb752a65c | |||
ed3eb61610 | |||
0993bcdc4e | |||
d28bb47a38 | |||
9d7dd5a69f | |||
77ce31c8ba | |||
08ca4d54a5 |
@ -6,7 +6,7 @@
|
|||||||
# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
|
# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -19,40 +19,22 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import shutil
|
||||||
|
|
||||||
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use
|
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use
|
||||||
|
|
||||||
with open(".clang-format") as f:
|
with open(".clang-format") as f:
|
||||||
fmt = f.read()
|
fmt = f.read()
|
||||||
|
|
||||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
|
CURRENT_LLVM = os.getenv('LLVM_VERSION', 14)
|
||||||
if CLANG_FORMAT_BIN is None:
|
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
|
||||||
o = 0
|
|
||||||
try:
|
if shutil.which(CLANG_FORMAT_BIN) is None:
|
||||||
p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
|
CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}"
|
||||||
o, _ = p.communicate()
|
|
||||||
o = str(o, "utf-8")
|
if shutil.which(CLANG_FORMAT_BIN) is None:
|
||||||
o = re.sub(r".*ersion ", "", o)
|
print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.")
|
||||||
# o = o[len("clang-format version "):].strip()
|
exit(1)
|
||||||
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"
|
|
||||||
|
|
||||||
COLUMN_LIMIT = 80
|
COLUMN_LIMIT = 80
|
||||||
for line in fmt.split("\n"):
|
for line in fmt.split("\n"):
|
||||||
|
@ -1,65 +1,75 @@
|
|||||||
|
!/coresight_mode
|
||||||
|
*.dSYM
|
||||||
|
*.o
|
||||||
|
*.pyc
|
||||||
|
*.so
|
||||||
|
.sync_tmp
|
||||||
.test
|
.test
|
||||||
.test2
|
.test2
|
||||||
.sync_tmp
|
.git
|
||||||
*.o
|
.dockerignore
|
||||||
*.so
|
.github
|
||||||
*.pyc
|
CITATION.cff
|
||||||
*.dSYM
|
CONTRIBUTING.md
|
||||||
as
|
Changelog.md
|
||||||
ld
|
Dockerfile
|
||||||
in
|
LICENSE
|
||||||
out
|
TODO.md
|
||||||
core*
|
|
||||||
afl-analyze
|
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-analyze.8
|
||||||
|
afl-as
|
||||||
afl-as.8
|
afl-as.8
|
||||||
afl-clang-fast\+\+.8
|
afl-clang
|
||||||
|
afl-clang-fast
|
||||||
afl-clang-fast.8
|
afl-clang-fast.8
|
||||||
|
afl-clang-fast\+\+
|
||||||
|
afl-clang-fast\+\+.8
|
||||||
|
afl-clang-lto
|
||||||
afl-clang-lto.8
|
afl-clang-lto.8
|
||||||
|
afl-clang-lto\+\+
|
||||||
afl-clang-lto\+\+.8
|
afl-clang-lto\+\+.8
|
||||||
|
afl-clang\+\+
|
||||||
afl-cmin.8
|
afl-cmin.8
|
||||||
afl-cmin.bash.8
|
afl-cmin.bash.8
|
||||||
|
afl-fuzz
|
||||||
afl-fuzz.8
|
afl-fuzz.8
|
||||||
afl-gcc.8
|
afl-g\+\+
|
||||||
afl-gcc-fast.8
|
afl-g\+\+-fast
|
||||||
afl-g\+\+-fast.8
|
afl-g\+\+-fast.8
|
||||||
|
afl-gcc
|
||||||
|
afl-gcc-fast
|
||||||
|
afl-gcc-fast.8
|
||||||
|
afl-gcc.8
|
||||||
|
afl-gotcpu
|
||||||
afl-gotcpu.8
|
afl-gotcpu.8
|
||||||
|
afl-ld
|
||||||
|
afl-ld-lto
|
||||||
afl-plot.8
|
afl-plot.8
|
||||||
|
afl-qemu-trace
|
||||||
|
afl-showmap
|
||||||
afl-showmap.8
|
afl-showmap.8
|
||||||
afl-system-config.8
|
afl-system-config.8
|
||||||
|
afl-tmin
|
||||||
afl-tmin.8
|
afl-tmin.8
|
||||||
afl-whatsup.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/libcompcov/compcovtest
|
||||||
qemu_mode/qemu-*
|
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/*/\.test-*
|
||||||
unicorn_mode/samples/*/output
|
unicorn_mode/samples/*/output
|
||||||
unicorn_mode/unicornafl
|
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
|
|
25
.github/workflows/build_aflplusplus_docker.yaml
vendored
@ -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
|
|
44
.github/workflows/ci.yml
vendored
@ -2,29 +2,55 @@ name: CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- stable
|
||||||
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- dev # No need for stable-pull-request, as that equals dev-push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
linux:
|
||||||
runs-on: '${{ matrix.os }}'
|
runs-on: "${{ matrix.os }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: debug
|
- name: debug
|
||||||
run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format-
|
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
|
||||||
- name: update
|
- name: update
|
||||||
run: sudo apt-get update && sudo apt-get upgrade -y
|
run: sudo apt-get update && sudo apt-get upgrade -y
|
||||||
- name: install packages
|
- name: install packages
|
||||||
run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build
|
run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build
|
||||||
- name: compiler installed
|
- name: compiler installed
|
||||||
run: gcc -v ; echo ; clang -v
|
run: gcc -v; echo; clang -v
|
||||||
- name: install gcc plugin
|
- name: install gcc plugin
|
||||||
run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev
|
run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev
|
||||||
- name: build afl++
|
- name: build afl++
|
||||||
run: make distrib ASAN_BUILD=1
|
run: make distrib ASAN_BUILD=1
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: sudo -E ./afl-system-config ; export AFL_SKIP_CPUFREQ=1 ; make tests
|
run: sudo -E ./afl-system-config; make tests
|
||||||
|
macos:
|
||||||
|
runs-on: macOS-latest
|
||||||
|
env:
|
||||||
|
AFL_MAP_SIZE: 65536
|
||||||
|
AFL_SKIP_CPUFREQ: 1
|
||||||
|
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: install
|
||||||
|
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
|
||||||
|
run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
|
||||||
|
- name: frida
|
||||||
|
run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||||
|
- name: run tests
|
||||||
|
run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||||
|
- name: force frida test for MacOS
|
||||||
|
run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||||
|
33
.github/workflows/code-format.yml
vendored
Normal 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
|
43
.github/workflows/codeql-analysis.yml
vendored
@ -2,31 +2,32 @@ name: "CodeQL"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- stable
|
||||||
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- dev # No need for stable-pull-request, as that equals dev-push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container: # We use a previous image as it's expected to have all the dependencies
|
||||||
strategy:
|
image: docker.io/aflplusplus/aflplusplus:dev
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'cpp' ]
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Fix for using external repo in container build # https://github.com/actions/checkout/issues/760
|
||||||
uses: actions/checkout@v2
|
run: git config --global --add safe.directory /__w/AFLplusplus/AFLplusplus
|
||||||
|
- name: Checkout
|
||||||
- name: Initialize CodeQL
|
uses: actions/checkout@v3
|
||||||
uses: github/codeql-action/init@v1
|
- name: Initialize CodeQL
|
||||||
with:
|
uses: github/codeql-action/init@v2
|
||||||
languages: ${{ matrix.language }}
|
with:
|
||||||
|
languages: cpp, python
|
||||||
- name: Autobuild
|
- name: Build AFLplusplus # Rebuild because CodeQL needs to monitor the build process
|
||||||
uses: github/codeql-action/autobuild@v1
|
env:
|
||||||
|
CC: gcc # These are symlinked to the version used in the container build
|
||||||
- name: Perform CodeQL Analysis
|
CXX: g++
|
||||||
uses: github/codeql-action/analyze@v1
|
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
@ -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
|
13
.github/workflows/rust_custom_mutator.yml
vendored
@ -2,9 +2,12 @@ name: Rust Custom Mutators
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- stable
|
||||||
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ stable, dev ]
|
branches:
|
||||||
|
- dev # No need for stable-pull-request, as that equals dev-push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -15,9 +18,9 @@ jobs:
|
|||||||
working-directory: custom_mutators/rust
|
working-directory: custom_mutators/rust
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-22.04, ubuntu-20.04]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install Rust Toolchain
|
- name: Install Rust Toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -27,4 +30,4 @@ jobs:
|
|||||||
- name: Run General Tests
|
- name: Run General Tests
|
||||||
run: cargo test
|
run: cargo test
|
||||||
- name: Run Tests for afl_internals feature flag
|
- 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
@ -97,3 +97,4 @@ utils/persistent_mode/persistent_demo_new
|
|||||||
utils/persistent_mode/test-instr
|
utils/persistent_mode/test-instr
|
||||||
!coresight_mode
|
!coresight_mode
|
||||||
!coresight_mode/coresight-trace
|
!coresight_mode/coresight-trace
|
||||||
|
vuln_prog
|
12
.gitmodules
vendored
@ -10,12 +10,18 @@
|
|||||||
[submodule "custom_mutators/gramatron/json-c"]
|
[submodule "custom_mutators/gramatron/json-c"]
|
||||||
path = custom_mutators/gramatron/json-c
|
path = custom_mutators/gramatron/json-c
|
||||||
url = https://github.com/json-c/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"]
|
[submodule "coresight_mode/patchelf"]
|
||||||
path = coresight_mode/patchelf
|
path = coresight_mode/patchelf
|
||||||
url = https://github.com/NixOS/patchelf.git
|
url = https://github.com/NixOS/patchelf.git
|
||||||
[submodule "coresight_mode/coresight-trace"]
|
[submodule "coresight_mode/coresight-trace"]
|
||||||
path = coresight_mode/coresight-trace
|
path = coresight_mode/coresight-trace
|
||||||
url = https://github.com/RICSecLab/coresight-trace.git
|
url = https://github.com/RICSecLab/coresight-trace.git
|
||||||
|
[submodule "nyx_mode/libnyx"]
|
||||||
|
path = nyx_mode/libnyx
|
||||||
|
url = https://github.com/nyx-fuzz/libnyx.git
|
||||||
|
[submodule "nyx_mode/QEMU-Nyx"]
|
||||||
|
path = nyx_mode/QEMU-Nyx
|
||||||
|
url = https://github.com/nyx-fuzz/qemu-nyx.git
|
||||||
|
[submodule "nyx_mode/packer"]
|
||||||
|
path = nyx_mode/packer
|
||||||
|
url = https://github.com/nyx-fuzz/packer.git
|
||||||
|
19
Android.bp
@ -1,3 +1,11 @@
|
|||||||
|
//
|
||||||
|
// NOTE: This file is outdated. None of the AFL++ team uses Android hence
|
||||||
|
// we need users to keep this updated.
|
||||||
|
// In the current state it will likely fail, please send fixes!
|
||||||
|
// Also, this should build frida_mode.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
cc_defaults {
|
cc_defaults {
|
||||||
name: "afl-defaults",
|
name: "afl-defaults",
|
||||||
|
|
||||||
@ -68,6 +76,7 @@ cc_binary {
|
|||||||
srcs: [
|
srcs: [
|
||||||
"src/afl-fuzz*.c",
|
"src/afl-fuzz*.c",
|
||||||
"src/afl-common.c",
|
"src/afl-common.c",
|
||||||
|
"src/afl-forkserver.c",
|
||||||
"src/afl-sharedmem.c",
|
"src/afl-sharedmem.c",
|
||||||
"src/afl-forkserver.c",
|
"src/afl-forkserver.c",
|
||||||
"src/afl-performance.c",
|
"src/afl-performance.c",
|
||||||
@ -175,7 +184,7 @@ cc_binary_host {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cc_library_static {
|
cc_library_static {
|
||||||
name: "afl-llvm-rt",
|
name: "afl-compiler-rt",
|
||||||
compile_multilib: "64",
|
compile_multilib: "64",
|
||||||
vendor_available: true,
|
vendor_available: true,
|
||||||
host_supported: true,
|
host_supported: true,
|
||||||
@ -225,6 +234,7 @@ cc_library_headers {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
cc_prebuilt_library_static {
|
cc_prebuilt_library_static {
|
||||||
name: "libfrida-gum",
|
name: "libfrida-gum",
|
||||||
compile_multilib: "64",
|
compile_multilib: "64",
|
||||||
@ -272,7 +282,7 @@ cc_binary {
|
|||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"afl-llvm-rt",
|
"afl-compiler-rt",
|
||||||
"libfrida-gum",
|
"libfrida-gum",
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -290,6 +300,7 @@ cc_binary {
|
|||||||
"utils/afl_frida/android",
|
"utils/afl_frida/android",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
cc_binary {
|
cc_binary {
|
||||||
name: "afl-fuzz-32",
|
name: "afl-fuzz-32",
|
||||||
@ -346,7 +357,7 @@ cc_binary_host {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cc_library_static {
|
cc_library_static {
|
||||||
name: "afl-llvm-rt-32",
|
name: "afl-compiler-rt-32",
|
||||||
compile_multilib: "32",
|
compile_multilib: "32",
|
||||||
vendor_available: true,
|
vendor_available: true,
|
||||||
host_supported: true,
|
host_supported: true,
|
||||||
@ -385,6 +396,7 @@ cc_library_static {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
cc_prebuilt_library_static {
|
cc_prebuilt_library_static {
|
||||||
name: "libfrida-gum-32",
|
name: "libfrida-gum-32",
|
||||||
compile_multilib: "32",
|
compile_multilib: "32",
|
||||||
@ -400,6 +412,7 @@ cc_prebuilt_library_static {
|
|||||||
"utils/afl_frida/android/arm",
|
"utils/afl_frida/android/arm",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
subdirs = [
|
subdirs = [
|
||||||
"custom_mutators",
|
"custom_mutators",
|
||||||
|
31
CITATION.cff
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
cff-version: 1.2.0
|
||||||
|
message: "If you use this software, please cite it as below."
|
||||||
|
authors:
|
||||||
|
- given-names: Marc
|
||||||
|
family-names: Heuse
|
||||||
|
email: mh@mh-sec.de
|
||||||
|
- given-names: Heiko
|
||||||
|
family-names: Eißfeldt
|
||||||
|
email: heiko.eissfeldt@hexco.de
|
||||||
|
- given-names: Andrea
|
||||||
|
family-names: Fioraldi
|
||||||
|
email: andreafioraldi@gmail.com
|
||||||
|
- given-names: Dominik
|
||||||
|
family-names: Maier
|
||||||
|
email: mail@dmnk.co
|
||||||
|
title: "AFL++"
|
||||||
|
version: 4.00c
|
||||||
|
type: software
|
||||||
|
date-released: 2022-01-26
|
||||||
|
url: "https://github.com/AFLplusplus/AFLplusplus"
|
||||||
|
keywords:
|
||||||
|
- fuzzing
|
||||||
|
- fuzzer
|
||||||
|
- fuzz-testing
|
||||||
|
- instrumentation
|
||||||
|
- afl-fuzz
|
||||||
|
- qemu
|
||||||
|
- llvm
|
||||||
|
- unicorn-emulator
|
||||||
|
- securiy
|
||||||
|
license: AGPL-3.0-or-later
|
123
Dockerfile
@ -1,75 +1,88 @@
|
|||||||
#
|
#
|
||||||
# This Dockerfile for AFLplusplus uses Ubuntu 20.04 focal and
|
# This Dockerfile for AFLplusplus uses Ubuntu 22.04 jammy and
|
||||||
# installs LLVM 11 from llvm.org for afl-clang-lto support :-)
|
# installs LLVM 14 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 ...
|
# 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 "maintainer"="afl++ team <afl@aflplus.plus>"
|
||||||
LABEL "about"="AFLplusplus docker image"
|
LABEL "about"="AFLplusplus container image"
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
env NO_ARCH_OPT 1
|
ENV NO_ARCH_OPT=1
|
||||||
|
ENV IS_DOCKER=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
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get full-upgrade -y && \
|
RUN apt-get update && apt-get full-upgrade -y && \
|
||||||
apt-get -y install --no-install-suggests --no-install-recommends \
|
apt-get install -y --no-install-recommends wget ca-certificates && \
|
||||||
gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib gcc-multilib gdb lcov \
|
rm -rf /var/lib/apt/lists/*
|
||||||
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/*
|
|
||||||
|
|
||||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 0
|
ENV LLVM_VERSION=14
|
||||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
|
ENV GCC_VERSION=11
|
||||||
|
|
||||||
ENV LLVM_CONFIG=llvm-config-12
|
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
|
||||||
|
|
||||||
|
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-utils 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_SKIP_CPUFREQ=1
|
||||||
ENV AFL_TRY_AFFINITY=1
|
ENV AFL_TRY_AFFINITY=1
|
||||||
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=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 git clone --depth=1 https://github.com/vanhauser-thc/afl-cov && \
|
||||||
RUN cd /afl-cov && make install && cd ..
|
(cd afl-cov && make install) && rm -rf afl-cov
|
||||||
|
|
||||||
|
# Build currently broken
|
||||||
|
ENV NO_CORESIGHT=1
|
||||||
|
ENV NO_UNICORN_ARM64=1
|
||||||
|
|
||||||
COPY . /AFLplusplus
|
|
||||||
WORKDIR /AFLplusplus
|
WORKDIR /AFLplusplus
|
||||||
|
COPY . .
|
||||||
|
|
||||||
RUN export CC=gcc-10 && export CXX=g++-10 && make clean && \
|
ARG CC=gcc-$GCC_VERSION
|
||||||
make distrib && make install && make clean
|
ARG CXX=g++-$GCC_VERSION
|
||||||
|
|
||||||
RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc'
|
# Used in CI to prevent a 'make clean' which would remove the binaries to be tested
|
||||||
RUN echo '. /etc/bash_completion' >> ~/.bashrc
|
ARG TEST_BUILD
|
||||||
RUN echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc
|
|
||||||
RUN echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc
|
|
||||||
ENV IS_DOCKER="1"
|
|
||||||
|
|
||||||
# Disabled until we have the container ready
|
RUN sed -i.bak 's/^ -/ /g' GNUmakefile && \
|
||||||
#COPY --from=aflplusplus/afl-dyninst /usr/local/lib/libdyninstAPI_RT.so /usr/local/lib/libdyninstAPI_RT.so
|
make clean && make distrib && \
|
||||||
#COPY --from=aflplusplus/afl-dyninst /afl-dyninst/libAflDyninst.so /usr/local/lib/libAflDyninst.so
|
([ "${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
|
||||||
|
146
GNUmakefile
@ -76,9 +76,9 @@ else
|
|||||||
endif
|
endif
|
||||||
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"
|
#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
|
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
|
||||||
endif
|
#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"
|
#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
|
# ifndef SOURCE_DATE_EPOCH
|
||||||
@ -92,9 +92,13 @@ ifneq "$(SYS)" "Darwin"
|
|||||||
# SPECIAL_PERFORMANCE += -march=native
|
# SPECIAL_PERFORMANCE += -march=native
|
||||||
#endif
|
#endif
|
||||||
# OS X does not like _FORTIFY_SOURCE=2
|
# OS X does not like _FORTIFY_SOURCE=2
|
||||||
ifndef DEBUG
|
ifndef DEBUG
|
||||||
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
||||||
endif
|
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
|
endif
|
||||||
|
|
||||||
ifeq "$(SYS)" "SunOS"
|
ifeq "$(SYS)" "SunOS"
|
||||||
@ -138,12 +142,13 @@ ifdef DEBUG
|
|||||||
$(info Compiling DEBUG version of binaries)
|
$(info Compiling DEBUG version of binaries)
|
||||||
override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
|
override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
|
||||||
else
|
else
|
||||||
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
|
CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
|
||||||
endif
|
endif
|
||||||
|
|
||||||
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
|
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wno-pointer-arith \
|
||||||
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
-fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
||||||
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
||||||
|
# -fstack-protector
|
||||||
|
|
||||||
ifeq "$(SYS)" "FreeBSD"
|
ifeq "$(SYS)" "FreeBSD"
|
||||||
override CFLAGS += -I /usr/local/include/
|
override CFLAGS += -I /usr/local/include/
|
||||||
@ -167,9 +172,9 @@ endif
|
|||||||
|
|
||||||
ifeq "$(SYS)" "Haiku"
|
ifeq "$(SYS)" "Haiku"
|
||||||
SHMAT_OK=0
|
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
|
override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
|
||||||
SPECIAL_PERFORMANCE += -DUSEMMAP=1
|
#SPECIAL_PERFORMANCE += -DUSEMMAP=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
||||||
@ -241,9 +246,6 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq "$(filter Linux GNU%,$(SYS))" ""
|
ifneq "$(filter Linux GNU%,$(SYS))" ""
|
||||||
ifndef DEBUG
|
|
||||||
override CFLAGS += -D_FORTIFY_SOURCE=2
|
|
||||||
endif
|
|
||||||
override LDFLAGS += -ldl -lrt -lm
|
override LDFLAGS += -ldl -lrt -lm
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -310,7 +312,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
|
|||||||
|
|
||||||
.PHONY: llvm
|
.PHONY: llvm
|
||||||
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; }
|
@test -e afl-cc || { echo "[-] Compiling afl-cc failed. You seem not to have a working compiler." ; exit 1; }
|
||||||
|
|
||||||
.PHONY: gcc_plugin
|
.PHONY: gcc_plugin
|
||||||
@ -345,9 +347,9 @@ performance-test: source-only
|
|||||||
help:
|
help:
|
||||||
@echo "HELP --- the following make targets exist:"
|
@echo "HELP --- the following make targets exist:"
|
||||||
@echo "=========================================="
|
@echo "=========================================="
|
||||||
@echo "all: just the main afl++ binaries"
|
@echo "all: the main afl++ binaries and llvm/gcc instrumentation"
|
||||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
|
@echo "binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
|
||||||
@echo "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap"
|
@echo "source-only: everything for source code fuzzing: nyx_mode, libdislocator, libtokencap"
|
||||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||||
@echo "man: creates simple man pages from the help option of the programs"
|
@echo "man: creates simple man pages from the help option of the programs"
|
||||||
@echo "install: installs everything you have compiled with the build option above"
|
@echo "install: installs everything you have compiled with the build option above"
|
||||||
@ -365,14 +367,18 @@ help:
|
|||||||
@echo Known build environment options:
|
@echo Known build environment options:
|
||||||
@echo "=========================================="
|
@echo "=========================================="
|
||||||
@echo STATIC - compile AFL++ static
|
@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 DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||||
@echo PROFILING - compile afl-fuzz with profiling information
|
@echo PROFILING - compile afl-fuzz with profiling information
|
||||||
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
|
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
|
||||||
@echo NO_PYTHON - disable python support
|
@echo NO_PYTHON - disable python support
|
||||||
@echo NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
|
@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 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 "=========================================="
|
||||||
@echo e.g.: make ASAN_BUILD=1
|
@echo e.g.: make ASAN_BUILD=1
|
||||||
|
|
||||||
@ -384,7 +390,7 @@ test_x86:
|
|||||||
@echo "[*] Testing the PATH environment variable..."
|
@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; } || :
|
@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 "[*] 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
|
@rm -f .test1
|
||||||
else
|
else
|
||||||
test_x86:
|
test_x86:
|
||||||
@ -420,7 +426,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
|||||||
@ln -sf afl-as as
|
@ln -sf afl-as as
|
||||||
|
|
||||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
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
|
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
|
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
|
||||||
@ -528,7 +534,7 @@ code-format:
|
|||||||
ifndef AFL_NO_X86
|
ifndef AFL_NO_X86
|
||||||
test_build: afl-cc afl-gcc afl-as afl-showmap
|
test_build: afl-cc afl-gcc afl-as afl-showmap
|
||||||
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
|
@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
|
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
|
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||||
@rm -f test-instr
|
@rm -f test-instr
|
||||||
@ -564,24 +570,26 @@ all_done: test_build
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROGS) libradamsa.so 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-gcc-pass.so 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.llvm clean
|
||||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||||
$(MAKE) -C utils/libdislocator clean
|
-$(MAKE) -C utils/libdislocator clean
|
||||||
$(MAKE) -C utils/libtokencap 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/afl_network_proxy clean
|
||||||
$(MAKE) -C utils/socket_fuzzing clean
|
-$(MAKE) -C utils/socket_fuzzing clean
|
||||||
$(MAKE) -C utils/argv_fuzzing clean
|
-$(MAKE) -C utils/argv_fuzzing clean
|
||||||
-$(MAKE) -C utils/plot_ui clean
|
-$(MAKE) -C utils/plot_ui clean
|
||||||
$(MAKE) -C qemu_mode/unsigaction clean
|
-$(MAKE) -C qemu_mode/unsigaction clean
|
||||||
$(MAKE) -C qemu_mode/libcompcov clean
|
-$(MAKE) -C qemu_mode/libcompcov clean
|
||||||
$(MAKE) -C qemu_mode/libqasan clean
|
-$(MAKE) -C qemu_mode/libqasan clean
|
||||||
-$(MAKE) -C frida_mode clean
|
-$(MAKE) -C frida_mode clean
|
||||||
|
rm -rf nyx_mode/packer/linux_initramfs/init.cpio.gz nyx_mode/libnyx/libnyx/target/release/* nyx_mode/QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64
|
||||||
ifeq "$(IN_REPO)" "1"
|
ifeq "$(IN_REPO)" "1"
|
||||||
-test -e coresight_mode/coresight-trace/Makefile && $(MAKE) -C coresight_mode/coresight-trace clean || true
|
-test -e coresight_mode/coresight-trace/Makefile && $(MAKE) -C coresight_mode/coresight-trace clean || true
|
||||||
-test -e qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true
|
-test -e qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true
|
||||||
test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
-test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||||
|
-test -e nyx_mode/QEMU-Nyx/Makefile && $(MAKE) -C nyx_mode/QEMU-Nyx clean || true
|
||||||
else
|
else
|
||||||
rm -rf coresight_mode/coresight_trace
|
rm -rf coresight_mode/coresight_trace
|
||||||
rm -rf qemu_mode/qemuafl
|
rm -rf qemu_mode/qemuafl
|
||||||
@ -593,60 +601,94 @@ deepclean: clean
|
|||||||
rm -rf coresight_mode/coresight-trace
|
rm -rf coresight_mode/coresight-trace
|
||||||
rm -rf unicorn_mode/unicornafl
|
rm -rf unicorn_mode/unicornafl
|
||||||
rm -rf qemu_mode/qemuafl
|
rm -rf qemu_mode/qemuafl
|
||||||
|
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
|
||||||
ifeq "$(IN_REPO)" "1"
|
ifeq "$(IN_REPO)" "1"
|
||||||
# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true
|
|
||||||
git checkout coresight_mode/coresight-trace
|
git checkout coresight_mode/coresight-trace
|
||||||
git checkout unicorn_mode/unicornafl
|
git checkout unicorn_mode/unicornafl
|
||||||
git checkout qemu_mode/qemuafl
|
git checkout qemu_mode/qemuafl
|
||||||
|
git checkout nyx_mode/libnyx
|
||||||
|
git checkout nyx_mode/packer
|
||||||
|
git checkout nyx_mode/QEMU-Nyx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: distrib
|
.PHONY: distrib
|
||||||
distrib: all
|
distrib: all
|
||||||
-$(MAKE) -j4 -f GNUmakefile.llvm
|
-$(MAKE) -j$(nproc) -f GNUmakefile.llvm
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||||
endif
|
endif
|
||||||
$(MAKE) -C utils/libdislocator
|
-$(MAKE) -C utils/libdislocator
|
||||||
$(MAKE) -C utils/libtokencap
|
-$(MAKE) -C utils/libtokencap
|
||||||
$(MAKE) -C utils/afl_network_proxy
|
-$(MAKE) -C utils/afl_network_proxy
|
||||||
$(MAKE) -C utils/socket_fuzzing
|
-$(MAKE) -C utils/socket_fuzzing
|
||||||
$(MAKE) -C utils/argv_fuzzing
|
-$(MAKE) -C utils/argv_fuzzing
|
||||||
# -$(MAKE) -C utils/plot_ui
|
# -$(MAKE) -C utils/plot_ui
|
||||||
-$(MAKE) -C frida_mode
|
-$(MAKE) -C frida_mode
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
ifeq "$(ARCH)" "aarch64"
|
ifeq "$(ARCH)" "aarch64"
|
||||||
|
ifndef NO_CORESIGHT
|
||||||
-$(MAKE) -C coresight_mode
|
-$(MAKE) -C coresight_mode
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq "$(SYS)" "Linux"
|
||||||
|
ifndef NO_NYX
|
||||||
|
-cd nyx_mode && ./build_nyx_support.sh
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
-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
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: binary-only
|
.PHONY: binary-only
|
||||||
binary-only: test_shm test_python ready $(PROGS)
|
binary-only: test_shm test_python ready $(PROGS)
|
||||||
$(MAKE) -C utils/libdislocator
|
-$(MAKE) -C utils/libdislocator
|
||||||
$(MAKE) -C utils/libtokencap
|
-$(MAKE) -C utils/libtokencap
|
||||||
$(MAKE) -C utils/afl_network_proxy
|
-$(MAKE) -C utils/afl_network_proxy
|
||||||
$(MAKE) -C utils/socket_fuzzing
|
-$(MAKE) -C utils/socket_fuzzing
|
||||||
$(MAKE) -C utils/argv_fuzzing
|
-$(MAKE) -C utils/argv_fuzzing
|
||||||
# -$(MAKE) -C utils/plot_ui
|
# -$(MAKE) -C utils/plot_ui
|
||||||
-$(MAKE) -C frida_mode
|
-$(MAKE) -C frida_mode
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
ifeq "$(ARCH)" "aarch64"
|
ifeq "$(ARCH)" "aarch64"
|
||||||
|
ifndef NO_CORESIGHT
|
||||||
-$(MAKE) -C coresight_mode
|
-$(MAKE) -C coresight_mode
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq "$(SYS)" "Linux"
|
||||||
|
ifndef NO_NYX
|
||||||
|
-cd nyx_mode && ./build_nyx_support.sh
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
-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
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: source-only
|
.PHONY: source-only
|
||||||
source-only: all
|
source-only: all
|
||||||
-$(MAKE) -j4 -f GNUmakefile.llvm
|
-$(MAKE) -j$(nproc) -f GNUmakefile.llvm
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||||
endif
|
endif
|
||||||
$(MAKE) -C utils/libdislocator
|
-$(MAKE) -C utils/libdislocator
|
||||||
$(MAKE) -C utils/libtokencap
|
-$(MAKE) -C utils/libtokencap
|
||||||
# -$(MAKE) -C utils/plot_ui
|
# -$(MAKE) -C utils/plot_ui
|
||||||
|
ifeq "$(SYS)" "Linux"
|
||||||
|
ifndef NO_NYX
|
||||||
|
-cd nyx_mode && ./build_nyx_support.sh
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
%.8: %
|
%.8: %
|
||||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||||
@ -673,6 +715,7 @@ install: all $(MANPAGES)
|
|||||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
@rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
@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
|
@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)
|
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 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
|
@if [ -f utils/plot_ui/afl-plot-ui ]; then install -m 755 utils/plot_ui/afl-plot-ui $${DESTDIR}$(BIN_PATH); fi
|
||||||
@ -684,6 +727,7 @@ install: all $(MANPAGES)
|
|||||||
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
|
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
|
||||||
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
|
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
|
||||||
@if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
|
@if [ -f libnyx.so ]; then install -m 755 libnyx.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
|
@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
|
||||||
@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@ -706,7 +750,7 @@ endif
|
|||||||
.PHONY: uninstall
|
.PHONY: uninstall
|
||||||
uninstall:
|
uninstall:
|
||||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
|
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
|
||||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt
|
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt
|
||||||
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
|
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
|
||||||
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
||||||
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# from Laszlo Szekeres.
|
# from Laszlo Szekeres.
|
||||||
#
|
#
|
||||||
# Copyright 2015 Google Inc. All rights reserved.
|
# Copyright 2015 Google Inc. All rights reserved.
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -100,7 +100,9 @@ ifeq "$(SYS)" "SunOS"
|
|||||||
endif
|
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
|
.PHONY: all
|
||||||
all: test_shm test_deps $(PROGS) test_build all_done
|
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
|
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
|
||||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
@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
|
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
|
||||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
@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
|
./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
|
||||||
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
|
$(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-gcc-fast.8
|
||||||
ln -sf afl-cc.8 afl-g++-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
|
.PHONY: test_build
|
||||||
test_build: $(PROGS)
|
test_build: $(PROGS)
|
||||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
@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-c++ $${DESTDIR}$(BIN_PATH)/afl-g++-fast
|
||||||
ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
|
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-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
|
install -m 644 -T instrumentation/README.gcc_plugin.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
@ -46,7 +46,7 @@ LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's
|
|||||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
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_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_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_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[5-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_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_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_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]' && echo 1 || echo 0 )
|
||||||
@ -86,6 +86,12 @@ ifeq "$(LLVM_TOO_OLD)" "1"
|
|||||||
$(shell sleep 1)
|
$(shell sleep 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq "$(LLVM_MAJOR)" "15"
|
||||||
|
$(info [!] llvm_mode detected llvm 15, which is currently broken for LTO plugins.)
|
||||||
|
LLVM_LTO = 0
|
||||||
|
LLVM_HAVE_LTO = 0
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_HAVE_LTO)" "1"
|
ifeq "$(LLVM_HAVE_LTO)" "1"
|
||||||
$(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation)
|
$(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation)
|
||||||
LLVM_LTO = 1
|
LLVM_LTO = 1
|
||||||
@ -93,7 +99,7 @@ ifeq "$(LLVM_HAVE_LTO)" "1"
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_LTO)" "0"
|
ifeq "$(LLVM_LTO)" "0"
|
||||||
$(info [+] llvm_mode detected llvm < 11, afl-lto LTO will not be build.)
|
$(info [+] llvm_mode detected llvm < 11 or llvm 15, afl-lto LTO will not be build.)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||||
@ -394,7 +400,7 @@ endif
|
|||||||
|
|
||||||
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
|
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||||
ifeq "$(LLVM_10_OK)" "1"
|
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
|
endif
|
||||||
|
|
||||||
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
|
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
|
||||||
@ -407,7 +413,7 @@ ifeq "$(LLVM_LTO)" "1"
|
|||||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc
|
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
|
||||||
ifeq "$(LLVM_LTO)" "1"
|
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
|
$(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
|
$(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 +453,11 @@ document:
|
|||||||
|
|
||||||
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
|
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
|
||||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
@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
|
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
|
||||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
@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
|
.PHONY: test_build
|
||||||
test_build: $(PROGS)
|
test_build: $(PROGS)
|
||||||
@ -474,11 +480,11 @@ install: all
|
|||||||
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
@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
|
@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
|
@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-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-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-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); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o ; 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; 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 ./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
|
@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 +526,4 @@ endif
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
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
|
||||||
|
60
README.md
@ -1,20 +1,21 @@
|
|||||||
# American Fuzzy Lop plus plus (AFL++)
|
# American Fuzzy Lop plus plus (AFL++)
|
||||||
|
|
||||||
<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ logo">
|
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/master/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||||
|
|
||||||
Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
Release version: [4.02c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||||
|
|
||||||
GitHub version: 3.15a
|
GitHub version: 4.02c
|
||||||
|
|
||||||
Repository:
|
Repository:
|
||||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||||
|
|
||||||
AFL++ is maintained by:
|
AFL++ is maintained by:
|
||||||
|
|
||||||
* Marc "van Hauser" Heuse <mh@mh-sec.de>,
|
* Marc "van Hauser" Heuse <mh@mh-sec.de>
|
||||||
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>,
|
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
|
||||||
* Andrea Fioraldi <andreafioraldi@gmail.com> and
|
* Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
* Dominik Maier <mail@dmnk.co>.
|
* Dominik Maier <mail@dmnk.co>
|
||||||
|
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
|
||||||
|
|
||||||
Originally developed by Michał "lcamtuf" Zalewski.
|
Originally developed by Michał "lcamtuf" Zalewski.
|
||||||
|
|
||||||
@ -28,9 +29,14 @@ terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
|
|||||||
|
|
||||||
Here is some information to get you started:
|
Here is some information to get you started:
|
||||||
|
|
||||||
|
* For an overview of the AFL++ documentation and a very helpful graphical guide,
|
||||||
|
please visit [docs/README.md](docs/README.md).
|
||||||
|
* To get you started with tutorials, go to
|
||||||
|
[docs/tutorials.md](docs/tutorials.md).
|
||||||
* For releases, see the
|
* For releases, see the
|
||||||
[Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and
|
[Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and
|
||||||
[branches](#branches). Also take a look at the list of
|
[branches](#branches). The best branches to use are, however, `stable` or
|
||||||
|
`dev` - depending on your risk appetite. Also take a look at the list of
|
||||||
[important changes in AFL++](docs/important_changes.md) and the list of
|
[important changes in AFL++](docs/important_changes.md) and the list of
|
||||||
[features](docs/features.md).
|
[features](docs/features.md).
|
||||||
* If you want to use AFL++ for your academic work, check the
|
* If you want to use AFL++ for your academic work, check the
|
||||||
@ -40,24 +46,26 @@ Here is some information to get you started:
|
|||||||
`afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
|
`afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
|
||||||
default configuration on Google's
|
default configuration on Google's
|
||||||
[fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
[fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
||||||
* To get you started with tutorials, go to
|
|
||||||
[docs/tutorials.md](docs/tutorials.md).
|
|
||||||
|
|
||||||
## Building and installing AFL++
|
## Building and installing AFL++
|
||||||
|
|
||||||
To have AFL++ easily available with everything compiled, pull the image directly
|
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
|
```shell
|
||||||
docker pull aflplusplus/aflplusplus
|
docker pull aflplusplus/aflplusplus
|
||||||
docker run -ti -v /location/of/your/target:/src 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 published when a push to the stable branch happens
|
||||||
(see [branches](#branches)). You will find your target source code in `/src` in
|
(see [branches](#branches)). If you use the command above, you will find your
|
||||||
the container.
|
target source code in `/src` in the container.
|
||||||
|
|
||||||
To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md).
|
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++
|
## Quick start: Fuzzing with AFL++
|
||||||
|
|
||||||
@ -107,7 +115,7 @@ Step-by-step quick start:
|
|||||||
|
|
||||||
5. You will find found crashes and hangs in the subdirectories `crashes/` and
|
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
|
`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...]
|
cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]
|
||||||
@ -115,20 +123,24 @@ Step-by-step quick start:
|
|||||||
|
|
||||||
You can generate cores or use gdb directly to follow up the crashes.
|
You can generate cores or use gdb directly to follow up the crashes.
|
||||||
|
|
||||||
|
6. We cannot stress this enough - if you want to fuzz effectively, read the
|
||||||
|
[docs/fuzzing_in_depth.md](docs/fuzzing_in_depth.md) document!
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
Questions? Concerns? Bug reports?
|
Questions? Concerns? Bug reports?
|
||||||
|
|
||||||
* The contributors can be reached via
|
* The contributors can be reached via (e.g., by creating an issue):
|
||||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
|
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
|
||||||
* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important
|
* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important
|
||||||
question missing, submit it via
|
question missing, submit it via
|
||||||
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
||||||
* There is a mailing list for the AFL/AFL++ project
|
* Best: join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
|
||||||
|
* There is a (not really used) mailing list for the AFL/AFL++ project
|
||||||
([browse archive](https://groups.google.com/group/afl-users)). To compare
|
([browse archive](https://groups.google.com/group/afl-users)). To compare
|
||||||
notes with other users or to get notified about major new features, send an
|
notes with other users or to get notified about major new features, send an
|
||||||
email to <afl-users+subscribe@googlegroups.com>.
|
email to <afl-users+subscribe@googlegroups.com>, but note that this is not
|
||||||
* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
|
managed by us.
|
||||||
|
|
||||||
## Branches
|
## Branches
|
||||||
|
|
||||||
@ -141,7 +153,7 @@ The following branches exist:
|
|||||||
stability
|
stability
|
||||||
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state
|
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state
|
||||||
of AFL++ - bleeding edge and you might catch a checkout which does not compile
|
of AFL++ - bleeding edge and you might catch a checkout which does not compile
|
||||||
or has a bug. *We only accept PRs in dev!!*
|
or has a bug. **We only accept PRs (pull requests) for the 'dev' branch!**
|
||||||
* (any other): experimental branches to work on specific features or testing new
|
* (any other): experimental branches to work on specific features or testing new
|
||||||
functionality or changes.
|
functionality or changes.
|
||||||
|
|
||||||
@ -155,7 +167,7 @@ This can be your way to support and contribute to AFL++ - extend it to do
|
|||||||
something cool.
|
something cool.
|
||||||
|
|
||||||
For everyone who wants to contribute (and send pull requests), please read our
|
For everyone who wants to contribute (and send pull requests), please read our
|
||||||
[contributing guidelines](CONTRIBUTING.md) before your submit.
|
[contributing guidelines](CONTRIBUTING.md) before you submit.
|
||||||
|
|
||||||
## Special thanks
|
## Special thanks
|
||||||
|
|
||||||
@ -215,7 +227,7 @@ Thank you! (For people sending pull requests - please add yourself to this list
|
|||||||
Josephine Calliotte Konrad Welc
|
Josephine Calliotte Konrad Welc
|
||||||
Thomas Rooijakkers David Carlier
|
Thomas Rooijakkers David Carlier
|
||||||
Ruben ten Hove Joey Jiao
|
Ruben ten Hove Joey Jiao
|
||||||
fuzzah
|
fuzzah @intrigus-lgtm
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@ -243,4 +255,4 @@ presented at WOOT'20:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
6
TODO.md
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Should
|
## Should
|
||||||
|
|
||||||
|
- makefiles should show provide a build summary success/failure
|
||||||
|
- better documentation for custom mutators
|
||||||
- better autodetection of shifting runtime timeout values
|
- better autodetection of shifting runtime timeout values
|
||||||
- Update afl->pending_not_fuzzed for MOpt
|
- Update afl->pending_not_fuzzed for MOpt
|
||||||
- afl-plot to support multiple plot_data
|
- afl-plot to support multiple plot_data
|
||||||
@ -10,6 +12,8 @@
|
|||||||
|
|
||||||
## Maybe
|
## 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_fuzz_splice_optin()
|
||||||
- afl_custom_splice()
|
- afl_custom_splice()
|
||||||
- cmdline option from-to range for mutations
|
- cmdline option from-to range for mutations
|
||||||
@ -29,4 +33,4 @@ QEMU mode/FRIDA mode:
|
|||||||
using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow up
|
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
|
edge numbers that both following cmp paths have been found and then disable
|
||||||
working on this edge id -> cmplog_intelligence branch
|
working on this edge id -> cmplog_intelligence branch
|
||||||
- use cmplog colorization taint result for havoc locations?
|
- use cmplog colorization taint result for havoc locations?
|
||||||
|
16
afl-cmin
@ -135,6 +135,12 @@ function exists_and_is_executable(binarypath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
|
if (0 != system( "test -t 1")) {
|
||||||
|
redirected = 1
|
||||||
|
} else {
|
||||||
|
redirected = 0
|
||||||
|
}
|
||||||
|
|
||||||
print "corpus minimization tool for afl++ (awk version)\n"
|
print "corpus minimization tool for afl++ (awk version)\n"
|
||||||
|
|
||||||
# defaults
|
# defaults
|
||||||
@ -217,7 +223,7 @@ BEGIN {
|
|||||||
for (; Optind < ARGC; Optind++) {
|
for (; Optind < ARGC; Optind++) {
|
||||||
prog_args[i++] = ARGV[Optind]
|
prog_args[i++] = ARGV[Optind]
|
||||||
if (i > 1)
|
if (i > 1)
|
||||||
prog_args_string = prog_args_string" "ARGV[Optind]
|
prog_args_string = prog_args_string" '"ARGV[Optind]"'"
|
||||||
}
|
}
|
||||||
|
|
||||||
# sanity checks
|
# sanity checks
|
||||||
@ -463,7 +469,8 @@ BEGIN {
|
|||||||
while (cur < in_count) {
|
while (cur < in_count) {
|
||||||
fn = infilesSmallToBig[cur]
|
fn = infilesSmallToBig[cur]
|
||||||
++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
|
# create path for the trace file from afl-showmap
|
||||||
tracefile_path = trace_dir"/"fn
|
tracefile_path = trace_dir"/"fn
|
||||||
# gather all keys, and count them
|
# gather all keys, and count them
|
||||||
@ -502,7 +509,9 @@ BEGIN {
|
|||||||
key = field[nrFields]
|
key = field[nrFields]
|
||||||
|
|
||||||
++tcnt;
|
++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) {
|
if (key in keyAlreadyKnown) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -525,7 +534,6 @@ BEGIN {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(sortedKeys)
|
close(sortedKeys)
|
||||||
print ""
|
|
||||||
print "[+] Found "tuple_count" unique tuples across "in_count" files."
|
print "[+] Found "tuple_count" unique tuples across "in_count" files."
|
||||||
|
|
||||||
if (out_count == 1) {
|
if (out_count == 1) {
|
||||||
|
@ -76,6 +76,9 @@ EOF
|
|||||||
DONE=1
|
DONE=1
|
||||||
fi
|
fi
|
||||||
if [ "$PLATFORM" = "OpenBSD" ] ; then
|
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 'System security features cannot be disabled on OpenBSD.'
|
||||||
echo
|
echo
|
||||||
DONE=1
|
DONE=1
|
||||||
@ -115,7 +118,7 @@ if [ "$PLATFORM" = "Darwin" ] ; then
|
|||||||
sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1
|
sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1
|
||||||
echo
|
echo
|
||||||
fi
|
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
|
echo
|
||||||
DONE=1
|
DONE=1
|
||||||
fi
|
fi
|
||||||
|
38
afl-whatsup
@ -6,7 +6,7 @@
|
|||||||
# Originally written by Michal Zalewski
|
# Originally written by Michal Zalewski
|
||||||
#
|
#
|
||||||
# Copyright 2015 Google Inc. All rights reserved.
|
# Copyright 2015 Google Inc. All rights reserved.
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -91,9 +91,9 @@ TOTAL_CRASHES=0
|
|||||||
TOTAL_PFAV=0
|
TOTAL_PFAV=0
|
||||||
TOTAL_PENDING=0
|
TOTAL_PENDING=0
|
||||||
|
|
||||||
# Time since last path / crash / hang, formatted as string
|
# Time since last find / crash / hang, formatted as string
|
||||||
FMT_TIME="0 days 0 hours"
|
FMT_TIME="0 days 0 hours"
|
||||||
FMT_PATH="${RED}none seen yet${NC}"
|
FMT_FIND="${RED}none seen yet${NC}"
|
||||||
FMT_CRASH="none seen yet"
|
FMT_CRASH="none seen yet"
|
||||||
FMT_HANG="none seen yet"
|
FMT_HANG="none seen yet"
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ fmt_duration()
|
|||||||
|
|
||||||
FIRST=true
|
FIRST=true
|
||||||
TOTAL_WCOP=
|
TOTAL_WCOP=
|
||||||
TOTAL_LAST_PATH=0
|
TOTAL_LAST_FIND=0
|
||||||
|
|
||||||
for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
DEAD_CNT=$((DEAD_CNT + 1))
|
DEAD_CNT=$((DEAD_CNT + 1))
|
||||||
last_path=0
|
last_find=0
|
||||||
|
|
||||||
if [ "$PROCESS_DEAD" = "" ]; then
|
if [ "$PROCESS_DEAD" = "" ]; then
|
||||||
|
|
||||||
@ -183,17 +183,17 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
|
|
||||||
EXEC_SEC=0
|
EXEC_SEC=0
|
||||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||||
PATH_PERC=$((cur_path * 100 / paths_total))
|
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||||
|
|
||||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||||
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
||||||
TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes))
|
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
||||||
TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
|
TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
|
||||||
TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
|
TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
|
||||||
|
|
||||||
if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then
|
if [ "$last_find" -gt "$TOTAL_LAST_FIND" ]; then
|
||||||
TOTAL_LAST_PATH=$last_path
|
TOTAL_LAST_FIND=$last_find
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$SUMMARY_ONLY" = "" ]; then
|
if [ "$SUMMARY_ONLY" = "" ]; then
|
||||||
@ -210,7 +210,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
echo " ${RED}slow execution, $EXEC_SEC execs/sec${NC}"
|
echo " ${RED}slow execution, $EXEC_SEC execs/sec${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fmt_duration $last_path && FMT_PATH=$DUR_STRING
|
fmt_duration $last_find && FMT_FIND=$DUR_STRING
|
||||||
fmt_duration $last_crash && FMT_CRASH=$DUR_STRING
|
fmt_duration $last_crash && FMT_CRASH=$DUR_STRING
|
||||||
fmt_duration $last_hang && FMT_HANG=$DUR_STRING
|
fmt_duration $last_hang && FMT_HANG=$DUR_STRING
|
||||||
FMT_CWOP="not available"
|
FMT_CWOP="not available"
|
||||||
@ -220,7 +220,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
test "$cycles_wo_finds" -gt 50 && FMT_CWOP="${RED}$cycles_wo_finds${NC}"
|
test "$cycles_wo_finds" -gt 50 && FMT_CWOP="${RED}$cycles_wo_finds${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
echo " last_path : $FMT_PATH"
|
echo " last_find : $FMT_FIND"
|
||||||
echo " last_crash : $FMT_CRASH"
|
echo " last_crash : $FMT_CRASH"
|
||||||
echo " last_hang : $FMT_HANG"
|
echo " last_hang : $FMT_HANG"
|
||||||
echo " cycles_wo_finds : $FMT_CWOP"
|
echo " cycles_wo_finds : $FMT_CWOP"
|
||||||
@ -229,12 +229,12 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}')
|
MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}')
|
||||||
|
|
||||||
echo " cpu usage $CPU_USAGE%, memory usage $MEM_USAGE%"
|
echo " cpu usage $CPU_USAGE%, memory usage $MEM_USAGE%"
|
||||||
echo " cycle $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, path $cur_path/$paths_total (${PATH_PERC}%)"
|
echo " cycles $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, items $cur_item/$corpus_count (${PATH_PERC}%)"
|
||||||
|
|
||||||
if [ "$unique_crashes" = "0" ]; then
|
if [ "$saved_crashes" = "0" ]; then
|
||||||
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, no crashes yet"
|
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, no crashes yet"
|
||||||
else
|
else
|
||||||
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, crash count $unique_crashes (!)"
|
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, crashes saved $saved_crashes (!)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
@ -243,7 +243,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
|||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Formatting for total time, time since last path, crash, and hang
|
# Formatting for total time, time since last find, crash, and hang
|
||||||
fmt_duration $((CUR_TIME - TOTAL_TIME)) && FMT_TIME=$DUR_STRING
|
fmt_duration $((CUR_TIME - TOTAL_TIME)) && FMT_TIME=$DUR_STRING
|
||||||
# Formatting for total execution
|
# Formatting for total execution
|
||||||
FMT_EXECS="0 millions"
|
FMT_EXECS="0 millions"
|
||||||
@ -263,7 +263,7 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
|
|||||||
TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
|
TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
|
||||||
|
|
||||||
test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
|
test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
|
||||||
fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
|
fmt_duration $TOTAL_LAST_FIND && TOTAL_LAST_FIND=$DUR_STRING
|
||||||
|
|
||||||
test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
|
test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
|
||||||
|
|
||||||
@ -293,15 +293,15 @@ echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
|||||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||||
fi
|
fi
|
||||||
echo " Pending paths : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||||
|
|
||||||
if [ "$ALIVE_CNT" -gt "1" ]; then
|
if [ "$ALIVE_CNT" -gt "1" ]; then
|
||||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Crashes found : $TOTAL_CRASHES locally unique"
|
echo " Crashes saved : $TOTAL_CRASHES"
|
||||||
echo "Cycles without finds : $TOTAL_WCOP"
|
echo "Cycles without finds : $TOTAL_WCOP"
|
||||||
echo " Time without finds : $TOTAL_LAST_PATH"
|
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -54,7 +54,7 @@ $(GLIBC_LDSO): | $(GLIBC_NAME).tar.xz
|
|||||||
$(MAKE) install
|
$(MAKE) install
|
||||||
|
|
||||||
$(GLIBC_NAME).tar.xz:
|
$(GLIBC_NAME).tar.xz:
|
||||||
wget -O $@ $(GLIBC_URL_BASE)/$@
|
wget -qO $@ $(GLIBC_URL_BASE)/$@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C $(CS_TRACE) clean
|
$(MAKE) -C $(CS_TRACE) clean
|
||||||
|
@ -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)
|
* @return if the file contents was modified return 1 (True), 0 (False)
|
||||||
* otherwise
|
* 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_new_queue,
|
||||||
const uint8_t *filename_orig_queue) {
|
const uint8_t *filename_orig_queue) {
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "alloc-inl.h"
|
||||||
|
|
||||||
/* Header that must be present at the beginning of every test case: */
|
/* 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
|
/* 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
|
/* 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
|
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. */
|
if (len > strlen(HEADER))
|
||||||
|
memcpy(*out_buf + strlen(HEADER), in_buf + strlen(HEADER),
|
||||||
memcpy(*out_buf, in_buf, len);
|
len - strlen(HEADER));
|
||||||
|
|
||||||
/* Insert the new header. */
|
/* Insert the new header. */
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include "alloc-inl.h"
|
||||||
|
|
||||||
/* A macro to round an integer up to 4 kB. */
|
/* 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,
|
unsigned int len,
|
||||||
const unsigned char **out_buf) {
|
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
|
/* Don't do anything if there's not enough room for the PNG header
|
||||||
(8 bytes). */
|
(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
|
/* Minimum size of a zero-length PNG chunk is 12 bytes; if we
|
||||||
don't have that, we can bail out. */
|
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) {
|
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;
|
*(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
||||||
#
|
#
|
||||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -115,9 +115,9 @@ if [ $? -eq 0 ]; then
|
|||||||
git submodule update ./json-c 2>/dev/null # ignore errors
|
git submodule update ./json-c 2>/dev/null # ignore errors
|
||||||
else
|
else
|
||||||
echo "[*] cloning json-c"
|
echo "[*] cloning json-c"
|
||||||
test -d json-c || {
|
test -d json-c/.git || {
|
||||||
CNT=1
|
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)"
|
echo "Trying to clone json-c (attempt $CNT/3)"
|
||||||
git clone "$JSONC_REPO"
|
git clone "$JSONC_REPO"
|
||||||
CNT=`expr "$CNT" + 1`
|
CNT=`expr "$CNT" + 1`
|
||||||
@ -125,7 +125,7 @@ else
|
|||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test -d json-c || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
test -d json-c/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||||
echo "[+] Got json-c."
|
echo "[+] Got json-c."
|
||||||
|
|
||||||
test -e json-c/.libs/libjson-c.a || {
|
test -e json-c/.libs/libjson-c.a || {
|
||||||
|
@ -1 +1 @@
|
|||||||
eedf07d
|
ff4e5a2
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# <andreafioraldi@gmail.com>
|
# <andreafioraldi@gmail.com>
|
||||||
#
|
#
|
||||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -109,9 +109,9 @@ if [ $? -eq 0 ]; then
|
|||||||
git submodule update ./grammar_mutator 2>/dev/null # ignore errors
|
git submodule update ./grammar_mutator 2>/dev/null # ignore errors
|
||||||
else
|
else
|
||||||
echo "[*] cloning grammar mutator"
|
echo "[*] cloning grammar mutator"
|
||||||
test -d grammar_mutator || {
|
test -d grammar_mutator/.git || {
|
||||||
CNT=1
|
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)"
|
echo "Trying to clone grammar_mutator (attempt $CNT/3)"
|
||||||
git clone "$GRAMMAR_REPO"
|
git clone "$GRAMMAR_REPO"
|
||||||
CNT=`expr "$CNT" + 1`
|
CNT=`expr "$CNT" + 1`
|
||||||
@ -119,15 +119,16 @@ else
|
|||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test -d grammar_mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
test -f grammar_mutator/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||||
echo "[+] Got grammar mutator."
|
echo "[+] Got grammar mutator."
|
||||||
|
|
||||||
cd "grammar_mutator" || exit 1
|
cd "grammar_mutator" || exit 1
|
||||||
echo "[*] Checking out $GRAMMAR_VERSION"
|
echo "[*] Checking out $GRAMMAR_VERSION"
|
||||||
|
git pull >/dev/null 2>&1
|
||||||
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
||||||
git checkout "$GRAMMAR_VERSION" || exit 1
|
git checkout "$GRAMMAR_VERSION" || exit 1
|
||||||
echo "[*] Downloading antlr..."
|
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 ..
|
cd ..
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
10
custom_mutators/libafl_base/.gitignore
vendored
Normal 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
|
14
custom_mutators/libafl_base/Cargo.toml
Normal 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"]
|
9
custom_mutators/libafl_base/Makefile
Normal 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
|
11
custom_mutators/libafl_base/README.md
Normal 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 ...
|
||||||
|
```
|
238
custom_mutators/libafl_base/src/lib.rs
Normal 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);
|
@ -100,8 +100,8 @@ extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_c
|
|||||||
// Copy to a new buffer ( mutated_out )
|
// Copy to a new buffer ( mutated_out )
|
||||||
size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
|
size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
|
||||||
|
|
||||||
delete mutator->mutated_out;
|
delete[] mutator->mutated_out;
|
||||||
mutator->mutated_out = new uint8_t[mutated_size+1];
|
mutator->mutated_out = new uint8_t[mutated_size];
|
||||||
memcpy(mutator->mutated_out, s.c_str(), mutated_size); // copy the mutated data
|
memcpy(mutator->mutated_out, s.c_str(), mutated_size); // copy the mutated data
|
||||||
// Assign the mutated data and return mutated_size
|
// Assign the mutated data and return mutated_size
|
||||||
*out_buf = mutator->mutated_out;
|
*out_buf = mutator->mutated_out;
|
||||||
|
@ -4,4 +4,7 @@
|
|||||||
class MyMutator : public protobuf_mutator::Mutator {
|
class MyMutator : public protobuf_mutator::Mutator {
|
||||||
public:
|
public:
|
||||||
uint8_t *mutated_out = nullptr;
|
uint8_t *mutated_out = nullptr;
|
||||||
|
~MyMutator() {
|
||||||
|
delete[] mutated_out;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -4473,6 +4473,10 @@ static word prim_sys(word op, word a, word b, word c) {
|
|||||||
FD_CLOEXEC,
|
FD_CLOEXEC,
|
||||||
F_DUPFD,
|
F_DUPFD,
|
||||||
F_DUPFD_CLOEXEC,
|
F_DUPFD_CLOEXEC,
|
||||||
|
#if defined(F_DUP2FD)
|
||||||
|
F_DUP2FD,
|
||||||
|
F_DUP2FD_CLOEXEC,
|
||||||
|
#endif
|
||||||
F_GETFD,
|
F_GETFD,
|
||||||
F_SETFD,
|
F_SETFD,
|
||||||
F_GETFL,
|
F_GETFL,
|
||||||
|
@ -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.
|
/// 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.
|
/// It is not possible to call this macro multiple times, because it would define the custom mutator symbols multiple times.
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -381,23 +411,7 @@ pub mod wrappers {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! export_mutator {
|
macro_rules! export_mutator {
|
||||||
($mutator_type:ty) => {
|
($mutator_type:ty) => {
|
||||||
#[cfg(feature = "afl_internals")]
|
$crate::_define_afl_custom_init!($mutator_type);
|
||||||
#[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)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn afl_custom_fuzz_count(
|
pub unsafe extern "C" fn afl_custom_fuzz_count(
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
# custum mutator: symcc
|
# 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
|
To use this custom mutator follow the steps in the symcc repository
|
||||||
[https://github.com/eurecom-s3/symcc/](https://github.com/eurecom-s3/symcc/)
|
[https://github.com/eurecom-s3/symcc/](https://github.com/eurecom-s3/symcc/)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# AFL++ dictionaries
|
# AFL++ dictionaries
|
||||||
|
|
||||||
(See [../README.md](../README.md) for the general instruction manual.)
|
For the general instruction manual, see [docs/README.md](../docs/README.md).
|
||||||
|
|
||||||
This subdirectory contains a set of dictionaries that can be used in conjunction
|
This subdirectory contains a set of dictionaries that can be used in conjunction
|
||||||
with the -x option to allow the fuzzer to effortlessly explore the grammar of
|
with the -x option to allow the fuzzer to effortlessly explore the grammar of
|
||||||
|
@ -1,24 +1,87 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
This is the list of all noteworthy changes made in every public release of
|
This is the list of all noteworthy changes made in every public
|
||||||
the tool. See README.md for the general instruction manual.
|
release of the tool. See README.md for the general instruction manual.
|
||||||
|
|
||||||
## Staying informed
|
## Staying informed
|
||||||
|
|
||||||
Want to stay in the loop on major new features? Join our mailing list by
|
Want to stay in the loop on major new features? Join our mailing list by
|
||||||
sending a mail to <afl-users+subscribe@googlegroups.com>.
|
sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||||
|
|
||||||
### Version ++3.15a (dev)
|
### Version ++4.02c (release)
|
||||||
- documentation restructuring, made possible by Google Season of Docs
|
- 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
|
||||||
|
of Docs :) thank you Jana!
|
||||||
- we renamed several UI and fuzzer_stat entries to be more precise,
|
- we renamed several UI and fuzzer_stat entries to be more precise,
|
||||||
e.g. "unique crashes" -> "saved crashes", "total paths" ->
|
e.g. "unique crashes" -> "saved crashes", "total paths" ->
|
||||||
"corpus count", "current path" -> "current item".
|
"corpus count", "current path" -> "current item".
|
||||||
This might need changing custom scripting!
|
This might need changing custom scripting!
|
||||||
|
- Nyx mode (full system emulation with snapshot capability) has been
|
||||||
|
added - thanks to @schumilo and @eqv!
|
||||||
|
- unicorn_mode:
|
||||||
|
- Moved to unicorn2! by Ziqiao Kong (@lazymio)
|
||||||
|
- Faster, more accurate emulation (newer QEMU base), risc-v support
|
||||||
|
- removed indirections in rust callbacks
|
||||||
- new binary-only fuzzing mode: coresight_mode for aarch64 CPUs :)
|
- new binary-only fuzzing mode: coresight_mode for aarch64 CPUs :)
|
||||||
thanks to RICSecLab submitting!
|
thanks to RICSecLab submitting!
|
||||||
- if instrumented libaries are dlopen()'ed after the forkserver you
|
- if instrumented libaries are dlopen()'ed after the forkserver you
|
||||||
will now see crashes. before you would have colliding coverage.
|
will now see a crash. Before you would have colliding coverage.
|
||||||
we changed this to force fixing a broken setup rather then allowing
|
We changed this to force fixing a broken setup rather then allowing
|
||||||
ineffective fuzzing.
|
ineffective fuzzing.
|
||||||
See docs/best_practices.md how to fix such setups.
|
See docs/best_practices.md how to fix such setups.
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
@ -26,14 +89,17 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
(it is better!)
|
(it is better!)
|
||||||
- fix a regression introduced in 3.10 that resulted in less
|
- fix a regression introduced in 3.10 that resulted in less
|
||||||
coverage being detected. thanks to Collin May for reporting!
|
coverage being detected. thanks to Collin May for reporting!
|
||||||
|
- ensure all spawned targets are killed on exit
|
||||||
- added AFL_IGNORE_PROBLEMS, plus checks to identify and abort on
|
- added AFL_IGNORE_PROBLEMS, plus checks to identify and abort on
|
||||||
incorrect LTO usage setups and enhanced the READMEs for better
|
incorrect LTO usage setups and enhanced the READMEs for better
|
||||||
information on how to deal with instrumenting libraries
|
information on how to deal with instrumenting libraries
|
||||||
- fix -n dumb mode (nobody should use this)
|
- fix -n dumb mode (nobody should use this mode though)
|
||||||
- fix stability issue with LTO and cmplog
|
- fix stability issue with LTO and cmplog
|
||||||
- better banner
|
- better banner
|
||||||
- more effective cmplog mode
|
- more effective cmplog mode
|
||||||
- more often update the UI when in input2stage mode
|
- more often update the UI when in input2stage mode
|
||||||
|
- qemu_mode/unicorn_mode: fixed OOB write when using libcompcov,
|
||||||
|
thanks to kotee4ko for reporting!
|
||||||
- frida_mode:
|
- frida_mode:
|
||||||
- better performance, bug fixes
|
- better performance, bug fixes
|
||||||
- David Carlier added Android support :)
|
- David Carlier added Android support :)
|
||||||
@ -43,16 +109,22 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- fix bug where targets are not killed on timeouts
|
- fix bug where targets are not killed on timeouts
|
||||||
- moved hidden afl-showmap -A option to -H to be used for
|
- moved hidden afl-showmap -A option to -H to be used for
|
||||||
coresight_mode
|
coresight_mode
|
||||||
- Prevent accidently killing non-afl/fuzz services when aborting
|
- Prevent accidentally killing non-afl/fuzz services when aborting
|
||||||
afl-showmap and other tools.
|
afl-showmap and other tools.
|
||||||
- afl-cc:
|
- afl-cc:
|
||||||
|
- detect overflow reads on initial input buffer for asan
|
||||||
- new cmplog mode (incompatible with older afl++ versions)
|
- new cmplog mode (incompatible with older afl++ versions)
|
||||||
- support llvm IR select instrumentation for default PCGUARD and LTO
|
- support llvm IR select instrumentation for default PCGUARD and LTO
|
||||||
- fix for shared linking on MacOS
|
- fix for shared linking on MacOS
|
||||||
|
- better selective instrumentation AFL_LLVM_{ALLOW|DENY}LIST
|
||||||
|
on filename matching (requires llvm 11 or newer)
|
||||||
- fixed a potential crash in targets for LAF string handling
|
- fixed a potential crash in targets for LAF string handling
|
||||||
|
- fixed a bad assert in LAF split switches
|
||||||
- added AFL_USE_TSAN thread sanitizer support
|
- added AFL_USE_TSAN thread sanitizer support
|
||||||
- llvm and LTO mode modified to work with new llvm 14-dev (again. again.)
|
- llvm and LTO mode modified to work with new llvm 14-dev (again.)
|
||||||
- fix for AFL_REAL_LD
|
- fix for AFL_REAL_LD
|
||||||
|
- more -z defs filtering
|
||||||
|
- make -v without options work
|
||||||
- added the very good grammar mutator "GramaTron" to the
|
- added the very good grammar mutator "GramaTron" to the
|
||||||
custom_mutators
|
custom_mutators
|
||||||
- added optimin, a faster and better corpus minimizer by
|
- added optimin, a faster and better corpus minimizer by
|
||||||
@ -60,11 +132,10 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- added afl-persistent-config script to set perform permanent system
|
- added afl-persistent-config script to set perform permanent system
|
||||||
configuration settings for fuzzing, for Linux and Macos.
|
configuration settings for fuzzing, for Linux and Macos.
|
||||||
thanks to jhertz!
|
thanks to jhertz!
|
||||||
- added xml, curl and exotic string functions to llvm dictionary features
|
- added xml, curl & exotic string functions to llvm dictionary feature
|
||||||
- fix AFL_PRELOAD issues on MacOS
|
- fix AFL_PRELOAD issues on MacOS
|
||||||
- removed utils/afl_frida because frida_mode/ is now so much better
|
- removed utils/afl_frida because frida_mode/ is now so much better
|
||||||
- added uninstall target to makefile (todo: update new readme!)
|
- added uninstall target to makefile (todo: update new readme!)
|
||||||
- removed indirections in rust callbacks for unicornafl
|
|
||||||
|
|
||||||
### Version ++3.14c (release)
|
### Version ++3.14c (release)
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
@ -84,7 +155,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- Fix to instrument global namespace functions in c++
|
- Fix to instrument global namespace functions in c++
|
||||||
- Fix for llvm 13
|
- Fix for llvm 13
|
||||||
- support partial linking
|
- support partial linking
|
||||||
- do honor AFL_LLVM_{ALLOW/DENY}LIST for LTO autodictionary and DICT2FILE
|
- do honor AFL_LLVM_{ALLOW/DENY}LIST for LTO autodictionary andDICT2FILE
|
||||||
- We do support llvm versions from 3.8 to 5.0 again
|
- We do support llvm versions from 3.8 to 5.0 again
|
||||||
- frida_mode:
|
- frida_mode:
|
||||||
- several fixes for cmplog
|
- several fixes for cmplog
|
||||||
|
60
docs/FAQ.md
@ -58,10 +58,10 @@ If you find an interesting or important question missing, submit it via
|
|||||||
|
|
||||||
A program contains `functions`, `functions` contain the compiled machine code.
|
A program contains `functions`, `functions` contain the compiled machine code.
|
||||||
The compiled machine code in a `function` can be in a single or many `basic
|
The compiled machine code in a `function` can be in a single or many `basic
|
||||||
blocks`. A `basic block` is the largest possible number of subsequent machine
|
blocks`. A `basic block` is the **largest possible number of subsequent machine
|
||||||
code instructions that has exactly one entry point (which can be be entered by
|
code instructions** that has **exactly one entry point** (which can be be entered by
|
||||||
multiple other basic blocks) and runs linearly without branching or jumping to
|
multiple other basic blocks) and runs linearly **without branching or jumping to
|
||||||
other addresses (except at the end).
|
other addresses** (except at the end).
|
||||||
|
|
||||||
```
|
```
|
||||||
function() {
|
function() {
|
||||||
@ -180,8 +180,58 @@ If you find an interesting or important question missing, submit it via
|
|||||||
[best_practices.md#improving-stability](best_practices.md#improving-stability).
|
[best_practices.md#improving-stability](best_practices.md#improving-stability).
|
||||||
</p></details>
|
</p></details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary id="what-are-power-schedules">What are power schedules?</summary><p>
|
||||||
|
|
||||||
|
Not every item in our queue/corpus is the same, some are more interesting,
|
||||||
|
others provide little value.
|
||||||
|
A power schedule measures how "interesting" a value is, and depending on
|
||||||
|
the calculated value spends more or less time mutating it.
|
||||||
|
|
||||||
|
AFL++ comes with several power schedules, initially ported from
|
||||||
|
[AFLFast](https://github.com/mboehme/aflfast), however, modified to be more
|
||||||
|
effective and several more modes added.
|
||||||
|
|
||||||
|
The most effective modes are `-p fast` (default) and `-p explore`.
|
||||||
|
|
||||||
|
If you fuzz with several parallel afl-fuzz instances, then it is beneficial
|
||||||
|
to assign a different schedule to each instance, however the majority should
|
||||||
|
be `fast` and `explore`.
|
||||||
|
|
||||||
|
It does not make sense to explain the details of the calculation and
|
||||||
|
reasoning behind all of the schedules. If you are interested, read the source
|
||||||
|
code and the AFLFast paper.
|
||||||
|
</p></details>
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary id="fatal-forkserver-is-already-up-but-an-instrumented-dlopen-library-loaded-afterwards">FATAL: forkserver is already up but an instrumented dlopen library loaded afterwards</summary><p>
|
||||||
|
|
||||||
|
It can happen that you see this error on startup when fuzzing a target:
|
||||||
|
|
||||||
|
```
|
||||||
|
[-] FATAL: forkserver is already up, but an instrumented dlopen() library
|
||||||
|
loaded afterwards. You must AFL_PRELOAD such libraries to be able
|
||||||
|
to fuzz them or LD_PRELOAD to run outside of afl-fuzz.
|
||||||
|
To ignore this set AFL_IGNORE_PROBLEMS=1.
|
||||||
|
```
|
||||||
|
|
||||||
|
As the error describes, a dlopen() call is happening in the target that is
|
||||||
|
loading an instrumented library after the forkserver is already in place. This
|
||||||
|
is a problem for afl-fuzz because when the forkserver is started, we must know
|
||||||
|
the map size already and it can't be changed later.
|
||||||
|
|
||||||
|
The best solution is to simply set `AFL_PRELOAD=foo.so` to the libraries that
|
||||||
|
are dlopen'ed (e.g., use `strace` to see which), or to set a manual forkserver
|
||||||
|
after the final dlopen().
|
||||||
|
|
||||||
|
If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then
|
||||||
|
the existing map will be used also for the newly loaded libraries, which
|
||||||
|
allows it to work, however, the efficiency of the fuzzing will be partially
|
||||||
|
degraded.
|
||||||
|
</p></details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary id="i-got-a-weird-compile-error-from-clang">I got a weird compile error from clang.</summary><p>
|
<summary id="i-got-a-weird-compile-error-from-clang">I got a weird compile error from clang.</summary><p>
|
||||||
|
|
||||||
@ -204,4 +254,4 @@ If you find an interesting or important question missing, submit it via
|
|||||||
package and because of that the AFL++ llvm plugins do not match anymore.
|
package and because of that the AFL++ llvm plugins do not match anymore.
|
||||||
|
|
||||||
Solution: `git pull ; make clean install` of AFL++.
|
Solution: `git pull ; make clean install` of AFL++.
|
||||||
</p></details>
|
</p></details>
|
||||||
|
@ -3,26 +3,33 @@
|
|||||||
## Linux on x86
|
## Linux on x86
|
||||||
|
|
||||||
An easy way to install AFL++ with everything compiled is available via docker:
|
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 -
|
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:
|
hence afl-clang-lto is available) or just pull directly from the Docker Hub
|
||||||
|
(for x86_64 and arm64):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker pull aflplusplus/aflplusplus
|
docker pull aflplusplus/aflplusplus:
|
||||||
docker run -ti -v /location/of/your/target:/src 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.
|
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
|
If you want to build AFL++ yourself, you have many options. The easiest choice
|
||||||
is to build and install everything:
|
is to build and install everything:
|
||||||
|
|
||||||
|
NOTE: depending on your Debian/Ubuntu/Kali/... version release `-12` with
|
||||||
|
whatever llvm version is available!
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apt-get update
|
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
|
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 11 and install the distro default if that fails
|
# try to install llvm 12 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 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 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
|
sudo apt-get install -y ninja-build # for QEMU mode
|
||||||
git clone https://github.com/AFLplusplus/AFLplusplus
|
git clone https://github.com/AFLplusplus/AFLplusplus
|
||||||
cd AFLplusplus
|
cd AFLplusplus
|
||||||
@ -33,10 +40,10 @@ sudo make install
|
|||||||
It is recommended to install the newest available gcc, clang and llvm-dev
|
It is recommended to install the newest available gcc, clang and llvm-dev
|
||||||
possible in your distribution!
|
possible in your distribution!
|
||||||
|
|
||||||
Note that "make distrib" also builds instrumentation, QEMU mode, unicorn_mode
|
Note that `make distrib` also builds FRIDA mode, QEMU mode, unicorn_mode, and
|
||||||
and more. If you just want plain AFL++, then do "make all". However, compiling
|
more. If you just want plain AFL++, then do `make all`. If you want some
|
||||||
and using at least instrumentation is highly recommended for much better results
|
assisting tooling compiled but are not interested in binary-only targets, then
|
||||||
- hence in this case choose:
|
instead choose:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
make source-only
|
make source-only
|
||||||
@ -44,11 +51,12 @@ make source-only
|
|||||||
|
|
||||||
These build targets exist:
|
These build targets exist:
|
||||||
|
|
||||||
* all: just the main AFL++ binaries
|
* all: the main afl++ binaries and llvm/gcc instrumentation
|
||||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode,
|
* binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode,
|
||||||
libdislocator, libtokencap
|
qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator,
|
||||||
* source-only: everything for source code fuzzing: instrumentation,
|
libtokencap
|
||||||
libdislocator, libtokencap
|
* source-only: everything for source code fuzzing: nyx_mode, libdislocator,
|
||||||
|
libtokencap
|
||||||
* distrib: everything (for both binary-only and source code fuzzing)
|
* distrib: everything (for both binary-only and source code fuzzing)
|
||||||
* man: creates simple man pages from the help option of the programs
|
* man: creates simple man pages from the help option of the programs
|
||||||
* install: installs everything you have compiled with the build options above
|
* install: installs everything you have compiled with the build options above
|
||||||
@ -71,47 +79,59 @@ make STATIC=1
|
|||||||
These build options exist:
|
These build options exist:
|
||||||
|
|
||||||
* STATIC - compile AFL++ static
|
* 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
|
* 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
|
* INTROSPECTION - compile afl-fuzz with mutation introspection
|
||||||
* NO_PYTHON - disable python support
|
* NO_PYTHON - disable python support
|
||||||
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for
|
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for
|
||||||
normal fuzzing
|
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
|
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||||
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config
|
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config
|
||||||
(e.g., Debian)
|
(e.g., Debian)
|
||||||
|
|
||||||
e.g.: `make ASAN_BUILD=1`
|
e.g.: `make LLVM_CONFIG=llvm-config-14`
|
||||||
|
|
||||||
## MacOS X on x86 and arm64 (M1)
|
## MacOS X on x86 and arm64 (M1)
|
||||||
|
|
||||||
MacOS X should work, but there are some gotchas due to the idiosyncrasies of the
|
MacOS has some gotchas due to the idiosyncrasies of the platform.
|
||||||
platform. On top of this, we have limited release testing capabilities and
|
|
||||||
depend mostly on user feedback.
|
|
||||||
|
|
||||||
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
||||||
instructions for Linux. If possible, avoid Xcode at all cost.
|
instructions for Linux. If possible, avoid Xcode at all cost.
|
||||||
|
|
||||||
`brew install wget git make cmake llvm gdb`
|
```shell
|
||||||
|
brew install wget git make cmake llvm gdb coreutils
|
||||||
|
```
|
||||||
|
|
||||||
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
||||||
freshly installed clang, clang++ and gmake, e.g.:
|
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
|
||||||
|
|
||||||
```
|
```shell
|
||||||
export PATH="/usr/local/Cellar/llvm/12.0.1/bin/:$PATH"
|
# Depending on your MacOS system + brew version it is either
|
||||||
|
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||||
|
# or
|
||||||
|
export PATH="/usr/local/opt/llvm/bin:$PATH"
|
||||||
|
# you can check with "brew info llvm"
|
||||||
|
|
||||||
|
export PATH="/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:$PATH"
|
||||||
export CC=clang
|
export CC=clang
|
||||||
export CXX=clang++
|
export CXX=clang++
|
||||||
gmake
|
gmake
|
||||||
cd frida_mode
|
cd frida_mode
|
||||||
gmake
|
gmake
|
||||||
cd ..
|
cd ..
|
||||||
gmake install
|
sudo gmake install
|
||||||
```
|
```
|
||||||
|
|
||||||
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
||||||
instrumentation anyway. You don't want that. Note that `afl-clang-lto`,
|
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
|
||||||
`afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
|
||||||
|
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
||||||
|
|
||||||
The crash reporting daemon that comes by default with MacOS X will cause
|
The crash reporting daemon that comes by default with MacOS X will cause
|
||||||
problems with fuzzing. You need to turn it off:
|
problems with fuzzing. You need to turn it off:
|
||||||
@ -132,8 +152,8 @@ and definitely don't look POSIX-compliant. This means two things:
|
|||||||
environment before starting afl-fuzz.
|
environment before starting afl-fuzz.
|
||||||
|
|
||||||
User emulation mode of QEMU does not appear to be supported on MacOS X, so
|
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`)
|
||||||
should work on x86 and arm64 MacOS boxes.
|
works on both x86 and arm64 MacOS boxes.
|
||||||
|
|
||||||
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
|
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
|
||||||
default settings aren't usable with AFL++. The default settings on 10.14 seem to
|
default settings aren't usable with AFL++. The default settings on 10.14 seem to
|
||||||
@ -169,4 +189,4 @@ sysctl kern.sysv.shmall=98304
|
|||||||
|
|
||||||
See
|
See
|
||||||
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||||
for documentation for these settings and how to make them permanent.
|
for documentation for these settings and how to make them permanent.
|
||||||
|
65
docs/README.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# AFL++ documentation
|
||||||
|
|
||||||
|
This is the overview of the AFL++ docs content.
|
||||||
|
|
||||||
|
For general information on AFL++, see the
|
||||||
|
[README.md of the repository](../README.md).
|
||||||
|
|
||||||
|
Also take a look at our [FAQ.md](FAQ.md) and
|
||||||
|
[best_practices.md](best_practices.md).
|
||||||
|
|
||||||
|
## Fuzzing targets with the source code available
|
||||||
|
|
||||||
|
You can find a quickstart for fuzzing targets with the source code available in
|
||||||
|
the [README.md of the repository](../README.md#quick-start-fuzzing-with-afl).
|
||||||
|
|
||||||
|
For in-depth information on the steps of the fuzzing process, see
|
||||||
|
[fuzzing_in_depth.md](fuzzing_in_depth.md) or click on the following
|
||||||
|
image and select a step.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
For further information on instrumentation, see the
|
||||||
|
[READMEs in the instrumentation/ folder](../instrumentation/).
|
||||||
|
|
||||||
|
### Instrumenting the target
|
||||||
|
|
||||||
|
For more information, click on the following image and select a step.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Preparing the fuzzing campaign
|
||||||
|
|
||||||
|
For more information, click on the following image and select a step.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Fuzzing the target
|
||||||
|
|
||||||
|
For more information, click on the following image and select a step.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Managing the fuzzing campaign
|
||||||
|
|
||||||
|
For more information, click on the following image and select a step.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Fuzzing other targets
|
||||||
|
|
||||||
|
To learn about fuzzing other targets, see:
|
||||||
|
|
||||||
|
* Binary-only: [fuzzing_binary-only_targets.md](fuzzing_binary-only_targets.md)
|
||||||
|
* GUI programs:
|
||||||
|
[best_practices.md#fuzzing-a-gui-program](best_practices.md#fuzzing-a-gui-program)
|
||||||
|
* Libraries: [frida_mode/README.md](../frida_mode/README.md)
|
||||||
|
* Network services:
|
||||||
|
[best_practices.md#fuzzing-a-network-service](best_practices.md#fuzzing-a-network-service)
|
||||||
|
* Non-linux: [unicorn_mode/README.md](../unicorn_mode/README.md)
|
||||||
|
|
||||||
|
## Additional information
|
||||||
|
|
||||||
|
* Tools that help fuzzing with AFL++:
|
||||||
|
[third_party_tools.md](third_party_tools.md)
|
||||||
|
* Tutorials: [tutorials.md](tutorials.md)
|
@ -40,7 +40,7 @@ superior to blind fuzzing or coverage-only tools.
|
|||||||
This section provides an overview of the status screen - plus tips for
|
This section provides an overview of the status screen - plus tips for
|
||||||
troubleshooting any warnings and red text shown in the UI.
|
troubleshooting any warnings and red text shown in the UI.
|
||||||
|
|
||||||
For the general instruction manual, see [README.md](../README.md).
|
For the general instruction manual, see [README.md](README.md).
|
||||||
|
|
||||||
### A note about colors
|
### A note about colors
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ allows you to define network state with different type of data packets.
|
|||||||
|
|
||||||
### Improving stability
|
### Improving stability
|
||||||
|
|
||||||
For fuzzing a 100% stable target that covers all edges is the best case. A 90%
|
For fuzzing, a 100% stable target that covers all edges is the best case. A 90%
|
||||||
stable target that covers all edges is, however, better than a 100% stable
|
stable target that covers all edges is, however, better than a 100% stable
|
||||||
target that ignores 10% of the edges.
|
target that ignores 10% of the edges.
|
||||||
|
|
||||||
@ -189,4 +189,4 @@ coding and/or disassembly and is effectively possible only with `afl-clang-fast`
|
|||||||
Recompile, fuzz it, be happy :)
|
Recompile, fuzz it, be happy :)
|
||||||
|
|
||||||
This link explains this process for
|
This link explains this process for
|
||||||
[Fuzzbench](https://github.com/google/fuzzbench/issues/677).
|
[Fuzzbench](https://github.com/google/fuzzbench/issues/677).
|
||||||
|
@ -38,6 +38,11 @@ performed with the custom mutator.
|
|||||||
|
|
||||||
## 2) APIs
|
## 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/C++:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
@ -159,6 +164,10 @@ def deinit(): # optional for Python
|
|||||||
This can return any python object that implements the buffer protocol and
|
This can return any python object that implements the buffer protocol and
|
||||||
supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
|
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):
|
- `queue_new_entry` (optional):
|
||||||
|
|
||||||
This methods is called after adding a new test case to the queue. If the
|
This methods is called after adding a new test case to the queue. If the
|
||||||
|
122
docs/docs.md
@ -1,122 +0,0 @@
|
|||||||
# Restructure AFL++'s documentation
|
|
||||||
|
|
||||||
## About us
|
|
||||||
|
|
||||||
We are dedicated to everything around fuzzing, our main and most well known
|
|
||||||
contribution is the fuzzer `AFL++` which is part of all major Unix
|
|
||||||
distributions (e.g. Debian, Arch, FreeBSD, etc.) and is deployed on Google's
|
|
||||||
oss-fuzz and clusterfuzz. It is rated the top fuzzer on Google's fuzzbench.
|
|
||||||
|
|
||||||
We are four individuals from Europe supported by a large community.
|
|
||||||
|
|
||||||
All our tools are open source.
|
|
||||||
|
|
||||||
## About the AFL++ fuzzer project
|
|
||||||
|
|
||||||
AFL++ inherited it's documentation from the original Google AFL project.
|
|
||||||
Since then it has been massively improved - feature and performance wise -
|
|
||||||
and although the documenation has likewise been continued it has grown out
|
|
||||||
of proportion.
|
|
||||||
The documentation is done by non-natives to the English language, plus
|
|
||||||
none of us has a writer background.
|
|
||||||
|
|
||||||
We see questions on AFL++ usage on mailing lists (e.g. afl-users), discord
|
|
||||||
channels, web forums and as issues in our repository.
|
|
||||||
|
|
||||||
This only increases as AFL++ has been on the top of Google's fuzzbench
|
|
||||||
statistics (which measures the performance of fuzzers) and is now being
|
|
||||||
integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix
|
|
||||||
packaging repositories, e.g. Debian, FreeBSD, etc.
|
|
||||||
|
|
||||||
AFL++ now has 44 (!) documentation files with 13k total lines of content.
|
|
||||||
This is way too much.
|
|
||||||
|
|
||||||
Hence AFL++ needs a complete overhaul of it's documentation, both on a
|
|
||||||
organisation/structural level as well as the content.
|
|
||||||
|
|
||||||
Overall the following actions have to be performed:
|
|
||||||
* Create a better structure of documentation so it is easier to find the
|
|
||||||
information that is being looked for, combining and/or splitting up the
|
|
||||||
existing documents as needed.
|
|
||||||
* Rewrite some documentation to remove duplication. Several information is
|
|
||||||
present several times in the documentation. These should be removed to
|
|
||||||
where needed so that we have as little bloat as possible.
|
|
||||||
* The documents have been written and modified by a lot of different people,
|
|
||||||
most of them non-native English speaker. Hence an overall review where
|
|
||||||
parts should be rewritten has to be performed and then the rewrite done.
|
|
||||||
* Create a cheat-sheet for a very short best-setup build and run of AFL++
|
|
||||||
* Pictures explain more than 1000 words. We need at least 4 images that
|
|
||||||
explain the workflow with AFL++:
|
|
||||||
- the build workflow
|
|
||||||
- the fuzzing workflow
|
|
||||||
- the fuzzing campaign management workflow
|
|
||||||
- the overall workflow that is an overview of the above
|
|
||||||
- maybe more? where the technical writes seems it necessary for
|
|
||||||
understanding.
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
* Documentation has to be in Markdown format
|
|
||||||
* Images have to be either in SVG or PNG format.
|
|
||||||
* All documentation should be (moved) in(to) docs/
|
|
||||||
|
|
||||||
The project does not require writing new documentation or tutorials beside the
|
|
||||||
cheat sheet. The technical information for the cheat sheet will be provided by
|
|
||||||
us.
|
|
||||||
|
|
||||||
## Metrics
|
|
||||||
|
|
||||||
AFL++ is a the highest performant fuzzer publicly available - but is also the
|
|
||||||
most feature rich and complex. With the publicity of AFL++' success and
|
|
||||||
deployment in Google projects internally and externally and availability as
|
|
||||||
a package on most Linux distributions we see more and more issues being
|
|
||||||
created and help requests on our Discord channel that would not be
|
|
||||||
necessary if people would have read through all our documentation - which
|
|
||||||
is unrealistic.
|
|
||||||
|
|
||||||
We expect the the new documenation after this project to be cleaner, easier
|
|
||||||
accessible and lighter to digest by our users, resulting in much less
|
|
||||||
help requests. On the other hand the amount of users using AFL++ should
|
|
||||||
increase as well as it will be more accessible which would also increase
|
|
||||||
questions again - but overall resulting in a reduction of help requests.
|
|
||||||
|
|
||||||
In numbers: we currently have per week on average 5 issues on Github,
|
|
||||||
10 questions on discord and 1 on mailing lists that would not be necessary
|
|
||||||
with perfect documentation and perfect people.
|
|
||||||
|
|
||||||
We would consider this project a success if afterwards we only have
|
|
||||||
2 issues on Github and 3 questions on discord anymore that would be answered
|
|
||||||
by reading the documentation. The mailing list is usually used by the most
|
|
||||||
novice users and we don't expect any less questions there.
|
|
||||||
|
|
||||||
## Project Budget
|
|
||||||
|
|
||||||
We have zero experience with technical writers, so this is very hard for us
|
|
||||||
to calculate. We expect it to be a lot of work though because of the amount
|
|
||||||
of documentation we have that needs to be restructured and partially rewritten
|
|
||||||
(44 documents with 13k total lines of content).
|
|
||||||
|
|
||||||
We assume the daily rate of a very good and experienced technical writer in
|
|
||||||
times of a pandemic to be ~500$ (according to web research), and calculate
|
|
||||||
the overall amout of work to be around 20 days for everything incl. the
|
|
||||||
graphics (but again - this is basically just guessing).
|
|
||||||
|
|
||||||
Technical Writer 10000$
|
|
||||||
Volunteer stipends 0$ (waved)
|
|
||||||
T-Shirts for the top 10 contributors and helpers to this documentation project:
|
|
||||||
10 AFL++ logo t-shirts 20$ each 200$
|
|
||||||
10 shipping cost of t-shirts 10$ each 100$
|
|
||||||
|
|
||||||
Total: 10.300$
|
|
||||||
(in the submission form 10.280$ was entered)
|
|
||||||
|
|
||||||
## Additional Information
|
|
||||||
|
|
||||||
We have participated in Google Summer of Code in 2020 and hope to be selected
|
|
||||||
again in 2021.
|
|
||||||
|
|
||||||
We have no experience with a technical writer, but we will support that person
|
|
||||||
with video calls, chats, emails and messaging, provide all necessary information
|
|
||||||
and write technical contents that is required for the success of this project.
|
|
||||||
It is clear to us that a technical writer knows how to write, but cannot know
|
|
||||||
the technical details in a complex tooling like in AFL++. This guidance, input,
|
|
||||||
etc. has to come from us.
|
|
124
docs/docs2.md
@ -1,124 +0,0 @@
|
|||||||
# Restructure AFL++'s documentation - Case Study
|
|
||||||
|
|
||||||
## Problem statement
|
|
||||||
|
|
||||||
AFL++ inherited it's documentation from the original Google AFL project.
|
|
||||||
Since then it has been massively improved - feature and performance wise -
|
|
||||||
and although the documenation has likewise been continued it has grown out
|
|
||||||
of proportion.
|
|
||||||
The documentation is done by non-natives to the English language, plus
|
|
||||||
none of us has a writer background.
|
|
||||||
|
|
||||||
We see questions on AFL++ usage on mailing lists (e.g. afl-users), discord
|
|
||||||
channels, web forums and as issues in our repository.
|
|
||||||
Most of them could be answered if people would read through all the
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
This only increases as AFL++ has been on the top of Google's fuzzbench
|
|
||||||
statistics (which measures the performance of fuzzers) and has been
|
|
||||||
integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix
|
|
||||||
packaging repositories, e.g. Debian, FreeBSD, etc.
|
|
||||||
|
|
||||||
AFL++ had 44 (!) documentation files with 13k total lines of content.
|
|
||||||
This was way too much.
|
|
||||||
|
|
||||||
## Proposal abstract
|
|
||||||
|
|
||||||
AFL++'s documentatin needs a complete overhaul, both on a
|
|
||||||
organisation/structural level as well as the content.
|
|
||||||
|
|
||||||
Overall the following actions have to be performed:
|
|
||||||
* Create a better structure of documentation so it is easier to find the
|
|
||||||
information that is being looked for, combining and/or splitting up the
|
|
||||||
existing documents as needed.
|
|
||||||
* Rewrite some documentation to remove duplication. Several information is
|
|
||||||
present several times in the documentation. These should be removed to
|
|
||||||
where needed so that we have as little bloat as possible.
|
|
||||||
* The documents have been written and modified by a lot of different people,
|
|
||||||
most of them non-native English speaker. Hence an overall review where
|
|
||||||
parts should be rewritten has to be performed and then the rewrite done.
|
|
||||||
* Create a cheat-sheet for a very short best-setup build and run of AFL++
|
|
||||||
* Pictures explain more than 1000 words. We need at least 4 images that
|
|
||||||
explain the workflow with AFL++:
|
|
||||||
- the build workflow
|
|
||||||
- the fuzzing workflow
|
|
||||||
- the fuzzing campaign management workflow
|
|
||||||
- the overall workflow that is an overview of the above
|
|
||||||
- maybe more? where the technical writes seems it necessary for
|
|
||||||
understanding.
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
* Documentation has to be in Markdown format
|
|
||||||
* Images have to be either in SVG or PNG format.
|
|
||||||
* All documentation should be (moved) in(to) docs/
|
|
||||||
|
|
||||||
## Project description
|
|
||||||
|
|
||||||
We created our proposal by discussing in the team what the issues are and
|
|
||||||
what was needed to fix it.
|
|
||||||
This resulted in the [project proposal](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/docs.md).
|
|
||||||
|
|
||||||
We did not want to be selected by a writer but select a writer ourselves, so
|
|
||||||
we combed through the list and reviewed every single one of them.
|
|
||||||
We were not looking for coders writing technical documentation, but rather
|
|
||||||
someone who is an experienced writer and has documented experience with
|
|
||||||
structuring documentation.
|
|
||||||
Few fit that profile and we sent out messages to 6 people.
|
|
||||||
We finally decided on Jana because she had a strong background in technical
|
|
||||||
documentation and structuring information.
|
|
||||||
She had no technical experience in fuzzing whatsoever, but we saw that as
|
|
||||||
a plus - of course this made the whole process longer to explain details,
|
|
||||||
but overall ensured that the documentation can be read by (mostly) everyone.
|
|
||||||
|
|
||||||
We communicated via video calls every few weeks and she kept a public kanban
|
|
||||||
board about her todos, additional we used a Signal channel.
|
|
||||||
Her changes were imported via PRs where we discussed details.
|
|
||||||
|
|
||||||
The project was off to a good start, but then Jana got pregnant with serious
|
|
||||||
side effects that made working impossible for her for a longer time, hence
|
|
||||||
the schedule was thrown back.
|
|
||||||
She offered to rescind the payment and we select a new writer, but we saw
|
|
||||||
little opportunity in that, as that would mean a new selection of a writer,
|
|
||||||
someone else with a different vision on how the result should look like so
|
|
||||||
basically a full restart of the project and a large impact on our own time.
|
|
||||||
So we agreed on - after discussion with the Google GSoD team - that she
|
|
||||||
continues the project after the GSoD completion deadline as best as she can.
|
|
||||||
|
|
||||||
End of November she took one week off from work and fully dedicated her time
|
|
||||||
for the documenation which brought the project a big step forward.
|
|
||||||
|
|
||||||
Originally the project should have been ended begin of October, but now - at
|
|
||||||
nearing the end of November, we are at about 85% completion, with the end
|
|
||||||
being expected around mid of December.
|
|
||||||
|
|
||||||
## Metrics
|
|
||||||
|
|
||||||
We merged most of the changes in our development branch and are getting
|
|
||||||
close to a state where the user documentation part is completed and we
|
|
||||||
can create a new release. Only then the new documentatin is actually visible
|
|
||||||
to users. Therefore no metrics could be collected so far.
|
|
||||||
|
|
||||||
We plan on a user-assisted QA review end of November/begin of December.
|
|
||||||
|
|
||||||
The documentation was reviewed by a few test users so far however who gave
|
|
||||||
it a thumbs up.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
The GSoD project itself is great. It helps to get the documentation back in
|
|
||||||
line.
|
|
||||||
It was and is a larger time investment from our side, but we expected that.
|
|
||||||
When the project is done, the documentation will be more accessible by users
|
|
||||||
and also need less maintenance by us.
|
|
||||||
There is still follow-up work to be done by us afterwards (web site for the
|
|
||||||
docs, etc.).
|
|
||||||
|
|
||||||
Not sure what we would do differently next time. I think we prepared best as
|
|
||||||
possible and reacted best as possible to the unexpected.
|
|
||||||
|
|
||||||
Recommendations for other organizations who would like to participate in GSoD:
|
|
||||||
- expect the process to take a larger part of your time. the writer needs
|
|
||||||
your full support.
|
|
||||||
- have someone dedicated from the dev/org side to support, educate and
|
|
||||||
supervice the writer
|
|
||||||
- set clear goals and expectations
|
|
@ -105,7 +105,8 @@ fairly broad use of environment variables instead:
|
|||||||
within your program at a certain point (such as at the end of an
|
within your program at a certain point (such as at the end of an
|
||||||
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
|
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
|
||||||
cause an abort if any memory is leaked (you can combine this with the
|
cause an abort if any memory is leaked (you can combine this with the
|
||||||
`LSAN_OPTIONS=...` suppression option to suppress some known leaks).
|
`__AFL_LSAN_OFF();` and `__AFL_LSAN_ON();` macros to avoid checking for
|
||||||
|
memory leaks from memory allocated between these two calls.
|
||||||
- `AFL_USE_MSAN=1` - activates the memory sanitizer (uninitialized memory)
|
- `AFL_USE_MSAN=1` - activates the memory sanitizer (uninitialized memory)
|
||||||
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
|
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
|
||||||
conditions
|
conditions
|
||||||
@ -159,6 +160,8 @@ Available options:
|
|||||||
Setting `AFL_LLVM_CMPLOG=1` during compilation will tell afl-clang-fast to
|
Setting `AFL_LLVM_CMPLOG=1` during compilation will tell afl-clang-fast to
|
||||||
produce a CmpLog binary.
|
produce a CmpLog binary.
|
||||||
|
|
||||||
|
For afl-gcc-fast, set `AFL_GCC_CMPLOG=1` instead.
|
||||||
|
|
||||||
For more information, see
|
For more information, see
|
||||||
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
|
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
|
||||||
|
|
||||||
@ -283,12 +286,24 @@ mode.
|
|||||||
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
|
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
|
||||||
```
|
```
|
||||||
|
|
||||||
- GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` with a filename will
|
- GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` or
|
||||||
only instrument those files that match the names listed in this file (one
|
`AFL_GCC_ALLOWLIST` with a filename will only instrument those files that
|
||||||
filename per line). See
|
match the names listed in this file (one filename per line).
|
||||||
|
|
||||||
|
Setting `AFL_GCC_DENYLIST` or `AFL_GCC_BLOCKLIST` with a file name and/or
|
||||||
|
function will only skip those files that match the names listed in the
|
||||||
|
specified file. See
|
||||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
|
Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the
|
||||||
|
code with calls to an injected subroutine instead of the much more efficient
|
||||||
|
inline instrumentation.
|
||||||
|
|
||||||
|
Setting `AFL_GCC_SKIP_NEVERZERO=1` will not implement the skip zero test. If
|
||||||
|
the target performs only a few loops, then this will give a small
|
||||||
|
performance boost.
|
||||||
|
|
||||||
## 4) Settings for afl-fuzz
|
## 4) Settings for afl-fuzz
|
||||||
|
|
||||||
The main fuzzer binary accepts several options that disable a couple of sanity
|
The main fuzzer binary accepts several options that disable a couple of sanity
|
||||||
@ -336,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
|
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
|
||||||
usually a bad idea!
|
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
|
- `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.
|
does not allow crashes or timeout seeds in the initial -i corpus.
|
||||||
|
|
||||||
@ -387,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
|
This makes the "own finds" counter in the UI more accurate. Beyond counter
|
||||||
aesthetics, not much else should change.
|
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
|
- `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on
|
||||||
timeout. Unless you implement your own targets or instrumentation, you
|
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`
|
likely don't have to set it. By default, on timeout and on exit, `SIGKILL`
|
||||||
@ -397,7 +419,7 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
target. This must be equal or larger than the size the target was compiled
|
target. This must be equal or larger than the size the target was compiled
|
||||||
with.
|
with.
|
||||||
|
|
||||||
- Setting `AFL_MAX_DET_EXRAS` will change the threshold at what number of
|
- Setting `AFL_MAX_DET_EXTRAS` will change the threshold at what number of
|
||||||
elements in the `-x` dictionary and LTO autodict (combined) the
|
elements in the `-x` dictionary and LTO autodict (combined) the
|
||||||
probabilistic mode will kick off. In probabilistic mode, not all dictionary
|
probabilistic mode will kick off. In probabilistic mode, not all dictionary
|
||||||
entries will be used all of the time for fuzzing mutations to not slow down
|
entries will be used all of the time for fuzzing mutations to not slow down
|
||||||
@ -440,7 +462,7 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
some basic stats. This behavior is also automatically triggered when the
|
some basic stats. This behavior is also automatically triggered when the
|
||||||
output from afl-fuzz is redirected to a file or to a pipe.
|
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
|
- In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for
|
||||||
afl-qemu-trace and afl-frida-trace.so.
|
afl-qemu-trace and afl-frida-trace.so.
|
||||||
|
|
||||||
- If you are using persistent mode (you should, see
|
- If you are using persistent mode (you should, see
|
||||||
@ -497,11 +519,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,
|
(empty/non present) will add no tags to the metrics. For more information,
|
||||||
see [rpc_statsd.md](rpc_statsd.md).
|
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
|
- 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
|
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
|
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
|
||||||
theoretically allow fuzzing of AFL++ itself (with 'target' AFL++ using some
|
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
|
- `AFL_TESTCACHE_SIZE` allows you to override the size of `#define
|
||||||
TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if
|
TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if
|
||||||
@ -515,9 +546,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
|
- Setting `AFL_TRY_AFFINITY` tries to attempt binding to a specific CPU core
|
||||||
on Linux systems, but will not terminate if that fails.
|
on Linux systems, but will not terminate if that fails.
|
||||||
|
|
||||||
- Outdated environment variables that are not supported anymore:
|
- The following environment variables are only needed if you implemented
|
||||||
- `AFL_DEFER_FORKSRV`
|
your own forkserver or persistent mode, or if __AFL_LOOP or __AFL_INIT
|
||||||
- `AFL_PERSISTENT`
|
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
|
## 5) Settings for afl-qemu-trace
|
||||||
|
|
||||||
@ -579,6 +621,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
|
emulation" variables (e.g., `QEMU_STACK_SIZE`), but there should be no
|
||||||
reason to touch them.
|
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
|
## 7) Settings for afl-frida-trace
|
||||||
|
|
||||||
The FRIDA wrapper used to instrument binary-only code supports many of the same
|
The FRIDA wrapper used to instrument binary-only code supports many of the same
|
||||||
|
103
docs/features.md
@ -1,39 +1,96 @@
|
|||||||
# Important features of AFL++
|
# Important features of AFL++
|
||||||
|
|
||||||
AFL++ supports llvm from 3.8 up to version 12, very fast binary fuzzing with
|
AFL++ supports llvm from 3.8 up to version 12, very fast binary fuzzing with
|
||||||
QEMU 5.1 with laf-intel and redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
||||||
*BSD, Mac OS, Solaris and Android support and much, much, much more.
|
*BSD, Mac OS, Solaris and Android support and much, much, much more.
|
||||||
|
|
||||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) |unicorn_mode(10) |coresight_mode(11)|
|
## Features and instrumentation
|
||||||
| -------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|:----------------:|
|
|
||||||
| Threadsafe counters | | x(3) | | | | | |
|
|
||||||
| NeverZero | x86[_64]| x(1) | x | x | x | x | |
|
|
||||||
| Persistent Mode | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | |
|
|
||||||
| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | |
|
|
||||||
| CmpLog | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | |
|
|
||||||
| Selective Instrumentation| | x | x | x | x | | |
|
|
||||||
| Non-Colliding Coverage | | x(4) | | | (x)(5) | | |
|
|
||||||
| Ngram prev_loc Coverage | | x(6) | | | | | |
|
|
||||||
| Context Coverage | | x(6) | | | | | |
|
|
||||||
| Auto Dictionary | | x(7) | | | | | |
|
|
||||||
| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | | |
|
|
||||||
| Shared Memory Test cases | | x | x | x86[_64]/arm64 | x | x | |
|
|
||||||
|
|
||||||
1. default for LLVM >= 9.0, environment variable for older version due an
|
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||||
|
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||||
|
| Threadsafe counters [A] | | x(3) | | | | | x | |
|
||||||
|
| 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 | 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) | | | | | | |
|
||||||
|
| Context Coverage [I] | | x(6) | | | | | | |
|
||||||
|
| Auto Dictionary [J] | | x(7) | | | | | | |
|
||||||
|
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||||
|
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | |
|
||||||
|
|
||||||
|
## More information about features
|
||||||
|
|
||||||
|
A. Default is not thread-safe coverage counter updates for better performance,
|
||||||
|
see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md)
|
||||||
|
|
||||||
|
B. On wrapping coverage counters (255 + 1), skip the 0 value and jump to 1
|
||||||
|
instead. This has shown to give better coverage data and is the default; see
|
||||||
|
[instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||||
|
|
||||||
|
C. Instead of forking, reiterate the fuzz target function in a loop (like
|
||||||
|
`LLVMFuzzerTestOneInput`. Great speed increase but only works with target
|
||||||
|
functions that do not keep state, leak memory, or exit; see
|
||||||
|
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||||
|
|
||||||
|
D. Split any non-8-bit comparison to 8-bit comparison; see
|
||||||
|
[instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md)
|
||||||
|
|
||||||
|
E. CmpLog is our enhanced
|
||||||
|
[Redqueen](https://www.ndss-symposium.org/ndss-paper/redqueen-fuzzing-with-input-to-state-correspondence/)
|
||||||
|
implementation, see
|
||||||
|
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md)
|
||||||
|
|
||||||
|
F. Similar and compatible to clang 13+ sancov sanitize-coverage-allow/deny but
|
||||||
|
for all llvm versions and all our compile modes, only instrument what should
|
||||||
|
be instrumented, for more speed, directed fuzzing and less instability; see
|
||||||
|
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||||
|
|
||||||
|
G. Vanilla AFL uses coverage where edges could collide to the same coverage
|
||||||
|
bytes the larger the target is. Our default instrumentation in LTO and
|
||||||
|
afl-clang-fast (PCGUARD) uses non-colliding coverage that also makes it
|
||||||
|
faster. Vanilla AFL style is available with `AFL_LLVM_INSTRUMENT=AFL`; see
|
||||||
|
[instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||||
|
|
||||||
|
H.+I. Alternative coverage based on previous edges (NGRAM) or depending on the
|
||||||
|
caller (CTX), based on
|
||||||
|
[https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf](https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf);
|
||||||
|
see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||||
|
|
||||||
|
J. An LTO feature that creates a fuzzing dictionary based on comparisons found
|
||||||
|
during compilation/instrumentation. Automatic feature :) See
|
||||||
|
[instrumentation/README.lto.md](../instrumentation/README.lto.md)
|
||||||
|
|
||||||
|
K. The snapshot feature requires a kernel module that was a lot of work to get
|
||||||
|
right and maintained so it is no longer supported. We have
|
||||||
|
[nyx_mode](../nyx_mode/README.md) instead.
|
||||||
|
|
||||||
|
L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase
|
||||||
|
delivery, see
|
||||||
|
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||||
|
|
||||||
|
## More information about instrumentation
|
||||||
|
|
||||||
|
1. Default for LLVM >= 9.0, environment variable for older version due an
|
||||||
efficiency bug in previous llvm versions
|
efficiency bug in previous llvm versions
|
||||||
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
|
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
|
||||||
3. with `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
|
3. With `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
|
||||||
4. with pcguard mode and LTO mode for LLVM 11 and newer
|
4. With pcguard mode and LTO mode for LLVM 11 and newer
|
||||||
5. upcoming, development in the branch
|
5. Upcoming, development in the branch
|
||||||
6. not compatible with LTO instrumentation and needs at least LLVM v4.1
|
6. Not compatible with LTO instrumentation and needs at least LLVM v4.1
|
||||||
7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM
|
7. Automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM
|
||||||
versions that write to a file to use with afl-fuzz' `-x`
|
versions that write to a file to use with afl-fuzz' `-x`
|
||||||
8. the snapshot LKM is currently unmaintained due to too many kernel changes
|
8. The snapshot LKM is currently unmaintained due to too many kernel changes
|
||||||
coming too fast :-(
|
coming too fast :-(
|
||||||
9. FRIDA mode is supported on Linux and MacOS for Intel and ARM
|
9. FRIDA mode is supported on Linux and MacOS for Intel and ARM
|
||||||
10. QEMU/Unicorn is only supported on Linux
|
10. QEMU/Unicorn is only supported on Linux
|
||||||
11. Coresight mode is only available on AARCH64 Linux with a CPU with Coresight
|
11. Coresight mode is only available on AARCH64 Linux with a CPU with Coresight
|
||||||
extension
|
extension
|
||||||
|
12. Nyx mode is only supported on Linux and currently restricted to x86_x64
|
||||||
|
|
||||||
|
## Integrated features and patches
|
||||||
|
|
||||||
Among others, the following features and patches have been integrated:
|
Among others, the following features and patches have been integrated:
|
||||||
|
|
||||||
@ -43,7 +100,7 @@ Among others, the following features and patches have been integrated:
|
|||||||
* Unicorn mode which allows fuzzing of binaries from completely different
|
* Unicorn mode which allows fuzzing of binaries from completely different
|
||||||
platforms (integration provided by domenukk)
|
platforms (integration provided by domenukk)
|
||||||
* The new CmpLog instrumentation for LLVM and QEMU inspired by
|
* The new CmpLog instrumentation for LLVM and QEMU inspired by
|
||||||
[Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
|
[Redqueen](https://github.com/RUB-SysSec/redqueen)
|
||||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||||
* AFLfast's power schedules by Marcel Böhme:
|
* AFLfast's power schedules by Marcel Böhme:
|
||||||
[https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
[https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||||
|
@ -12,11 +12,11 @@ fuzzed with AFL++.
|
|||||||
|
|
||||||
## TL;DR:
|
## TL;DR:
|
||||||
|
|
||||||
QEMU mode in persistent mode is the fastest - if the stability is high enough.
|
FRIDA mode and QEMU mode in persistent mode are the fastest - if persistent mode
|
||||||
Otherwise, try RetroWrite, Dyninst, and if these fail, too, then try standard
|
is possible and the stability is high enough.
|
||||||
QEMU mode with `AFL_ENTRYPOINT` to where you need it.
|
|
||||||
|
|
||||||
If your target is a library, then use FRIDA mode.
|
Otherwise, try Zafl, RetroWrite, Dyninst, and if these fail, too, then try
|
||||||
|
standard FRIDA/QEMU mode with `AFL_ENTRYPOINT` to where you need it.
|
||||||
|
|
||||||
If your target is non-linux, then use unicorn_mode.
|
If your target is non-linux, then use unicorn_mode.
|
||||||
|
|
||||||
@ -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
|
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.
|
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
|
If a binary rewriter works for your target then you can use afl-fuzz normally
|
||||||
binary, then you can use afl-fuzz normally and it will have twice the speed
|
and it will have twice the speed compared to QEMU mode (but slower than QEMU
|
||||||
compared to QEMU mode (but slower than QEMU persistent mode). Note that several
|
persistent mode).
|
||||||
other binary rewriters exist, all with their advantages and caveats.
|
|
||||||
|
|
||||||
The speed decrease of QEMU mode is at about 50%. However, various options exist
|
The speed decrease of QEMU mode is at about 50%. However, various options exist
|
||||||
to increase the speed:
|
to increase the speed:
|
||||||
@ -92,7 +93,7 @@ For more information, see
|
|||||||
### FRIDA mode
|
### FRIDA mode
|
||||||
|
|
||||||
In FRIDA mode, you can fuzz binary-only targets as easily as with QEMU mode.
|
In FRIDA mode, you can fuzz binary-only targets as easily as with QEMU mode.
|
||||||
FRIDA mode is sometimes faster and sometimes slower than QEMU mode. It is also
|
FRIDA mode is most of the times slightly faster than QEMU mode. It is also
|
||||||
newer, lacks COMPCOV, and has the advantage that it works on MacOS (both intel
|
newer, lacks COMPCOV, and has the advantage that it works on MacOS (both intel
|
||||||
and M1).
|
and M1).
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ To build FRIDA mode:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd frida_mode
|
cd frida_mode
|
||||||
make
|
gmake
|
||||||
```
|
```
|
||||||
|
|
||||||
For additional instructions and caveats, see
|
For additional instructions and caveats, see
|
||||||
@ -126,6 +127,16 @@ to check out our sister project libafl which supports Frida, too:
|
|||||||
[https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL).
|
[https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL).
|
||||||
Working examples already exist :-)
|
Working examples already exist :-)
|
||||||
|
|
||||||
|
### Nyx mode
|
||||||
|
|
||||||
|
Nyx is a full system emulation fuzzing environment with snapshot support that is
|
||||||
|
built upon KVM and QEMU. It is only available on Linux and currently restricted
|
||||||
|
to x86_x64.
|
||||||
|
|
||||||
|
For binary-only fuzzing a special 5.10 kernel is required.
|
||||||
|
|
||||||
|
See [nyx_mode/README.md](../nyx_mode/README.md).
|
||||||
|
|
||||||
### Unicorn
|
### Unicorn
|
||||||
|
|
||||||
Unicorn is a fork of QEMU. The instrumentation is, therefore, very similar. In
|
Unicorn is a fork of QEMU. The instrumentation is, therefore, very similar. In
|
||||||
@ -189,12 +200,15 @@ afl-clang-fast's.
|
|||||||
|
|
||||||
### RetroWrite
|
### RetroWrite
|
||||||
|
|
||||||
If you have an x86/x86_64 binary that still has its symbols, is compiled with
|
RetroWrite is a static binary rewriter that can be combined with AFL++. If you
|
||||||
position independent code (PIC/PIE), and does not use most of the C++ features,
|
have an x86_64 binary that still has its symbols (i.e., not stripped binary), is
|
||||||
then the RetroWrite solution might be for you. It decompiles to ASM files which
|
compiled with position independent code (PIC/PIE), and does not contain C++
|
||||||
can then be instrumented with afl-gcc.
|
exceptions, then the RetroWrite solution might be for you. It decompiles to ASM
|
||||||
|
files which can then be instrumented with afl-gcc.
|
||||||
|
|
||||||
It is at about 80-85% performance.
|
Binaries that are statically instrumented for fuzzing using RetroWrite are close
|
||||||
|
in performance to compiler-instrumented binaries and outperform the QEMU-based
|
||||||
|
instrumentation.
|
||||||
|
|
||||||
[https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite)
|
[https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite)
|
||||||
|
|
||||||
@ -293,4 +307,4 @@ some are very hard to set-up...
|
|||||||
|
|
||||||
## Closing words
|
## Closing words
|
||||||
|
|
||||||
That's it! News, corrections, updates? Send an email to vh@thc.org.
|
That's it! News, corrections, updates? Send an email to vh@thc.org.
|
||||||
|
@ -55,7 +55,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
|
|||||||
### a) Selecting the best AFL++ compiler for instrumenting the target
|
### a) Selecting the best AFL++ compiler for instrumenting the target
|
||||||
|
|
||||||
AFL++ comes with a central compiler `afl-cc` that incorporates various different
|
AFL++ comes with a central compiler `afl-cc` that incorporates various different
|
||||||
kinds of compiler targets and and instrumentation options. The following
|
kinds of compiler targets and instrumentation options. The following
|
||||||
evaluation flow will help you to select the best possible.
|
evaluation flow will help you to select the best possible.
|
||||||
|
|
||||||
It is highly recommended to have the newest llvm version possible installed,
|
It is highly recommended to have the newest llvm version possible installed,
|
||||||
@ -95,38 +95,43 @@ Clickable README links for the chosen compiler:
|
|||||||
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
|
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
|
||||||
features
|
features
|
||||||
|
|
||||||
You can select the mode for the afl-cc compiler by:
|
You can select the mode for the afl-cc compiler by one of the following methods:
|
||||||
1. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
|
||||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
|
||||||
afl-gcc-fast, afl-g++-fast (recommended!)
|
|
||||||
2. using the environment variable AFL_CC_COMPILER with MODE
|
|
||||||
3. passing --afl-MODE command line options to the compiler via
|
|
||||||
CFLAGS/CXXFLAGS/CPPFLAGS
|
|
||||||
|
|
||||||
MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN
|
* Using a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||||
(afl-g*-fast) or GCC (afl-gcc/afl-g++) or CLANG(afl-clang/afl-clang++).
|
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||||
|
afl-gcc-fast, afl-g++-fast (recommended!).
|
||||||
|
* Using the environment variable `AFL_CC_COMPILER` with `MODE`.
|
||||||
|
* Passing --afl-`MODE` command line options to the compiler via
|
||||||
|
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`.
|
||||||
|
|
||||||
|
`MODE` can be one of the following:
|
||||||
|
|
||||||
|
* LTO (afl-clang-lto*)
|
||||||
|
* LLVM (afl-clang-fast*)
|
||||||
|
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++)
|
||||||
|
* CLANG(afl-clang/afl-clang++)
|
||||||
|
|
||||||
Because no AFL++ specific command-line options are accepted (beside the
|
Because no AFL++ specific command-line options are accepted (beside the
|
||||||
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
||||||
variables, which can be listed with `afl-cc -hh` or by reading
|
variables, which can be listed with `afl-cc -hh` or looked up in
|
||||||
[env_variables.md](env_variables.md).
|
[env_variables.md](env_variables.md).
|
||||||
|
|
||||||
### b) Selecting instrumentation options
|
### b) Selecting instrumentation options
|
||||||
|
|
||||||
The following options are available when you instrument with LTO mode
|
If you instrument with LTO mode (afl-clang-fast/afl-clang-lto), the following
|
||||||
(afl-clang-fast/afl-clang-lto):
|
options are available:
|
||||||
|
|
||||||
* Splitting integer, string, float and switch comparisons so AFL++ can easier
|
* Splitting integer, string, float, and switch comparisons so AFL++ can easier
|
||||||
solve these. This is an important option if you do not have a very good and
|
solve these. This is an important option if you do not have a very good and
|
||||||
large input corpus. This technique is called laf-intel or COMPCOV. To use this
|
large input corpus. This technique is called laf-intel or COMPCOV. To use
|
||||||
set the following environment variable before compiling the target: `export
|
this, set the following environment variable before compiling the target:
|
||||||
AFL_LLVM_LAF_ALL=1` You can read more about this in
|
`export AFL_LLVM_LAF_ALL=1`. You can read more about this in
|
||||||
[instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md).
|
[instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md).
|
||||||
* A different technique (and usually a better one than laf-intel) is to
|
* A different technique (and usually a better one than laf-intel) is to
|
||||||
instrument the target so that any compare values in the target are sent to
|
instrument the target so that any compare values in the target are sent to
|
||||||
AFL++ which then tries to put these values into the fuzzing data at different
|
AFL++ which then tries to put these values into the fuzzing data at different
|
||||||
locations. This technique is very fast and good - if the target does not
|
locations. This technique is very fast and good - if the target does not
|
||||||
transform input data before comparison. Therefore this technique is called
|
transform input data before comparison. Therefore, this technique is called
|
||||||
`input to state` or `redqueen`. If you want to use this technique, then you
|
`input to state` or `redqueen`. If you want to use this technique, then you
|
||||||
have to compile the target twice, once specifically with/for this mode by
|
have to compile the target twice, once specifically with/for this mode by
|
||||||
setting `AFL_LLVM_CMPLOG=1`, and pass this binary to afl-fuzz via the `-c`
|
setting `AFL_LLVM_CMPLOG=1`, and pass this binary to afl-fuzz via the `-c`
|
||||||
@ -135,24 +140,49 @@ The following options are available when you instrument with LTO mode
|
|||||||
about this in
|
about this in
|
||||||
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
|
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
|
||||||
|
|
||||||
If you use LTO, LLVM or GCC_PLUGIN mode
|
If you use LTO, LLVM, or GCC_PLUGIN mode
|
||||||
(afl-clang-fast/afl-clang-lto/afl-gcc-fast) you have the option to selectively
|
(afl-clang-fast/afl-clang-lto/afl-gcc-fast), you have the option to selectively
|
||||||
only instrument parts of the target that you are interested in:
|
instrument _parts_ of the target that you are interested in. For afl-clang-fast,
|
||||||
|
you have to use an llvm version newer than 10.0.0 or a mode other than
|
||||||
|
DEFAULT/PCGUARD.
|
||||||
|
|
||||||
* To instrument only those parts of the target that you are interested in create
|
This step can be done either by explicitly including parts to be instrumented or
|
||||||
a file with all the filenames of the source code that should be instrumented.
|
by explicitly excluding parts from instrumentation.
|
||||||
For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode other than
|
|
||||||
DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one filename or
|
* To instrument _only specified parts_, create a file (e.g., `allowlist.txt`)
|
||||||
function per line (no directory information necessary for filenames9, and
|
with all the filenames and/or functions of the source code that should be
|
||||||
either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or** `export
|
instrumented and then:
|
||||||
AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per default to
|
|
||||||
instrument unless noted (DENYLIST) or not perform instrumentation unless
|
1. Just put one filename or function (prefixing with `fun: `) per line (no
|
||||||
requested (ALLOWLIST). **NOTE:** During optimization functions might be
|
directory information necessary for filenames) in the file `allowlist.txt`.
|
||||||
inlined and then would not match! See
|
|
||||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
foo.cpp # will match foo/foo.cpp, bar/foo.cpp, barfoo.cpp etc.
|
||||||
|
fun: foo_func # will match the function foo_func
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set `export AFL_LLVM_ALLOWLIST=allowlist.txt` to enable selective positive
|
||||||
|
instrumentation.
|
||||||
|
|
||||||
|
* Similarly to _exclude_ specified parts from instrumentation, create a file
|
||||||
|
(e.g., `denylist.txt`) with all the filenames of the source code that should
|
||||||
|
be skipped during instrumentation and then:
|
||||||
|
|
||||||
|
1. Same as above. Just put one filename or function per line in the file
|
||||||
|
`denylist.txt`.
|
||||||
|
|
||||||
|
2. Set `export AFL_LLVM_DENYLIST=denylist.txt` to enable selective negative
|
||||||
|
instrumentation.
|
||||||
|
|
||||||
|
**NOTE:** During optimization functions might be
|
||||||
|
inlined and then would not match the list! See
|
||||||
|
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
|
||||||
|
|
||||||
There are many more options and modes available, however, these are most of the
|
There are many more options and modes available, however, these are most of the
|
||||||
time less effective. See:
|
time less effective. See:
|
||||||
|
|
||||||
* [instrumentation/README.llvm.md#6) AFL++ Context Sensitive Branch Coverage](../instrumentation/README.llvm.md#6-afl-context-sensitive-branch-coverage)
|
* [instrumentation/README.llvm.md#6) AFL++ Context Sensitive Branch Coverage](../instrumentation/README.llvm.md#6-afl-context-sensitive-branch-coverage)
|
||||||
* [instrumentation/README.llvm.md#7) AFL++ N-Gram Branch Coverage](../instrumentation/README.llvm.md#7-afl-n-gram-branch-coverage)
|
* [instrumentation/README.llvm.md#7) AFL++ N-Gram Branch Coverage](../instrumentation/README.llvm.md#7-afl-n-gram-branch-coverage)
|
||||||
|
|
||||||
@ -166,26 +196,27 @@ It is possible to use sanitizers when instrumenting targets for fuzzing, which
|
|||||||
allows you to find bugs that would not necessarily result in a crash.
|
allows you to find bugs that would not necessarily result in a crash.
|
||||||
|
|
||||||
Note that sanitizers have a huge impact on CPU (= less executions per second)
|
Note that sanitizers have a huge impact on CPU (= less executions per second)
|
||||||
and RAM usage. Also you should only run one afl-fuzz instance per sanitizer
|
and RAM usage. Also, you should only run one afl-fuzz instance per sanitizer
|
||||||
type. This is enough because a use-after-free bug will be picked up, e.g., by
|
type. This is enough because e.g. a use-after-free bug will be picked up by ASAN
|
||||||
ASAN (address sanitizer) anyway when syncing to other fuzzing instances, so not
|
(address sanitizer) anyway after syncing test cases from other fuzzing
|
||||||
all fuzzing instances need to be instrumented with ASAN.
|
instances, so running more than one address sanitized target would be a waste.
|
||||||
|
|
||||||
The following sanitizers have built-in support in AFL++:
|
The following sanitizers have built-in support in AFL++:
|
||||||
|
|
||||||
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
|
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
|
||||||
use-after-free, NULL pointer dereference, buffer overruns, etc. Enabled with
|
use-after-free, NULL pointer dereference, buffer overruns, etc. Enabled with
|
||||||
`export AFL_USE_ASAN=1` before compiling.
|
`export AFL_USE_ASAN=1` before compiling.
|
||||||
* MSAN = Memory SANitizer, finds read access to uninitialized memory, e.g., a
|
* MSAN = Memory SANitizer, finds read accesses to uninitialized memory, e.g., a
|
||||||
local variable that is defined and read before it is even set. Enabled with
|
local variable that is defined and read before it is even set. Enabled with
|
||||||
`export AFL_USE_MSAN=1` before compiling.
|
`export AFL_USE_MSAN=1` before compiling.
|
||||||
* UBSAN = Undefined Behavior SANitizer, finds instances where - by the C and C++
|
* UBSAN = Undefined Behavior SANitizer, finds instances where - by the C and C++
|
||||||
standards - undefined behavior happens, e.g., adding two signed integers
|
standards - undefined behavior happens, e.g., adding two signed integers where
|
||||||
together where the result is larger than a signed integer can hold. Enabled
|
the result is larger than what a signed integer can hold. Enabled with `export
|
||||||
with `export AFL_USE_UBSAN=1` before compiling.
|
AFL_USE_UBSAN=1` before compiling.
|
||||||
* CFISAN = Control Flow Integrity SANitizer, finds instances where the control
|
* CFISAN = Control Flow Integrity SANitizer, finds instances where the control
|
||||||
flow is found to be illegal. Originally this was rather to prevent return
|
flow is found to be illegal. Originally this was rather to prevent return
|
||||||
oriented programming exploit chains from functioning, in fuzzing this is
|
oriented programming (ROP) exploit chains from functioning. In fuzzing, this
|
||||||
mostly reduced to detecting type confusion vulnerabilities - which is,
|
is mostly reduced to detecting type confusion vulnerabilities - which is,
|
||||||
however, one of the most important and dangerous C++ memory corruption
|
however, one of the most important and dangerous C++ memory corruption
|
||||||
classes! Enabled with `export AFL_USE_CFISAN=1` before compiling.
|
classes! Enabled with `export AFL_USE_CFISAN=1` before compiling.
|
||||||
* TSAN = Thread SANitizer, finds thread race conditions. Enabled with `export
|
* TSAN = Thread SANitizer, finds thread race conditions. Enabled with `export
|
||||||
@ -194,7 +225,10 @@ The following sanitizers have built-in support in AFL++:
|
|||||||
security issue, but for developers this can be very valuable. Note that unlike
|
security issue, but for developers this can be very valuable. Note that unlike
|
||||||
the other sanitizers above this needs `__AFL_LEAK_CHECK();` added to all areas
|
the other sanitizers above this needs `__AFL_LEAK_CHECK();` added to all areas
|
||||||
of the target source code where you find a leak check necessary! Enabled with
|
of the target source code where you find a leak check necessary! Enabled with
|
||||||
`export AFL_USE_LSAN=1` before compiling.
|
`export AFL_USE_LSAN=1` before compiling. To ignore the memory-leaking check
|
||||||
|
for certain allocations, `__AFL_LSAN_OFF();` can be used before memory is
|
||||||
|
allocated, and `__AFL_LSAN_ON();` afterwards. Memory allocated between these
|
||||||
|
two macros will not be checked for memory leaks.
|
||||||
|
|
||||||
It is possible to further modify the behavior of the sanitizers at run-time by
|
It is possible to further modify the behavior of the sanitizers at run-time by
|
||||||
setting `ASAN_OPTIONS=...`, `LSAN_OPTIONS` etc. - the available parameters can
|
setting `ASAN_OPTIONS=...`, `LSAN_OPTIONS` etc. - the available parameters can
|
||||||
@ -227,20 +261,20 @@ All AFL++ compilers will set this preprocessor definition automatically.
|
|||||||
|
|
||||||
### e) Instrumenting the target
|
### e) Instrumenting the target
|
||||||
|
|
||||||
In this step the target source code is compiled so that it can be fuzzed.
|
In this step, the target source code is compiled so that it can be fuzzed.
|
||||||
|
|
||||||
Basically you have to tell the target build system that the selected AFL++
|
Basically, you have to tell the target build system that the selected AFL++
|
||||||
compiler is used. Also - if possible - you should always configure the build
|
compiler is used. Also - if possible - you should always configure the build
|
||||||
system such that the target is compiled statically and not dynamically. How to
|
system in such way that the target is compiled statically and not dynamically.
|
||||||
do this is described below.
|
How to do this is described below.
|
||||||
|
|
||||||
The #1 rule when instrumenting a target is: avoid instrumenting shared libraries
|
The #1 rule when instrumenting a target is: avoid instrumenting shared libraries
|
||||||
at all cost. You would need to set LD_LIBRARY_PATH to point to these, you could
|
at all cost. You would need to set `LD_LIBRARY_PATH` to point to these, you
|
||||||
accidentally type "make install" and install them system wide - so don't. Really
|
could accidentally type "make install" and install them system wide - so don't.
|
||||||
don't. **Always compile libraries you want to have instrumented as static and
|
Really don't. **Always compile libraries you want to have instrumented as static
|
||||||
link these to the target program!**
|
and link these to the target program!**
|
||||||
|
|
||||||
Then build the target. (Usually with `make`)
|
Then build the target. (Usually with `make`.)
|
||||||
|
|
||||||
**NOTES**
|
**NOTES**
|
||||||
|
|
||||||
@ -254,45 +288,75 @@ Then build the target. (Usually with `make`)
|
|||||||
|
|
||||||
3. In case the configure/build system complains about AFL++'s compiler and
|
3. In case the configure/build system complains about AFL++'s compiler and
|
||||||
aborts, then set `export AFL_NOOPT=1` which will then just behave like the
|
aborts, then set `export AFL_NOOPT=1` which will then just behave like the
|
||||||
real compiler. This option has to be unset again before building the target!
|
real compiler and run the configure step separately. For building the target
|
||||||
|
afterwards this option has to be unset again!
|
||||||
|
|
||||||
#### configure
|
#### configure
|
||||||
|
|
||||||
For `configure` build systems this is usually done by:
|
For `configure` build systems, this is usually done by:
|
||||||
|
|
||||||
`CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared`
|
```
|
||||||
|
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if you are using the (better) afl-clang-lto compiler, you also have to
|
||||||
|
set `AR` to llvm-ar[-VERSION] and `RANLIB` to llvm-ranlib[-VERSION] - as is
|
||||||
|
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||||
|
|
||||||
|
#### CMake
|
||||||
|
|
||||||
|
For CMake build systems, this is usually done by:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..
|
||||||
|
```
|
||||||
|
|
||||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
||||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
||||||
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||||
|
|
||||||
#### cmake
|
#### Meson Build System
|
||||||
|
|
||||||
For `cmake` build systems this is usually done by:
|
For the Meson Build System, you have to set the AFL++ compiler with the very
|
||||||
|
first command!
|
||||||
|
|
||||||
`mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
|
```
|
||||||
|
CC=afl-cc CXX=afl-c++ meson
|
||||||
|
```
|
||||||
|
|
||||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
#### Other build systems or if configure/cmake didn't work
|
||||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
|
||||||
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
|
||||||
|
|
||||||
#### meson
|
Sometimes `cmake` and `configure` do not pick up the AFL++ compiler or the
|
||||||
|
`RANLIB`/`AR` that is needed - because this was just not foreseen by the
|
||||||
|
developer of the target. Or they have non-standard options. Figure out if there
|
||||||
|
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`).
|
||||||
|
|
||||||
For meson you have to set the AFL++ compiler with the very first command!
|
In complex, weird, alien build systems you can try this neat project:
|
||||||
`CC=afl-cc CXX=afl-c++ meson`
|
[https://github.com/fuzzah/exeptor](https://github.com/fuzzah/exeptor)
|
||||||
|
|
||||||
#### other build systems or if configure/cmake didn't work
|
#### Linker scripts
|
||||||
|
|
||||||
Sometimes cmake and configure do not pick up the AFL++ compiler, or the
|
If the project uses linker scripts to hide the symbols exported by the
|
||||||
ranlib/ar that is needed - because this was just not foreseen by the developer
|
binary, then you may see errors such as:
|
||||||
of the target. Or they have non-standard options. Figure out if there 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
|
undefined symbol: __afl_area_ptr
|
||||||
compiler (and/or ranlib and ar).
|
```
|
||||||
|
|
||||||
|
The solution is to modify the linker script to add:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
global:
|
||||||
|
__afl_*;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### f) Better instrumentation
|
### f) Better instrumentation
|
||||||
|
|
||||||
If you just fuzz a target program as-is you are wasting a great opportunity for
|
If you just fuzz a target program as-is, you are wasting a great opportunity for
|
||||||
much more fuzzing speed.
|
much more fuzzing speed.
|
||||||
|
|
||||||
This variant requires the usage of afl-clang-lto, afl-clang-fast or
|
This variant requires the usage of afl-clang-lto, afl-clang-fast or
|
||||||
@ -304,7 +368,7 @@ that you want to fuzz, plus a few specific AFL++ functions around it. See
|
|||||||
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
Basically if you do not fuzz a target in persistent mode, then you are just
|
Basically, if you do not fuzz a target in persistent mode, then you are just
|
||||||
doing it for a hobby and not professionally :-).
|
doing it for a hobby and not professionally :-).
|
||||||
|
|
||||||
### g) libfuzzer fuzzer harnesses with LLVMFuzzerTestOneInput()
|
### g) libfuzzer fuzzer harnesses with LLVMFuzzerTestOneInput()
|
||||||
@ -319,7 +383,7 @@ afl-clang-fast++ -fsanitize=fuzzer -o harness harness.cpp targetlib.a
|
|||||||
```
|
```
|
||||||
|
|
||||||
You can even use advanced libfuzzer features like `FuzzedDataProvider`,
|
You can even use advanced libfuzzer features like `FuzzedDataProvider`,
|
||||||
`LLVMFuzzerMutate()` etc. and they will work!
|
`LLVMFuzzerInitialize()` etc. and they will work!
|
||||||
|
|
||||||
The generated binary is fuzzed with afl-fuzz like any other fuzz target.
|
The generated binary is fuzzed with afl-fuzz like any other fuzz target.
|
||||||
|
|
||||||
@ -354,22 +418,28 @@ You can find many good examples of starting files in the
|
|||||||
### b) Making the input corpus unique
|
### b) Making the input corpus unique
|
||||||
|
|
||||||
Use the AFL++ tool `afl-cmin` to remove inputs from the corpus that do not
|
Use the AFL++ tool `afl-cmin` to remove inputs from the corpus that do not
|
||||||
produce a new path/coverage in the target.
|
produce a new path/coverage in the target:
|
||||||
|
|
||||||
Put all files from step a) into one directory, e.g., INPUTS.
|
1. Put all files from [step a](#a-collecting-inputs) into one directory, e.g.,
|
||||||
|
`INPUTS`.
|
||||||
|
2. Run afl-cmin:
|
||||||
|
* If the target program is to be called by fuzzing as `bin/target INPUTFILE`,
|
||||||
|
replace the INPUTFILE argument that the target program would read from with
|
||||||
|
`@@`:
|
||||||
|
|
||||||
If the target program is to be called by fuzzing as `bin/target -d INPUTFILE`
|
```
|
||||||
the run afl-cmin like this:
|
afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt @@
|
||||||
|
```
|
||||||
|
|
||||||
`afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -d @@`
|
* If the target reads from stdin (standard input) instead, just omit the `@@`
|
||||||
|
as this is the default:
|
||||||
|
|
||||||
Note that the INPUTFILE argument that the target program would read from has to
|
```
|
||||||
be set as `@@`.
|
afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt
|
||||||
|
```
|
||||||
|
|
||||||
If the target reads from stdin instead, just omit the `@@` as this is the
|
This step is highly recommended, because afterwards the testcase corpus is not
|
||||||
default.
|
bloated with duplicates anymore, which would slow down the fuzzing progress!
|
||||||
|
|
||||||
This step is highly recommended!
|
|
||||||
|
|
||||||
### c) Minimizing all corpus files
|
### c) Minimizing all corpus files
|
||||||
|
|
||||||
@ -381,18 +451,20 @@ however, it is a long process as this has to be done for every file:
|
|||||||
mkdir input
|
mkdir input
|
||||||
cd INPUTS_UNIQUE
|
cd INPUTS_UNIQUE
|
||||||
for i in *; do
|
for i in *; do
|
||||||
afl-tmin -i "$i" -o "../input/$i" -- bin/target -d @@
|
afl-tmin -i "$i" -o "../input/$i" -- bin/target -someopt @@
|
||||||
done
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
This step can also be parallelized, e.g., with `parallel`. Note that this step
|
This step can also be parallelized, e.g., with `parallel`.
|
||||||
is rather optional though.
|
|
||||||
|
Note that this step is rather optional though.
|
||||||
|
|
||||||
### Done!
|
### Done!
|
||||||
|
|
||||||
The INPUTS_UNIQUE/ directory from step b) - or even better the directory input/
|
The INPUTS_UNIQUE/ directory from [step b](#b-making-the-input-corpus-unique) -
|
||||||
if you minimized the corpus in step c) - is the resulting input corpus directory
|
or even better the directory input/ if you minimized the corpus in
|
||||||
to be used in fuzzing! :-)
|
[step c](#c-minimizing-all-corpus-files) - is the resulting input corpus
|
||||||
|
directory to be used in fuzzing! :-)
|
||||||
|
|
||||||
## 3. Fuzzing the target
|
## 3. Fuzzing the target
|
||||||
|
|
||||||
@ -400,77 +472,90 @@ In this final step, fuzz the target. There are not that many important options
|
|||||||
to run the target - unless you want to use many CPU cores/threads for the
|
to run the target - unless you want to use many CPU cores/threads for the
|
||||||
fuzzing, which will make the fuzzing much more useful.
|
fuzzing, which will make the fuzzing much more useful.
|
||||||
|
|
||||||
If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
|
If you just use one instance for fuzzing, then you are fuzzing just for fun and
|
||||||
seriously :-)
|
not seriously :-)
|
||||||
|
|
||||||
### a) Running afl-fuzz
|
### a) Running afl-fuzz
|
||||||
|
|
||||||
Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
|
Before you do even a test run of afl-fuzz, execute `sudo afl-system-config` (on
|
||||||
the host if you execute afl-fuzz in a docker container). This reconfigures the
|
the host if you execute afl-fuzz in a Docker container). This reconfigures the
|
||||||
system for optimal speed - which afl-fuzz checks and bails otherwise. Set
|
system for optimal speed - which afl-fuzz checks and bails otherwise. Set
|
||||||
`export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot run
|
`export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot run
|
||||||
afl-system-config with root privileges on the host for whatever reason.
|
afl-system-config with root privileges on the host for whatever reason.
|
||||||
|
|
||||||
Note there is also `sudo afl-persistent-config` which sets additional permanent
|
Note:
|
||||||
boot options for a much better fuzzing performance.
|
|
||||||
|
|
||||||
Note that both scripts improve your fuzzing performance but also decrease your
|
* There is also `sudo afl-persistent-config` which sets additional permanent
|
||||||
system protection against attacks! So set strong firewall rules and only expose
|
boot options for a much better fuzzing performance.
|
||||||
SSH as a network service if you use these (which is highly recommended).
|
* Both scripts improve your fuzzing performance but also decrease your system
|
||||||
|
protection against attacks! So set strong firewall rules and only expose SSH
|
||||||
|
as a network service if you use these (which is highly recommended).
|
||||||
|
|
||||||
If you have an input corpus from step 2, then specify this directory with the
|
If you have an input corpus from [step 2](#2-preparing-the-fuzzing-campaign),
|
||||||
`-i` option. Otherwise, create a new directory and create a file with any
|
then specify this directory with the `-i` option. Otherwise, create a new
|
||||||
content as test data in there.
|
directory and create a file with any content as test data in there.
|
||||||
|
|
||||||
If you do not want anything special, the defaults are already usually best,
|
If you do not want anything special, the defaults are already usually best,
|
||||||
hence all you need is to specify the seed input directory with the result of
|
hence all you need is to specify the seed input directory with the result of
|
||||||
step [2a) Collect inputs](#a-collect-inputs):
|
step [2a) Collecting inputs](#a-collecting-inputs):
|
||||||
|
|
||||||
`afl-fuzz -i input -o output -- bin/target -d @@`
|
```
|
||||||
|
afl-fuzz -i input -o output -- bin/target -someopt @@
|
||||||
|
```
|
||||||
|
|
||||||
Note that the directory specified with `-o` will be created if it does not
|
Note that the directory specified with `-o` will be created if it does not
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
It can be valuable to run afl-fuzz in a screen or tmux shell so you can log off,
|
It can be valuable to run afl-fuzz in a `screen` or `tmux` shell so you can log
|
||||||
or afl-fuzz is not aborted if you are running it in a remote ssh session where
|
off, or afl-fuzz is not aborted if you are running it in a remote ssh session
|
||||||
the connection fails in between. Only do that though once you have verified that
|
where the connection fails in between. Only do that though once you have
|
||||||
your fuzzing setup works! Run it like `screen -dmS afl-main -- afl-fuzz -M
|
verified that your fuzzing setup works! Run it like `screen -dmS afl-main --
|
||||||
main-$HOSTNAME -i ...` and it will start away in a screen session. To enter this
|
afl-fuzz -M main-$HOSTNAME -i ...` and it will start away in a screen session.
|
||||||
session, type `screen -r afl-main`. You see - it makes sense to name the screen
|
To enter this session, type `screen -r afl-main`. You see - it makes sense to
|
||||||
session same as the afl-fuzz -M/-S naming :-) For more information on screen or
|
name the screen session same as the afl-fuzz `-M`/`-S` naming :-) For more
|
||||||
tmux, check their documentation.
|
information on screen or tmux, check their documentation.
|
||||||
|
|
||||||
If you need to stop and re-start the fuzzing, use the same command line options
|
If you need to stop and re-start the fuzzing, use the same command line options
|
||||||
(or even change them by selecting a different power schedule or another mutation
|
(or even change them by selecting a different power schedule or another mutation
|
||||||
mode!) and switch the input directory with a dash (`-`):
|
mode!) and switch the input directory with a dash (`-`):
|
||||||
|
|
||||||
`afl-fuzz -i - -o output -- bin/target -d @@`
|
```
|
||||||
|
afl-fuzz -i - -o output -- bin/target -someopt @@
|
||||||
|
```
|
||||||
|
|
||||||
Adding a dictionary is helpful. See the directory
|
Adding a dictionary is helpful. You have to following options:
|
||||||
[dictionaries/](../dictionaries/) if something is already included for your data
|
|
||||||
format, and tell afl-fuzz to load that dictionary by adding `-x
|
* See the directory
|
||||||
dictionaries/FORMAT.dict`. With afl-clang-lto, you have an autodictionary
|
[dictionaries/](../dictionaries/), if something is already included for your
|
||||||
generation for which you need to do nothing except to use afl-clang-lto as the
|
data format, and tell afl-fuzz to load that dictionary by adding `-x
|
||||||
compiler. You also have the option to generate a dictionary yourself, see
|
dictionaries/FORMAT.dict`.
|
||||||
[utils/libtokencap/README.md](../utils/libtokencap/README.md).
|
* With `afl-clang-lto`, you have an autodictionary generation for which you need
|
||||||
|
to do nothing except to use afl-clang-lto as the compiler.
|
||||||
|
* With `afl-clang-fast`, you can set
|
||||||
|
`AFL_LLVM_DICT2FILE=/full/path/to/new/file.dic` to automatically generate a
|
||||||
|
dictionary during target compilation.
|
||||||
|
* You also have the option to generate a dictionary yourself during an
|
||||||
|
independent run of the target, see
|
||||||
|
[utils/libtokencap/README.md](../utils/libtokencap/README.md).
|
||||||
|
* Finally, you can also write a dictionary file manually, of course.
|
||||||
|
|
||||||
afl-fuzz has a variety of options that help to workaround target quirks like
|
afl-fuzz has a variety of options that help to workaround target quirks like
|
||||||
specific locations for the input file (`-f`), performing deterministic fuzzing
|
very specific locations for the input file (`-f`), performing deterministic
|
||||||
(`-D`) and many more. Check out `afl-fuzz -h`.
|
fuzzing (`-D`) and many more. Check out `afl-fuzz -h`.
|
||||||
|
|
||||||
We highly recommend that you set a memory limit for running the target with `-m`
|
We highly recommend that you set a memory limit for running the target with `-m`
|
||||||
which defines the maximum memory in MB. This prevents a potential out-of-memory
|
which defines the maximum memory in MB. This prevents a potential out-of-memory
|
||||||
problem for your system plus helps you detect missing `malloc()` failure
|
problem for your system plus helps you detect missing `malloc()` failure
|
||||||
handling in the target. Play around with various -m values until you find one
|
handling in the target. Play around with various `-m` values until you find one
|
||||||
that safely works for all your input seeds (if you have good ones and then
|
that safely works for all your input seeds (if you have good ones and then
|
||||||
double or quadruple that.
|
double or quadruple that).
|
||||||
|
|
||||||
By default, afl-fuzz never stops fuzzing. To terminate AFL++, press Control-C or
|
By default, afl-fuzz never stops fuzzing. To terminate AFL++, press Control-C or
|
||||||
send a signal SIGINT. You can limit the number of executions or approximate
|
send a signal SIGINT. You can limit the number of executions or approximate
|
||||||
runtime in seconds with options also.
|
runtime in seconds with options also.
|
||||||
|
|
||||||
When you start afl-fuzz you will see a user interface that shows what the status
|
When you start afl-fuzz, you will see a user interface that shows what the
|
||||||
is:
|
status is:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -514,8 +599,8 @@ can set the cache size (in MB) by setting the environment variable
|
|||||||
|
|
||||||
There should be one main fuzzer (`-M main-$HOSTNAME` option) and as many
|
There should be one main fuzzer (`-M main-$HOSTNAME` option) and as many
|
||||||
secondary fuzzers (e.g., `-S variant1`) as you have cores that you use. Every
|
secondary fuzzers (e.g., `-S variant1`) as you have cores that you use. Every
|
||||||
-M/-S entry needs a unique name (that can be whatever), however, the same -o
|
`-M`/`-S` entry needs a unique name (that can be whatever), however, the same
|
||||||
output directory location has to be used for all instances.
|
`-o` output directory location has to be used for all instances.
|
||||||
|
|
||||||
For every secondary fuzzer there should be a variation, e.g.:
|
For every secondary fuzzer there should be a variation, e.g.:
|
||||||
* one should fuzz the target that was compiled differently: with sanitizers
|
* one should fuzz the target that was compiled differently: with sanitizers
|
||||||
@ -530,9 +615,10 @@ For every secondary fuzzer there should be a variation, e.g.:
|
|||||||
|
|
||||||
All other secondaries should be used like this:
|
All other secondaries should be used like this:
|
||||||
* a quarter to a third with the MOpt mutator enabled: `-L 0`
|
* a quarter to a third with the MOpt mutator enabled: `-L 0`
|
||||||
* run with a different power schedule, recommended are:
|
* run with a different power schedule, recommended are: `fast` (default),
|
||||||
`fast (default), explore, coe, lin, quad, exploit and rare` which you can set
|
`explore`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
|
||||||
with, e.g., `-p explore`
|
the `-p` option, e.g., `-p explore`. See the
|
||||||
|
[FAQ](FAQ.md#what-are-power-schedules) for details.
|
||||||
* a few instances should use the old queue cycling with `-Z`
|
* a few instances should use the old queue cycling with `-Z`
|
||||||
|
|
||||||
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
|
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
|
||||||
@ -556,7 +642,7 @@ A long list can be found at
|
|||||||
[https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL).
|
[https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL).
|
||||||
|
|
||||||
However, you can also sync AFL++ with honggfuzz, libfuzzer with `-entropic=1`,
|
However, you can also sync AFL++ with honggfuzz, libfuzzer with `-entropic=1`,
|
||||||
etc. Just show the main fuzzer (-M) with the `-F` option where the queue/work
|
etc. Just show the main fuzzer (`-M`) with the `-F` option where the queue/work
|
||||||
directory of a different fuzzer is, e.g., `-F /src/target/honggfuzz`. Using
|
directory of a different fuzzer is, e.g., `-F /src/target/honggfuzz`. Using
|
||||||
honggfuzz (with `-n 1` or `-n 2`) and libfuzzer in parallel is highly
|
honggfuzz (with `-n 1` or `-n 2`) and libfuzzer in parallel is highly
|
||||||
recommended!
|
recommended!
|
||||||
@ -575,7 +661,7 @@ Now there are three strategies on how you can sync between the servers:
|
|||||||
* regularly (~4h): this ensures that all fuzzing campaigns on the servers "see"
|
* regularly (~4h): this ensures that all fuzzing campaigns on the servers "see"
|
||||||
the same thing. It is like fuzzing on a huge server.
|
the same thing. It is like fuzzing on a huge server.
|
||||||
* in intervals of 1/10th of the overall expected runtime of the fuzzing you
|
* in intervals of 1/10th of the overall expected runtime of the fuzzing you
|
||||||
sync. This tries a bit to combine both. have some individuality of the paths
|
sync. This tries a bit to combine both. Have some individuality of the paths
|
||||||
each campaign on a server explores, on the other hand if one gets stuck where
|
each campaign on a server explores, on the other hand if one gets stuck where
|
||||||
another found progress this is handed over making it unstuck.
|
another found progress this is handed over making it unstuck.
|
||||||
|
|
||||||
@ -596,7 +682,8 @@ done
|
|||||||
```
|
```
|
||||||
|
|
||||||
You can run this manually, per cron job - as you need it. There is a more
|
You can run this manually, per cron job - as you need it. There is a more
|
||||||
complex and configurable script in `utils/distributed_fuzzing`.
|
complex and configurable script in
|
||||||
|
[utils/distributed_fuzzing](../utils/distributed_fuzzing).
|
||||||
|
|
||||||
### e) The status of the fuzz campaign
|
### e) The status of the fuzz campaign
|
||||||
|
|
||||||
@ -612,7 +699,7 @@ If you have multiple servers, then use the command after a sync or you have to
|
|||||||
execute this script per server.
|
execute this script per server.
|
||||||
|
|
||||||
Another tool to inspect the current state and history of a specific instance is
|
Another tool to inspect the current state and history of a specific instance is
|
||||||
afl-plot, which generates an index.html file and a graphs that show how the
|
afl-plot, which generates an index.html file and graphs that show how the
|
||||||
fuzzing instance is performing. The syntax is `afl-plot instance_dir web_dir`,
|
fuzzing instance is performing. The syntax is `afl-plot instance_dir web_dir`,
|
||||||
e.g., `afl-plot out/default /srv/www/htdocs/plot`.
|
e.g., `afl-plot out/default /srv/www/htdocs/plot`.
|
||||||
|
|
||||||
@ -623,7 +710,7 @@ To stop an afl-fuzz run, press Control-C.
|
|||||||
To restart an afl-fuzz run, just reuse the same command line but replace the `-i
|
To restart an afl-fuzz run, just reuse the same command line but replace the `-i
|
||||||
directory` with `-i -` or set `AFL_AUTORESUME=1`.
|
directory` with `-i -` or set `AFL_AUTORESUME=1`.
|
||||||
|
|
||||||
If you want to add new seeds to a fuzzing campaign you can run a temporary
|
If you want to add new seeds to a fuzzing campaign, you can run a temporary
|
||||||
fuzzing instance, e.g., when your main fuzzer is using `-o out` and the new
|
fuzzing instance, e.g., when your main fuzzer is using `-o out` and the new
|
||||||
seeds are in `newseeds/` directory:
|
seeds are in `newseeds/` directory:
|
||||||
|
|
||||||
@ -686,21 +773,21 @@ or honggfuzz.
|
|||||||
### i) Improve the speed!
|
### i) Improve the speed!
|
||||||
|
|
||||||
* Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20
|
* Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20
|
||||||
speed increase)
|
speed increase).
|
||||||
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input
|
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input
|
||||||
file on a tempfs location, see [env_variables.md](env_variables.md)
|
file on a tempfs location, see [env_variables.md](env_variables.md).
|
||||||
* Linux: Improve kernel performance: modify `/etc/default/grub`, set
|
* Linux: Improve kernel performance: modify `/etc/default/grub`, set
|
||||||
`GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off
|
`GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off
|
||||||
mitigations=off no_stf_barrier noibpb noibrs nopcid nopti
|
mitigations=off no_stf_barrier noibpb noibrs nopcid nopti
|
||||||
nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off
|
nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off
|
||||||
spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then
|
spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then
|
||||||
`update-grub` and `reboot` (warning: makes the system more insecure) - you can
|
`update-grub` and `reboot` (warning: makes the system more insecure) - you can
|
||||||
also just run `sudo afl-persistent-config`
|
also just run `sudo afl-persistent-config`.
|
||||||
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a
|
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a
|
||||||
bit faster than on any other journaling filesystem
|
bit faster than on any other journaling filesystem.
|
||||||
* Use your cores! [3c) Using multiple cores](#c-using-multiple-cores)
|
* Use your cores! See [3c) Using multiple cores](#c-using-multiple-cores).
|
||||||
* Run `sudo afl-system-config` before starting the first afl-fuzz instance after
|
* Run `sudo afl-system-config` before starting the first afl-fuzz instance after
|
||||||
a reboot
|
a reboot.
|
||||||
|
|
||||||
### j) Going beyond crashes
|
### j) Going beyond crashes
|
||||||
|
|
||||||
@ -751,9 +838,10 @@ Here are some of the most important caveats for AFL++:
|
|||||||
|
|
||||||
- There is no direct support for fuzzing network services, background daemons,
|
- 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
|
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
|
simple code changes to make them behave in a more traditional way. Preeny or
|
||||||
offer a relatively simple option, too - see:
|
libdesock may offer a relatively simple option, too - see:
|
||||||
[https://github.com/zardus/preeny](https://github.com/zardus/preeny)
|
[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:
|
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)
|
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
|
||||||
@ -774,7 +862,7 @@ making it easier to diagnose faults.
|
|||||||
Having said that, it's important to acknowledge that some fuzzing crashes can be
|
Having said that, it's important to acknowledge that some fuzzing crashes can be
|
||||||
difficult to quickly evaluate for exploitability without a lot of debugging and
|
difficult to quickly evaluate for exploitability without a lot of debugging and
|
||||||
code analysis work. To assist with this task, afl-fuzz supports a very unique
|
code analysis work. To assist with this task, afl-fuzz supports a very unique
|
||||||
"crash exploration" mode enabled with the -C flag.
|
"crash exploration" mode enabled with the `-C` flag.
|
||||||
|
|
||||||
In this mode, the fuzzer takes one or more crashing test cases as the input and
|
In this mode, the fuzzer takes one or more crashing test cases as the input and
|
||||||
uses its feedback-driven fuzzing strategies to very quickly enumerate all code
|
uses its feedback-driven fuzzing strategies to very quickly enumerate all code
|
||||||
@ -800,43 +888,44 @@ mode, it will happily accept instrumented and non-instrumented binaries. In the
|
|||||||
non-crashing mode, the minimizer relies on standard AFL++ instrumentation to
|
non-crashing mode, the minimizer relies on standard AFL++ instrumentation to
|
||||||
make the file simpler without altering the execution path.
|
make the file simpler without altering the execution path.
|
||||||
|
|
||||||
The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with
|
The minimizer accepts the `-m`, `-t`, `-f`, and `@@` syntax in a manner
|
||||||
afl-fuzz.
|
compatible with afl-fuzz.
|
||||||
|
|
||||||
Another tool in AFL++ is the afl-analyze tool. It takes an input file, attempts
|
Another tool in AFL++ is the afl-analyze tool. It takes an input file, attempts
|
||||||
to sequentially flip bytes, and observes the behavior of the tested program. It
|
to sequentially flip bytes and observes the behavior of the tested program. It
|
||||||
then color-codes the input based on which sections appear to be critical, and
|
then color-codes the input based on which sections appear to be critical and
|
||||||
which are not; while not bulletproof, it can often offer quick insights into
|
which are not; while not bulletproof, it can often offer quick insights into
|
||||||
complex file formats.
|
complex file formats.
|
||||||
|
|
||||||
## 5. CI fuzzing
|
## 5. CI fuzzing
|
||||||
|
|
||||||
Some notes on CI fuzzing - this fuzzing is different to normal fuzzing campaigns
|
Some notes on continuous integration (CI) fuzzing - this fuzzing is different to
|
||||||
as these are much shorter runnings.
|
normal fuzzing campaigns as these are much shorter runnings.
|
||||||
|
|
||||||
1. Always:
|
1. Always:
|
||||||
* LTO has a much longer compile time which is diametrical to short fuzzing -
|
* LTO has a much longer compile time which is diametrical to short fuzzing -
|
||||||
hence use afl-clang-fast instead.
|
hence use afl-clang-fast instead.
|
||||||
* If you compile with CMPLOG, then you can save fuzzing time and reuse that
|
* If you compile with CMPLOG, then you can save compilation time and reuse
|
||||||
compiled target for both the `-c` option and the main fuzz target. This
|
that compiled target with the `-c` option and as the main fuzz target.
|
||||||
will impact the speed by ~15% though.
|
This will impact the speed by ~15% though.
|
||||||
* `AFL_FAST_CAL` - Enable fast calibration, this halves the time the
|
* `AFL_FAST_CAL` - enables fast calibration, this halves the time the
|
||||||
saturated corpus needs to be loaded.
|
saturated corpus needs to be loaded.
|
||||||
* `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new finds, not the
|
* `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new finds, not the initial
|
||||||
initial corpus as this very likely has been done for them already.
|
corpus as this very likely has been done for them already.
|
||||||
* Keep the generated corpus, use afl-cmin and reuse it every time!
|
* Keep the generated corpus, use afl-cmin and reuse it every time!
|
||||||
|
|
||||||
2. Additionally randomize the AFL++ compilation options, e.g.:
|
2. Additionally randomize the AFL++ compilation options, e.g.:
|
||||||
* 40% for `AFL_LLVM_CMPLOG`
|
* 30% for `AFL_LLVM_CMPLOG`
|
||||||
* 10% for `AFL_LLVM_LAF_ALL`
|
* 5% for `AFL_LLVM_LAF_ALL`
|
||||||
|
|
||||||
3. Also randomize the afl-fuzz runtime options, e.g.:
|
3. Also randomize the afl-fuzz runtime options, e.g.:
|
||||||
* 65% for `AFL_DISABLE_TRIM`
|
* 65% for `AFL_DISABLE_TRIM`
|
||||||
|
* 50% for `AFL_KEEP_TIMEOUTS`
|
||||||
* 50% use a dictionary generated by `AFL_LLVM_DICT2FILE`
|
* 50% use a dictionary generated by `AFL_LLVM_DICT2FILE`
|
||||||
* 40% use MOpt (`-L 0`)
|
* 40% use MOpt (`-L 0`)
|
||||||
* 40% for `AFL_EXPAND_HAVOC_NOW`
|
* 40% for `AFL_EXPAND_HAVOC_NOW`
|
||||||
* 20% for old queue processing (`-Z`)
|
* 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
|
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
|
fuzzing. `-M` enables old queue handling etc. which is good for a fuzzing
|
||||||
@ -849,8 +938,8 @@ and
|
|||||||
|
|
||||||
## The End
|
## The End
|
||||||
|
|
||||||
Check out the [FAQ](FAQ.md) if it maybe answers your question (that you might
|
Check out the [FAQ](FAQ.md). Maybe it answers your question (that you might not
|
||||||
not even have known you had ;-) ).
|
even have known you had ;-) ).
|
||||||
|
|
||||||
This is basically all you need to know to professionally run fuzzing campaigns.
|
This is basically all you need to know to professionally run fuzzing campaigns.
|
||||||
If you want to know more, the tons of texts in [docs/](./) will have you
|
If you want to know more, the tons of texts in [docs/](./) will have you
|
||||||
@ -858,4 +947,4 @@ covered.
|
|||||||
|
|
||||||
Note that there are also a lot of tools out there that help fuzzing with AFL++
|
Note that there are also a lot of tools out there that help fuzzing with AFL++
|
||||||
(some might be deprecated or unsupported), see
|
(some might be deprecated or unsupported), see
|
||||||
[third_party_tools.md](third_party_tools.md).
|
[third_party_tools.md](third_party_tools.md).
|
||||||
|
@ -19,18 +19,18 @@ Mentor: vanhauser-thc
|
|||||||
## WASM Instrumentation
|
## WASM Instrumentation
|
||||||
|
|
||||||
Currently, AFL++ can be used for source code fuzzing and traditional binaries.
|
Currently, AFL++ can be used for source code fuzzing and traditional binaries.
|
||||||
With the rise of WASM as compile target, however, a novel way of instrumentation
|
With the rise of WASM as a compile target, however, a novel way of
|
||||||
needs to be implemented for binaries compiled to Webassembly. This can either be
|
instrumentation needs to be implemented for binaries compiled to Webassembly.
|
||||||
done by inserting instrumentation directly into the WASM AST, or by patching
|
This can either be done by inserting instrumentation directly into the WASM AST,
|
||||||
feedback into a WASM VMs of choice, similar to the current Unicorn
|
or by patching feedback into a WASM VM of choice, similar to the current Unicorn
|
||||||
instrumentation.
|
instrumentation.
|
||||||
|
|
||||||
Mentor: any
|
Mentor: any
|
||||||
|
|
||||||
## Support other programming languages
|
## Support other programming languages
|
||||||
|
|
||||||
Other programming languages also use llvm hence they could (easily?) supported
|
Other programming languages also use llvm hence they could be (easily?)
|
||||||
for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ...
|
supported for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ...
|
||||||
|
|
||||||
GCC also supports: Objective-C, Fortran, Ada, Go, and D (according to
|
GCC also supports: Objective-C, Fortran, Ada, Go, and D (according to
|
||||||
[Gcc homepage](https://gcc.gnu.org/))
|
[Gcc homepage](https://gcc.gnu.org/))
|
||||||
@ -54,4 +54,4 @@ Mentor: domenukk
|
|||||||
## Your idea!
|
## Your idea!
|
||||||
|
|
||||||
Finally, we are open to proposals! Create an issue at
|
Finally, we are open to proposals! Create an issue at
|
||||||
https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-)
|
https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-)
|
||||||
|
@ -5,24 +5,25 @@ changes.
|
|||||||
|
|
||||||
## From version 3.00 onwards
|
## From version 3.00 onwards
|
||||||
|
|
||||||
With AFL++ 3.13-3.20, we introduce FRIDA mode (`-O`) to have an alternative for
|
With AFL++ 4.00, we introduced the following changes from previous behaviors:
|
||||||
binary-only fuzzing. It is slower than QEMU mode but works on MacOS, Android,
|
* the complete documentation was overhauled and restructured thanks to @llzmb!
|
||||||
iOS etc.
|
* a new CMPLOG target format requires recompiling CMPLOG targets for use with
|
||||||
|
AFL++ 4.0 onwards
|
||||||
|
* better naming for several fields in the UI
|
||||||
|
|
||||||
With AFL++ 3.15, we introduced the following changes from previous behaviors:
|
With AFL++ 3.15, we introduced the following changes from previous behaviors:
|
||||||
* Also -M main mode does not do deterministic fuzzing by default anymore
|
* afl-cmin and afl-showmap `-Ci` now descend into subdirectories like afl-fuzz
|
||||||
* afl-cmin and afl-showmap -Ci now descent into subdirectories like afl-fuzz
|
`-i` does (but note that afl-cmin.bash does not)
|
||||||
-i does (but note that afl-cmin.bash does not)
|
|
||||||
|
|
||||||
With AFL++ 3.14, we introduced the following changes from previous behaviors:
|
With AFL++ 3.14, we introduced the following changes from previous behaviors:
|
||||||
* afl-fuzz: deterministic fuzzing it not a default for -M main anymore
|
* afl-fuzz: deterministic fuzzing is not a default for `-M main` anymore
|
||||||
* afl-cmin/afl-showmap -i now descends into subdirectories (afl-cmin.bash,
|
* afl-cmin/afl-showmap -i now descends into subdirectories (afl-cmin.bash,
|
||||||
however, does not)
|
however, does not)
|
||||||
|
|
||||||
With AFL++ 3.10, we introduced the following changes from previous behaviors:
|
With AFL++ 3.10, we introduced the following changes from previous behaviors:
|
||||||
* The '+' feature of the '-t' option now means to auto-calculate the timeout
|
* The '+' feature of the `-t` option now means to auto-calculate the timeout
|
||||||
with the value given being the maximum timeout. The original meaning of
|
with the value given being the maximum timeout. The original meaning of
|
||||||
"skipping timeouts instead of abort" is now inherent to the -t option.
|
"skipping timeouts instead of abort" is now inherent to the `-t` option.
|
||||||
|
|
||||||
With AFL++ 3.00, we introduced changes that break some previous AFL and AFL++
|
With AFL++ 3.00, we introduced changes that break some previous AFL and AFL++
|
||||||
behaviors and defaults:
|
behaviors and defaults:
|
||||||
@ -40,19 +41,20 @@ behaviors and defaults:
|
|||||||
if any were given. This allows to fuzz targets build regularly like those
|
if any were given. This allows to fuzz targets build regularly like those
|
||||||
for debug or release versions.
|
for debug or release versions.
|
||||||
* afl-fuzz:
|
* afl-fuzz:
|
||||||
* if neither -M or -S is specified, `-S default` is assumed, so more fuzzers
|
* if neither `-M` or `-S` is specified, `-S default` is assumed, so more
|
||||||
can easily be added later
|
fuzzers can easily be added later
|
||||||
* `-i` input directory option now descends into subdirectories. It also does
|
* `-i` input directory option now descends into subdirectories. It also does
|
||||||
not fatal on crashes and too large files, instead it skips them and uses
|
not fail on crashes and too large files, instead it skips them and uses
|
||||||
them for splicing mutations
|
them for splicing mutations
|
||||||
* -m none is now default, set memory limits (in MB) with, e.g., -m 250
|
* `-m` none is now the default, set memory limits (in MB) with, e.g., `-m
|
||||||
* deterministic fuzzing is now disabled by default (unless using -M) and can
|
250`
|
||||||
be enabled with -D
|
* deterministic fuzzing is now disabled by default (unless using `-M`) and
|
||||||
|
can be enabled with `-D`
|
||||||
* a caching of test cases can now be performed and can be modified by
|
* a caching of test cases can now be performed and can be modified by
|
||||||
editing config.h for TESTCASE_CACHE or by specifying the environment
|
editing config.h for `TESTCASE_CACHE` or by specifying the environment
|
||||||
variable `AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500
|
variable `AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500
|
||||||
(default: 50).
|
(default: 50).
|
||||||
* -M mains do not perform trimming
|
* `-M` mains do not perform trimming
|
||||||
* examples/ got renamed to utils/
|
* `examples/` got renamed to `utils/`
|
||||||
* libtokencap/ libdislocator/ and qdbi_mode/ were moved to utils/
|
* `libtokencap/`, `libdislocator/`, and `qdbi_mode/` were moved to `utils/`
|
||||||
* afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH
|
* afl-cmin/afl-cmin.bash now search first in `PATH` and last in `AFL_PATH`
|
||||||
|
4
docs/resources/0_fuzzing_process_overview.drawio.svg
Normal file
After Width: | Height: | Size: 32 KiB |
4
docs/resources/1_instrument_target.drawio.svg
Normal file
After Width: | Height: | Size: 14 KiB |
4
docs/resources/2_prepare_campaign.drawio.svg
Normal file
After Width: | Height: | Size: 10 KiB |
4
docs/resources/3_fuzz_target.drawio.svg
Normal file
After Width: | Height: | Size: 11 KiB |
4
docs/resources/4_manage_campaign.drawio.svg
Normal file
After Width: | Height: | Size: 13 KiB |
@ -424,7 +424,7 @@
|
|||||||
"steppedLine": false,
|
"steppedLine": false,
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "fuzzing{type=\"unique_crashes\"}",
|
"expr": "fuzzing{type=\"saved_crashes\"}",
|
||||||
"interval": "",
|
"interval": "",
|
||||||
"legendFormat": "",
|
"legendFormat": "",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
@ -519,7 +519,7 @@
|
|||||||
"steppedLine": false,
|
"steppedLine": false,
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "fuzzing{type=\"unique_hangs\"}",
|
"expr": "fuzzing{type=\"saved_hangs\"}",
|
||||||
"interval": "",
|
"interval": "",
|
||||||
"legendFormat": "",
|
"legendFormat": "",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 141 KiB |
@ -1,11 +1,13 @@
|
|||||||
# Tools that help fuzzing with AFL++
|
# Tools that help fuzzing with AFL++
|
||||||
|
|
||||||
Speeding up fuzzing:
|
## Speeding up fuzzing
|
||||||
|
|
||||||
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
|
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
|
||||||
function you want to fuzz requires loading a file, this allows using the
|
function you want to fuzz requires loading a file, this allows using the
|
||||||
shared memory test case feature :-) - recommended.
|
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
|
* [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
|
that tries to speed up the process of minimization of a single test case by
|
||||||
using many CPU cores.
|
using many CPU cores.
|
||||||
@ -14,7 +16,8 @@ Minimization of test cases:
|
|||||||
* [halfempty](https://github.com/googleprojectzero/halfempty) - is a fast
|
* [halfempty](https://github.com/googleprojectzero/halfempty) - is a fast
|
||||||
utility for minimizing test cases by Tavis Ormandy based on parallelization.
|
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
|
* [disfuzz-afl](https://github.com/MartijnB/disfuzz-afl) - distributed fuzzing
|
||||||
for AFL.
|
for AFL.
|
||||||
* [AFLDFF](https://github.com/quantumvm/AFLDFF) - AFL distributed fuzzing
|
* [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
|
* [afl-in-the-cloud](https://github.com/abhisek/afl-in-the-cloud) - another
|
||||||
script for running AFL in AWS.
|
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
|
* [afl-utils](https://gitlab.com/rc0r/afl-utils) - a set of utilities for
|
||||||
automatic processing/analysis of crashes and reducing the number of test
|
automatic processing/analysis of crashes and reducing the number of test
|
||||||
cases.
|
cases.
|
||||||
@ -44,7 +48,10 @@ Deployment, management, monitoring, reporting
|
|||||||
* [afl-extras](https://github.com/fekir/afl-extras) - shell scripts to
|
* [afl-extras](https://github.com/fekir/afl-extras) - shell scripts to
|
||||||
parallelize afl-tmin, startup, and data collection.
|
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) -
|
* [afl-crash-analyzer](https://github.com/floyd-fuh/afl-crash-analyzer) -
|
||||||
another crash analyzer for AFL.
|
another crash analyzer for AFL.
|
||||||
* [fuzzer-utils](https://github.com/ThePatrickStar/fuzzer-utils) - a set of
|
* [fuzzer-utils](https://github.com/ThePatrickStar/fuzzer-utils) - a set of
|
||||||
@ -54,4 +61,4 @@ Crash processing
|
|||||||
* [AFLize](https://github.com/d33tah/aflize) - a tool that automatically
|
* [AFLize](https://github.com/d33tah/aflize) - a tool that automatically
|
||||||
generates builds of debian packages suitable for AFL.
|
generates builds of debian packages suitable for AFL.
|
||||||
* [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for
|
* [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for
|
||||||
working with input data.
|
working with input data.
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# Tutorials
|
# 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++:
|
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/)
|
* [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
|
||||||
@ -9,6 +13,7 @@ Here are some good write-ups to show how to effectively use AFL++:
|
|||||||
* [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
|
* [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
|
||||||
* [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
|
* [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
|
||||||
* [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
|
* [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
|
||||||
|
* [https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/](https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/)
|
||||||
|
|
||||||
If you do not want to follow a tutorial but rather try an exercise type of
|
If you do not want to follow a tutorial but rather try an exercise type of
|
||||||
training, then we can highly recommend the following:
|
training, then we can highly recommend the following:
|
||||||
@ -16,15 +21,25 @@ training, then we can highly recommend the following:
|
|||||||
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
|
* [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
|
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):
|
||||||
|
|
||||||
* Superion for AFL++:
|
|
||||||
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
|
|
||||||
* libprotobuf for AFL++:
|
* libprotobuf for AFL++:
|
||||||
[https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
|
[https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
|
||||||
* libprotobuf raw:
|
* libprotobuf raw:
|
||||||
[https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
|
[https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
|
||||||
* libprotobuf for old AFL++ API:
|
* libprotobuf for old AFL++ API:
|
||||||
[https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
|
[https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
|
||||||
|
* Superion for AFL++:
|
||||||
|
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
|
||||||
|
|
||||||
If you find other good ones, please send them to us :-)
|
## 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)
|
||||||
|
* [Blackbox Fuzzing #1: Start Binary-Only Fuzzing using AFL++ QEMU mode](https://www.youtube.com/watch?v=sjLFf9q2NRc)
|
||||||
|
* [HOPE 2020 (2020): Hunting Bugs in Your Sleep - How to Fuzz (Almost) Anything With AFL/AFL++](https://www.youtube.com/watch?v=A8ex1hqaQ7E)
|
||||||
|
* [How Fuzzing with AFL works!](https://www.youtube.com/watch?v=COHUWuLTbdk)
|
||||||
|
* [WOOT '20 - AFL++ : Combining Incremental Steps of Fuzzing Research](https://www.youtube.com/watch?v=cZidm6I7KWU)
|
||||||
|
|
||||||
|
If you find other good ones, please send them to us :-)
|
||||||
|
@ -13,6 +13,16 @@ JS_SRC:=$(BUILD_DIR)api.c
|
|||||||
JS_OBJ:=$(BUILD_DIR)api.o
|
JS_OBJ:=$(BUILD_DIR)api.o
|
||||||
SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
|
SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
|
||||||
OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))
|
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 \
|
CFLAGS+=-fPIC \
|
||||||
-D_GNU_SOURCE \
|
-D_GNU_SOURCE \
|
||||||
-D_FORTIFY_SOURCE=2 \
|
-D_FORTIFY_SOURCE=2 \
|
||||||
@ -21,6 +31,10 @@ CFLAGS+=-fPIC \
|
|||||||
-funroll-loops \
|
-funroll-loops \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
|
|
||||||
|
ifdef IS_ANDROID
|
||||||
|
CFLAGS+=-DANDROID
|
||||||
|
endif
|
||||||
|
|
||||||
AFL_CFLAGS:=-Wno-unused-parameter \
|
AFL_CFLAGS:=-Wno-unused-parameter \
|
||||||
-Wno-sign-compare \
|
-Wno-sign-compare \
|
||||||
-Wno-unused-function \
|
-Wno-unused-function \
|
||||||
@ -28,9 +42,16 @@ AFL_CFLAGS:=-Wno-unused-parameter \
|
|||||||
-Wno-int-to-pointer-cast \
|
-Wno-int-to-pointer-cast \
|
||||||
-Wno-pointer-sign
|
-Wno-pointer-sign
|
||||||
|
|
||||||
|
ifdef IS_ANDROID
|
||||||
|
LDFLAGS+= -static-libstdc++ \
|
||||||
|
-DANDROID \
|
||||||
|
-llog \
|
||||||
|
-shared
|
||||||
|
else
|
||||||
LDFLAGS+=-shared \
|
LDFLAGS+=-shared \
|
||||||
-lpthread \
|
-lpthread \
|
||||||
-lresolv
|
-lresolv
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
CFLAGS+=-Werror \
|
CFLAGS+=-Werror \
|
||||||
@ -43,10 +64,12 @@ endif
|
|||||||
|
|
||||||
FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
|
FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
|
||||||
FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so
|
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
|
FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded
|
||||||
|
|
||||||
TARGET_CC?=$(CC)
|
TARGET_CC?=$(CC)
|
||||||
TARGET_CXX?=$(CXX)
|
TARGET_CXX?=$(CXX)
|
||||||
|
TARGET_AR?=$(AR)
|
||||||
HOST_CC?=$(CC)
|
HOST_CC?=$(CC)
|
||||||
HOST_CXX?=$(CXX)
|
HOST_CXX?=$(CXX)
|
||||||
|
|
||||||
@ -66,18 +89,21 @@ ifeq "$(ARCH)" "i686"
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
GUM_ARCH="-$(ARCH)"
|
||||||
|
|
||||||
ifeq "$(shell uname)" "Darwin"
|
ifeq "$(shell uname)" "Darwin"
|
||||||
OS:=macos
|
OS:=macos
|
||||||
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
|
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
|
||||||
|
GUM_ARCH:=""
|
||||||
else
|
else
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor
|
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS+= -z noexecstack \
|
LDFLAGS+= -z noexecstack \
|
||||||
-Wl,--gc-sections \
|
-Wl,--gc-sections \
|
||||||
-Wl,--exclude-libs,ALL \
|
-Wl,--exclude-libs,ALL \
|
||||||
-ldl \
|
-ldl
|
||||||
-lrt
|
|
||||||
LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
|
LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -88,46 +114,48 @@ ifeq "$(shell uname)" "Linux"
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
|
||||||
|
ifdef IS_ANDROID
|
||||||
OS:=android
|
OS:=android
|
||||||
ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" ""
|
ifdef IS_x86
|
||||||
ARCH:=arm64
|
ARCH:=x86
|
||||||
endif
|
endif
|
||||||
ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" ""
|
ifdef IS_x86
|
||||||
|
ARCH:=x86_64
|
||||||
|
endif
|
||||||
|
ifdef IS_ARM
|
||||||
ARCH:=arm
|
ARCH:=arm
|
||||||
endif
|
endif
|
||||||
ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" ""
|
ifdef IS_ARM64
|
||||||
ARCH:=x86_64
|
ARCH:=arm64
|
||||||
endif
|
|
||||||
ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" ""
|
|
||||||
ARCH:=x86
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifeq "$(ARCH)" "armhf"
|
ifeq "$(ARCH)" "armhf"
|
||||||
TARGET_CC:=arm-linux-gnueabihf-gcc
|
TARGET_CC:=arm-linux-gnueabihf-gcc
|
||||||
TARGET_CXX:=arm-linux-gnueabihf-g++
|
TARGET_CXX:=arm-linux-gnueabihf-g++
|
||||||
|
TARGET_AR:=arm-linux-gnueabihf-ar
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef OS
|
ifndef OS
|
||||||
$(error "Operating system unsupported")
|
$(error "Operating system unsupported")
|
||||||
endif
|
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_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_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
|
||||||
|
|
||||||
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
|
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
|
||||||
|
ifdef FRIDA_SOURCE
|
||||||
|
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
|
GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a
|
||||||
|
endif
|
||||||
GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h
|
GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h
|
||||||
|
|
||||||
FRIDA_DIR:=$(PWD)build/frida-source/
|
FRIDA_DIR:=$(PWD)build/frida-source/
|
||||||
FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile
|
FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile
|
||||||
FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gumjs-1.0.a
|
|
||||||
FRIDA_GUM_DEVKIT_DIR:=$(FRIDA_DIR)build/gum-devkit/
|
|
||||||
FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gumjs.h
|
|
||||||
FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar
|
|
||||||
FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME)
|
|
||||||
|
|
||||||
AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
|
AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
|
||||||
AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
|
AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
|
||||||
@ -142,14 +170,20 @@ AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(BUILD_DIR)frida_hook.so
|
|||||||
AFLPP_QEMU_DRIVER_HOOK_SRC:=$(HOOK_DIR)qemu_hook.c
|
AFLPP_QEMU_DRIVER_HOOK_SRC:=$(HOOK_DIR)qemu_hook.c
|
||||||
AFLPP_QEMU_DRIVER_HOOK_OBJ:=$(BUILD_DIR)qemu_hook.so
|
AFLPP_QEMU_DRIVER_HOOK_OBJ:=$(BUILD_DIR)qemu_hook.so
|
||||||
|
|
||||||
|
ifneq "$(shell uname)" "Darwin"
|
||||||
|
ADDR_DIR:=$(PWD)addr/
|
||||||
|
ADDR_SRC:=$(ADDR_DIR)addr.c
|
||||||
|
ADDR_BIN:=$(BUILD_DIR)addr
|
||||||
|
endif
|
||||||
|
|
||||||
BIN2C:=$(BUILD_DIR)bin2c
|
BIN2C:=$(BUILD_DIR)bin2c
|
||||||
BIN2C_SRC:=$(PWD)util/bin2c.c
|
BIN2C_SRC:=$(PWD)util/bin2c.c
|
||||||
|
|
||||||
.PHONY: all 32 clean format hook $(FRIDA_GUM)
|
.PHONY: all 32 clean format hook addr $(FRIDA_GUM)
|
||||||
|
|
||||||
############################## ALL #############################################
|
############################## ALL #############################################
|
||||||
|
|
||||||
all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN)
|
||||||
|
|
||||||
32:
|
32:
|
||||||
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
|
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
|
||||||
@ -160,44 +194,135 @@ $(BUILD_DIR):
|
|||||||
$(OBJ_DIR): | $(BUILD_DIR)
|
$(OBJ_DIR): | $(BUILD_DIR)
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
############################# FRIDA ############################################
|
|
||||||
|
|
||||||
$(FRIDA_MAKEFILE): | $(BUILD_DIR)
|
|
||||||
git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR)
|
|
||||||
|
|
||||||
$(FRIDA_GUM): $(FRIDA_MAKEFILE)
|
|
||||||
cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
|
|
||||||
|
|
||||||
$(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM)
|
|
||||||
$(FRIDA_DIR)releng/devkit.py frida-gumjs linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/
|
|
||||||
|
|
||||||
$(FRIDA_GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_HEADER)
|
|
||||||
cd $(FRIDA_GUM_DEVKIT_DIR) && tar cvf $(FRIDA_GUM_DEVKIT_TARBALL) .
|
|
||||||
|
|
||||||
$(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL): $(FRIDA_GUM_DEVKIT_TARBALL)
|
|
||||||
xz -k -f -0 $(FRIDA_GUM_DEVKIT_TARBALL)
|
|
||||||
|
|
||||||
############################# DEVKIT ###########################################
|
############################# DEVKIT ###########################################
|
||||||
|
|
||||||
$(FRIDA_BUILD_DIR): | $(BUILD_DIR)
|
$(FRIDA_BUILD_DIR): | $(BUILD_DIR)
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
ifdef FRIDA_SOURCE
|
ifdef FRIDA_SOURCE
|
||||||
$(GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL)| $(FRIDA_BUILD_DIR)
|
$(FRIDA_MAKEFILE): | $(BUILD_DIR)
|
||||||
cp -v $< $@
|
git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR)
|
||||||
|
|
||||||
|
.PHONY: $(GUM_DEVIT_LIBRARY)
|
||||||
|
|
||||||
|
$(GUM_DEVIT_LIBRARY): $(FRIDA_MAKEFILE)
|
||||||
|
cd $(FRIDA_DIR) && make gum-$(OS)$(GUM_ARCH)
|
||||||
|
|
||||||
|
$(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
|
||||||
|
echo "#include <stdio.h>" > $@
|
||||||
|
echo "#include <unistd.h>" >> $@
|
||||||
|
echo "#include <gum/gumreturnaddress.h>" >> $@
|
||||||
|
echo "#include <gum/gumbacktracer.h>" >> $@
|
||||||
|
echo "#include <gum/gumsymbolutil.h>" >> $@
|
||||||
|
echo "#include <gum/gumstalker.h>" >> $@
|
||||||
|
echo "#include <gum/gumlibc.h>" >> $@
|
||||||
|
echo "#include <gumjs/gumscriptbackend.h>" >> $@
|
||||||
|
|
||||||
|
ifeq "$(OS)" "macos"
|
||||||
|
|
||||||
|
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-$(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_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
|
else
|
||||||
$(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
|
$(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)
|
||||||
endif
|
|
||||||
|
|
||||||
$(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL)
|
$(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL)
|
||||||
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
||||||
|
|
||||||
$(GUM_DEVIT_HEADER): $(GUM_DEVKIT_TARBALL)
|
$(GUM_DEVIT_HEADER): $(GUM_DEVKIT_TARBALL)
|
||||||
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############################## AFL #############################################
|
############################## AFL #############################################
|
||||||
$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC)
|
$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC) $(ROOT)include/config.h
|
||||||
$(TARGET_CC) \
|
$(TARGET_CC) \
|
||||||
$(CFLAGS) \
|
$(CFLAGS) \
|
||||||
$(AFL_CFLAGS) \
|
$(AFL_CFLAGS) \
|
||||||
@ -235,7 +360,7 @@ $(JS_OBJ): $(JS_SRC) GNUmakefile
|
|||||||
############################# SOURCE ###########################################
|
############################# SOURCE ###########################################
|
||||||
|
|
||||||
define BUILD_SOURCE
|
define BUILD_SOURCE
|
||||||
$(2): $(1) $(INCLUDES) GNUmakefile | $(OBJ_DIR)
|
$(2): $(1) $(INCLUDES) $(GUM_DEVIT_HEADER) | $(OBJ_DIR)
|
||||||
$(TARGET_CC) \
|
$(TARGET_CC) \
|
||||||
$(CFLAGS) \
|
$(CFLAGS) \
|
||||||
-I $(ROOT)include \
|
-I $(ROOT)include \
|
||||||
@ -256,12 +381,22 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL
|
|||||||
$(GUM_DEVIT_LIBRARY) \
|
$(GUM_DEVIT_LIBRARY) \
|
||||||
$(AFL_COMPILER_RT_OBJ) \
|
$(AFL_COMPILER_RT_OBJ) \
|
||||||
$(AFL_PERFORMANCE_OBJ) \
|
$(AFL_PERFORMANCE_OBJ) \
|
||||||
|
$(TRACE_LDFLAGS) \
|
||||||
$(LDFLAGS) \
|
$(LDFLAGS) \
|
||||||
$(LDSCRIPT) \
|
$(LDSCRIPT) \
|
||||||
-o $@ \
|
-o $@ \
|
||||||
|
|
||||||
cp -v $(FRIDA_TRACE) $(ROOT)
|
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 #############################################
|
############################# HOOK #############################################
|
||||||
|
|
||||||
$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR)
|
$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR)
|
||||||
@ -272,13 +407,44 @@ $(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR)
|
|||||||
|
|
||||||
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
||||||
|
|
||||||
|
############################# ADDR #############################################
|
||||||
|
ifneq "$(OS)" "android"
|
||||||
|
$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR)
|
||||||
|
-$(TARGET_CC) \
|
||||||
|
$(CFLAGS) \
|
||||||
|
-Werror \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wpointer-arith \
|
||||||
|
-z noexecstack \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,--exclude-libs,ALL \
|
||||||
|
-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 ############################################
|
############################# CLEAN ############################################
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
############################# FORMAT ###########################################
|
############################# FORMAT ###########################################
|
||||||
format:
|
format:
|
||||||
cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) | xargs -L1 ./.custom-format.py -i
|
cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) $(ADDR_BIN ) | xargs -L1 ./.custom-format.py -i
|
||||||
cd $(ROOT) && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i
|
cd $(ROOT) && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i
|
||||||
|
|
||||||
############################# RUN #############################################
|
############################# RUN #############################################
|
||||||
|
@ -146,39 +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
|
QEMU driver to provide a `main` loop for a user provided
|
||||||
`LLVMFuzzerTestOneInput`, this option configures the driver to read input from
|
`LLVMFuzzerTestOneInput`, this option configures the driver to read input from
|
||||||
`stdin` rather than using in-memory test cases.
|
`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
|
* `AFL_FRIDA_INST_COVERAGE_FILE` - File to write DynamoRIO format coverage
|
||||||
information (e.g., to be loaded within IDA lighthouse).
|
information (e.g., to be loaded within IDA lighthouse).
|
||||||
* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
|
* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
|
||||||
and their instrumented counterparts during block compilation.
|
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:
|
Generated block 0x7ffff75e98e2
|
||||||
0x7ffff7953313 mov qword ptr [rax], 0
|
0x7ffff75e98e2 mov qword ptr [rax], 0
|
||||||
0x7ffff795331a add rsp, 8
|
0x7ffff75e98e9 add rsp, 8
|
||||||
0x7ffff795331e ret
|
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
|
* `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
|
code. Code is considered to be JIT if the executable segment is not backed by
|
||||||
a file.
|
a file.
|
||||||
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
|
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
|
||||||
instrumentation (the default where available). Required to use
|
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_TRACE`.
|
||||||
* `AFL_FRIDA_INST_NO_BACKPATCH` - Disable backpatching. At the end of executing
|
* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to
|
||||||
each block, control will return to FRIDA to identify the next block to
|
instrumented address block translations.
|
||||||
execute.
|
|
||||||
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will
|
* `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
|
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
|
them and they be inherited by the next child on fork, implies
|
||||||
@ -227,6 +233,9 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
|
|||||||
* `AFL_FRIDA_STALKER_IC_ENTRIES` - Configure the number of inline cache entries
|
* `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
|
stored along-side branch instructions which provide a cache to avoid having to
|
||||||
call back into FRIDA to find the next block. Default is 32.
|
call back into FRIDA to find the next block. Default is 32.
|
||||||
|
* `AFL_FRIDA_STALKER_NO_BACKPATCH` - Disable backpatching. At the end of executing
|
||||||
|
each block, control will return to FRIDA to identify the next block to
|
||||||
|
execute.
|
||||||
* `AFL_FRIDA_STATS_FILE` - Write statistics information about the code being
|
* `AFL_FRIDA_STATS_FILE` - Write statistics information about the code being
|
||||||
instrumented to the given file name. The statistics are written only for the
|
instrumented to the given file name. The statistics are written only for the
|
||||||
child process when new block is instrumented (when the
|
child process when new block is instrumented (when the
|
||||||
@ -307,6 +316,7 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
|
|||||||
core dump of the instrumented target. Note that in order to capture the core
|
core dump of the instrumented target. Note that in order to capture the core
|
||||||
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
||||||
killing the process whilst it is being dumped.
|
killing the process whilst it is being dumped.
|
||||||
|
* `AFL_FRIDA_VERBOSE` - Enable verbose output from FRIDA mode.
|
||||||
|
|
||||||
## FASAN - FRIDA Address Sanitizer mode
|
## FASAN - FRIDA Address Sanitizer mode
|
||||||
|
|
||||||
@ -376,4 +386,4 @@ Should you encounter problems with FRIDA mode, refer to
|
|||||||
The next features to be added are Aarch32 support as well as looking at
|
The next features to be added are Aarch32 support as well as looking at
|
||||||
potential performance improvements. The intention is to achieve feature parity
|
potential performance improvements. The intention is to achieve feature parity
|
||||||
with QEMU mode in due course. Contributions are welcome, but please get in touch
|
with QEMU mode in due course. Contributions are welcome, but please get in touch
|
||||||
to ensure that efforts are deconflicted.
|
to ensure that efforts are deconflicted.
|
||||||
|
@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code...
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
Copyright 2014 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at:
|
You may obtain a copy of the License at:
|
||||||
@ -782,7 +782,7 @@ class Afl {
|
|||||||
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* See `AFL_FRIDA_INST_NO_BACKPATCH`.
|
* See `AFL_FRIDA_STALKER_NO_BACKPATCH`.
|
||||||
*/
|
*/
|
||||||
static setBackpatchDisable() {
|
static setBackpatchDisable() {
|
||||||
Afl.jsApiSetBackpatchDisable();
|
Afl.jsApiSetBackpatchDisable();
|
||||||
@ -850,6 +850,14 @@ class Afl {
|
|||||||
static setInstrumentNoOptimize() {
|
static setInstrumentNoOptimize() {
|
||||||
Afl.jsApiSetInstrumentNoOptimize();
|
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`
|
* See `AFL_FRIDA_INST_SEED`
|
||||||
*/
|
*/
|
||||||
@ -995,4 +1003,4 @@ class Afl {
|
|||||||
return Afl.module.getExportByName(name);
|
return Afl.module.getExportByName(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
39
frida_mode/addr/addr.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <link.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/personality.h>
|
||||||
|
|
||||||
|
#define UNUSED_PARAMETER(x) (void)(x)
|
||||||
|
|
||||||
|
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||||
|
{
|
||||||
|
UNUSED_PARAMETER (size);
|
||||||
|
|
||||||
|
ElfW(Addr) * base = data;
|
||||||
|
|
||||||
|
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char** argv, char** envp) {
|
||||||
|
UNUSED_PARAMETER (argc);
|
||||||
|
|
||||||
|
ElfW(Addr) base = 0;
|
||||||
|
|
||||||
|
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||||
|
if (persona == -1) {
|
||||||
|
|
||||||
|
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||||
|
|
||||||
|
dl_iterate_phdr(phdr_callback, &base);
|
||||||
|
|
||||||
|
printf("%p\n", (void *)base);
|
||||||
|
if (base == 0) { return 1; }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -9,13 +9,18 @@
|
|||||||
js_api_done;
|
js_api_done;
|
||||||
js_api_error;
|
js_api_error;
|
||||||
js_api_set_backpatch_disable;
|
js_api_set_backpatch_disable;
|
||||||
|
js_api_set_cache_disable;
|
||||||
js_api_set_debug_maps;
|
js_api_set_debug_maps;
|
||||||
js_api_set_entrypoint;
|
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_coverage_file;
|
||||||
js_api_set_instrument_debug_file;
|
js_api_set_instrument_debug_file;
|
||||||
js_api_set_instrument_jit;
|
js_api_set_instrument_jit;
|
||||||
js_api_set_instrument_libraries;
|
js_api_set_instrument_libraries;
|
||||||
|
js_api_set_instrument_instructions;
|
||||||
js_api_set_instrument_no_optimize;
|
js_api_set_instrument_no_optimize;
|
||||||
|
js_api_set_instrument_regs_file;
|
||||||
js_api_set_instrument_seed;
|
js_api_set_instrument_seed;
|
||||||
js_api_set_instrument_trace;
|
js_api_set_instrument_trace;
|
||||||
js_api_set_instrument_trace_unique;
|
js_api_set_instrument_trace_unique;
|
||||||
@ -37,6 +42,7 @@
|
|||||||
js_api_set_stderr;
|
js_api_set_stderr;
|
||||||
js_api_set_stdout;
|
js_api_set_stdout;
|
||||||
js_api_set_traceable;
|
js_api_set_traceable;
|
||||||
|
js_api_set_verbose;
|
||||||
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
|
@ -31,7 +31,7 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
|
|||||||
// do a length check matching the target!
|
// do a length check matching the target!
|
||||||
|
|
||||||
void **esp = (void **)regs->esp;
|
void **esp = (void **)regs->esp;
|
||||||
void * arg1 = esp[0];
|
void *arg1 = esp[0];
|
||||||
void **arg2 = &esp[1];
|
void **arg2 = &esp[1];
|
||||||
memcpy(arg1, input_buf, input_buf_len);
|
memcpy(arg1, input_buf, input_buf_len);
|
||||||
*arg2 = (void *)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
|
#else
|
||||||
#pragma error "Unsupported architecture"
|
#pragma error "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
extern char * instrument_debug_filename;
|
extern char *instrument_debug_filename;
|
||||||
extern char * instrument_coverage_filename;
|
extern char *instrument_coverage_filename;
|
||||||
extern gboolean instrument_tracing;
|
extern bool instrument_coverage_absolute;
|
||||||
extern gboolean instrument_optimize;
|
extern gboolean instrument_tracing;
|
||||||
extern gboolean instrument_unique;
|
extern gboolean instrument_optimize;
|
||||||
extern __thread guint64 instrument_previous_pc;
|
extern gboolean instrument_unique;
|
||||||
extern guint64 instrument_hash_zero;
|
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 gboolean instrument_use_fixed_seed;
|
||||||
extern guint64 instrument_fixed_seed;
|
extern guint64 instrument_fixed_seed;
|
||||||
@ -20,6 +22,11 @@ extern guint64 instrument_fixed_seed;
|
|||||||
extern uint8_t *__afl_area_ptr;
|
extern uint8_t *__afl_area_ptr;
|
||||||
extern uint32_t __afl_map_size;
|
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_config(void);
|
||||||
|
|
||||||
void instrument_init(void);
|
void instrument_init(void);
|
||||||
@ -30,8 +37,10 @@ GumStalkerTransformer *instrument_get_transformer(void);
|
|||||||
gboolean instrument_is_coverage_optimize_supported(void);
|
gboolean instrument_is_coverage_optimize_supported(void);
|
||||||
|
|
||||||
void instrument_coverage_optimize_init(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);
|
GumStalkerOutput *output);
|
||||||
|
void instrument_coverage_optimize_insn(const cs_insn *instr,
|
||||||
|
GumStalkerOutput *output);
|
||||||
|
|
||||||
void instrument_debug_config(void);
|
void instrument_debug_config(void);
|
||||||
void instrument_debug_init(void);
|
void instrument_debug_init(void);
|
||||||
@ -51,9 +60,16 @@ void instrument_coverage_unstable(guint64 edge, guint64 previous_rip,
|
|||||||
guint64 previous_end, guint64 current_rip,
|
guint64 previous_end, guint64 current_rip,
|
||||||
guint64 current_end);
|
guint64 current_end);
|
||||||
|
|
||||||
void instrument_on_fork();
|
void instrument_on_fork(void);
|
||||||
|
|
||||||
guint64 instrument_get_offset_hash(GumAddress current_rip);
|
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
|
#endif
|
||||||
|
|
||||||
|
11
frida_mode/include/module.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef _MODULE_H
|
||||||
|
#define _MODULE_H
|
||||||
|
|
||||||
|
#include "frida-gumjs.h"
|
||||||
|
|
||||||
|
void module_config(void);
|
||||||
|
|
||||||
|
void module_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -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 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 unsigned char *__afl_fuzz_ptr;
|
||||||
|
|
||||||
extern guint64 persistent_start;
|
extern guint64 persistent_start;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef _SECCOMP_H
|
#ifndef _SECCOMP_H
|
||||||
#define _SECCOMP_H
|
#define _SECCOMP_H
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#if !defined(__APPLE__) && !defined(__ANDROID__)
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
@ -401,9 +401,9 @@ enum {
|
|||||||
|
|
||||||
typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
|
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,
|
struct seccomp_notif_resp *resp,
|
||||||
GumReturnAddressArray * frames);
|
GumReturnAddressArray *frames);
|
||||||
|
|
||||||
void seccomp_atomic_set(volatile bool *ptr, bool val);
|
void seccomp_atomic_set(volatile bool *ptr, bool val);
|
||||||
bool seccomp_atomic_try_set(volatile bool *ptr, bool val);
|
bool seccomp_atomic_try_set(volatile bool *ptr, bool val);
|
||||||
|
9
frida_mode/include/shm.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _SHM_H
|
||||||
|
#define _SHM_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void *shm_create(size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -43,7 +43,7 @@ typedef struct {
|
|||||||
G_DECLARE_FINAL_TYPE(GumAflStalkerStats, gum_afl_stalker_stats, GUM,
|
G_DECLARE_FINAL_TYPE(GumAflStalkerStats, gum_afl_stalker_stats, GUM,
|
||||||
AFL_STALKER_STATS, GObject)
|
AFL_STALKER_STATS, GObject)
|
||||||
|
|
||||||
extern char * stats_filename;
|
extern char *stats_filename;
|
||||||
extern guint64 stats_interval;
|
extern guint64 stats_interval;
|
||||||
|
|
||||||
void stats_config(void);
|
void stats_config(void);
|
||||||
|
@ -5,12 +5,23 @@
|
|||||||
|
|
||||||
#include "debug.h"
|
#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 UNUSED_PARAMETER(x) (void)(x)
|
||||||
#define IGNORED_RETURN(x) (void)!(x)
|
#define IGNORED_RETURN(x) (void)!(x)
|
||||||
|
|
||||||
|
extern gboolean util_verbose;
|
||||||
|
|
||||||
guint64 util_read_address(char *key, guint64 default_value);
|
guint64 util_read_address(char *key, guint64 default_value);
|
||||||
guint64 util_read_num(char *key, guint64 default_value);
|
guint64 util_read_num(char *key, guint64 default_value);
|
||||||
gboolean util_output_enabled(void);
|
gboolean util_output_enabled(void);
|
||||||
|
gboolean util_verbose_enabled(void);
|
||||||
gsize util_rotate(gsize val, gsize shift, gsize size);
|
gsize util_rotate(gsize val, gsize shift, gsize size);
|
||||||
gsize util_log2(gsize val);
|
gsize util_log2(gsize val);
|
||||||
|
|
||||||
@ -19,7 +30,8 @@ gsize util_log2(gsize val);
|
|||||||
\
|
\
|
||||||
if (!util_output_enabled()) { break; } \
|
if (!util_output_enabled()) { break; } \
|
||||||
\
|
\
|
||||||
OKF(x); \
|
SAYF(cLGN "[F] " cRST x); \
|
||||||
|
SAYF(cRST "\n"); \
|
||||||
\
|
\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -37,5 +49,15 @@ gsize util_log2(gsize val);
|
|||||||
\
|
\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define FVERBOSE(x...) \
|
||||||
|
do { \
|
||||||
|
\
|
||||||
|
if (!util_verbose_enabled()) { break; } \
|
||||||
|
\
|
||||||
|
SAYF(cGRA "[F] " x); \
|
||||||
|
SAYF(cRST "\n"); \
|
||||||
|
\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,21 +9,15 @@ gboolean asan_initialized = FALSE;
|
|||||||
|
|
||||||
void asan_config(void) {
|
void asan_config(void) {
|
||||||
|
|
||||||
if (getenv("AFL_USE_FASAN") != NULL) {
|
if (getenv("AFL_USE_FASAN") != NULL) { asan_enabled = TRUE; }
|
||||||
|
|
||||||
FOKF("Frida ASAN mode enabled");
|
|
||||||
asan_enabled = TRUE;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
FOKF("Frida ASAN mode disabled");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void asan_init(void) {
|
void asan_init(void) {
|
||||||
|
|
||||||
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "asan:" cYEL " [%c]",
|
||||||
|
asan_enabled ? 'X' : ' ');
|
||||||
|
|
||||||
if (asan_enabled) {
|
if (asan_enabled) {
|
||||||
|
|
||||||
asan_arch_init();
|
asan_arch_init();
|
||||||
@ -36,12 +30,21 @@ void asan_init(void) {
|
|||||||
static gboolean asan_exclude_module(const GumModuleDetails *details,
|
static gboolean asan_exclude_module(const GumModuleDetails *details,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
|
|
||||||
gchar * symbol_name = (gchar *)user_data;
|
gchar *symbol_name = (gchar *)user_data;
|
||||||
GumAddress address;
|
GumAddress address;
|
||||||
|
|
||||||
address = gum_module_find_export_by_name(details->name, symbol_name);
|
address = gum_module_find_export_by_name(details->name, symbol_name);
|
||||||
if (address == 0) { return TRUE; }
|
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);
|
ranges_add_exclude((GumMemoryRange *)details->range);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ asan_storeN_t asan_storeN = NULL;
|
|||||||
|
|
||||||
static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
||||||
|
|
||||||
asan_ctx_t * asan_ctx = (asan_ctx_t *)user_data;
|
asan_ctx_t *asan_ctx = (asan_ctx_t *)user_data;
|
||||||
cs_arm64_op * operand = &asan_ctx->operand;
|
cs_arm64_op *operand = &asan_ctx->operand;
|
||||||
arm64_op_mem *mem = &operand->mem;
|
arm64_op_mem *mem = &operand->mem;
|
||||||
gsize base = 0;
|
gsize base = 0;
|
||||||
gsize index = 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 arm64 = instr->detail->arm64;
|
||||||
cs_arm64_op *operand;
|
cs_arm64_op *operand;
|
||||||
asan_ctx_t * ctx;
|
asan_ctx_t *ctx;
|
||||||
|
|
||||||
if (!asan_initialized) return;
|
if (!asan_initialized) return;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
|||||||
|
|
||||||
UNUSED_PARAMETER(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;
|
x86_op_mem *mem = &operand->mem;
|
||||||
gsize base = 0;
|
gsize base = 0;
|
||||||
gsize index = 0;
|
gsize index = 0;
|
||||||
@ -48,9 +48,9 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
|
|||||||
UNUSED_PARAMETER(iterator);
|
UNUSED_PARAMETER(iterator);
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
cs_x86 x86 = instr->detail->x86;
|
||||||
cs_x86_op * operand;
|
cs_x86_op *operand;
|
||||||
x86_op_mem *mem;
|
x86_op_mem *mem;
|
||||||
cs_x86_op * ctx;
|
cs_x86_op *ctx;
|
||||||
|
|
||||||
if (!asan_initialized) return;
|
if (!asan_initialized) return;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
|||||||
|
|
||||||
UNUSED_PARAMETER(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;
|
x86_op_mem *mem = &operand->mem;
|
||||||
gsize base = 0;
|
gsize base = 0;
|
||||||
gsize index = 0;
|
gsize index = 0;
|
||||||
@ -48,9 +48,9 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
|
|||||||
UNUSED_PARAMETER(iterator);
|
UNUSED_PARAMETER(iterator);
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
cs_x86 x86 = instr->detail->x86;
|
||||||
cs_x86_op * operand;
|
cs_x86_op *operand;
|
||||||
x86_op_mem *mem;
|
x86_op_mem *mem;
|
||||||
cs_x86_op * ctx;
|
cs_x86_op *ctx;
|
||||||
|
|
||||||
if (!asan_initialized) return;
|
if (!asan_initialized) return;
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
#define MAX_MEMFD_SIZE (64UL << 10)
|
#define MAX_MEMFD_SIZE (64UL << 10)
|
||||||
|
|
||||||
extern struct cmp_map *__afl_cmp_map;
|
extern struct cmp_map *__afl_cmp_map;
|
||||||
static GArray * cmplog_ranges = NULL;
|
static GArray *cmplog_ranges = NULL;
|
||||||
static GHashTable * hash_yes = NULL;
|
static GHashTable *hash_yes = NULL;
|
||||||
static GHashTable * hash_no = NULL;
|
static GHashTable *hash_no = NULL;
|
||||||
|
|
||||||
static long page_size = 0;
|
static long page_size = 0;
|
||||||
static long page_offset_mask = 0;
|
static long page_offset_mask = 0;
|
||||||
@ -24,7 +24,7 @@ static long page_mask = 0;
|
|||||||
static gboolean cmplog_range(const GumRangeDetails *details,
|
static gboolean cmplog_range(const GumRangeDetails *details,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
|
|
||||||
GArray * cmplog_ranges = (GArray *)user_data;
|
GArray *cmplog_ranges = (GArray *)user_data;
|
||||||
GumMemoryRange range = *details->range;
|
GumMemoryRange range = *details->range;
|
||||||
g_array_append_val(cmplog_ranges, range);
|
g_array_append_val(cmplog_ranges, range);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -54,7 +54,7 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) {
|
|||||||
|
|
||||||
static void cmplog_get_ranges(void) {
|
static void cmplog_get_ranges(void) {
|
||||||
|
|
||||||
FOKF("CMPLOG - Collecting ranges");
|
FVERBOSE("CMPLOG - Collecting ranges");
|
||||||
|
|
||||||
cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
|
cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
|
||||||
gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges);
|
gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges);
|
||||||
@ -68,18 +68,21 @@ void cmplog_config(void) {
|
|||||||
|
|
||||||
void cmplog_init(void) {
|
void cmplog_init(void) {
|
||||||
|
|
||||||
FOKF("CMPLOG - Enabled [%c]", __afl_cmp_map == NULL ? ' ' : 'X');
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cmplog:" cYEL " [%c]",
|
||||||
|
__afl_cmp_map == NULL ? ' ' : 'X');
|
||||||
|
|
||||||
if (__afl_cmp_map == NULL) { return; }
|
if (__afl_cmp_map == NULL) { return; }
|
||||||
|
|
||||||
cmplog_get_ranges();
|
cmplog_get_ranges();
|
||||||
|
|
||||||
|
FVERBOSE("Cmplog Ranges");
|
||||||
|
|
||||||
for (guint i = 0; i < cmplog_ranges->len; i++) {
|
for (guint i = 0; i < cmplog_ranges->len; i++) {
|
||||||
|
|
||||||
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
|
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
|
||||||
FOKF("CMPLOG Range - %3u: 0x%016" G_GINT64_MODIFIER
|
FVERBOSE("\t%3u: 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
|
||||||
"X - 0x%016" G_GINT64_MODIFIER "X",
|
"X",
|
||||||
i, range->base_address, range->base_address + range->size);
|
i, range->base_address, range->base_address + range->size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,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_yes, GSIZE_TO_POINTER(addr))) { return true; }
|
||||||
if (g_hash_table_contains(hash_no, GSIZE_TO_POINTER(addr))) { return false; }
|
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;
|
size_t page_offset = addr & page_offset_mask;
|
||||||
|
|
||||||
/* If it spans a page, then bail */
|
/* If it spans a page, then bail */
|
||||||
|
@ -148,7 +148,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
||||||
cs_arm64_op * operand) {
|
cs_arm64_op *operand) {
|
||||||
|
|
||||||
ctx->type = operand->type;
|
ctx->type = operand->type;
|
||||||
switch (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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_arm64 arm64 = instr->detail->arm64;
|
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,
|
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
|
||||||
cs_arm64_op * operand1,
|
cs_arm64_op *operand1,
|
||||||
cs_arm64_op * operand2,
|
cs_arm64_op *operand2,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
|
|
||||||
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
|
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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_arm64 arm64 = instr->detail->arm64;
|
cs_arm64 arm64 = instr->detail->arm64;
|
||||||
|
@ -141,7 +141,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
||||||
cs_x86_op * operand) {
|
cs_x86_op *operand) {
|
||||||
|
|
||||||
ctx->type = operand->type;
|
ctx->type = operand->type;
|
||||||
ctx->size = operand->size;
|
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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
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,
|
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
|
||||||
cs_x86_op * operand1,
|
cs_x86_op *operand1,
|
||||||
cs_x86_op *operand2) {
|
cs_x86_op *operand2) {
|
||||||
|
|
||||||
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
|
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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
cs_x86 x86 = instr->detail->x86;
|
||||||
|
@ -146,7 +146,7 @@ static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
|
||||||
cs_x86_op * operand) {
|
cs_x86_op *operand) {
|
||||||
|
|
||||||
ctx->type = operand->type;
|
ctx->type = operand->type;
|
||||||
ctx->size = operand->size;
|
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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
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,
|
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
|
||||||
cs_x86_op * operand1,
|
cs_x86_op *operand1,
|
||||||
cs_x86_op *operand2) {
|
cs_x86_op *operand2) {
|
||||||
|
|
||||||
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
|
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) {
|
GumStalkerIterator *iterator) {
|
||||||
|
|
||||||
cs_x86 x86 = instr->detail->x86;
|
cs_x86 x86 = instr->detail->x86;
|
||||||
|
@ -24,7 +24,7 @@ gboolean entry_run = FALSE;
|
|||||||
|
|
||||||
static void entry_launch(void) {
|
static void entry_launch(void) {
|
||||||
|
|
||||||
FOKF("Entry point reached");
|
FVERBOSE("Entry point reached");
|
||||||
__afl_manual_init();
|
__afl_manual_init();
|
||||||
|
|
||||||
/* Child here */
|
/* Child here */
|
||||||
@ -69,8 +69,8 @@ void entry_config(void) {
|
|||||||
|
|
||||||
void entry_init(void) {
|
void entry_init(void) {
|
||||||
|
|
||||||
FOKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
FVERBOSE("Entry Point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
||||||
FOKF("dumpable: [%c]", traceable ? 'X' : ' ');
|
FVERBOSE("Dumpable: [%c]", traceable ? 'X' : ' ');
|
||||||
|
|
||||||
if (dlopen(NULL, RTLD_NOW) == NULL) { FFATAL("Failed to dlopen: %d", errno); }
|
if (dlopen(NULL, RTLD_NOW) == NULL) { FFATAL("Failed to dlopen: %d", errno); }
|
||||||
|
|
||||||
@ -78,6 +78,13 @@ void entry_init(void) {
|
|||||||
|
|
||||||
void entry_start(void) {
|
void entry_start(void) {
|
||||||
|
|
||||||
|
if (persistent_start == 0) {
|
||||||
|
|
||||||
|
ranges_exclude();
|
||||||
|
stalker_trust();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (entry_point == 0) { entry_launch(); }
|
if (entry_point == 0) { entry_launch(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -94,7 +101,7 @@ static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) {
|
|||||||
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
|
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
|
||||||
|
|
||||||
UNUSED_PARAMETER(output);
|
UNUSED_PARAMETER(output);
|
||||||
FOKF("AFL_ENTRYPOINT reached");
|
FVERBOSE("AFL_ENTRYPOINT reached");
|
||||||
|
|
||||||
if (persistent_start == 0) {
|
if (persistent_start == 0) {
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/shm.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
#include "frida-gumjs.h"
|
#include "frida-gumjs.h"
|
||||||
@ -16,10 +15,13 @@
|
|||||||
#include "persistent.h"
|
#include "persistent.h"
|
||||||
#include "prefetch.h"
|
#include "prefetch.h"
|
||||||
#include "ranges.h"
|
#include "ranges.h"
|
||||||
|
#include "shm.h"
|
||||||
#include "stalker.h"
|
#include "stalker.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#define FRIDA_DEFAULT_MAP_SIZE (64UL << 10)
|
||||||
|
|
||||||
gboolean instrument_tracing = false;
|
gboolean instrument_tracing = false;
|
||||||
gboolean instrument_optimize = false;
|
gboolean instrument_optimize = false;
|
||||||
gboolean instrument_unique = false;
|
gboolean instrument_unique = false;
|
||||||
@ -28,15 +30,20 @@ guint64 instrument_hash_seed = 0;
|
|||||||
|
|
||||||
gboolean instrument_use_fixed_seed = FALSE;
|
gboolean instrument_use_fixed_seed = FALSE;
|
||||||
guint64 instrument_fixed_seed = 0;
|
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 GumStalkerTransformer *transformer = NULL;
|
||||||
|
|
||||||
__thread guint64 instrument_previous_pc = 0;
|
|
||||||
|
|
||||||
static GumAddress previous_rip = 0;
|
static GumAddress previous_rip = 0;
|
||||||
static GumAddress previous_end = 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;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
@ -105,8 +112,14 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
|
|||||||
guint16 current_end = ctx->end;
|
guint16 current_end = ctx->end;
|
||||||
guint64 current_pc = instrument_get_offset_hash(current_rip);
|
guint64 current_pc = instrument_get_offset_hash(current_rip);
|
||||||
guint64 edge;
|
guint64 edge;
|
||||||
|
if (instrument_previous_pc_addr == NULL) {
|
||||||
|
|
||||||
edge = current_pc ^ instrument_previous_pc;
|
instrument_previous_pc_addr = &instrument_previous_pc;
|
||||||
|
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
edge = current_pc ^ *instrument_previous_pc_addr;
|
||||||
|
|
||||||
instrument_increment_map(edge);
|
instrument_increment_map(edge);
|
||||||
|
|
||||||
@ -136,12 +149,12 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
|
|||||||
previous_end = current_end;
|
previous_end = current_end;
|
||||||
|
|
||||||
gsize map_size_pow2 = util_log2(__afl_map_size);
|
gsize map_size_pow2 = util_log2(__afl_map_size);
|
||||||
instrument_previous_pc = util_rotate(current_pc, 1, map_size_pow2);
|
*instrument_previous_pc_addr = util_rotate(current_pc, 1, map_size_pow2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void instrument_basic_block(GumStalkerIterator *iterator,
|
static void instrument_basic_block(GumStalkerIterator *iterator,
|
||||||
GumStalkerOutput * output,
|
GumStalkerOutput *output,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
|
|
||||||
UNUSED_PARAMETER(user_data);
|
UNUSED_PARAMETER(user_data);
|
||||||
@ -149,7 +162,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
|
|||||||
const cs_insn *instr;
|
const cs_insn *instr;
|
||||||
gboolean begin = TRUE;
|
gboolean begin = TRUE;
|
||||||
gboolean excluded;
|
gboolean excluded;
|
||||||
block_ctx_t * ctx = NULL;
|
block_ctx_t *ctx = NULL;
|
||||||
|
|
||||||
while (gum_stalker_iterator_next(iterator, &instr)) {
|
while (gum_stalker_iterator_next(iterator, &instr)) {
|
||||||
|
|
||||||
@ -222,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)) {
|
if (likely(!excluded)) {
|
||||||
|
|
||||||
@ -235,6 +259,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instrument_cache(instr, output);
|
||||||
|
|
||||||
if (js_stalker_callback(instr, begin, excluded, output)) {
|
if (js_stalker_callback(instr, begin, excluded, output)) {
|
||||||
|
|
||||||
gum_stalker_iterator_keep(iterator);
|
gum_stalker_iterator_keep(iterator);
|
||||||
@ -262,26 +288,38 @@ void instrument_config(void) {
|
|||||||
instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0);
|
instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0);
|
||||||
instrument_coverage_unstable_filename =
|
instrument_coverage_unstable_filename =
|
||||||
(getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE"));
|
(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_debug_config();
|
||||||
instrument_coverage_config();
|
instrument_coverage_config();
|
||||||
asan_config();
|
asan_config();
|
||||||
cmplog_config();
|
cmplog_config();
|
||||||
|
instrument_cache_config();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_init(void) {
|
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;
|
if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false;
|
||||||
|
|
||||||
FOKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' ');
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "optimize:" cYEL " [%c]",
|
||||||
FOKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' ');
|
instrument_optimize ? 'X' : ' ');
|
||||||
FOKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' ');
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "tracing:" cYEL " [%c]",
|
||||||
FOKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]",
|
instrument_tracing ? 'X' : ' ');
|
||||||
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unique:" cYEL " [%c]",
|
||||||
|
instrument_unique ? 'X' : ' ');
|
||||||
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "fixed seed:" cYEL
|
||||||
|
" [%c] [0x%016" G_GINT64_MODIFIER "x]",
|
||||||
instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed);
|
instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed);
|
||||||
FOKF("Instrumentation - unstable coverage [%c] [%s]",
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]",
|
||||||
instrument_coverage_unstable_filename == NULL ? ' ' : 'X',
|
instrument_coverage_unstable_filename == NULL
|
||||||
instrument_coverage_unstable_filename);
|
? " "
|
||||||
|
: instrument_coverage_unstable_filename);
|
||||||
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]",
|
||||||
|
instrument_coverage_insn ? 'X' : ' ');
|
||||||
|
|
||||||
if (instrument_tracing && instrument_optimize) {
|
if (instrument_tracing && instrument_optimize) {
|
||||||
|
|
||||||
@ -306,38 +344,10 @@ void instrument_init(void) {
|
|||||||
|
|
||||||
if (instrument_unique) { instrument_tracing = TRUE; }
|
if (instrument_unique) { instrument_tracing = TRUE; }
|
||||||
|
|
||||||
if (__afl_map_size != 0x10000) {
|
|
||||||
|
|
||||||
FATAL("Bad map size: 0x%08x", __afl_map_size);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
transformer = gum_stalker_transformer_make_from_callback(
|
transformer = gum_stalker_transformer_make_from_callback(
|
||||||
instrument_basic_block, NULL, NULL);
|
instrument_basic_block, NULL, NULL);
|
||||||
|
|
||||||
if (instrument_unique) {
|
if (instrument_unique) { edges_notified = shm_create(__afl_map_size); }
|
||||||
|
|
||||||
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_use_fixed_seed) {
|
if (instrument_use_fixed_seed) {
|
||||||
|
|
||||||
@ -366,15 +376,36 @@ void instrument_init(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FOKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]",
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "seed:" cYEL
|
||||||
|
" [0x%016" G_GINT64_MODIFIER "x]",
|
||||||
instrument_hash_seed);
|
instrument_hash_seed);
|
||||||
instrument_hash_zero = instrument_get_offset_hash(0);
|
instrument_hash_zero = instrument_get_offset_hash(0);
|
||||||
|
|
||||||
instrument_coverage_optimize_init();
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "regs:" cYEL " [%s]",
|
||||||
instrument_debug_init();
|
instrument_regs_filename == NULL ? " " : instrument_regs_filename);
|
||||||
instrument_coverage_init();
|
|
||||||
|
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();
|
asan_init();
|
||||||
cmplog_init();
|
cmplog_init();
|
||||||
|
instrument_coverage_init();
|
||||||
|
instrument_coverage_optimize_init();
|
||||||
|
instrument_debug_init();
|
||||||
|
instrument_cache_init();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,7 +418,30 @@ GumStalkerTransformer *instrument_get_transformer(void) {
|
|||||||
|
|
||||||
void instrument_on_fork() {
|
void instrument_on_fork() {
|
||||||
|
|
||||||
instrument_previous_pc = instrument_hash_zero;
|
if (instrument_previous_pc_addr != NULL) {
|
||||||
|
|
||||||
|
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,24 +5,193 @@
|
|||||||
|
|
||||||
#if defined(__arm__)
|
#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) {
|
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(instr);
|
||||||
UNUSED_PARAMETER(output);
|
UNUSED_PARAMETER(output);
|
||||||
FFATAL("Optimized coverage not supported on this architecture");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_optimize_init(void) {
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -1,50 +1,123 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "frida-gumjs.h"
|
#include "frida-gumjs.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "instrument.h"
|
#include "instrument.h"
|
||||||
|
#include "ranges.h"
|
||||||
|
#include "stalker.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define G_MININT33 ((gssize)0xffffffff00000000)
|
||||||
|
#define G_MAXINT33 ((gssize)0x00000000ffffffff)
|
||||||
|
|
||||||
|
#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__)
|
#if defined(__aarch64__)
|
||||||
|
|
||||||
static GumAddress current_log_impl = GUM_ADDRESS(0);
|
gboolean instrument_cache_enabled = FALSE;
|
||||||
|
gsize instrument_cache_size = 0;
|
||||||
|
static GHashTable *coverage_blocks = NULL;
|
||||||
|
|
||||||
static const guint8 afl_log_code[] = {
|
__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
|
||||||
|
|
||||||
// __afl_area_ptr[current_pc ^ previous_pc]++;
|
#pragma pack(push, 1)
|
||||||
// previous_pc = current_pc ROR 1;
|
typedef struct {
|
||||||
0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]!
|
|
||||||
0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]!
|
|
||||||
|
|
||||||
// x0 = current_pc
|
// cur_location = (block_address >> 4) ^ (block_address << 8);
|
||||||
0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr
|
// shared_mem[cur_location ^ prev_location]++;
|
||||||
0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr)
|
// prev_location = cur_location >> 1;
|
||||||
|
|
||||||
0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc
|
// stp x0, x1, [sp, #-160]
|
||||||
0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc)
|
// adrp x0, 0x7fb7738000
|
||||||
|
// ldr x1, [x0]
|
||||||
|
// mov x0, #0x18b8
|
||||||
|
// eor x0, x1, x0
|
||||||
|
// adrp x1, 0x7fb7d73000
|
||||||
|
// add x0, x1, x0
|
||||||
|
// ldrb w1, [x0]
|
||||||
|
// add w1, w1, #0x1
|
||||||
|
// add x1, x1, x1, lsr #8
|
||||||
|
// strb w1, [x0]
|
||||||
|
// adrp x0, 0x7fb7738000
|
||||||
|
// mov x1, #0xc5c
|
||||||
|
// str x1, [x0]
|
||||||
|
// ldp x0, x1, [sp, #-160]
|
||||||
|
// b 0x7fb6f0dee4
|
||||||
|
// ldp x16, x17, [sp], #144
|
||||||
|
|
||||||
// __afl_area_ptr[current_pc ^ previous_pc]++;
|
uint32_t b_imm8; /* br #68 */
|
||||||
0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0
|
uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */
|
||||||
0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2]
|
|
||||||
0x63, 0x04, 0x00, 0x91, // add x3, x3, #1
|
|
||||||
0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr
|
|
||||||
0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2]
|
|
||||||
|
|
||||||
// previous_pc = current_pc ROR 1;
|
uint32_t stp_x0_x1; /* stp x0, x1, [sp, #-0xa0] */
|
||||||
0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1
|
|
||||||
0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63
|
|
||||||
0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48
|
|
||||||
|
|
||||||
0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc
|
uint32_t adrp_x0_prev_loc1; /* adrp x0, #0xXXXX */
|
||||||
0x40, 0x00, 0x00, 0xf9, // str x0, [x2]
|
uint32_t ldr_x1_ptr_x0; /* ldr x1, [x0] */
|
||||||
|
|
||||||
0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10
|
uint32_t mov_x0_curr_loc; /* movz x0, #0xXXXX */
|
||||||
0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10
|
uint32_t eor_x0_x1_x0; /* eor x0, x1, x0 */
|
||||||
0xC0, 0x03, 0x5F, 0xD6, // ret
|
uint32_t adrp_x1_area_ptr; /* adrp x1, #0xXXXX */
|
||||||
|
uint32_t add_x0_x1_x0; /* add x0, x1, x0 */
|
||||||
|
|
||||||
// &afl_area_ptr_ptr
|
uint32_t ldrb_w1_x0; /* ldrb w1, [x0] */
|
||||||
// &afl_prev_loc_ptr
|
uint32_t add_w1_w1_1; /* add w1, w1, #1 */
|
||||||
|
uint32_t add_w1_w1_w1_lsr_8; /* add x1, x1, x1, lsr #8 */
|
||||||
|
|
||||||
};
|
uint32_t strb_w1_ptr_x0; /* strb w1, [x0] */
|
||||||
|
|
||||||
|
uint32_t adrp_x0_prev_loc2; /* adrp x0, #0xXXXX */
|
||||||
|
uint32_t mov_x1_curr_loc_shr_1; /* movz x1, #0xXXXX */
|
||||||
|
uint32_t str_x1_ptr_x0; /* str x1, [x0] */
|
||||||
|
|
||||||
|
uint32_t ldp_x0_x1; /* ldp x0, x1, [sp, #-0xa0] */
|
||||||
|
|
||||||
|
} afl_log_code_asm_t;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
|
||||||
|
afl_log_code_asm_t code;
|
||||||
|
uint8_t bytes[0];
|
||||||
|
|
||||||
|
} afl_log_code;
|
||||||
|
|
||||||
|
static const afl_log_code_asm_t template =
|
||||||
|
{
|
||||||
|
|
||||||
|
.b_imm8 = 0x14000011,
|
||||||
|
|
||||||
|
.restoration_prolog = 0xa8c947f0,
|
||||||
|
.stp_x0_x1 = 0xa93607e0,
|
||||||
|
|
||||||
|
.adrp_x0_prev_loc1 = 0x90000000,
|
||||||
|
.ldr_x1_ptr_x0 = 0xf9400001,
|
||||||
|
|
||||||
|
.mov_x0_curr_loc = 0xd2800000,
|
||||||
|
.eor_x0_x1_x0 = 0xca000020,
|
||||||
|
|
||||||
|
.adrp_x1_area_ptr = 0x90000001,
|
||||||
|
.add_x0_x1_x0 = 0x8b000020,
|
||||||
|
|
||||||
|
.ldrb_w1_x0 = 0x39400001,
|
||||||
|
|
||||||
|
.add_w1_w1_1 = 0x11000421,
|
||||||
|
.add_w1_w1_w1_lsr_8 = 0x8b412021,
|
||||||
|
|
||||||
|
.strb_w1_ptr_x0 = 0x39000001,
|
||||||
|
|
||||||
|
.adrp_x0_prev_loc2 = 0x90000000,
|
||||||
|
.mov_x1_curr_loc_shr_1 = 0xd2800001,
|
||||||
|
.str_x1_ptr_x0 = 0xf9000001,
|
||||||
|
|
||||||
|
.ldp_x0_x1 = 0xa97607e0,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
gboolean instrument_is_coverage_optimize_supported(void) {
|
gboolean instrument_is_coverage_optimize_supported(void) {
|
||||||
|
|
||||||
@ -52,50 +125,251 @@ gboolean instrument_is_coverage_optimize_supported(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_optimize(const cs_insn * instr,
|
static gboolean instrument_is_deterministic(const cs_insn *from_insn) {
|
||||||
GumStalkerOutput *output) {
|
|
||||||
|
|
||||||
guint64 current_pc = instr->address;
|
cs_arm64 *arm64;
|
||||||
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
|
arm64_cc cc;
|
||||||
GumArm64Writer *cw = output->writer.arm64;
|
|
||||||
|
|
||||||
if (current_log_impl == 0 ||
|
if (from_insn == NULL) { return FALSE; }
|
||||||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc,
|
|
||||||
current_log_impl) ||
|
|
||||||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128,
|
|
||||||
current_log_impl)) {
|
|
||||||
|
|
||||||
gconstpointer after_log_impl = cw->code + 1;
|
arm64 = &from_insn->detail->arm64;
|
||||||
|
cc = arm64->cc;
|
||||||
|
|
||||||
gum_arm64_writer_put_b_label(cw, after_log_impl);
|
switch (from_insn->id) {
|
||||||
|
|
||||||
current_log_impl = cw->pc;
|
case ARM64_INS_B:
|
||||||
gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
|
case ARM64_INS_BL:
|
||||||
|
if (cc == ARM64_CC_INVALID) { return TRUE; }
|
||||||
|
break;
|
||||||
|
|
||||||
uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
|
case ARM64_INS_RET:
|
||||||
uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
|
case ARM64_INS_RETAA:
|
||||||
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
|
case ARM64_INS_RETAB:
|
||||||
sizeof(afl_area_ptr_ptr));
|
if (arm64->op_count == 0) { return TRUE; }
|
||||||
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
|
break;
|
||||||
sizeof(afl_prev_loc_ptr));
|
default:
|
||||||
|
return FALSE;
|
||||||
gum_arm64_writer_put_label(cw, after_log_impl);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gum_arm64_writer_put_stp_reg_reg_reg_offset(
|
return FALSE;
|
||||||
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE),
|
|
||||||
GUM_INDEX_PRE_ADJUST);
|
}
|
||||||
gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset);
|
|
||||||
gum_arm64_writer_put_bl_imm(cw, current_log_impl);
|
static void instrument_coverage_switch(GumStalkerObserver *self,
|
||||||
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
|
gpointer from_address,
|
||||||
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE,
|
gpointer start_address,
|
||||||
GUM_INDEX_POST_ADJUST);
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
|
||||||
|
GumAddress target) {
|
||||||
|
|
||||||
|
if (!PAGE_ALIGNED(target)) { FATAL("Target not page aligned"); }
|
||||||
|
|
||||||
|
gssize distance = target - (GUM_ADDRESS(insn) & PAGE_MASK);
|
||||||
|
if (!instrument_coverage_in_range(distance)) {
|
||||||
|
|
||||||
|
FATAL("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
|
||||||
|
distance);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
guint32 imm_low = ((distance >> 12) & 0x3) << 29;
|
||||||
|
guint32 imm_high = ((distance >> 14) & 0x7FFFF) << 5;
|
||||||
|
*patch |= imm_low;
|
||||||
|
*patch |= imm_high;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
GumAddress code_addr = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given our map is allocated on a 64KB boundary and our map is a multiple of
|
||||||
|
* 64KB in size, then it should also end on a 64 KB boundary. It is followed
|
||||||
|
* by our previous_pc, so this too should be 64KB aligned.
|
||||||
|
*/
|
||||||
|
g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
|
||||||
|
g_assert(PAGE_ALIGNED(__afl_area_ptr));
|
||||||
|
|
||||||
|
instrument_patch_ardp(
|
||||||
|
&code.code.adrp_x0_prev_loc1,
|
||||||
|
code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
|
||||||
|
GUM_ADDRESS(instrument_previous_pc_addr));
|
||||||
|
|
||||||
|
code.code.mov_x0_curr_loc |= area_offset << 5;
|
||||||
|
|
||||||
|
instrument_patch_ardp(
|
||||||
|
&code.code.adrp_x1_area_ptr,
|
||||||
|
code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
|
||||||
|
GUM_ADDRESS(__afl_area_ptr));
|
||||||
|
|
||||||
|
map_size_pow2 = util_log2(__afl_map_size);
|
||||||
|
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
|
||||||
|
|
||||||
|
instrument_patch_ardp(
|
||||||
|
&code.code.adrp_x0_prev_loc2,
|
||||||
|
code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
|
||||||
|
GUM_ADDRESS(instrument_previous_pc_addr));
|
||||||
|
|
||||||
|
code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
|
||||||
|
|
||||||
|
gum_arm64_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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_optimize_init(void) {
|
void instrument_coverage_optimize_init(void) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_flush(GumStalkerOutput *output) {
|
void instrument_flush(GumStalkerOutput *output) {
|
||||||
@ -110,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
|
#endif
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
char *instrument_coverage_filename = NULL;
|
char *instrument_coverage_filename = NULL;
|
||||||
|
bool instrument_coverage_absolute = false;
|
||||||
|
|
||||||
static int normal_coverage_fd = -1;
|
static int normal_coverage_fd = -1;
|
||||||
static int normal_coverage_pipes[2] = {-1, -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 int unstable_coverage_pipes[2] = {-1, -1};
|
||||||
|
|
||||||
static uint64_t normal_coverage_last_start = 0;
|
static uint64_t normal_coverage_last_start = 0;
|
||||||
static gchar * unstable_coverage_fuzzer_stats = NULL;
|
static gchar *unstable_coverage_fuzzer_stats = NULL;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ typedef struct {
|
|||||||
static gboolean coverage_range(const GumRangeDetails *details,
|
static gboolean coverage_range(const GumRangeDetails *details,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
|
|
||||||
GArray * coverage_ranges = (GArray *)user_data;
|
GArray *coverage_ranges = (GArray *)user_data;
|
||||||
coverage_range_t coverage = {0};
|
coverage_range_t coverage = {0};
|
||||||
|
|
||||||
if (details->file == NULL) { return TRUE; }
|
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) {
|
static void instrument_coverage_mark(void *key, void *value, void *user_data) {
|
||||||
|
|
||||||
UNUSED_PARAMETER(key);
|
UNUSED_PARAMETER(key);
|
||||||
coverage_mark_ctx_t * ctx = (coverage_mark_ctx_t *)user_data;
|
coverage_mark_ctx_t *ctx = (coverage_mark_ctx_t *)user_data;
|
||||||
GArray * coverage_modules = ctx->modules;
|
GArray *coverage_modules = ctx->modules;
|
||||||
normal_coverage_data_t *val = (normal_coverage_data_t *)value;
|
normal_coverage_data_t *val = (normal_coverage_data_t *)value;
|
||||||
guint i;
|
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) {
|
static void coverage_write(int fd, void *data, size_t size) {
|
||||||
|
|
||||||
ssize_t written;
|
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->base_address);
|
||||||
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->limit);
|
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->limit);
|
||||||
/* entry */
|
/* entry */
|
||||||
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0);
|
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0UL);
|
||||||
/* checksum */
|
/* checksum */
|
||||||
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0);
|
coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0UL);
|
||||||
/* timestamp */
|
/* timestamp */
|
||||||
coverage_format(fd, "%08" G_GINT32_MODIFIER "X, ", 0);
|
coverage_format(fd, "%08" G_GINT32_MODIFIER "X, ", 0);
|
||||||
coverage_format(fd, "%s\n", module->path);
|
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));
|
coverage_write(fd, &evt, sizeof(coverage_event_t));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -398,35 +417,76 @@ static void instrument_coverage_normal_run() {
|
|||||||
|
|
||||||
instrument_coverage_print("Coverage - Preparing\n");
|
instrument_coverage_print("Coverage - Preparing\n");
|
||||||
|
|
||||||
GArray *coverage_modules = coverage_get_modules();
|
if (instrument_coverage_absolute) {
|
||||||
|
|
||||||
guint size = g_hash_table_size(coverage_hash);
|
guint size = g_hash_table_size(coverage_hash);
|
||||||
instrument_coverage_print("Coverage - Total Entries: %u\n", size);
|
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);
|
.base_address = GUM_ADDRESS(0),
|
||||||
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
|
.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);
|
instrument_coverage_print("Coverage Module - 0x%016" G_GINT64_MODIFIER
|
||||||
coverage_write_modules(normal_coverage_fd, coverage_modules);
|
"X - 0x%016" G_GINT64_MODIFIER "X (%s)\n",
|
||||||
coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", ctx.count);
|
module.base_address, module.limit, module.path);
|
||||||
g_hash_table_foreach(coverage_hash, coverage_write_events,
|
|
||||||
&normal_coverage_fd);
|
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);
|
g_hash_table_unref(coverage_hash);
|
||||||
|
|
||||||
instrument_coverage_print("Coverage - Completed\n");
|
instrument_coverage_print("Coverage - Completed\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GArray *instrument_coverage_unstable_read_unstable_ids(void) {
|
static GArray *instrument_coverage_unstable_read_unstable_ids(void) {
|
||||||
|
|
||||||
gchar * contents = NULL;
|
gchar *contents = NULL;
|
||||||
gsize length = 0;
|
gsize length = 0;
|
||||||
GArray *unstable_edge_ids =
|
GArray *unstable_edge_ids =
|
||||||
g_array_sized_new(false, false, sizeof(gpointer), 100);
|
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)) {
|
while (g_hash_table_iter_next(&iter, NULL, &value)) {
|
||||||
|
|
||||||
unstable_coverage_data_t *unstable = (unstable_coverage_data_t *)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));
|
gum_malloc0(sizeof(normal_coverage_data_t));
|
||||||
normal_coverage_data_t *to = gum_malloc0(sizeof(normal_coverage_data_t));
|
normal_coverage_data_t *to = gum_malloc0(sizeof(normal_coverage_data_t));
|
||||||
from->start = unstable->from;
|
from->start = unstable->from;
|
||||||
@ -616,8 +676,6 @@ static void instrument_coverage_unstable_run(void) {
|
|||||||
|
|
||||||
instrument_coverage_print("Coverage - Preparing\n");
|
instrument_coverage_print("Coverage - Preparing\n");
|
||||||
|
|
||||||
GArray *coverage_modules = coverage_get_modules();
|
|
||||||
|
|
||||||
instrument_coverage_print("Found edges: %u\n", edges);
|
instrument_coverage_print("Found edges: %u\n", edges);
|
||||||
|
|
||||||
GArray *unstable_edge_ids = instrument_coverage_unstable_read_unstable_ids();
|
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);
|
guint size = g_hash_table_size(unstable_blocks);
|
||||||
instrument_coverage_print("Unstable blocks: %u\n", size);
|
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 - Total Entries: %u\n", size);
|
||||||
instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count);
|
|
||||||
|
|
||||||
guint coverage_marked_modules = coverage_mark_modules(coverage_modules);
|
coverage_range_t module = {
|
||||||
instrument_coverage_print("Coverage - Marked Modules: %u\n",
|
|
||||||
coverage_marked_modules);
|
|
||||||
|
|
||||||
coverage_write_header(unstable_coverage_fd, coverage_marked_modules);
|
.base_address = GUM_ADDRESS(0),
|
||||||
coverage_write_modules(unstable_coverage_fd, coverage_modules);
|
.limit = GUM_ADDRESS(-1),
|
||||||
coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", ctx.count);
|
.size = GUM_ADDRESS(-1),
|
||||||
g_hash_table_foreach(unstable_blocks, coverage_write_events,
|
.path = "absolute",
|
||||||
&unstable_coverage_fd);
|
.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_hash_table_unref(unstable_blocks);
|
||||||
g_array_free(unstable_edge_ids, TRUE);
|
g_array_free(unstable_edge_ids, TRUE);
|
||||||
@ -654,22 +752,24 @@ static void instrument_coverage_unstable_run(void) {
|
|||||||
void instrument_coverage_config(void) {
|
void instrument_coverage_config(void) {
|
||||||
|
|
||||||
instrument_coverage_filename = getenv("AFL_FRIDA_INST_COVERAGE_FILE");
|
instrument_coverage_filename = getenv("AFL_FRIDA_INST_COVERAGE_FILE");
|
||||||
|
instrument_coverage_absolute =
|
||||||
|
(getenv("AFL_FRIDA_INST_COVERAGE_ABSOLUTE") != NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_normal_init(void) {
|
void instrument_coverage_normal_init(void) {
|
||||||
|
|
||||||
FOKF("Coverage - enabled [%c]",
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage:" cYEL " [%s]",
|
||||||
instrument_coverage_filename == NULL ? ' ' : 'X');
|
instrument_coverage_filename == NULL ? " "
|
||||||
|
: instrument_coverage_filename);
|
||||||
|
|
||||||
if (instrument_coverage_filename == NULL) { return; }
|
if (instrument_coverage_filename == NULL) { return; }
|
||||||
|
|
||||||
FOKF("Coverage - file [%s]", instrument_coverage_filename);
|
|
||||||
|
|
||||||
char *path = g_canonicalize_filename(instrument_coverage_filename,
|
char *path = g_canonicalize_filename(instrument_coverage_filename,
|
||||||
g_get_current_dir());
|
g_get_current_dir());
|
||||||
|
|
||||||
FOKF("Coverage - path [%s]", path);
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage path:" cYEL " [%s]",
|
||||||
|
path);
|
||||||
|
|
||||||
normal_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
normal_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||||
@ -718,7 +818,7 @@ void instrument_coverage_unstable_find_output(void) {
|
|||||||
|
|
||||||
GDir *dir = g_dir_open(fds_name, 0, NULL);
|
GDir *dir = g_dir_open(fds_name, 0, NULL);
|
||||||
|
|
||||||
FOKF("Coverage Unstable - fds: %s", fds_name);
|
FVERBOSE("Coverage Unstable - fds: %s", fds_name);
|
||||||
|
|
||||||
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
|
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
|
||||||
filename = g_dir_read_name(dir)) {
|
filename = g_dir_read_name(dir)) {
|
||||||
@ -782,18 +882,24 @@ void instrument_coverage_unstable_find_output(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FOKF("Fuzzer stats: %s", unstable_coverage_fuzzer_stats);
|
FVERBOSE("Fuzzer stats: %s", unstable_coverage_fuzzer_stats);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_unstable_init(void) {
|
void instrument_coverage_unstable_init(void) {
|
||||||
|
|
||||||
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]",
|
||||||
|
instrument_coverage_unstable_filename == NULL
|
||||||
|
? " "
|
||||||
|
: instrument_coverage_unstable_filename);
|
||||||
if (instrument_coverage_unstable_filename == NULL) { return; }
|
if (instrument_coverage_unstable_filename == NULL) { return; }
|
||||||
|
|
||||||
char *path = g_canonicalize_filename(instrument_coverage_unstable_filename,
|
char *path = g_canonicalize_filename(instrument_coverage_unstable_filename,
|
||||||
g_get_current_dir());
|
g_get_current_dir());
|
||||||
|
|
||||||
FOKF("Coverage - unstable path [%s]", instrument_coverage_unstable_filename);
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage path:" cYEL
|
||||||
|
" [%s]",
|
||||||
|
path == NULL ? " " : path);
|
||||||
|
|
||||||
unstable_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
unstable_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||||
|
@ -35,6 +35,10 @@ static void instrument_debug(char *format, ...) {
|
|||||||
static void instrument_disasm(guint8 *start, guint8 *end,
|
static void instrument_disasm(guint8 *start, guint8 *end,
|
||||||
GumStalkerOutput *output) {
|
GumStalkerOutput *output) {
|
||||||
|
|
||||||
|
#if !defined(__arm__)
|
||||||
|
UNUSED_PARAMETER(output);
|
||||||
|
#endif
|
||||||
|
|
||||||
csh capstone;
|
csh capstone;
|
||||||
cs_err err;
|
cs_err err;
|
||||||
cs_mode mode;
|
cs_mode mode;
|
||||||
@ -50,9 +54,7 @@ static void instrument_disasm(guint8 *start, guint8 *end,
|
|||||||
if (output->encoding == GUM_INSTRUCTION_SPECIAL) { mode |= CS_MODE_THUMB; }
|
if (output->encoding == GUM_INSTRUCTION_SPECIAL) { mode |= CS_MODE_THUMB; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = cs_open(GUM_DEFAULT_CS_ARCH,
|
err = cs_open(GUM_DEFAULT_CS_ARCH, mode, &capstone);
|
||||||
CS_MODE_THUMB | GUM_DEFAULT_CS_MODE | GUM_DEFAULT_CS_ENDIAN,
|
|
||||||
&capstone);
|
|
||||||
g_assert(err == CS_ERR_OK);
|
g_assert(err == CS_ERR_OK);
|
||||||
|
|
||||||
size = GPOINTER_TO_SIZE(end) - GPOINTER_TO_SIZE(start);
|
size = GPOINTER_TO_SIZE(end) - GPOINTER_TO_SIZE(start);
|
||||||
@ -64,7 +66,7 @@ static void instrument_disasm(guint8 *start, guint8 *end,
|
|||||||
|
|
||||||
instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t* 0x%016" G_GSIZE_MODIFIER
|
instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t* 0x%016" G_GSIZE_MODIFIER
|
||||||
"x\n",
|
"x\n",
|
||||||
curr, *(size_t *)curr);
|
(uint64_t)(size_t)curr, *(size_t *)curr);
|
||||||
|
|
||||||
len += sizeof(size_t);
|
len += sizeof(size_t);
|
||||||
continue;
|
continue;
|
||||||
@ -96,19 +98,15 @@ void instrument_debug_config(void) {
|
|||||||
|
|
||||||
void instrument_debug_init(void) {
|
void instrument_debug_init(void) {
|
||||||
|
|
||||||
FOKF("Instrumentation debugging - enabled [%c]",
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "debugging:" cYEL " [%s]",
|
||||||
instrument_debug_filename == NULL ? ' ' : 'X');
|
instrument_debug_filename == NULL ? " " : instrument_debug_filename);
|
||||||
|
|
||||||
if (instrument_debug_filename == NULL) { return; }
|
|
||||||
|
|
||||||
FOKF("Instrumentation debugging - file [%s]", instrument_debug_filename);
|
|
||||||
|
|
||||||
if (instrument_debug_filename == NULL) { return; }
|
if (instrument_debug_filename == NULL) { return; }
|
||||||
|
|
||||||
char *path =
|
char *path =
|
||||||
g_canonicalize_filename(instrument_debug_filename, g_get_current_dir());
|
g_canonicalize_filename(instrument_debug_filename, g_get_current_dir());
|
||||||
|
|
||||||
FOKF("Instrumentation debugging - path [%s]", path);
|
FOKF(cBLU "Instrumentation" cRST " - " cGRN "path:" cYEL " [%s]", path);
|
||||||
|
|
||||||
debugging_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
debugging_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||||
|
@ -23,13 +23,39 @@
|
|||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
#ifndef MAP_FIXED_NOREPLACE
|
enum jcc_opcodes {
|
||||||
#ifdef MAP_EXCL
|
|
||||||
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
|
OPC_JO = 0x70,
|
||||||
#else
|
OPC_JNO = 0x71,
|
||||||
#define MAP_FIXED_NOREPLACE MAP_FIXED
|
OPC_JB = 0x72,
|
||||||
#endif
|
OPC_JAE = 0x73,
|
||||||
#endif
|
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;
|
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 {
|
typedef struct {
|
||||||
|
|
||||||
@ -54,21 +79,28 @@ typedef struct {
|
|||||||
// shared_mem[cur_location ^ prev_location]++;
|
// shared_mem[cur_location ^ prev_location]++;
|
||||||
// prev_location = cur_location >> 1;
|
// prev_location = cur_location >> 1;
|
||||||
|
|
||||||
// mov QWORD PTR [rsp-0x80],rax
|
// mov QWORD PTR [rsp-0x88],rax
|
||||||
// lahf
|
// lahf
|
||||||
// mov QWORD PTR [rsp-0x88],rax
|
// mov QWORD PTR [rsp-0x90],rax
|
||||||
// mov QWORD PTR [rsp-0x90],rbx
|
// mov QWORD PTR [rsp-0x98],rbx
|
||||||
// mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740
|
|
||||||
// mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740
|
// mov eax,DWORD PTR [rip+0x1312334]
|
||||||
// lea rax,[rip + 0x103f77]
|
// xor eax,0x3f77
|
||||||
// mov bl,BYTE PTR [rax]
|
|
||||||
// add bl,0x1
|
// lea rbx,[rip+0x132338]
|
||||||
// adc bl,0x0
|
// add rax,rbx
|
||||||
// mov BYTE PTR [rax],bl
|
|
||||||
// mov rbx,QWORD PTR [rsp-0x90]
|
// mov bl,BYTE PTR [rax]
|
||||||
// mov rax,QWORD PTR [rsp-0x88]
|
// add bl,0x1
|
||||||
// sahf
|
// adc bl,0x0
|
||||||
// mov rax,QWORD PTR [rsp-0x80]
|
// 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 mov_rax_rsp_88[8];
|
||||||
uint8_t lahf;
|
uint8_t lahf;
|
||||||
@ -76,84 +108,11 @@ typedef struct {
|
|||||||
uint8_t mov_rbx_rsp_98[8];
|
uint8_t mov_rbx_rsp_98[8];
|
||||||
|
|
||||||
uint8_t mov_eax_prev_loc[6];
|
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 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 mov_rbx_ptr_rax[2];
|
||||||
uint8_t add_bl_1[3];
|
uint8_t add_bl_1[3];
|
||||||
uint8_t adc_bl_0[3];
|
uint8_t adc_bl_0[3];
|
||||||
@ -164,9 +123,11 @@ typedef struct {
|
|||||||
uint8_t sahf;
|
uint8_t sahf;
|
||||||
uint8_t mov_rsp_88_rax[8];
|
uint8_t mov_rsp_88_rax[8];
|
||||||
|
|
||||||
|
uint8_t mov_prev_loc_curr_loc_shr1[10];
|
||||||
|
|
||||||
} afl_log_code_asm_t;
|
} afl_log_code_asm_t;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
static const afl_log_code_asm_t template =
|
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_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
|
||||||
|
|
||||||
.mov_eax_prev_loc = {0x8b, 0x05},
|
.mov_eax_prev_loc = {0x8b, 0x05},
|
||||||
.mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
|
|
||||||
|
|
||||||
.xor_eax_curr_loc = {0x35},
|
.xor_eax_curr_loc = {0x35},
|
||||||
|
.lea_rbx_area_ptr = {0x48, 0x8d, 0x1d},
|
||||||
|
.add_rax_rbx = {0x48, 0x01, 0xd8},
|
||||||
|
|
||||||
.mov_rbx_ptr_rax = {0x8a, 0x18},
|
.mov_rbx_ptr_rax = {0x8a, 0x18},
|
||||||
.add_bl_1 = {0x80, 0xc3, 0x01},
|
.add_bl_1 = {0x80, 0xc3, 0x01},
|
||||||
.adc_bl_0 = {0x80, 0xd3, 0x00},
|
.adc_bl_0 = {0x80, 0xd3, 0x00},
|
||||||
@ -190,10 +152,11 @@ static const afl_log_code_asm_t template =
|
|||||||
.sahf = 0x9e,
|
.sahf = 0x9e,
|
||||||
.mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
|
.mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
|
||||||
|
|
||||||
|
.mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|
||||||
@ -202,179 +165,22 @@ typedef union {
|
|||||||
|
|
||||||
} afl_log_code;
|
} afl_log_code;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
void instrument_coverage_optimize_init(void) {
|
void instrument_coverage_optimize_init(void) {
|
||||||
|
|
||||||
}
|
FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
|
|
||||||
gpointer user_data) {
|
|
||||||
|
|
||||||
static GumAddress last_limit = (64ULL << 10);
|
|
||||||
gpointer * address = (gpointer *)user_data;
|
|
||||||
|
|
||||||
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, (64ULL << 10));
|
|
||||||
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);
|
|
||||||
|
|
||||||
FOKF("Low address: %p", low_address);
|
|
||||||
|
|
||||||
if (low_address == 0 ||
|
|
||||||
GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) {
|
|
||||||
|
|
||||||
FATAL("Invalid low_address: %p", low_address);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ranges_print_debug_maps();
|
|
||||||
|
|
||||||
char *shm_env = getenv(SHM_ENV_VAR);
|
|
||||||
FOKF("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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
FOKF("__afl_area_ptr: %p", __afl_area_ptr);
|
|
||||||
FOKF("instrument_previous_pc: %p", &instrument_previous_pc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void instrument_coverage_switch(GumStalkerObserver *self,
|
static void instrument_coverage_switch(GumStalkerObserver *self,
|
||||||
|
gpointer from_address,
|
||||||
gpointer start_address,
|
gpointer start_address,
|
||||||
const cs_insn * from_insn,
|
const cs_insn *from_insn,
|
||||||
gpointer * target) {
|
gpointer *target) {
|
||||||
|
|
||||||
UNUSED_PARAMETER(self);
|
UNUSED_PARAMETER(self);
|
||||||
UNUSED_PARAMETER(start_address);
|
UNUSED_PARAMETER(from_address);
|
||||||
|
|
||||||
cs_x86 * x86;
|
cs_x86 *x86;
|
||||||
cs_x86_op *op;
|
cs_x86_op *op;
|
||||||
if (from_insn == NULL) { return; }
|
if (from_insn == NULL) { return; }
|
||||||
|
|
||||||
@ -397,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;
|
break;
|
||||||
case X86_INS_RET:
|
case X86_INS_RET:
|
||||||
|
instrument_cache_insert(start_address,
|
||||||
|
(guint8 *)*target + sizeof(afl_log_code));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@ -417,7 +230,7 @@ static void instrument_coverage_suppress_init(void) {
|
|||||||
if (initialized) { return; }
|
if (initialized) { return; }
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
GumStalkerObserver * observer = stalker_get_observer();
|
GumStalkerObserver *observer = stalker_get_observer();
|
||||||
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
|
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
|
||||||
iface->switch_callback = instrument_coverage_switch;
|
iface->switch_callback = instrument_coverage_switch;
|
||||||
|
|
||||||
@ -430,39 +243,22 @@ static void instrument_coverage_suppress_init(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void instrument_coverage_optimize(const cs_insn * instr,
|
static void instrument_coverage_write(GumAddress address,
|
||||||
GumStalkerOutput *output) {
|
GumStalkerOutput *output) {
|
||||||
|
|
||||||
afl_log_code code = {0};
|
afl_log_code code = {0};
|
||||||
GumX86Writer *cw = output->writer.x86;
|
GumX86Writer *cw = output->writer.x86;
|
||||||
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
|
guint64 area_offset = instrument_get_offset_hash(address);
|
||||||
gsize map_size_pow2;
|
gsize map_size_pow2;
|
||||||
gsize area_offset_ror;
|
gsize area_offset_ror;
|
||||||
GumAddress code_addr = 0;
|
GumAddress code_addr = cw->pc;
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
code.code = template;
|
code.code = template;
|
||||||
|
|
||||||
gssize curr_loc_shr_1_offset =
|
/* mov_prev_loc_curr_loc_shr1 */
|
||||||
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);
|
|
||||||
|
|
||||||
gssize prev_loc_value =
|
gssize prev_loc_value =
|
||||||
GPOINTER_TO_SIZE(&instrument_previous_pc) -
|
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
|
||||||
(code_addr + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
(code_addr + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
||||||
sizeof(code.code.mov_prev_loc_curr_loc_shr1));
|
sizeof(code.code.mov_prev_loc_curr_loc_shr1));
|
||||||
gssize prev_loc_value_offset =
|
gssize prev_loc_value_offset =
|
||||||
@ -477,8 +273,10 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
|||||||
|
|
||||||
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
|
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
|
||||||
|
|
||||||
|
/* mov_eax_prev_loc */
|
||||||
|
|
||||||
gssize prev_loc_value2 =
|
gssize prev_loc_value2 =
|
||||||
GPOINTER_TO_SIZE(&instrument_previous_pc) -
|
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
|
||||||
(code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
|
(code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
|
||||||
sizeof(code.code.mov_eax_prev_loc));
|
sizeof(code.code.mov_eax_prev_loc));
|
||||||
gssize prev_loc_value_offset2 =
|
gssize prev_loc_value_offset2 =
|
||||||
@ -492,40 +290,172 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
|||||||
|
|
||||||
*((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2;
|
*((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
/* xor_eax_curr_loc */
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.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(code.code.xor_eax_curr_loc) -
|
||||||
sizeof(guint32);
|
sizeof(guint32);
|
||||||
|
|
||||||
*((guint32 *)&code.bytes[xor_curr_loc_offset]) =
|
*((guint32 *)&code.bytes[xor_curr_loc_offset]) = area_offset;
|
||||||
(guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset);
|
|
||||||
#endif
|
/* 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));
|
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) {
|
void instrument_flush(GumStalkerOutput *output) {
|
||||||
|
|
||||||
gum_x86_writer_flush(output->writer.x86);
|
gum_x86_writer_flush(output->writer.x86);
|
||||||
@ -538,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
|
#endif
|
||||||
|
|
||||||
|
435
frida_mode/src/instrument/instrument_x64_cache.c
Normal 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
|
||||||
|
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
|
|
||||||
|
gboolean instrument_cache_enabled = FALSE;
|
||||||
|
gsize instrument_cache_size = 0;
|
||||||
|
|
||||||
static GHashTable *coverage_blocks = NULL;
|
static GHashTable *coverage_blocks = NULL;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@ -81,14 +84,16 @@ gboolean instrument_is_coverage_optimize_supported(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void instrument_coverage_switch(GumStalkerObserver *self,
|
static void instrument_coverage_switch(GumStalkerObserver *self,
|
||||||
|
gpointer from_address,
|
||||||
gpointer start_address,
|
gpointer start_address,
|
||||||
const cs_insn * from_insn,
|
const cs_insn *from_insn,
|
||||||
gpointer * target) {
|
gpointer *target) {
|
||||||
|
|
||||||
UNUSED_PARAMETER(self);
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(from_address);
|
||||||
UNUSED_PARAMETER(start_address);
|
UNUSED_PARAMETER(start_address);
|
||||||
|
|
||||||
cs_x86 * x86;
|
cs_x86 *x86;
|
||||||
cs_x86_op *op;
|
cs_x86_op *op;
|
||||||
if (from_insn == NULL) { return; }
|
if (from_insn == NULL) { return; }
|
||||||
|
|
||||||
@ -131,7 +136,7 @@ static void instrument_coverage_suppress_init(void) {
|
|||||||
if (initialized) { return; }
|
if (initialized) { return; }
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
GumStalkerObserver * observer = stalker_get_observer();
|
GumStalkerObserver *observer = stalker_get_observer();
|
||||||
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
|
GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
|
||||||
iface->switch_callback = instrument_coverage_switch;
|
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) {
|
GumStalkerOutput *output) {
|
||||||
|
|
||||||
afl_log_code code = {0};
|
afl_log_code code = {0};
|
||||||
@ -153,6 +158,20 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
|||||||
gsize map_size_pow2;
|
gsize map_size_pow2;
|
||||||
gsize area_offset_ror;
|
gsize area_offset_ror;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
code.code = template;
|
code.code = template;
|
||||||
|
|
||||||
instrument_coverage_suppress_init();
|
instrument_coverage_suppress_init();
|
||||||
@ -170,7 +189,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
|||||||
sizeof(code.code.mov_eax_prev_loc) - sizeof(gint);
|
sizeof(code.code.mov_eax_prev_loc) - sizeof(gint);
|
||||||
|
|
||||||
*((gint *)&code.bytes[prev_loc_value_offset2]) =
|
*((gint *)&code.bytes[prev_loc_value_offset2]) =
|
||||||
(gint)GPOINTER_TO_SIZE(&instrument_previous_pc);
|
(gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr);
|
||||||
|
|
||||||
gssize curr_loc_shr_1_offset =
|
gssize curr_loc_shr_1_offset =
|
||||||
offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
||||||
@ -187,7 +206,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
|||||||
sizeof(guint32);
|
sizeof(guint32);
|
||||||
|
|
||||||
*((gint *)&code.bytes[prev_loc_value_offset]) =
|
*((gint *)&code.bytes[prev_loc_value_offset]) =
|
||||||
(gint)GPOINTER_TO_SIZE(&instrument_previous_pc);
|
(gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr);
|
||||||
|
|
||||||
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.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(code.code.xor_eax_curr_loc) -
|
||||||
@ -205,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) {
|
void instrument_coverage_optimize_init(void) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -221,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
|
#endif
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ void intercept_hook(void *address, gpointer replacement, gpointer user_data) {
|
|||||||
|
|
||||||
GumInterceptor *interceptor = gum_interceptor_obtain();
|
GumInterceptor *interceptor = gum_interceptor_obtain();
|
||||||
gum_interceptor_begin_transaction(interceptor);
|
gum_interceptor_begin_transaction(interceptor);
|
||||||
GumReplaceReturn ret =
|
GumReplaceReturn ret = gum_interceptor_replace(interceptor, address,
|
||||||
gum_interceptor_replace(interceptor, address, replacement, user_data);
|
replacement, user_data, NULL);
|
||||||
if (ret != GUM_REPLACE_OK) { FFATAL("gum_interceptor_attach: %d", ret); }
|
if (ret != GUM_REPLACE_OK) { FFATAL("gum_interceptor_attach: %d", ret); }
|
||||||
gum_interceptor_end_transaction(interceptor);
|
gum_interceptor_end_transaction(interceptor);
|
||||||
|
|
||||||
|
@ -63,11 +63,17 @@ class Afl {
|
|||||||
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* See `AFL_FRIDA_INST_NO_BACKPATCH`.
|
* See `AFL_FRIDA_STALKER_NO_BACKPATCH`.
|
||||||
*/
|
*/
|
||||||
static setBackpatchDisable() {
|
static setBackpatchDisable() {
|
||||||
Afl.jsApiSetBackpatchDisable();
|
Afl.jsApiSetBackpatchDisable();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* See `AFL_FRIDA_INST_NO_CACHE`.
|
||||||
|
*/
|
||||||
|
static setCacheDisable() {
|
||||||
|
Afl.jsApiSetCacheDisable();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* See `AFL_FRIDA_DEBUG_MAPS`.
|
* See `AFL_FRIDA_DEBUG_MAPS`.
|
||||||
*/
|
*/
|
||||||
@ -91,6 +97,19 @@ class Afl {
|
|||||||
static setInMemoryFuzzing() {
|
static setInMemoryFuzzing() {
|
||||||
Afl.jsApiAflSharedMemFuzzing.writeInt(1);
|
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`
|
* See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
|
||||||
* as an argument.
|
* as an argument.
|
||||||
@ -113,6 +132,12 @@ class Afl {
|
|||||||
static setInstrumentEnableTracing() {
|
static setInstrumentEnableTracing() {
|
||||||
Afl.jsApiSetInstrumentTrace();
|
Afl.jsApiSetInstrumentTrace();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* See `AFL_FRIDA_INST_INSN`
|
||||||
|
*/
|
||||||
|
static setInstrumentInstructions() {
|
||||||
|
Afl.jsApiSetInstrumentInstructions();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* See `AFL_FRIDA_INST_JIT`.
|
* See `AFL_FRIDA_INST_JIT`.
|
||||||
*/
|
*/
|
||||||
@ -131,6 +156,14 @@ class Afl {
|
|||||||
static setInstrumentNoOptimize() {
|
static setInstrumentNoOptimize() {
|
||||||
Afl.jsApiSetInstrumentNoOptimize();
|
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`
|
* See `AFL_FRIDA_INST_SEED`
|
||||||
*/
|
*/
|
||||||
@ -268,6 +301,12 @@ class Afl {
|
|||||||
static setTraceable() {
|
static setTraceable() {
|
||||||
Afl.jsApiSetTraceable();
|
Afl.jsApiSetTraceable();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* See `AFL_FRIDA_VERBOSE`
|
||||||
|
*/
|
||||||
|
static setVerbose() {
|
||||||
|
Afl.jsApiSetVerbose();
|
||||||
|
}
|
||||||
static jsApiGetFunction(name, retType, argTypes) {
|
static jsApiGetFunction(name, retType, argTypes) {
|
||||||
const addr = Afl.module.getExportByName(name);
|
const addr = Afl.module.getExportByName(name);
|
||||||
return new NativeFunction(addr, retType, argTypes);
|
return new NativeFunction(addr, retType, argTypes);
|
||||||
@ -287,13 +326,18 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing");
|
|||||||
Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []);
|
Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []);
|
||||||
Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
|
Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
|
||||||
Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []);
|
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.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []);
|
||||||
Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]);
|
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.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]);
|
||||||
Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_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.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
|
||||||
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
|
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
|
||||||
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "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.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]);
|
||||||
Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []);
|
Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []);
|
||||||
Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []);
|
Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []);
|
||||||
@ -315,6 +359,7 @@ Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "v
|
|||||||
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
||||||
Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]);
|
Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]);
|
||||||
Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []);
|
Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []);
|
||||||
|
Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
|
||||||
Afl.jsApiWrite = new NativeFunction(
|
Afl.jsApiWrite = new NativeFunction(
|
||||||
/* tslint:disable-next-line:no-null-keyword */
|
/* tslint:disable-next-line:no-null-keyword */
|
||||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||||
|
@ -7,16 +7,16 @@ gboolean js_done = FALSE;
|
|||||||
js_api_stalker_callback_t js_user_callback = NULL;
|
js_api_stalker_callback_t js_user_callback = NULL;
|
||||||
js_main_hook_t js_main_hook = NULL;
|
js_main_hook_t js_main_hook = NULL;
|
||||||
|
|
||||||
static char * js_script = NULL;
|
static char *js_script = NULL;
|
||||||
static gchar * filename = "afl.js";
|
static gchar *filename = "afl.js";
|
||||||
static gchar * contents;
|
static gchar *contents;
|
||||||
static GumScriptBackend * backend;
|
static GumScriptBackend *backend;
|
||||||
static GCancellable * cancellable = NULL;
|
static GCancellable *cancellable = NULL;
|
||||||
static GError * error = NULL;
|
static GError *error = NULL;
|
||||||
static GumScript * script;
|
static GumScript *script;
|
||||||
static GumScriptScheduler *scheduler;
|
static GumScriptScheduler *scheduler;
|
||||||
static GMainContext * context;
|
static GMainContext *context;
|
||||||
static GMainLoop * main_loop;
|
static GMainLoop *main_loop;
|
||||||
|
|
||||||
static void js_msg(GumScript *script, const gchar *message, GBytes *data,
|
static void js_msg(GumScript *script, const gchar *message, GBytes *data,
|
||||||
gpointer user_data) {
|
gpointer user_data) {
|
||||||
@ -55,7 +55,10 @@ static gchar *js_get_script() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
FOKF("Loaded AFL script: %s, %" G_GSIZE_MODIFIER "d bytes", filename,
|
FOKF(cBLU "Javascript" cRST " - " cGRN "script:" cYEL " [%s]",
|
||||||
|
filename == NULL ? " " : filename);
|
||||||
|
FOKF(cBLU "Javascript" cRST " - " cGRN "size: " cYEL "%" G_GSIZE_MODIFIER
|
||||||
|
"d bytes",
|
||||||
length);
|
length);
|
||||||
|
|
||||||
gchar *source = g_malloc0(api_js_len + length + 1);
|
gchar *source = g_malloc0(api_js_len + length + 1);
|
||||||
@ -74,7 +77,7 @@ static void js_print_script(gchar *source) {
|
|||||||
|
|
||||||
for (size_t i = 0; split[i] != NULL; i++) {
|
for (size_t i = 0; split[i] != NULL; i++) {
|
||||||
|
|
||||||
FOKF("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);
|
FVERBOSE("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|