mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
3144 Commits
Author | SHA1 | Date | |
---|---|---|---|
4094750803 | |||
92352951d7 | |||
bb509765df | |||
6705953a49 | |||
c83635e1d2 | |||
fd404194f2 | |||
88077d4136 | |||
cfb0257c99 | |||
9a93688e3e | |||
48c2d51689 | |||
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 | |||
9f6394242b | |||
2c144e88fb | |||
5c7e84c5c8 | |||
52cae6d132 | |||
6eb752a65c | |||
ed3eb61610 | |||
0993bcdc4e | |||
d28bb47a38 | |||
9d7dd5a69f | |||
4bcd96ce68 | |||
e903f12e8c | |||
663889bc94 | |||
6c39e2cc2e | |||
77ce31c8ba | |||
4ce1ec3219 | |||
4544a90b6e | |||
34c9654690 | |||
d40a4fe366 | |||
5ec91ad529 | |||
602eafc223 | |||
5b9397f3dd | |||
269054e5c5 | |||
7603e49765 | |||
74aa826b60 | |||
16011ec057 | |||
7650547614 | |||
2e2e35ea61 | |||
46b250c243 | |||
883e6eb665 | |||
0648772967 | |||
82f1cf0735 | |||
0c4118ba7c | |||
2fc764a43f | |||
3ee6ff0f8c | |||
6ce72deb75 | |||
caf67efab1 | |||
3b287b7b0c | |||
def386ae43 | |||
db360332c4 | |||
9063002af2 | |||
08ca4d54a5 | |||
4c6d94ea5f | |||
eea020ee6a | |||
e46adb0be7 | |||
1f6c72ea1b | |||
5469112db9 | |||
bb506de0b8 | |||
139db40cfc | |||
89df436290 | |||
f65ca11e8e | |||
cdd176c52f | |||
a7c6b54514 | |||
3506077fd6 | |||
415be06c54 | |||
6eab6a55af | |||
ae59ed8e9e | |||
8d696c9396 | |||
667c2e58b2 | |||
bcd81c377d | |||
13eedcd5e8 | |||
0594bcb0cb | |||
29e4c315d9 | |||
ed808fe92f | |||
fc094dee13 | |||
a915c05740 | |||
aa6586a761 | |||
377adb776e | |||
65c3db8625 | |||
a7694e299a | |||
c85e0dc4f0 | |||
fcbaddfd2b | |||
b7395fa467 | |||
86dae0b16a | |||
0fbaaa4b32 | |||
3023a36d4d | |||
7a8e4018a5 | |||
f63c2ed145 | |||
73e9677a88 | |||
9cb32ca142 | |||
0ae9b0dff4 | |||
d9e39be4e8 | |||
ca7144161f | |||
80d5afa373 | |||
d4ae8fde5d | |||
78b0e108a6 | |||
22827e8070 | |||
c2779cc6f9 | |||
c14ccdf264 | |||
da13111117 | |||
f2ff029cc2 | |||
5525f8c9ef | |||
edbf41f786 | |||
8968bee836 | |||
11b3961e68 | |||
70236b854f | |||
b48999f7c9 | |||
b0c51964b7 | |||
2cdd75a274 | |||
af2fcbc1d4 | |||
a699dc2d2d | |||
235bb3235e | |||
ce0edcff2e | |||
934daec8ce | |||
042da82f6c | |||
655b63d2b2 | |||
a37c6eef3f | |||
e323512ca1 | |||
55ed2a443c | |||
7604dba6d6 | |||
f1d2332657 | |||
2412ff63e3 | |||
b8a8837875 | |||
133fba724a | |||
9a485106b0 | |||
e0c8a5c0c6 | |||
1a57253a1c | |||
ce21346053 | |||
5011877980 | |||
116531af58 | |||
4f1310db51 | |||
fce93647cc | |||
43928461e8 | |||
5b480f9451 | |||
f11cf068dc | |||
c866e9c3cc | |||
22726315c3 | |||
91f1c17c8f | |||
cfa89c6bc7 | |||
8c4435e7ef | |||
1fbb7cb2fa | |||
6cce577b90 | |||
90d7931af6 | |||
11f89ab785 | |||
39e2003630 | |||
6f5ba59d99 | |||
a0cc3dc101 | |||
d9ff3745d0 | |||
d50da14f60 | |||
4dad895bbb | |||
10365a22bd | |||
745408be60 | |||
8b5eafe7c5 | |||
0e9b208949 | |||
6f9a98c4a9 | |||
3a7a8704ee | |||
ef35c803da | |||
c31f4646cb | |||
492dbe9fb2 | |||
36514a2e4f | |||
4434aa103c | |||
de027b3b6b | |||
5ec859cece | |||
581cb16965 | |||
3d18243fd7 | |||
eb7db334a5 | |||
d73b400704 | |||
5c1b2412a5 | |||
24f5e8a6db | |||
f85edd9181 | |||
0aae4589ee | |||
2101c651f5 | |||
d61a4def5e | |||
4a2d944df3 | |||
8c9ce591e5 | |||
2cd4f4e7fa | |||
7777045c09 | |||
9283967a6e | |||
b18b8f553f | |||
0c26e43486 | |||
7c3d4e54eb | |||
b0f7691c29 | |||
af02fa1670 | |||
3b9545854f | |||
e131d0fc55 | |||
a7b9433850 | |||
e88509ac22 | |||
43458f7e8b | |||
67a6481b36 | |||
7514565858 | |||
8a9f3bcca8 | |||
132630d48d | |||
b659be1549 | |||
1a8d3f82f2 | |||
268339a683 | |||
464f1a78df | |||
3f864fa129 | |||
2d4b18f98e | |||
02b621e83c | |||
ca1e078597 | |||
f719b426e3 | |||
e1d3fe30de | |||
de90fd652e | |||
d4a0fd41cd | |||
feff8191ec | |||
c2feee4ed1 | |||
cf0fd0ff33 | |||
d63d69a1f6 | |||
96430fc9e0 | |||
b033a2d98b | |||
a15b5ef458 | |||
9100f3c416 | |||
2623851680 | |||
62a7ed635e | |||
7e1dba2e6b | |||
533e979010 | |||
b47344e8f7 | |||
6570327c2b | |||
45748fd752 | |||
8a861d0947 | |||
02e8919cbc | |||
66ca8618ea | |||
8578b6b01c | |||
75821d2943 | |||
89eefe044f | |||
3d9b2b459f | |||
b834f934d0 | |||
3521268269 | |||
93b8f17242 | |||
f4312255d9 | |||
33f9af976b | |||
7dcaf64eed | |||
c94f07bfdf | |||
d92d1e5685 | |||
3483715789 | |||
fb443eaf23 | |||
5b06413a5f | |||
93852a2312 | |||
92c91f25f0 | |||
72878cc14b | |||
2ddbaa439c | |||
da45eb6b41 | |||
64704403ca | |||
61039b410c | |||
b5d7f6bd60 | |||
9325a4fcbb | |||
ddc930f5ff | |||
9506772984 | |||
67ed01c560 | |||
b34bc6c426 | |||
74b4274e35 | |||
6ce3d7fede | |||
5e0e385e62 | |||
809f4922b9 | |||
f5535e348d | |||
9278f27d74 | |||
25c947cd5a | |||
02a5d96846 | |||
afc84438c6 | |||
331efc740d | |||
651133ea00 | |||
3670412d2e | |||
45399b7a56 | |||
701997a2a5 | |||
7a7630ae91 | |||
ccded9fc5c | |||
caf68e5bf2 | |||
5bcb7a8fed | |||
f35e71ca11 | |||
ce41f881a0 | |||
682e1d835c | |||
fb3a71bd25 | |||
cd9f596ce0 | |||
f97c5dba2a | |||
7e813ca492 | |||
0cbb406451 | |||
d918a9e85b | |||
01d266f2b4 | |||
639d108512 | |||
c64735df9e | |||
36d8f97972 | |||
bb255fdd79 | |||
b1aecf4ff0 | |||
94ab015a48 | |||
45b8e05793 | |||
e2ca7a6397 | |||
873f5a979e | |||
69d82cf9d7 | |||
471081e1b8 | |||
d85f5d4d62 | |||
9a11c8ac24 | |||
15bc729757 | |||
245e91eb27 | |||
f14b3bd9de | |||
b4e328803c | |||
4b631c9a19 | |||
efec2b5a99 | |||
86409092a1 | |||
7407e2fb11 | |||
695da56808 | |||
85ca0df989 | |||
0348ede4bc | |||
0f49463ede | |||
a7ee11a174 | |||
4dfb7bfe4f | |||
b12864b0be | |||
1a9ced30ce | |||
f68b9f5110 | |||
e03897a070 | |||
06b23c7dcb | |||
e637ca216e | |||
4e3fec2666 | |||
47a333af4d | |||
90786e2ce9 | |||
0bc3367b55 | |||
23e69f1107 | |||
77a63d8ccf | |||
bb8a4d71da | |||
fd43daee6a | |||
73531e5dd6 | |||
edaa25a48c | |||
45d668a671 | |||
7cd98f565f | |||
699df8f8ce | |||
72d10fee40 | |||
6403fa4f70 | |||
9c278df038 | |||
4b4244bcf6 | |||
fb481231b7 | |||
efda110240 | |||
462149de64 | |||
65c94d914d | |||
bf0fbc24ad | |||
2363a04750 | |||
e8cf04c90d | |||
ed10f3783b | |||
8bc2b52f65 | |||
34f1074ba3 | |||
88bcc34802 | |||
c96fdfac01 | |||
7d0e0cde0a | |||
1f2fa22dad | |||
c49b308794 | |||
8b1910e268 | |||
3deca3b09b | |||
17c59de1c2 | |||
319db6759b | |||
e0c052cad7 | |||
379c580658 | |||
6e08e80907 | |||
544a65db54 | |||
8e66289809 | |||
ea05d4ed13 | |||
269dc29efe | |||
28df6d5a57 | |||
d22b28d17b | |||
d0fc985e22 | |||
00aa689f40 | |||
9c1eb51e5c | |||
a8844eaceb | |||
989f0d00a5 | |||
79d87f8544 | |||
659366ac60 | |||
228f6c5dad | |||
da865cbb9d | |||
f6fbbf8150 | |||
158e881ad4 | |||
65afe5addc | |||
7b1fed78d8 | |||
580401591f | |||
0a88a6c530 | |||
7a543f4325 | |||
f0e6a7a4f8 | |||
65e63b9cf1 | |||
02c9ae91aa | |||
b9f88ab166 | |||
46683d6516 | |||
8bde2bb13e | |||
716d2029c0 | |||
5df7b12b75 | |||
fc48a58e64 | |||
1a79a36762 | |||
e80131bef5 | |||
d668f9697c | |||
4473904bc0 | |||
2eac714ac1 | |||
0ed0c9493e | |||
c8f6a31311 | |||
a88f6d3b06 | |||
d6500eb298 | |||
8dab1db53f | |||
51b2e86ec0 | |||
82ef4a90b0 | |||
bd4ecd83b1 | |||
6546a0a5fd | |||
48e26d8e06 | |||
a6c1c24d8e | |||
8af84c203c | |||
f760e80729 | |||
cb01d56616 | |||
78d7944bbf | |||
70c03944d2 | |||
1a13ae9a98 | |||
e1eadecf59 | |||
1181f26a50 | |||
c206fb319b | |||
dc1f93cf8c | |||
3f7c5f80fe | |||
d63afa5046 | |||
a9b9a76bbb | |||
6d6353d917 | |||
5485ea3cc7 | |||
9586c77174 | |||
773baf9391 | |||
d4a8a9df69 | |||
9747ac4221 | |||
583b8e849b | |||
ec4cae448b | |||
fe5b2c355f | |||
5559dd9c24 | |||
353d402aaf | |||
7a2f81e0d9 | |||
ca28ca6c05 | |||
066f60dd2f | |||
31e34c1634 | |||
e5f5d5886a | |||
86f920f645 | |||
1a8819c9ad | |||
4cdf4d2eaf | |||
edda239131 | |||
e25f7cefdc | |||
9e2a94532b | |||
2e15661f18 | |||
ca9c87dd45 | |||
028f8ced8f | |||
d8c221fade | |||
64fbf973e0 | |||
b9b497241b | |||
5ba3601697 | |||
8779412171 | |||
23c240a94a | |||
f189668dd6 | |||
41a4c99d01 | |||
c2e02df9a5 | |||
56e2c55914 | |||
3513ba2e51 | |||
591d6c59c7 | |||
1959812e83 | |||
faac1651e4 | |||
17681405bc | |||
dbb793646e | |||
69b7f2cae4 | |||
10c98c2a4c | |||
c3641fbd97 | |||
5f20137e9d | |||
2a68d37b4f | |||
6191af7440 | |||
4a88e17a26 | |||
e05519baf4 | |||
b28b46daeb | |||
105454e51c | |||
8948fdcf4c | |||
85a7195631 | |||
4b3ba3e51a | |||
0c1dcadfb4 | |||
0715396cb2 | |||
bdd455e6fb | |||
a6adb6be2c | |||
95b794744b | |||
b8fd0a1463 | |||
cacee58fb7 | |||
11d62d51c5 | |||
d2d7585db5 | |||
cfbff436a5 | |||
20815d6850 | |||
c775f40ebf | |||
3c0e8528e3 | |||
baf4ae52c4 | |||
94e2f52abf | |||
40a837780a | |||
b4c96d686f | |||
5700b3c750 | |||
781e65ea42 | |||
50fc76faa8 | |||
3f1a2d596f | |||
b6b4ab0bd8 | |||
8f378ab00a | |||
ab43289c1a | |||
a92952fa03 | |||
df74625df0 | |||
1cffe27185 | |||
08cb3f8ab5 | |||
c779262d89 | |||
d832ed68ea | |||
73c7136bdb | |||
6b06d4c74d | |||
fda210aabd | |||
691af58b73 | |||
e7d8272aed | |||
9578546048 | |||
1095840b98 | |||
7e49b92848 | |||
ca98778b28 | |||
533c612dc9 | |||
df5e61de83 | |||
41aebad83e | |||
fa7e3453d3 | |||
7bedd862d3 | |||
6f3e63de05 | |||
c7a93d50c4 | |||
bb9be56dd6 | |||
f72430711b | |||
8ad6e7c140 | |||
382439b58f | |||
18db645a69 | |||
08080e70a6 | |||
b3eadc6a77 | |||
da23c4254b | |||
2702a713d7 | |||
233a628047 | |||
c3fbf5dca3 | |||
bcdb69289f | |||
8b66d95038 | |||
f9bc5d361f | |||
ac13902a93 | |||
50e26ea1a7 | |||
0bd6fda98b | |||
0dbd37a20b | |||
036282185b | |||
cc933bcc0c | |||
33f9f911c1 | |||
1afa0d7861 | |||
aebb14ceeb | |||
64daf10584 | |||
7123dd9d29 | |||
99d24d13f1 | |||
ea39e6d6e7 | |||
6d8813eb1a | |||
2a51358b15 | |||
d7caf1b0f2 | |||
07346cb06d | |||
a772cb0d00 | |||
58636fd54e | |||
d02483e40d | |||
30679edc1a | |||
dc16d8d998 | |||
7c3e78c2c9 | |||
87b17af751 | |||
9d3816abff | |||
e64aa57576 | |||
99a3644db1 | |||
bab487f4b5 | |||
0f299a3bef | |||
dc0fed6e0c | |||
0e563656fb | |||
c979d405e9 | |||
4d55a427f0 | |||
437b399e74 | |||
c9460c4788 | |||
183d9a3f07 | |||
44ffcf7ede | |||
3e00184c9a | |||
21db86af9b | |||
699a1b0120 | |||
549b01e68b | |||
a9328e40b3 | |||
60cbe5b4be | |||
fa2b164429 | |||
62f1bfed99 | |||
3d7a2fc869 | |||
a3a86afd0d | |||
4d7c23e231 | |||
bbff0c88fa | |||
5543bd5b63 | |||
6a6387582c | |||
a772fbf1cd | |||
53327f9ee7 | |||
3101e9c88d | |||
fff8c49f7c | |||
b3fe3b8877 | |||
f5e9fe17f2 | |||
0daffb6283 | |||
32a0d6ac31 | |||
8151618276 | |||
9321a24e68 | |||
1e23a8d678 | |||
cc57cc5f46 | |||
4fa56f0696 | |||
766217e79e | |||
c55f7af657 | |||
939729e504 | |||
18fd97fc5f | |||
a705b1548f | |||
b13b8c7e55 | |||
212fe5b6f5 | |||
2c19750d08 | |||
9e8afcc615 | |||
6f03749c73 | |||
6e704e8a10 | |||
b5422c1a52 | |||
8d873357a3 | |||
8a2b140f40 | |||
c279750689 | |||
7fb2d90c49 | |||
ed2d474369 | |||
2d8050c397 | |||
50fcd60bc7 | |||
21215ac21c | |||
cd683ed253 | |||
3dd39fec90 | |||
b7cd6db08f | |||
4560ecc647 | |||
6df597213a | |||
6e818ed078 | |||
d346d07b63 | |||
bb627c7e58 | |||
9ec63d3f17 | |||
4fe572b80f | |||
3a3ef7b6b4 | |||
94999782f1 | |||
7cec158b0e | |||
b6a9e54c60 | |||
ec4ad161fc | |||
d16d8dbb85 | |||
fc3d7e821c | |||
37fff16a36 | |||
4ef12d7215 | |||
5bcbb2f59a | |||
1b2637545b | |||
d354ec2586 | |||
e1d5009229 | |||
fd4acc935e | |||
19b01d763a | |||
a09ab99534 | |||
ac565bfe51 | |||
6d878a375d | |||
f4b975d6ad | |||
161d763334 | |||
49df0af628 | |||
70312789fd | |||
8dbe87bdf6 | |||
458eb0813a | |||
f1bcd378a2 | |||
405382cbdd | |||
43db577dbb | |||
0662c5580b | |||
4a02118fda | |||
2a433f90c4 | |||
bf9a155418 | |||
6ec295db4e | |||
f7fb4495c4 | |||
dcf450ecba | |||
886e2ba770 | |||
7283205fe3 | |||
cca11b08b1 | |||
a8529de592 | |||
a6cf9bb336 | |||
5d5624b930 | |||
7da632065f | |||
000b16af16 | |||
046a9520f3 | |||
cda62bab08 | |||
7038e56da3 | |||
6a3877dcd3 | |||
c88b98d1c9 | |||
89ddd9998c | |||
28e6b96276 | |||
61e1c74d52 | |||
f348a35ec6 | |||
4057134d3c | |||
906bede108 | |||
1fcb52957e | |||
ec781af2c7 | |||
93b9832acd | |||
ae50a50677 | |||
d64cde8370 | |||
c6b77d2d05 | |||
600058aeab | |||
ff4d45eed2 | |||
56851fa499 | |||
cbac22d82b | |||
ba9323f14c | |||
98dc0d2649 | |||
58747f9f4f | |||
35153e9b49 | |||
c46f8c1f70 | |||
a6c0b5f766 | |||
7bcd4e2901 | |||
f3362007ed | |||
0c3feba3f6 | |||
ef5fd33120 | |||
74fcb365e9 | |||
ade8cdca55 | |||
35c23be973 | |||
2516324d3e | |||
8c1b0aba5f | |||
444e15cff0 | |||
dfff952f53 | |||
d2e256e73a | |||
581593ccab | |||
0978c08f4b | |||
b9f260452e | |||
8dd30947cb | |||
63504f7b7e | |||
a7340a1ac6 | |||
b8092c6227 | |||
706c2ac8e0 | |||
a4cb2414d5 | |||
f9a1e87635 | |||
e0aa411647 | |||
b9d2a87f03 | |||
3b9f4441e5 | |||
d57f0e3a1c | |||
48c878a76d | |||
c88f650bf8 | |||
fff8c5e0a8 | |||
c7b9171c10 | |||
cd95dfe1e7 | |||
d64dd7a952 | |||
63ee9df54f | |||
2d2d9b0b77 | |||
2449866f21 | |||
76c0940cee | |||
c69edc2b3c | |||
4bf08566ca | |||
c78a9e4b37 | |||
92fcef4520 | |||
a5ff9f1beb | |||
436f997d26 | |||
8f04269e17 | |||
280814c3a2 | |||
ddd9154e78 | |||
1474e2db23 | |||
2988dd206c | |||
fd07853550 | |||
0d50ee4947 | |||
43eca8203a | |||
36671ce799 | |||
f3b1c5c382 | |||
0897377b13 | |||
70a2077107 | |||
c5d899e0f5 | |||
2ecf77db7a | |||
55da5e3e02 | |||
0fbe5fb436 | |||
beb97cdc89 | |||
a38aafc5d0 | |||
d5a24acb21 | |||
a321d4102b | |||
a47c312252 | |||
bee3902062 | |||
96c802fce8 | |||
4b964e0a28 | |||
97225f1f6f | |||
e3a0ede91c | |||
db6947452c | |||
64368d4ba7 | |||
4096360791 | |||
753d5d74ff | |||
bdc7aa1a94 | |||
9cf45db7f9 | |||
3d1cc8ec57 | |||
02294d368a | |||
f9ca2cf989 | |||
d20d031141 | |||
b9799bbe1d | |||
07c3e47e6b | |||
7e54c8d7f6 | |||
8017f88614 | |||
5f6ff95e6a | |||
17e904eedf | |||
5b5dff4584 | |||
7665354405 | |||
67b294890e | |||
21c8b22571 | |||
97a1f89881 | |||
1a2da67ed0 | |||
b246de7891 | |||
eb74a7a800 | |||
c9539aa6b7 | |||
67293b298d | |||
c78762e690 | |||
d2e85cce50 | |||
6883605d13 | |||
de7370c0e9 | |||
8e86f7ad80 | |||
e5083fbf25 | |||
f677be5e86 | |||
14178141dc | |||
9e0370aa99 | |||
73f4d44ddc | |||
0aeb871ac9 | |||
2af9a634d6 | |||
64d9b7dd21 | |||
2210472784 | |||
6bd3c26cfb | |||
a5e551ab91 | |||
3b93729213 | |||
314c0357a7 | |||
ad3dba047f | |||
654bc7bf32 | |||
87b16c4460 | |||
8e75adfee5 | |||
109383f438 | |||
909e43fd55 | |||
95f47ac3a4 | |||
07c8024ef1 | |||
bb45398d0b | |||
bc286035e9 | |||
197c8845ee | |||
12c8d339b1 | |||
5864430d93 | |||
58e39ecd8f | |||
9e6e7e8fe8 | |||
bd1ceb42c4 | |||
1fe06d3856 | |||
d14a758f69 | |||
f66a4de18a | |||
1edb89be0f | |||
5a14ceb504 | |||
a3392baaaa | |||
bceae82754 | |||
c7908688b5 | |||
3844e79492 | |||
06d703bf66 | |||
5997a4fc09 | |||
a1458ea671 | |||
da2d4d8258 | |||
cdae3d3d03 | |||
dee64e74a8 | |||
59595a6897 | |||
d776d40669 | |||
2ef9ff4468 | |||
af900bca98 | |||
b669e77268 | |||
257cc1e82a | |||
d0af55e78f | |||
e40c0c2da1 | |||
9d50ae7468 | |||
fa63f2652d | |||
ccf739f880 | |||
47e22e8d8d | |||
a3fffac90c | |||
738246465d | |||
7b033367c2 | |||
3d28925c13 | |||
000c729095 | |||
72ca9b4684 | |||
8929da3391 | |||
fd077e86bd | |||
09458343c0 | |||
8b7a7b29c6 | |||
d0fa8dcba5 | |||
50af4654e3 | |||
82d0e4f210 | |||
84e55e7a1b | |||
ceb138cefe | |||
114605df53 | |||
340fc13de1 | |||
24551382d2 | |||
d982fddb18 | |||
7e0000021c | |||
de69ba01ba | |||
6c20d54b23 | |||
1b7aa1b63b | |||
b409d63fd3 | |||
6c274546c4 | |||
62d5bf5f41 | |||
069e61dfc6 | |||
2fd9629478 | |||
32be08d7b3 | |||
1d9a3d955c | |||
187ca8e18b | |||
70e2737222 | |||
7317a594fe | |||
c3b19f5bf8 | |||
6dc82e620b | |||
0618722e49 | |||
c695a031b8 | |||
be493f0aba | |||
b35e6deb09 | |||
dd96f01a16 | |||
361dd6e361 | |||
e2e7f3f0b5 | |||
26f1607766 | |||
6119c2eb5f | |||
c6e8314446 | |||
86452cc959 | |||
d0225c2c4d | |||
f4cc718fdc | |||
56882f3a49 | |||
094cd917b6 | |||
38f1394e3a | |||
e9d2f72382 | |||
b15fcde477 | |||
758bc770a8 | |||
caf282040f | |||
070c9923e2 | |||
765f3e5169 | |||
c9d066038f | |||
17b860d811 | |||
29dbe665a7 | |||
26b84e3521 | |||
aeb6883532 | |||
423c32969c | |||
97dbf5b671 | |||
6a134e4a26 | |||
dedeb01ffa | |||
3a0d4fe0d0 | |||
f112357e61 | |||
da65eef572 | |||
dde0538b48 | |||
39ad3b8946 | |||
976969dce5 | |||
8da5cba401 | |||
bd38fb6722 | |||
4d40afe54f | |||
5c705fbb92 | |||
a3f8fc5d1c | |||
3d830daa46 | |||
ade1d2819e | |||
4e402ba9fc | |||
48cef3c747 | |||
3b5fa3632b | |||
86a8ef168d | |||
b41ea92a67 | |||
2bd7206ec5 | |||
ec49c7fbf5 | |||
00e54565ef | |||
70bf4b4ab0 | |||
b6643a8ad1 | |||
495cbd42b7 | |||
6e75832082 | |||
c30999562e | |||
3c68208dd3 | |||
b03424073e | |||
11be1fa86e | |||
400ab10cfd | |||
5dad048674 | |||
98989f1088 | |||
2019b42ced | |||
523aaaebef | |||
846a46e060 | |||
89d4565092 | |||
624c1dce46 | |||
72a4bc7039 | |||
950648c513 | |||
e41d1183cc | |||
c8e96e5253 | |||
4f93220c4b | |||
45b5e3622e | |||
43e16cf13d | |||
d0390f3b76 | |||
9d3a2b693a | |||
f2a83c4a50 | |||
b815c32f0e | |||
71f3d82d43 | |||
cd40fa1745 | |||
61a918f820 | |||
ab0f13ed06 | |||
4a0e0270ad | |||
fd8dc14552 | |||
f0d300b32a | |||
eb3aa2a227 | |||
6069cac313 | |||
92a3081337 | |||
5e72568a45 | |||
ae9087b390 | |||
36c7c49738 | |||
1fabfd5a32 | |||
be880f2476 | |||
50bb931ea6 | |||
0c06371cda | |||
86bf55ff8b | |||
ef33193d77 | |||
c19d1f0c75 | |||
019b26de58 | |||
43ca2d3113 | |||
9c517199b2 | |||
bfe7e3fd55 | |||
46e35e9401 | |||
28878c69e0 | |||
9d1be3162a | |||
7181112233 | |||
2e6e1e566b | |||
19690b606d | |||
5ab14f22a5 | |||
201d82ae0d | |||
43b1a0d46b | |||
a02d84a11c | |||
f2efd94035 | |||
96b743094d | |||
3c846859ee | |||
845c584b9c | |||
f7179e44f6 | |||
c23183f1dc | |||
99819cf5d1 | |||
53facd8882 | |||
fee7470083 | |||
afc4da47f7 | |||
d35a90101f | |||
a7141b6a6e | |||
2b4e93faba | |||
c4ad4681cf | |||
05c13588d7 | |||
050f331c54 | |||
d5fc03b718 | |||
70e9757044 | |||
6c88b6b362 | |||
8d894eec90 | |||
7a3dfbce71 | |||
7f6d256014 | |||
4291c3db5d | |||
8f9d1fd7b0 | |||
b7d12c8532 | |||
b418c31479 | |||
6514e33ab6 | |||
920e9402a4 | |||
bc99b5ba03 | |||
c4f418c3b2 | |||
67989e9f2a | |||
7a383342de | |||
01658fb2e8 | |||
cabde32140 | |||
6088a0d4c2 | |||
a26ed3b758 | |||
565f61a6ab | |||
3ff4ca348c | |||
e20f0bf0ea | |||
c9a96b268b | |||
1004fb9a41 | |||
e190ba1a2f | |||
221616a1b7 | |||
049ace8a40 | |||
89eb285a23 | |||
0709d00b10 | |||
84a99f49b8 | |||
7ca51fab19 | |||
1edc3ece61 | |||
eda1ee0807 | |||
5ee2dd6bbd | |||
eac254ae57 | |||
fa349b4f4c | |||
a50d95b831 | |||
3439d641c0 | |||
1006abffad | |||
1f3d5c271a | |||
96533f627e | |||
2c5844f665 | |||
22c696ff1c | |||
c169cb3911 | |||
00a53a870d | |||
1725e6be31 | |||
0029c1a83e | |||
c892642057 | |||
236a67621b | |||
2d662ace87 | |||
447d232caf | |||
90e7543038 | |||
3b860c1dd6 | |||
ab394836a9 | |||
d319b4a381 | |||
e1384b5086 | |||
55224e5150 | |||
836aeef595 | |||
c2b58cff6f | |||
6e2a0ef233 | |||
958436be4b | |||
7dc4847869 | |||
f0e08e6486 | |||
2dac4e785f | |||
ee5078f43c | |||
2b3642aa39 | |||
d68bd656fe | |||
8bd5d7676e | |||
70c1de5d64 | |||
2fef89950f | |||
a908a98225 | |||
82554677a8 | |||
dfe6f7f8c9 | |||
5fcd634f05 | |||
28f1e94ab9 | |||
e1d37a802b | |||
0f9dceff3d | |||
8868648f76 | |||
72a70423c2 | |||
84534ae2e8 | |||
687dd9cb67 | |||
ede03a96ed | |||
33dd2ce021 | |||
bc0ff559f5 | |||
090128b3f8 | |||
d7e121e2c9 | |||
749b03d812 | |||
fc73a18e9a | |||
7e67a735e6 | |||
14e1b0ffba | |||
e98cd00822 | |||
2102264acf | |||
e73c7c59c1 | |||
99525dee38 | |||
848ea17154 | |||
1cdf0a898c | |||
00913bce81 | |||
5be7d9c1cc | |||
44347beff0 | |||
166c8f93b5 | |||
9393452d1c | |||
66fa76a061 | |||
d2e7c4ec05 | |||
10fb46301c | |||
c397becd81 | |||
62508c3b44 | |||
94312796f9 | |||
adeeed9e43 | |||
513bd70384 | |||
cdd30c766b | |||
5e2a5f1110 | |||
a7797f0cb9 | |||
d17abce59b | |||
b715050de9 | |||
da5a32792d | |||
f36341b3b4 | |||
dda4757b35 | |||
c6f1c56c15 | |||
413807db01 | |||
f59ef29c26 | |||
65b90001f6 | |||
6840e8fd2a | |||
7c2436c711 | |||
c2df65a0af | |||
175a275a3d | |||
bd64315395 | |||
65e3770bad | |||
f5420e737a | |||
4e567d3f5d | |||
1227776251 | |||
862cb3217f | |||
8e11546536 | |||
73641be796 | |||
ff9f3fbe96 | |||
1dcc3549b6 | |||
3782976528 | |||
23f7bee81c | |||
ac795ae1e1 | |||
aa6a50c2b4 | |||
62f067ec71 | |||
01ad7610be | |||
d4fb7f8b40 | |||
61c8304f24 | |||
27c0480866 | |||
b289e7ad07 | |||
70403f7e1b | |||
1ab125de63 | |||
96574854b3 | |||
281cd47c15 | |||
01ad0f3c6a | |||
db342c9c81 | |||
f1d8a01047 | |||
3753f56c25 | |||
d32b1d6b0c | |||
e5bdba4b9f | |||
c725cb71de | |||
8ff5063545 | |||
e549102563 | |||
b7d90a9e31 | |||
adeb0d18b1 | |||
16e3e2a7f7 | |||
0484d9b024 | |||
d60bbff0d9 | |||
966eba50a6 | |||
ffd8fae22a | |||
cb0fe044dd | |||
4f3b5f8adc | |||
3bb12b456f | |||
a10a627622 | |||
2777784f4f | |||
4bd0d4cbaf | |||
2d92bb483e | |||
071edb1a2d | |||
7f36290703 | |||
6cc59a38be | |||
87eb44abe4 | |||
a0c3011673 | |||
69f3095045 | |||
d678d59372 | |||
b2feada293 | |||
bff02dae0d | |||
851231c846 | |||
f21a5c42c1 | |||
d471fc9509 | |||
9f22a151f3 | |||
0c2478cae6 | |||
b865fc6080 | |||
d44b650cd4 | |||
aa12e46013 | |||
2c18fbbb2e | |||
4131965d48 | |||
5fab0fa51f | |||
9c9232b4e8 | |||
0d6e571237 | |||
40ba8814b3 | |||
a0a917ad87 | |||
8628839c55 | |||
5001779984 | |||
93d91dd7a1 | |||
791c5c171d | |||
a723156740 | |||
0868ea8348 | |||
5a6ad71f3f | |||
47f2650a32 | |||
74a6044b3f | |||
e82ce95251 | |||
e226d1bbb3 | |||
54c1087340 | |||
eb1e8619eb | |||
c96fca6833 | |||
d3f69ab4c6 | |||
517db1b8dc | |||
7f062524c9 | |||
99b4c3f362 | |||
4a0d4c50fc | |||
976cb3e36c | |||
81442ba3f9 | |||
9b3d8c327d | |||
7b907e45ad | |||
e8d580f54d | |||
2dd5a02061 | |||
9844e1a856 | |||
44be521ab8 | |||
c9819e3b94 | |||
16d6f35aa6 | |||
c9854ec8cb | |||
c429021de1 | |||
41ad23041b | |||
3e5ac0af52 | |||
f848562732 | |||
3342aa751d | |||
a2f40aa285 | |||
f34a860d5f | |||
af9aeb89d4 | |||
be5274d4a9 | |||
b6dc529bc3 | |||
0aa93afeb8 | |||
79d75d8e42 | |||
96c526cb78 | |||
02f3319256 | |||
8f538e77ed | |||
1e76079e93 | |||
0e736276e6 | |||
08ef8d6b78 | |||
3977d50b55 | |||
3bcfbf5038 | |||
f0c7967fbf | |||
8bdb40b763 | |||
f0bc2e0e8b | |||
108e588e88 | |||
333509bb0a | |||
c269c3977c | |||
c3a8052a16 | |||
d0a61279b8 | |||
7259075b71 | |||
14fd477147 | |||
05e2f577f6 | |||
a29b360d55 | |||
75d6a8b701 | |||
ad7a7fcf07 | |||
41788950cc | |||
82c05630ba | |||
bd0a23de73 | |||
4619a1395b | |||
0c38850f95 | |||
07884e0054 | |||
bdadbb7207 | |||
e389eb9842 | |||
5cf0655071 | |||
f81ef4abf4 | |||
6036cf8437 | |||
1cad645400 | |||
36846836ed | |||
79f1a44a01 | |||
c2127e3ff7 | |||
2ad495ad0a | |||
8e051fd075 | |||
af628b16d1 | |||
c219502f0f | |||
a5da9ce42c | |||
79e02c2a9b | |||
3a461944ec | |||
78d96c4dc8 | |||
ee0ca07f3c | |||
7ae7b0f373 | |||
e2b4bc9310 | |||
6c9777de13 | |||
2f7e57f6aa | |||
5c239451cf | |||
35ca51c5a8 | |||
047f3436e9 | |||
5d181950eb | |||
48a1a29baa | |||
c05d392cd9 | |||
cc7c651dc9 | |||
e6ef2ee338 | |||
a090b2013f | |||
564f491566 | |||
2daeeab844 | |||
4ab90e739f | |||
745bc083d1 | |||
7674dac1a1 | |||
fb2a6b6941 | |||
70fe872940 | |||
a252943236 | |||
8c133b607c | |||
2785c8b197 | |||
a81b5aa921 | |||
8ad78f5b65 | |||
ac9cfd89da | |||
c67c4ce757 | |||
974aab6cf6 | |||
b957218a3a | |||
f629f4e341 | |||
871c3c91ec | |||
100aac4dd3 | |||
d941da33ae | |||
62767a42dc | |||
89cf94f0e6 | |||
17211253b2 | |||
6998489b26 | |||
4290cb5877 | |||
801f2449ec | |||
aaf5fcd98a | |||
5edfb7ba85 | |||
a5cb522f01 | |||
3195119dad | |||
d6fe6b9537 | |||
c0f9fba6d6 | |||
1a713ff420 | |||
89af2ef7a9 | |||
907c5d4276 | |||
5dd35f5281 | |||
857229654e | |||
4c47b242eb | |||
938512a6b9 | |||
7444cfa450 | |||
f091b8d692 | |||
7d97ffb1e8 | |||
80bdbf7be0 | |||
686719cdca | |||
6caec2169c | |||
5212481352 | |||
d999725de2 | |||
145c673a80 | |||
c5017945f7 | |||
5c4c49d9ca | |||
cebde1f9e6 | |||
0298ae82b0 | |||
512f53984c | |||
e3a5c31307 | |||
dd2fd80274 | |||
ffc1fc655f | |||
fe477e96ae | |||
98559ea8b0 | |||
f31d8b8401 | |||
389e348826 | |||
98fd50f78f | |||
95561ec5a7 | |||
fe9da70705 | |||
95c77c8486 | |||
e45333bcf9 | |||
c906c042be | |||
9bd1e19d7f | |||
6ce9230ed6 | |||
1d60c39191 | |||
70651d60bd | |||
385312c658 | |||
87a607c7d0 | |||
1ba5d1008e | |||
129a5adaf1 | |||
d827bc4580 | |||
64e46dcefc | |||
c0b3127b9d | |||
7cfa690d1c | |||
22a3c7f7d0 | |||
16ffbb37f5 | |||
ea05f3f4cd | |||
91f2f057e4 | |||
d44cf1344d | |||
756206e4d7 | |||
2ff6e5023f | |||
223bd70f1f | |||
dd3f4bb41c | |||
f3e783d343 | |||
f4cac37b04 | |||
5b2634f711 | |||
267b085f80 | |||
b6643743d6 | |||
17cbb03ba7 | |||
2cd4624779 | |||
e11665564b | |||
93cebd6c7f | |||
a124540e50 | |||
c465e48e27 | |||
c2c65fd9c1 | |||
84f0b4f187 | |||
0ad56167c5 | |||
aeb7d70483 | |||
209c5ba465 | |||
01327ad301 | |||
96cdc97c98 | |||
a763c61d89 | |||
d920104248 | |||
08076f0500 | |||
e81f30828f | |||
f54c4dbfdb | |||
bf289ce50e | |||
1a8c242d28 | |||
19d8f00963 | |||
bed789cd5a | |||
7e625c3687 | |||
f53a2e4b88 | |||
d8a18a03e3 | |||
1677481726 | |||
6f163bb0c5 | |||
3533df9453 | |||
faa9daf260 | |||
bf1198c4db | |||
ec737f3368 | |||
208254f47c | |||
d0ab2ded00 | |||
58a5372bf0 | |||
ea5d9c42b6 | |||
8bd70a50b1 | |||
6be3896bfa | |||
1f71b85426 | |||
654f389e73 | |||
cd95ee67bc | |||
90fdafa1ad | |||
b9f469e12f | |||
ba7bf99235 | |||
e954c891a0 | |||
80fc6166d0 | |||
4018e7f8e5 | |||
05472a0fc5 | |||
32110a04c0 | |||
812cf4c9e0 | |||
374fa8af47 | |||
fc5f865796 | |||
88155d2c3b | |||
d808a8401e | |||
bca4026f62 | |||
965b854803 | |||
981ffb27a8 | |||
522eacce71 | |||
19d02d7bf6 | |||
cc0210426a | |||
459dd8cb07 | |||
e5116c6d55 | |||
7a861498c2 | |||
893cd47d9c | |||
9d08f0d098 | |||
3b3565269d | |||
2f96f1e920 | |||
1b557d1a70 | |||
b06e3d9f2b | |||
aaec45b652 | |||
af24d87220 | |||
2e3bc3b613 | |||
29c1131fe0 | |||
debd832f36 | |||
8a8ecef6f5 | |||
66c290f804 | |||
40f609c735 | |||
28e1aaa0f1 | |||
6f5746d428 | |||
4488e8e10a | |||
d21ca3e480 | |||
1b1006ddd4 | |||
cb428e55bb | |||
0c616087e0 | |||
ce673ccab3 | |||
d5a170655f | |||
2a9fcd2a87 | |||
a61a30dee0 | |||
d62c83d58f | |||
ad63ba49c1 | |||
1dfea4e91a | |||
47f62eb0ca | |||
9bc8c7518f | |||
2044c7e2b5 | |||
6b721900d5 | |||
f5127c0e2b | |||
f571f074a8 | |||
d046b28f2f | |||
a754694ac4 | |||
36b5336152 | |||
9c393adbb9 | |||
e0663c91b9 | |||
7c381a782e | |||
cd8668ad3a | |||
9a7531942d | |||
107b624224 | |||
822aea3cb4 | |||
52af7caf8a | |||
afc15965c0 | |||
e82cd40440 | |||
08c716da9c | |||
0a3a708f9b | |||
a22c8ffdf2 | |||
4179affe2c | |||
46cef4bc11 | |||
fea0286989 | |||
b0a8bc28d2 | |||
e37e432952 | |||
c4118e869d | |||
258ae1632a | |||
1c19804834 | |||
9ed533a0e3 | |||
baf1ac2e69 | |||
46010a8704 | |||
ac21e4dd73 | |||
f0be89a5b6 | |||
0a12d519f7 | |||
2ef8dc4378 | |||
30148bc1a9 | |||
60764ebdf1 | |||
040bf5a61d | |||
b850951c72 | |||
43edd969d8 | |||
e8c1b43a3d | |||
3903dac1f5 | |||
1ee0946f69 | |||
fc3f06caec | |||
0d472adef0 | |||
ba47bee252 | |||
f7c93d741c | |||
cf5fee7c52 | |||
d20a50a413 | |||
b39b87b2f7 | |||
068bef5eab | |||
5174eb6741 | |||
b9e855b7b5 | |||
f380487bb4 | |||
02079d8ef9 | |||
9dff3495d5 | |||
2cd3010f82 | |||
bb9d275350 | |||
f3ef91e8d6 | |||
ac1117ffae | |||
7ad8f6c717 | |||
9d9e148e5c | |||
1e2da1dfb9 | |||
6dc20fc298 | |||
868ef6c10c | |||
52f1d535bd | |||
0306261fec | |||
17e3e65d96 | |||
e3835b4d68 | |||
e7b572af36 | |||
473b3e5fb0 | |||
86c567fa3a | |||
ed9f94c5b9 | |||
0367f6c723 | |||
292f91a55f | |||
95ee2cdd57 | |||
e91f3b0de6 | |||
ca1eb32552 | |||
a9ebf72a84 | |||
e2d9dc16e3 | |||
0b545aaeb4 | |||
94a15b8ca7 | |||
0c061186cf | |||
bbfaa6092d | |||
a8b0629163 | |||
7b97410060 | |||
8951f90623 | |||
6b375489ed | |||
c8c0983ab8 | |||
c71ce79963 | |||
d36af0d576 | |||
a0e884cf8b | |||
fba8790e32 | |||
8eb00a5dfa | |||
d5049da5e4 | |||
9646960f88 | |||
7ba17d182f | |||
c42875ddea | |||
53c7aaa57b | |||
68acd3d101 | |||
0ddbffd80e | |||
b9ba2805e5 | |||
efd8042431 | |||
dc81f681c9 | |||
4581ad3df9 | |||
3196a5f666 | |||
20a47cb23e | |||
813627cbd3 | |||
1827c65596 | |||
3d1a25ce4e | |||
34732e3c5e | |||
7b8c8cf12f | |||
7eaca9c840 | |||
a06b25538f | |||
9cdf5c4150 | |||
52c221fc48 | |||
4c78bb7080 | |||
59b86b0db0 | |||
1a85fca49f | |||
9d4614ce2f | |||
faefad564b | |||
6b54310452 | |||
caf1fbd632 | |||
a561de6e97 | |||
7acf410ab6 | |||
6c095b3937 | |||
d367b033a2 | |||
7f4b3a460a | |||
251e72f136 | |||
c6e038fe25 | |||
5c22472616 | |||
b7cd6d4035 | |||
1842c8390f | |||
9c15f53a47 | |||
b7af98e945 | |||
5cdbfeef4a | |||
33a7d6f168 | |||
c423aebb1a | |||
58039d181a | |||
880513651d | |||
1857df8d06 | |||
3c88de565a | |||
8bcb17b11f | |||
848db92196 | |||
6ed465bacc | |||
e83a1bc0d1 | |||
33abd70647 | |||
84d3192f01 | |||
d2a1f05a69 | |||
7620f6f396 | |||
214da5c42e | |||
697e3e285b | |||
fac373ec9e | |||
16d2bd3177 | |||
af10a635f5 | |||
935724557f | |||
7e6645d5a2 | |||
271116f870 | |||
84e72b0a51 | |||
b0d69f1b69 | |||
f38595f6b4 | |||
5a99e67e02 | |||
0246fe9200 | |||
5d560c1ece | |||
d687fbdfb4 | |||
e9a306a50e | |||
107c79b84b | |||
80767480f0 | |||
83c1378fc1 | |||
871d42e389 | |||
0922763db1 | |||
d103e39f58 | |||
3f871d1d8f | |||
688f4ffb89 | |||
41dad9ab7d | |||
108e28ff10 | |||
e22db8d609 | |||
f1b4b38152 | |||
8e2b59ffca | |||
7375d8fcb7 | |||
2c4b51b437 | |||
fe0dca9d96 | |||
159707f74c | |||
4af0065f4a | |||
fa933036a7 | |||
0b9ca807f2 | |||
450fd17451 | |||
a4fd4ea0f4 | |||
949f075247 | |||
895d0778b6 | |||
dbdb95bc23 | |||
92bf656cd3 | |||
849b8cd084 | |||
03849d147a | |||
1c79687dfe | |||
1fe3af0418 | |||
7dc433a0c0 | |||
8d10d12ab3 | |||
ceed19f275 | |||
9a5ea5b5c2 | |||
e790667fd2 | |||
8241ded12e | |||
f18afa8ccd | |||
2a994e457a | |||
9759320266 | |||
27b9ba4502 | |||
e8374e3deb | |||
f37cc223d8 | |||
6f0f167b73 | |||
a39228def6 | |||
f7ceafab1c | |||
2a22dc433c | |||
6e27c66058 | |||
7172302be8 | |||
b42f405e60 | |||
816ba61080 | |||
7e27448dac | |||
2a0d066121 | |||
1078409875 | |||
45a68760ee | |||
ed85d5374b | |||
47e04548d4 | |||
6d1f17d78d | |||
c28ecbbb2b | |||
bf3ba489a0 | |||
f9d9ff2cd2 | |||
0b4f6adfee | |||
81e3e991a7 | |||
eddabf6b05 | |||
2e3cf10070 | |||
59c1c6a431 | |||
98ee17bc47 | |||
a6116ed533 | |||
bc9f956c84 | |||
e1a7ed9d6e | |||
7374503f14 | |||
12ebb351dc | |||
73dd6d86ab | |||
2748d5c962 | |||
ea9db86bb8 | |||
4ff9eb0e67 | |||
f0b6576f97 | |||
3ee12009c0 | |||
0011f2047b | |||
79c98731c9 | |||
b6b907705e | |||
fd6bff727a | |||
3282775a15 | |||
d07b0169cb | |||
14c67f15c9 | |||
6e0aeb9833 | |||
db76b06e01 | |||
1fc0918ac0 | |||
8e712d1a74 | |||
149ec41e90 | |||
e0ab846f7f | |||
df7c72fd66 | |||
76117b0471 | |||
ce9e127529 | |||
c5c852dada | |||
7382cf5f00 | |||
109560e73a | |||
befb1a2f39 | |||
fd30a4184a | |||
e4a113b953 | |||
7f50aa26db | |||
54f59c7403 | |||
dbbbeea36e | |||
1825e5f313 | |||
609f3d0265 | |||
12d62d5393 | |||
d5ded820e5 | |||
cc781e44f3 | |||
2bf68a0bf4 | |||
8a1acac559 | |||
1a3c9bc36d | |||
161c80014e | |||
af403e5872 | |||
a686c1361c | |||
b8a590b84d | |||
2c24cdbfc3 | |||
e5c50037d5 | |||
a8e568f248 | |||
39a4fac941 | |||
3997d06cbd | |||
2641082a76 | |||
cebbedd238 | |||
d1eb4eeb7f | |||
a7125c68eb | |||
1dbb1c7193 | |||
9534bb87b1 | |||
4e96447b43 | |||
ad29eef271 | |||
c70b7ffd80 | |||
6fb74342b8 | |||
2b543a64af | |||
5bb51688e4 | |||
6e61b2345c | |||
cf0c49dec5 | |||
064e63962f | |||
6d2ac3e314 | |||
8999023432 | |||
da6cddab90 | |||
46156957bd | |||
2f4166d5d6 | |||
e707a8d738 | |||
eda068751e | |||
5d6b1129f0 | |||
06ec5ab3d7 | |||
e6de85861c | |||
4c2e375e22 | |||
8f79116a15 | |||
f8c33f29e8 | |||
9e8e25729a | |||
9a7d045897 | |||
d59d1fcd9f | |||
1aebbd7490 | |||
330f33a435 | |||
3d233b34b8 | |||
eb85ded6ee | |||
c18ca63519 | |||
1dbefc14ea | |||
1f34b9f8e1 | |||
a19b3022d9 | |||
aca5b55b6d | |||
e9a342f3d9 | |||
b31d5a7cef | |||
f0e81b2301 | |||
295ddaf96b | |||
a2e2fae840 | |||
0f803c63df | |||
1890d7b9cf | |||
16a6bbb3c9 | |||
0942158ad1 | |||
c05e4efbe9 | |||
8584f9d2b5 | |||
f7d8643dc4 | |||
e769102491 | |||
1b75cc9f74 | |||
403b8a1086 | |||
e865f274f1 | |||
856968c13b | |||
63c317218b | |||
aff4ccb0b2 | |||
e83426a79b | |||
fdac887660 | |||
b792c59080 | |||
d1259d0914 | |||
4d9eb9bda1 | |||
cd0a25be5e | |||
b260204b72 | |||
211a6eb411 | |||
108a89b559 | |||
68e18dbb7a | |||
631b6d0187 | |||
f80f62f14b | |||
57f8aec381 | |||
23f37ff505 | |||
54fdec0e51 | |||
add108ec23 | |||
d042a63ab4 | |||
c06b5a1564 | |||
99c783821f | |||
9d22c8a02c | |||
1cc637a0a0 | |||
7000f2a2cf | |||
ea689076b3 | |||
3ac953ec33 | |||
76c5b8a3b4 | |||
40e10895a2 | |||
e750a5c856 | |||
30cd8a8397 | |||
bd313d4039 | |||
81493e4fe1 | |||
389ee822e8 | |||
fb38de8d73 | |||
155c2767a0 | |||
622f942555 | |||
7db5d87a32 | |||
79ed86da3f | |||
119d7d0025 | |||
54a312a5fe | |||
4a4c14c9a9 | |||
35fd6847fe | |||
ffe41e6fce | |||
c05c5b787b | |||
bb218b330f | |||
20a8a93fd1 | |||
14e76cf3c9 | |||
5357ae5f91 | |||
a3928e5a62 | |||
1dfd7df7c0 | |||
8e1047f5ef | |||
1661303248 | |||
4c59c5234a | |||
82d1c3e18d | |||
585ba4c1dd | |||
a728e8f9a5 | |||
3b799c09cd | |||
50c98445fe | |||
665802673d | |||
f8bbbf31ec | |||
61fe059ba2 | |||
6abe4d124e | |||
a8de605637 | |||
c43a12919d | |||
3cfc0174f7 | |||
7b4d1c4089 | |||
245f511a1d | |||
8bccf56553 | |||
7ed0bfb6f5 | |||
d795ec0451 | |||
350c3b323a | |||
d026a9a9c5 | |||
445d8f9917 | |||
eab60a084c | |||
050354a9de | |||
26d78ce2ec | |||
80401940e3 | |||
0863d940fe | |||
7d944e9512 | |||
fd20432deb | |||
a260d34b49 | |||
54ed02ef47 | |||
fdc364046e | |||
e24f8ba4b0 | |||
52512aa0af | |||
cbfd1c6535 | |||
e0fe546459 | |||
416e01d3c6 | |||
0fd98ae8b0 | |||
a0c0cf9712 | |||
ded80870a9 | |||
5a84db7c67 | |||
27c3423fb6 | |||
ed2f82eaf4 | |||
cf30f52f25 | |||
e32b7eeb83 | |||
5ecc4ae0ab | |||
f810639ab1 | |||
dfb847a51b | |||
efd27bd8ce | |||
e0bdfd87b6 | |||
b33306ca2c | |||
a2739ef5ff | |||
bdadba60f7 | |||
158efe49ac | |||
2decf1d088 | |||
3e17a90faa | |||
46a828212e | |||
d4b04f0790 | |||
9e3b818c35 | |||
9347ad49b8 | |||
abac876b3a | |||
7c8b0af84a | |||
b5686eb63e | |||
17c0d928e8 | |||
1f46171b39 | |||
587f66f1b3 | |||
93c9093817 | |||
fe705bb956 | |||
0b9b4adbd3 | |||
a09a6459ed | |||
55dd04132f | |||
d4bf0c7db7 | |||
90e04d4909 | |||
0f14057812 | |||
0d0e220b4b | |||
8cdf04ec90 | |||
987ddb72b1 | |||
29a9d3aa49 | |||
424438edfc | |||
868cb61ea6 | |||
44c65fa0a0 | |||
029d44a6ec | |||
ca938e7c4e | |||
18ad8a097c | |||
aac0ab8c67 | |||
e5f30c6908 | |||
e5c2779d56 | |||
eefc3608e7 | |||
4e99e3b36c | |||
4a5df3dcfe | |||
2e8ec1e339 | |||
aa0d378520 | |||
0e748ccda7 | |||
c866aef37f | |||
8d75c08938 | |||
982260c134 | |||
fa191017b5 | |||
73c0e1357f | |||
d0cdbc48ae | |||
ac1c3b8701 | |||
d8a058bf59 | |||
fcea01a8ea | |||
d5c3b4bafd | |||
b82e9ad3db | |||
fffe53136c | |||
bded51e4ea | |||
190a9cf1e4 | |||
1818d1c6a7 | |||
ee66cd7b27 | |||
f41aafa4f7 | |||
354bda2846 | |||
0f8529a3db | |||
ea0851c654 | |||
d1e18f9edf | |||
0139b8cdcb | |||
24e0c9cf65 | |||
7ca5524e55 | |||
638bf19b65 | |||
735e8c3956 | |||
23872d6f2c | |||
56ac3fcdc5 | |||
5ee63a6e62 | |||
c20ba2c2c5 | |||
d9b63766df | |||
5427f7ca98 | |||
15099f7f5a | |||
aef0cd5877 | |||
d6da5605c8 | |||
b7e0490bcd | |||
c03fbcedaa | |||
dab017ddda | |||
55e1726b23 | |||
59815cd447 | |||
6a397d6111 | |||
01ec0cce47 | |||
5540a055c5 | |||
445aba9221 | |||
5dc3bc175b | |||
c075003bd2 | |||
1ab83d7d89 | |||
cbf8212fe0 | |||
e5de66e463 | |||
125f8b6ba7 | |||
4cb4772e2a | |||
43d8296504 | |||
0220a8ff66 | |||
fd4a2dfec2 | |||
deab5a1532 | |||
c12b98e0a4 | |||
794e8d2d67 | |||
1fd2ffaf14 | |||
3e16cf5fbf | |||
17abe7d36e | |||
3d7bdc9f0b | |||
f519fff7bc | |||
231420775f | |||
2d5fadc1e6 | |||
4f207b4eba | |||
693252c737 | |||
74dc227c44 | |||
a4b60ca5b6 | |||
fd4efd04a1 | |||
9ac9aa2511 | |||
916b6fd317 | |||
2bf3a70e2b | |||
9b112fde1a | |||
bab60b68d9 | |||
1a12db1b59 | |||
1e0bc2e5c3 | |||
b0de6fed11 | |||
ca6106a1dc | |||
6006cce0cf | |||
ff8c6d2415 | |||
26dcddab0c | |||
2239743361 | |||
383cd487a2 | |||
fe08482c1b | |||
e87eca7fe8 | |||
e69b25e34b | |||
e85fde201e | |||
e301822c68 | |||
a55e0d1189 | |||
fc75d2b181 | |||
6b3b1775b6 | |||
3334eeb4eb | |||
e38ca0e750 | |||
a75e7594f7 | |||
888d63748a | |||
818c05cf29 | |||
60ef1f7305 | |||
b3b5e25091 | |||
f4a0407270 | |||
daa2285083 | |||
639372b644 | |||
52c135e1a2 | |||
093754f6bf | |||
207cbd5cf7 | |||
f34fe1f81e | |||
5f52f72761 | |||
6d99695108 | |||
a18523f018 | |||
7ff9800804 | |||
44c0dc6d96 | |||
1225f3aa70 | |||
9eed8fe588 | |||
4561a9590f | |||
5241d1221b | |||
a95427a873 | |||
c5c5570d97 | |||
3abace4f54 | |||
7cdbe3173e | |||
7f94fe3587 | |||
060dbe1239 | |||
a9ba907676 | |||
fe39e0184f | |||
688e2c87df | |||
38e6de1eff | |||
862b6d0382 | |||
543765bc0d | |||
380051868a | |||
fdb0452245 | |||
454a860020 | |||
a4cac3fce5 | |||
f8c0182e16 | |||
d3282ef1fe | |||
9b6564f0a3 | |||
eb9f323d7c | |||
fe98e2d760 | |||
ab744abc4b | |||
2802245da7 | |||
c091340a85 | |||
3890225c35 | |||
9544b3dbf2 | |||
43cb626ad3 | |||
13f2ac83a9 | |||
374e068f97 | |||
10f775be07 | |||
3565641c41 | |||
679b2d63a8 | |||
6404abd7d6 | |||
7bcbfd48e5 | |||
06ac2850c5 | |||
6114a48b89 | |||
e065ba9497 | |||
8ec41b2585 | |||
bd007c151d | |||
163e5ffd10 | |||
ded4d093ff | |||
2508922288 | |||
39c020ec74 | |||
81b1d85f61 | |||
2f90f2faba | |||
e30b2c6af6 | |||
4b3ad5f037 | |||
996986bed5 | |||
ee206da389 | |||
fac108476c | |||
4f7a8a4c70 | |||
976ee9022c | |||
0625eb0a05 | |||
77b824d101 | |||
b7b38205d8 | |||
6c715f1a69 | |||
fc19aa96f7 | |||
50f61b64b1 | |||
809a7cffe2 | |||
6399f84ba2 | |||
8459bcdf85 | |||
6adaacbb3a | |||
6c846bcf2c | |||
e45ae8e5da | |||
cea2fadbf4 | |||
4c48d3a3ad | |||
c39a552cc0 | |||
020b8a4964 | |||
08f6e1d66a | |||
28e457e8d8 | |||
c7255f2e26 | |||
6340674a23 | |||
4538f689ed | |||
415b759ed1 | |||
e4a86b40a5 | |||
b8d3a97a4f | |||
75c38d6243 | |||
6f75100602 | |||
07cee6b750 | |||
651ad18e21 | |||
664daa2f3c | |||
ed6243df5a | |||
bd57784664 | |||
7f621509ee | |||
4261e17b3e | |||
8ca4414d70 | |||
6090bb1bca | |||
a552631d3b | |||
c552229c4d | |||
2dffed1cff | |||
e93f78eca5 | |||
9bbbec3fa8 | |||
338638b124 | |||
17e1a72b3b | |||
3e6471b949 | |||
e4de4e3500 | |||
bea76b346c | |||
53e63e9ded | |||
b1b5e21600 | |||
d765740707 | |||
192cadee34 | |||
d7d8afa512 | |||
01fcee1190 | |||
0805437222 | |||
4398b9b517 | |||
909262f6c5 | |||
155ef8875a | |||
58cf030546 | |||
18ea9a8447 | |||
ebd1e6bc4b | |||
45d866d548 | |||
8087cf7988 | |||
9e8b3f13e1 | |||
ce4700ca6e | |||
8253f90134 | |||
86421f3469 | |||
811ef13b20 | |||
7fb72f1038 | |||
d2c9e4baa7 | |||
81767287c3 | |||
6c980e2a02 | |||
e7db4d4fe0 | |||
567042d146 | |||
4697e4a5a5 | |||
92b1f9cf36 | |||
bbf00204ea | |||
a42b74b624 | |||
7ee255cbcf | |||
961ddfd7f8 | |||
4566bcf122 | |||
ca0105ddf6 | |||
41bb359428 | |||
146ede0f29 | |||
c0fd7ba6d1 | |||
b0b2a15891 | |||
ff3c9cbd73 | |||
6e839f0f6a | |||
a3cd523250 | |||
b44620f0b0 | |||
9a6a32775f | |||
3e8beaafc8 | |||
33e58c1d4e | |||
4be0ea596b | |||
96ef7083c8 | |||
78eaa6b203 | |||
1efc6e59b7 | |||
19eddbb0c7 | |||
6a34c5aa3e | |||
c7f0d30668 | |||
a7c3f252d5 | |||
b9b6f06429 | |||
a1442bd1ac | |||
4d9d52e3d9 | |||
6184832ea9 | |||
e2b54bfa05 | |||
425908a00c | |||
1301552101 | |||
c4f71ab201 | |||
42ef1968a5 | |||
5ec91fce23 | |||
47878f6974 | |||
d5c77a9e96 | |||
4d2694c114 | |||
017c8a6940 | |||
b0a783e86f | |||
714e4d2b46 | |||
85a4c5e724 | |||
182b8b3e14 | |||
4ce5ed370a | |||
f7bac482e9 | |||
bd074e9150 | |||
d52ea44c27 | |||
9c1b6cfb99 | |||
631d3f274a | |||
3cdaf4dcf2 | |||
572944d726 | |||
779d8f6b7e | |||
322847755a | |||
f9f28b9c7c | |||
c3bc0145e7 | |||
17d403b8f8 | |||
9faf7b6fc8 | |||
5c759953f4 | |||
1c64048d0f | |||
b504b9313a | |||
1a94cfe2af | |||
7470b475a9 | |||
0a6084f361 | |||
f92607cff1 | |||
9532499ef5 | |||
1d56de6c1d | |||
266b51a842 | |||
cc1fe2f2d2 | |||
43214d6b46 | |||
2f28ecd3a5 | |||
73a629d6f2 | |||
0a251f93e0 | |||
1cf4738487 | |||
af14acf2c1 | |||
a7537b5511 | |||
15e799f7ae | |||
5f0a9c90c8 | |||
9ff9ff2ad2 | |||
d86b13384f | |||
17a4e9fadf | |||
ce513c4f3e | |||
ce92adcb9b | |||
e94cc1fae0 | |||
32fe047894 | |||
d1bc0207cc | |||
69f8c62955 | |||
83df65a66b | |||
c3a6e7e870 | |||
d0ab83a202 | |||
b5d1a021ef | |||
e9fb5f4cbc | |||
212bb990b7 | |||
8e984c2aa0 | |||
7f435ec5f1 | |||
47faf3dd33 | |||
c4e52e20c9 | |||
2c5e103278 | |||
7a6867e2f8 | |||
8044ae28be | |||
b38837f4ff | |||
c25479264d | |||
e9b3da5d96 | |||
132b57cf03 | |||
ee548df05f | |||
052d74b16c | |||
83281503b3 | |||
b604f5eafc | |||
220dc4a43d | |||
457f627101 | |||
4f695b6f4c | |||
3ec1b23743 | |||
0ba09ee85a | |||
67dac15226 | |||
9cf8637fab | |||
50e76fce12 | |||
432638404f | |||
1e38c10efb | |||
701fb95d24 | |||
7b5a18428e | |||
7d7a8c7c39 | |||
a422fcaa40 | |||
fee58a4d1b | |||
3ecafde29d | |||
8428b18d2a | |||
9c953ab51f | |||
f181a8307b | |||
84b9d551fd | |||
8f8555dfdf | |||
464c27082a | |||
3aa7d8081d | |||
fb84103ffb | |||
c270646722 | |||
87da1e7af6 | |||
9b71f7e5e4 | |||
9945c1648b | |||
e5d24827de | |||
a6521e89fc | |||
5e36fb32a8 | |||
fb0181f5bc | |||
6fa2c213ef | |||
9ec223c844 | |||
558a82891a | |||
4fc16b542e | |||
ff40359a60 | |||
e99d7e9730 | |||
b60663c031 | |||
32db31b555 | |||
a1129b67c2 | |||
8a1cf3f0f9 | |||
0bb59ba116 | |||
e4a0237cbc | |||
d8f5502d83 | |||
45d0e4765e | |||
9a1d526ed4 | |||
ebc6f52868 | |||
a19b31bf82 | |||
28251a495a | |||
f4592a8fb4 | |||
b29d91edf5 | |||
986af28df2 | |||
27abecbff5 | |||
33141cf8a3 | |||
8551d8e48e | |||
32558bc807 | |||
934cdc32f4 | |||
699ebaa8e2 | |||
44ad516edd | |||
fd9a7e719d | |||
e51f1ea5a5 | |||
22d3a5e90a | |||
673ace2a4b | |||
4a6d66d8c5 | |||
1978629d87 | |||
6b1ad311da | |||
5b06166144 | |||
a0fab35bbf | |||
420b202124 | |||
fb14e55cc9 | |||
e2434cf8c6 | |||
d94681186d | |||
58a710d192 | |||
716eb226b2 | |||
cb3631a322 | |||
bd1d148f83 | |||
7e0c9a36ef | |||
bbfff7d472 | |||
e048d95660 | |||
970d75d681 | |||
51f3a81037 | |||
8190436f8f | |||
08bcaa135f | |||
c4e5f75728 | |||
1064c7114e | |||
0281872ddf | |||
c6bf23377d | |||
2d650f8c22 | |||
19631851f6 | |||
f30ca1476c | |||
0712d44cbc | |||
15f3210d93 | |||
9864d9c189 | |||
bd36aac60a | |||
4a859aff70 | |||
8fc727e597 | |||
585ec04503 | |||
a1c93f24d4 | |||
f6c89ec3a9 | |||
3d8f054580 | |||
6d364dd2cb | |||
8ed6207b5c | |||
c8354d7516 | |||
79f873a597 | |||
8850e1a5bf | |||
194188fe56 | |||
cc74efa35e | |||
e7f2770275 | |||
af277a0b56 | |||
4163f47e09 | |||
b2aa8b03d9 | |||
e1d20706ca | |||
76888fdf59 | |||
e6e38d1703 | |||
44060590b4 | |||
38bed607d1 | |||
ed63364a77 | |||
55bd24b0c7 | |||
f18c2eb8ae | |||
898353c87a | |||
d5d8d664d0 | |||
409e4ae945 | |||
f335c48686 | |||
9d82c3cf5e | |||
491cee669f | |||
e0d1529061 | |||
1cddd51662 | |||
6041b1c486 | |||
349fed3fcd | |||
b708cf7d45 | |||
a267ff1ab5 | |||
8e0c776137 | |||
4512377fa1 | |||
9439ba1dac | |||
9c9c4a6b2b | |||
6efe51a8a7 | |||
593940c39a | |||
8ea19d4266 | |||
b7bcc50c61 | |||
e939677726 | |||
ca17ec3fe9 | |||
54d9668580 | |||
16b674c652 | |||
25ad992c62 | |||
37f1b7cddb | |||
729445b64f | |||
185f443659 | |||
c101a3f5ab | |||
cf9cb73afe | |||
071fcac430 | |||
a74ec89461 | |||
630d2a934b | |||
d5758c138b | |||
149b0021b7 | |||
68f46f6178 | |||
cd576fa59d | |||
320f26d26f | |||
c661587128 | |||
486e5365d9 | |||
8e809d8593 | |||
ea9ba53cdb | |||
1ba48a5ba0 | |||
7cb00b69f0 | |||
cbe8f0a9d0 | |||
da8b464e67 | |||
13350bf22f | |||
5ce55d87ec | |||
fc401f1acc | |||
fe39e4dfdf | |||
49b77207dd | |||
35a448ee92 | |||
3f9f00a798 | |||
ffe5619a9d | |||
3b194e1690 | |||
45b6508339 | |||
22921c493f | |||
f32811922e | |||
6cfa27d78a | |||
8e3ca8eaa9 | |||
4550613f58 | |||
015fde3703 | |||
827ecd61f6 | |||
565da10a8f | |||
d64c0e8887 | |||
0b8c44cbb1 | |||
a22f4dd1ac | |||
952e5b47eb | |||
b3f5b566b0 | |||
0b3332d579 | |||
a76e375d5c | |||
8b21c2e472 | |||
23718e5198 | |||
031aa240bc | |||
7944009a65 | |||
4eb06bb54b | |||
bd5308d839 | |||
b508532c78 | |||
fb9888a068 | |||
11f25747a9 | |||
8ebed3471f | |||
85684cd8b7 | |||
2585a33005 | |||
1bbeef48e1 | |||
7f3317110e | |||
298ff5c7d0 | |||
c3f65bff5b | |||
2323c30b5b | |||
80f4b32f0b | |||
16e362d2b9 | |||
23da490f26 | |||
ff107714f1 | |||
7e4703c328 | |||
ae41cedafe | |||
a879f72131 | |||
131df8bec9 | |||
89557d1607 | |||
7959808384 | |||
ecb0601bc1 | |||
30c0991543 | |||
9cddbc0420 | |||
2fa31dab60 | |||
4898db80cb | |||
aa3856261d | |||
3e04dbd5a1 | |||
72b46a07d6 | |||
2ba88dcd8a | |||
1ddb70e0d9 | |||
024a88a6bb | |||
af10c05ac3 | |||
a46a733dbe | |||
b015e4f07a | |||
44928a0265 | |||
d90328f6be | |||
ce9b4698fe | |||
9a33a29b4a | |||
b6e65f9882 | |||
6c163910ee | |||
9151cb9ba2 | |||
204ae75d7b | |||
f2d9b0096e | |||
67d2e6319b | |||
5e10f660e8 | |||
0da0b5cba0 | |||
67d7c364f6 | |||
67d58e2437 | |||
c2b04bdf6c | |||
6513bca07e | |||
0b0366d9b4 | |||
f465a75b65 | |||
4314e59af9 | |||
a84c958647 | |||
1ec2615a3e | |||
2077309c8d | |||
08d3169df4 | |||
3cc0445e27 | |||
ee77fe4094 | |||
133dfc8b69 | |||
a8726b8254 | |||
c5963f707c | |||
383b280531 | |||
95276f7da6 | |||
e1d4621796 | |||
e137b40eb5 | |||
4d929f80fb | |||
6b79e1f76d | |||
5a26656ea1 | |||
abb0d47985 | |||
b126a5d5a8 | |||
571031a467 | |||
2981f2025f | |||
c3a6065a21 | |||
60bb1afc72 | |||
84a320f834 | |||
88bd460100 | |||
90adc2cb85 | |||
7c8d823396 | |||
83790d65af | |||
70bd0f799d | |||
cbe029664e | |||
cade0214db | |||
2f5cdb72c8 | |||
0aed549df1 | |||
75fa1ac3b0 | |||
b5a00312e0 | |||
37697127dc | |||
8acc8b5389 | |||
8644c42482 | |||
20e63078f0 | |||
95fd080ca1 | |||
7d0af01d8b | |||
0f0230b068 | |||
869c602b99 | |||
3144f72e1c | |||
147b0a151c | |||
29102d6bf1 | |||
4fd145c52e | |||
e6d4d29af5 | |||
139665c01d | |||
509b991607 | |||
c671ecb511 | |||
1aa7c87ea8 | |||
00abb999e3 | |||
fc5cfc6cb3 | |||
25c3a29004 | |||
118cc88429 | |||
0dc9967984 |
@ -6,7 +6,7 @@
|
||||
# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
#
|
||||
# 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");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -29,30 +29,31 @@ CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
|
||||
if CLANG_FORMAT_BIN is None:
|
||||
o = 0
|
||||
try:
|
||||
p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE)
|
||||
p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
|
||||
o, _ = p.communicate()
|
||||
o = str(o, "utf-8")
|
||||
o = o[len("clang-format version "):].strip()
|
||||
o = o[:o.find(".")]
|
||||
o = re.sub(r".*ersion ", "", o)
|
||||
# o = o[len("clang-format version "):].strip()
|
||||
o = o[: o.find(".")]
|
||||
o = int(o)
|
||||
except:
|
||||
print ("clang-format-10 is needed. Aborted.")
|
||||
print("clang-format-11 is needed. Aborted.")
|
||||
exit(1)
|
||||
#if o < 7:
|
||||
# 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-10'], stdout=subprocess.PIPE) == 0:
|
||||
# CLANG_FORMAT_BIN = 'clang-format-10'
|
||||
# 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-10'
|
||||
|
||||
CLANG_FORMAT_BIN = "clang-format-11"
|
||||
|
||||
COLUMN_LIMIT = 80
|
||||
for line in fmt.split("\n"):
|
||||
line = line.split(":")
|
||||
@ -68,26 +69,47 @@ def custom_format(filename):
|
||||
in_define = False
|
||||
last_line = None
|
||||
out = ""
|
||||
|
||||
|
||||
for line in src.split("\n"):
|
||||
if line.lstrip().startswith("#"):
|
||||
if line[line.find("#")+1:].lstrip().startswith("define"):
|
||||
if line[line.find("#") + 1 :].lstrip().startswith("define"):
|
||||
in_define = True
|
||||
|
||||
if "/*" in line and not line.strip().startswith("/*") and line.endswith("*/") and len(line) < (COLUMN_LIMIT-2):
|
||||
|
||||
if (
|
||||
"/*" in line
|
||||
and not line.strip().startswith("/*")
|
||||
and line.endswith("*/")
|
||||
and len(line) < (COLUMN_LIMIT - 2)
|
||||
):
|
||||
cmt_start = line.rfind("/*")
|
||||
line = line[:cmt_start] + " " * (COLUMN_LIMIT-2 - len(line)) + line[cmt_start:]
|
||||
line = (
|
||||
line[:cmt_start]
|
||||
+ " " * (COLUMN_LIMIT - 2 - len(line))
|
||||
+ line[cmt_start:]
|
||||
)
|
||||
|
||||
define_padding = 0
|
||||
if last_line is not None and in_define and last_line.endswith("\\"):
|
||||
last_line = last_line[:-1]
|
||||
define_padding = max(0, len(last_line[last_line.rfind("\n")+1:]))
|
||||
define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :]))
|
||||
|
||||
if last_line is not None and last_line.strip().endswith("{") and line.strip() != "":
|
||||
if (
|
||||
last_line is not None
|
||||
and last_line.strip().endswith("{")
|
||||
and line.strip() != ""
|
||||
):
|
||||
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
|
||||
elif last_line is not None and last_line.strip().startswith("}") and line.strip() != "":
|
||||
elif (
|
||||
last_line is not None
|
||||
and last_line.strip().startswith("}")
|
||||
and line.strip() != ""
|
||||
):
|
||||
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
|
||||
elif line.strip().startswith("}") and last_line is not None and last_line.strip() != "":
|
||||
elif (
|
||||
line.strip().startswith("}")
|
||||
and last_line is not None
|
||||
and last_line.strip() != ""
|
||||
):
|
||||
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
|
||||
|
||||
if not line.endswith("\\"):
|
||||
@ -96,14 +118,15 @@ def custom_format(filename):
|
||||
out += line + "\n"
|
||||
last_line = line
|
||||
|
||||
return (out)
|
||||
return out
|
||||
|
||||
|
||||
args = sys.argv[1:]
|
||||
if len(args) == 0:
|
||||
print ("Usage: ./format.py [-i] <filename>")
|
||||
print ()
|
||||
print (" The -i option, if specified, let the script to modify in-place")
|
||||
print (" the source files. By default the results are written to stdout.")
|
||||
print("Usage: ./format.py [-i] <filename>")
|
||||
print()
|
||||
print(" The -i option, if specified, let the script to modify in-place")
|
||||
print(" the source files. By default the results are written to stdout.")
|
||||
print()
|
||||
exit(1)
|
||||
|
||||
@ -119,4 +142,3 @@ for filename in args:
|
||||
f.write(code)
|
||||
else:
|
||||
print(code)
|
||||
|
||||
|
65
.dockerignore
Normal file
65
.dockerignore
Normal file
@ -0,0 +1,65 @@
|
||||
.test
|
||||
.test2
|
||||
.sync_tmp
|
||||
*.o
|
||||
*.so
|
||||
*.pyc
|
||||
*.dSYM
|
||||
as
|
||||
ld
|
||||
in
|
||||
out
|
||||
core*
|
||||
afl-analyze
|
||||
afl-as
|
||||
afl-clang
|
||||
afl-clang\+\+
|
||||
afl-clang-fast
|
||||
afl-clang-fast\+\+
|
||||
afl-clang-lto
|
||||
afl-clang-lto\+\+
|
||||
afl-fuzz
|
||||
afl-g\+\+
|
||||
afl-gcc
|
||||
afl-gcc-fast
|
||||
afl-g\+\+-fast
|
||||
afl-gotcpu
|
||||
afl-ld
|
||||
afl-ld-lto
|
||||
afl-qemu-trace
|
||||
afl-showmap
|
||||
afl-tmin
|
||||
afl-analyze.8
|
||||
afl-as.8
|
||||
afl-clang-fast\+\+.8
|
||||
afl-clang-fast.8
|
||||
afl-clang-lto.8
|
||||
afl-clang-lto\+\+.8
|
||||
afl-cmin.8
|
||||
afl-cmin.bash.8
|
||||
afl-fuzz.8
|
||||
afl-gcc.8
|
||||
afl-gcc-fast.8
|
||||
afl-g\+\+-fast.8
|
||||
afl-gotcpu.8
|
||||
afl-plot.8
|
||||
afl-showmap.8
|
||||
afl-system-config.8
|
||||
afl-tmin.8
|
||||
afl-whatsup.8
|
||||
qemu_mode/libcompcov/compcovtest
|
||||
qemu_mode/qemu-*
|
||||
unicorn_mode/samples/*/\.test-*
|
||||
unicorn_mode/samples/*/output
|
||||
unicorn_mode/unicornafl
|
||||
test/unittests/unit_maybe_alloc
|
||||
test/unittests/unit_preallocable
|
||||
test/unittests/unit_list
|
||||
test/unittests/unit_rand
|
||||
test/unittests/unit_hash
|
||||
examples/afl_network_proxy/afl-network-server
|
||||
examples/afl_network_proxy/afl-network-client
|
||||
examples/afl_frida/afl-frida
|
||||
examples/afl_frida/libtestinstr.so
|
||||
examples/afl_frida/frida-gum-example.c
|
||||
examples/afl_frida/frida-gum.h
|
13
.github/FUNDING.yml
vendored
Normal file
13
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
github: AFLplusplus
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: AFLplusplusEU
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**IMPORTANT**
|
||||
1. You have verified that the issue to be present in the current `dev` branch.
|
||||
2. Please supply the command line options and relevant environment variables,
|
||||
e.g., a copy-paste of the contents of `out/default/fuzzer_setup`.
|
||||
|
||||
Thank you for making AFL++ better!
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screen output/Screenshots**
|
||||
If applicable, add copy-paste of the screen output or screenshot that shows the issue. Please ensure the output is in **English** and not in Chinese, Russian, German, etc.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
49
.github/workflows/build_aflplusplus_docker.yaml
vendored
Normal file
49
.github/workflows/build_aflplusplus_docker.yaml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: Publish Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- stable
|
||||
- dev
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
push_to_registry:
|
||||
name: Push Docker images to Dockerhub
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Dockerhub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Publish dev as dev to docker.io registry
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: aflplusplus/aflplusplus:${{ github.ref_name }}
|
||||
if: ${{ github.ref_name == 'dev' }}
|
||||
- name: Publish stable as stable and latest to docker.io registry
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: aflplusplus/aflplusplus:${{ github.ref_name }},aflplusplus/aflplusplus:latest
|
||||
if: ${{ github.ref_name == 'stable' }}
|
||||
- name: Publish tagged release to docker.io registry
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: aflplusplus/aflplusplus:${{ github.ref_name }}
|
||||
if: ${{ github.ref_type == 'tag' }}
|
53
.github/workflows/ci.yml
vendored
Normal file
53
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ stable, dev ]
|
||||
pull_request:
|
||||
branches: [ stable, dev ]
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
|
||||
env:
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: debug
|
||||
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
|
||||
- name: update
|
||||
run: sudo apt-get update && sudo apt-get upgrade -y
|
||||
- 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
|
||||
- name: compiler installed
|
||||
run: gcc -v; echo; clang -v
|
||||
- name: install gcc plugin
|
||||
run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev
|
||||
- name: build afl++
|
||||
run: make distrib ASAN_BUILD=1
|
||||
- name: run 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@v2
|
||||
- name: install
|
||||
run: brew install make gcc
|
||||
- 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
|
32
.github/workflows/codeql-analysis.yml
vendored
Normal file
32
.github/workflows/codeql-analysis.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ stable, dev ]
|
||||
pull_request:
|
||||
branches: [ stable, dev ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
30
.github/workflows/rust_custom_mutator.yml
vendored
Normal file
30
.github/workflows/rust_custom_mutator.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
name: Rust Custom Mutators
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ stable, dev ]
|
||||
pull_request:
|
||||
branches: [ stable, dev ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test Rust Custom Mutator Support
|
||||
runs-on: '${{ matrix.os }}'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: custom_mutators/rust
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Rust Toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Check Code Compiles
|
||||
run: cargo check
|
||||
- name: Run General Tests
|
||||
run: cargo test
|
||||
- name: Run Tests for afl_internals feature flag
|
||||
run: cd custom_mutator && cargo test --features=afl_internals
|
51
.gitignore
vendored
51
.gitignore
vendored
@ -1,8 +1,19 @@
|
||||
.test
|
||||
.test2
|
||||
.sync_tmp
|
||||
.vscode
|
||||
*.o
|
||||
*.so
|
||||
*.swp
|
||||
*.pyc
|
||||
*.dSYM
|
||||
as
|
||||
a.out
|
||||
ld
|
||||
in
|
||||
out
|
||||
core*
|
||||
compile_commands.json
|
||||
afl-analyze
|
||||
afl-as
|
||||
afl-clang
|
||||
@ -19,6 +30,7 @@ afl-g++-fast
|
||||
afl-gotcpu
|
||||
afl-ld
|
||||
afl-ld-lto
|
||||
afl-cs-proxy
|
||||
afl-qemu-trace
|
||||
afl-showmap
|
||||
afl-tmin
|
||||
@ -31,7 +43,10 @@ afl-clang-lto++.8
|
||||
afl-cmin.8
|
||||
afl-cmin.bash.8
|
||||
afl-fuzz.8
|
||||
afl-c++.8
|
||||
afl-cc.8
|
||||
afl-gcc.8
|
||||
afl-g++.8
|
||||
afl-gcc-fast.8
|
||||
afl-g++-fast.8
|
||||
afl-gotcpu.8
|
||||
@ -40,14 +55,18 @@ afl-showmap.8
|
||||
afl-system-config.8
|
||||
afl-tmin.8
|
||||
afl-whatsup.8
|
||||
afl-persistent-config.8
|
||||
afl-c++
|
||||
afl-cc
|
||||
afl-lto
|
||||
afl-lto++
|
||||
afl-lto++.8
|
||||
afl-lto.8
|
||||
qemu_mode/libcompcov/compcovtest
|
||||
as
|
||||
ld
|
||||
qemu_mode/qemu-*
|
||||
qemu_mode/qemuafl
|
||||
unicorn_mode/samples/*/\.test-*
|
||||
unicorn_mode/samples/*/output/
|
||||
unicorn_mode/unicornafl
|
||||
core\.*
|
||||
test/unittests/unit_maybe_alloc
|
||||
test/unittests/unit_preallocable
|
||||
test/unittests/unit_list
|
||||
@ -55,3 +74,27 @@ 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
|
||||
examples/aflpp_driver/libAFLDriver.a
|
||||
examples/aflpp_driver/libAFLQemuDriver.a
|
||||
libAFLDriver.a
|
||||
libAFLQemuDriver.a
|
||||
test/.afl_performance
|
||||
gmon.out
|
||||
afl-frida-trace.so
|
||||
utils/afl_network_proxy/afl-network-client
|
||||
utils/afl_network_proxy/afl-network-server
|
||||
utils/plot_ui/afl-plot-ui
|
||||
*.o.tmp
|
||||
utils/afl_proxy/afl-proxy
|
||||
utils/optimin/build
|
||||
utils/optimin/optimin
|
||||
utils/persistent_mode/persistent_demo
|
||||
utils/persistent_mode/persistent_demo_new
|
||||
utils/persistent_mode/test-instr
|
||||
!coresight_mode
|
||||
!coresight_mode/coresight-trace
|
||||
vuln_prog
|
26
.gitmodules
vendored
26
.gitmodules
vendored
@ -1,3 +1,27 @@
|
||||
[submodule "unicorn_mode/unicornafl"]
|
||||
path = unicorn_mode/unicornafl
|
||||
url = https://github.com/AFLplusplus/unicornafl.git
|
||||
url = https://github.com/AFLplusplus/unicornafl
|
||||
[submodule "custom_mutators/grammar_mutator"]
|
||||
path = custom_mutators/grammar_mutator/grammar_mutator
|
||||
url = https://github.com/AFLplusplus/Grammar-Mutator
|
||||
[submodule "qemu_mode/qemuafl"]
|
||||
path = qemu_mode/qemuafl
|
||||
url = https://github.com/AFLplusplus/qemuafl
|
||||
[submodule "custom_mutators/gramatron/json-c"]
|
||||
path = custom_mutators/gramatron/json-c
|
||||
url = https://github.com/json-c/json-c
|
||||
[submodule "coresight_mode/patchelf"]
|
||||
path = coresight_mode/patchelf
|
||||
url = https://github.com/NixOS/patchelf.git
|
||||
[submodule "coresight_mode/coresight-trace"]
|
||||
path = coresight_mode/coresight-trace
|
||||
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
|
||||
|
58
.travis.yml
58
.travis.yml
@ -1,58 +0,0 @@
|
||||
language: c
|
||||
|
||||
sudo: required
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# - os: linux # focal errors every run with a timeout while installing packages
|
||||
# dist: focal
|
||||
# env: NAME="focal-amd64" MODERN="yes" GCC="9"
|
||||
- os: linux
|
||||
dist: bionic
|
||||
env: NAME="bionic-amd64" MODERN="yes" GCC="7"
|
||||
- os: linux
|
||||
dist: xenial
|
||||
env: NAME="xenial-amd64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
env: NAME="trusty-amd64" MODERN="no" GCC="4.8"
|
||||
# - os: linux # until travis can fix this!
|
||||
# dist: xenial
|
||||
# arch: arm64
|
||||
# env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64"
|
||||
# - os: osx
|
||||
# osx_image: xcode11.2
|
||||
# env: NAME="osx" HOMEBREW_NO_ANALYTICS="1" LINK="http://releases.llvm.org/9.0.0/" NAME="clang+llvm-9.0.0-x86_64-darwin-apple"
|
||||
|
||||
jobs:
|
||||
allow_failures:
|
||||
- os: osx
|
||||
- arch: arm64
|
||||
|
||||
env:
|
||||
- AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1
|
||||
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_EXIT_WHEN_DONE=1
|
||||
# TODO: test AFL_BENCH_UNTIL_CRASH once we have a target that crashes
|
||||
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_BENCH_JUST_ONE=1
|
||||
|
||||
before_install:
|
||||
# export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
|
||||
- echo Testing on $NAME
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y git libtool libtool-bin automake bison libglib2.0-0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev python3-setuptools ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y git libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev python3-setuptools ; fi
|
||||
|
||||
script:
|
||||
- gcc -v
|
||||
- clang -v
|
||||
- sudo -E ./afl-system-config
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ASAN_BUILD=1 ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ASAN_BUILD=1 ; fi
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then echo DEBUG ; find / -name llvm-config.h 2>/dev/null; apt-cache search clang | grep clang- ; apt-cache search llvm | grep llvm- ; dpkg -l | egrep 'clang|llvm'; echo DEBUG ; export LLVM_CONFIG=llvm-config-6.0 ; make ASAN_BUILD=1 ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
|
||||
- make tests
|
||||
# - travis_terminate 0
|
336
Android.bp
336
Android.bp
@ -1,7 +1,21 @@
|
||||
//
|
||||
// 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 {
|
||||
name: "afl-defaults",
|
||||
|
||||
local_include_dirs: [
|
||||
"include",
|
||||
"instrumentation",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-flto=full",
|
||||
"-funroll-loops",
|
||||
"-Wno-pointer-sign",
|
||||
"-Wno-pointer-arith",
|
||||
@ -10,24 +24,62 @@ cc_defaults {
|
||||
"-Wno-unused-function",
|
||||
"-Wno-format",
|
||||
"-Wno-user-defined-warnings",
|
||||
"-DUSE_TRACE_PC=1",
|
||||
"-DAFL_LLVM_USE_TRACE_PC=1",
|
||||
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
|
||||
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
|
||||
"-D__USE_GNU",
|
||||
"-DDEBUG_BUILD",
|
||||
"-U_FORTIFY_SOURCE",
|
||||
"-ggdb3",
|
||||
"-g",
|
||||
"-O0",
|
||||
"-fno-omit-frame-pointer",
|
||||
"-fPIC",
|
||||
],
|
||||
|
||||
target: {
|
||||
android_arm64: {
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
],
|
||||
},
|
||||
android_arm: {
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
],
|
||||
},
|
||||
android_x86_64: {
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
],
|
||||
},
|
||||
android_x86: {
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-fuzz",
|
||||
static_executable: true,
|
||||
sanitize: {
|
||||
never: true,
|
||||
},
|
||||
host_supported: true,
|
||||
compile_multilib: "64",
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-fuzz.c",
|
||||
"src/afl-fuzz*.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -41,7 +93,11 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-showmap.c",
|
||||
"src/afl-showmap.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -55,7 +111,11 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-tmin.c",
|
||||
"src/afl-tmin.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -69,7 +129,10 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-analyze.c",
|
||||
"src/afl-analyze.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
@ -83,12 +146,13 @@ cc_binary {
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-gotcpu.c",
|
||||
"src/afl-gotcpu.c",
|
||||
"src/afl-common.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast",
|
||||
name: "afl-cc",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
@ -96,46 +160,260 @@ cc_binary_host {
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
"-DAFL_CLANG_FLTO=\"-flto=full\"",
|
||||
"-DUSE_BINDIR=1",
|
||||
"-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
|
||||
"-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
|
||||
"-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
|
||||
"-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
|
||||
"-DLLVM_LTO=1",
|
||||
"-DLLVM_MAJOR=11",
|
||||
"-DLLVM_MINOR=2",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-clang-fast.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast++",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
"src/afl-cc.c",
|
||||
"src/afl-common.c",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-clang-fast.c",
|
||||
symlinks: [
|
||||
"afl-clang-fast",
|
||||
"afl-clang-fast++",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "afl-llvm-rt",
|
||||
compile_multilib: "both",
|
||||
name: "afl-compiler-rt",
|
||||
compile_multilib: "64",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
recovery_available: true,
|
||||
sdk_version: "9",
|
||||
|
||||
apex_available: [
|
||||
"com.android.adbd",
|
||||
"com.android.appsearch",
|
||||
"com.android.art",
|
||||
"com.android.bluetooth.updatable",
|
||||
"com.android.cellbroadcast",
|
||||
"com.android.conscrypt",
|
||||
"com.android.extservices",
|
||||
"com.android.cronet",
|
||||
"com.android.neuralnetworks",
|
||||
"com.android.media",
|
||||
"com.android.media.swcodec",
|
||||
"com.android.mediaprovider",
|
||||
"com.android.permission",
|
||||
"com.android.runtime",
|
||||
"com.android.resolv",
|
||||
"com.android.tethering",
|
||||
"com.android.wifi",
|
||||
"com.android.sdkext",
|
||||
"com.android.os.statsd",
|
||||
"//any",
|
||||
],
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-llvm-rt.o.c",
|
||||
"instrumentation/afl-compiler-rt.o.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libafl_headers",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
export_include_dirs: [
|
||||
"include",
|
||||
"instrumentation",
|
||||
],
|
||||
}
|
||||
|
||||
/*
|
||||
cc_prebuilt_library_static {
|
||||
name: "libfrida-gum",
|
||||
compile_multilib: "64",
|
||||
strip: {
|
||||
none: true,
|
||||
},
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/android/libfrida-gum.a",
|
||||
],
|
||||
|
||||
export_include_dirs: [
|
||||
"utils/afl_frida/android",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libtestinstr",
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/libtestinstr.c",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-fPIC",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-frida",
|
||||
compile_multilib: "64",
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-Wno-format",
|
||||
"-Wno-pointer-sign",
|
||||
"-fpermissive",
|
||||
"-fPIC",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"afl-compiler-rt",
|
||||
"libfrida-gum",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libdl",
|
||||
"liblog",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/afl-frida.c",
|
||||
],
|
||||
|
||||
local_include_dirs: [
|
||||
"utils/afl_frida",
|
||||
"utils/afl_frida/android",
|
||||
],
|
||||
}
|
||||
*/
|
||||
|
||||
cc_binary {
|
||||
name: "afl-fuzz-32",
|
||||
sanitize: {
|
||||
never: true,
|
||||
},
|
||||
host_supported: true,
|
||||
compile_multilib: "32",
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/afl-fuzz*.c",
|
||||
"src/afl-common.c",
|
||||
"src/afl-sharedmem.c",
|
||||
"src/afl-forkserver.c",
|
||||
"src/afl-performance.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-cc-32",
|
||||
compile_multilib: "32",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
"-DAFL_CLANG_FLTO=\"-flto=full\"",
|
||||
"-DUSE_BINDIR=1",
|
||||
"-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
|
||||
"-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
|
||||
"-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
|
||||
"-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
|
||||
"-DLLVM_LTO=1",
|
||||
"-DLLVM_MAJOR=11",
|
||||
"-DLLVM_MINOR=2",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/afl-cc.c",
|
||||
"src/afl-common.c",
|
||||
],
|
||||
|
||||
symlinks: [
|
||||
"afl-clang-fast-32",
|
||||
"afl-clang-fast++-32",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "afl-compiler-rt-32",
|
||||
compile_multilib: "32",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
recovery_available: true,
|
||||
sdk_version: "9",
|
||||
|
||||
apex_available: [
|
||||
"com.android.adbd",
|
||||
"com.android.appsearch",
|
||||
"com.android.art",
|
||||
"com.android.bluetooth.updatable",
|
||||
"com.android.cellbroadcast",
|
||||
"com.android.conscrypt",
|
||||
"com.android.extservices",
|
||||
"com.android.cronet",
|
||||
"com.android.neuralnetworks",
|
||||
"com.android.media",
|
||||
"com.android.media.swcodec",
|
||||
"com.android.mediaprovider",
|
||||
"com.android.permission",
|
||||
"com.android.runtime",
|
||||
"com.android.resolv",
|
||||
"com.android.tethering",
|
||||
"com.android.wifi",
|
||||
"com.android.sdkext",
|
||||
"com.android.os.statsd",
|
||||
"//any",
|
||||
],
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"instrumentation/afl-compiler-rt.o.c",
|
||||
],
|
||||
}
|
||||
|
||||
/*
|
||||
cc_prebuilt_library_static {
|
||||
name: "libfrida-gum-32",
|
||||
compile_multilib: "32",
|
||||
strip: {
|
||||
none: true,
|
||||
},
|
||||
|
||||
srcs: [
|
||||
"utils/afl_frida/android/arm/libfrida-gum.a",
|
||||
],
|
||||
|
||||
export_include_dirs: [
|
||||
"utils/afl_frida/android/arm",
|
||||
],
|
||||
}
|
||||
*/
|
||||
|
||||
subdirs = [
|
||||
"custom_mutators",
|
||||
]
|
||||
|
@ -1 +0,0 @@
|
||||
Makefile
|
31
CITATION.cff
Normal file
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
|
@ -1,4 +1,8 @@
|
||||
# How to submit a Pull Request to AFLplusplus
|
||||
# Contributing to AFL++
|
||||
|
||||
## How to submit a pull request
|
||||
|
||||
All contributions (pull requests) must be made against our `dev` branch.
|
||||
|
||||
Each modified source file, before merging, must be formatted.
|
||||
|
||||
@ -13,10 +17,43 @@ project, or added a file in a directory we already format, otherwise run:
|
||||
./.custom-format.py -i file-that-you-have-created.c
|
||||
```
|
||||
|
||||
Regarding the coding style, please follow the AFL style.
|
||||
No camel case at all and use the AFL's macros wherever possible
|
||||
(e.g. WARNF, FATAL, MAP_SIZE, ...).
|
||||
Regarding the coding style, please follow the AFL style. No camel case at all
|
||||
and use AFL's macros wherever possible (e.g., WARNF, FATAL, MAP_SIZE, ...).
|
||||
|
||||
Remember that AFLplusplus has to build and run on many platforms, so
|
||||
generalize your Makefiles (or your patches to our pre-existing Makefiles)
|
||||
to be as much generic as possible.
|
||||
Remember that AFL++ has to build and run on many platforms, so generalize your
|
||||
Makefiles/GNUmakefile (or your patches to our pre-existing Makefiles) to be as
|
||||
generic as possible.
|
||||
|
||||
## How to contribute to the docs
|
||||
|
||||
We welcome contributions to our docs.
|
||||
|
||||
Before creating a new file, please check if your content matches an existing
|
||||
file in one the following folders:
|
||||
|
||||
* [docs/](docs/) (this is where you can find most of our docs content)
|
||||
* [frida_mode/](frida_mode/)
|
||||
* [instrumentation/](instrumentation/)
|
||||
* [qemu_mode/](qemu_mode/)
|
||||
* [unicorn_mode/](unicorn_mode/)
|
||||
|
||||
When working on the docs, please keep the following guidelines in mind:
|
||||
|
||||
* Edit or create Markdown files and use Markdown markup.
|
||||
* Do: fuzzing_gui_program.md
|
||||
* Don't: fuzzing_gui_program.txt
|
||||
* Use underscore in file names.
|
||||
* Do: fuzzing_network_service.md
|
||||
* Don't: fuzzing-network-service.md
|
||||
* Use a maximum of 80 characters per line to make reading in a console easier.
|
||||
* Make all pull requests against `dev`, see
|
||||
[#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl).
|
||||
|
||||
And finally, here are some best practices for writing docs content:
|
||||
|
||||
* Use clear and simple language.
|
||||
* Structure your content with headings and paragraphs.
|
||||
* Use bulleted lists to present similar content in a way that makes it easy to
|
||||
scan.
|
||||
* Use numbered lists for procedures or prioritizing.
|
||||
* Link to related content, for example, prerequisites or in-depth discussions.
|
95
Dockerfile
95
Dockerfile
@ -1,62 +1,81 @@
|
||||
#
|
||||
# This Dockerfile for AFLplusplus uses Ubuntu 20.04 focal and
|
||||
# installs LLVM 11 from llvm.org for afl-clang-lto support :-)
|
||||
# It also installs gcc/g++ 10 from the Ubuntu development platform
|
||||
# has focal has gcc-10 but not g++-10 ...
|
||||
# This Dockerfile for AFLplusplus uses Ubuntu 22.04 jammy and
|
||||
# installs LLVM 14 for afl-clang-lto support :-)
|
||||
#
|
||||
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER afl++ team <afl@aflplus.plus>
|
||||
FROM ubuntu:22.04 AS aflplusplus
|
||||
LABEL "maintainer"="afl++ team <afl@aflplus.plus>"
|
||||
LABEL "about"="AFLplusplus docker image"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
env NO_ARCH_OPT 1
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y install --no-install-suggests --no-install-recommends \
|
||||
automake \
|
||||
cmake \
|
||||
meson \
|
||||
ninja-build \
|
||||
bison flex \
|
||||
build-essential \
|
||||
git \
|
||||
python3 python3-dev python3-setuptools python-is-python3 \
|
||||
libtool libtool-bin \
|
||||
libglib2.0-dev \
|
||||
wget vim jupp nano \
|
||||
wget vim jupp nano bash-completion less \
|
||||
apt-utils apt-transport-https ca-certificates gnupg dialog \
|
||||
libpixman-1-dev
|
||||
libpixman-1-dev \
|
||||
gnuplot-nox \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN echo deb http://apt.llvm.org/focal/ llvm-toolchain-focal main >> /etc/apt/sources.list && \
|
||||
wget -O - 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 && \
|
||||
# TODO: reactivate in timely manner
|
||||
#RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 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 jammy main" >> /etc/apt/sources.list && \
|
||||
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 1E9377A2BA9EF27F
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y
|
||||
|
||||
RUN apt-get install -y gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib \
|
||||
libc++-10-dev gdb lcov
|
||||
RUN apt-get update && apt-get full-upgrade -y && \
|
||||
apt-get -y install --no-install-suggests --no-install-recommends \
|
||||
gcc-12 g++-12 gcc-12-plugin-dev gdb lcov \
|
||||
clang-14 clang-tools-14 libc++1-14 libc++-14-dev \
|
||||
libc++abi1-14 libc++abi-14-dev libclang1-14 libclang-14-dev \
|
||||
libclang-common-14-dev libclang-cpp14 libclang-cpp14-dev liblld-14 \
|
||||
liblld-14-dev liblldb-14 liblldb-14-dev libllvm14 libomp-14-dev \
|
||||
libomp5-14 lld-14 lldb-14 llvm-14 llvm-14-dev llvm-14-runtime llvm-14-tools
|
||||
|
||||
RUN apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \
|
||||
libc++abi1-11 libc++abi-11-dev libclang1-11 libclang-11-dev \
|
||||
libclang-common-11-dev libclang-cpp11 libclang-cpp11-dev liblld-11 \
|
||||
liblld-11-dev liblldb-11 liblldb-11-dev libllvm11 libomp-11-dev \
|
||||
libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools
|
||||
# arm64 doesn't have gcc-multilib, and it's only used for -m32 support on x86
|
||||
ARG TARGETPLATFORM
|
||||
RUN [ "$TARGETPLATFORM" = "linux/amd64" ] && \
|
||||
apt-get -y install --no-install-suggests --no-install-recommends \
|
||||
gcc-10-multilib gcc-multilib || true
|
||||
|
||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 0
|
||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
|
||||
RUN rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rm -rf /var/cache/apt/archives/*
|
||||
|
||||
ARG CC=gcc-10
|
||||
ARG CXX=g++-10
|
||||
ARG LLVM_CONFIG=llvm-config-11
|
||||
|
||||
RUN git clone https://github.com/AFLplusplus/AFLplusplus
|
||||
RUN cd AFLplusplus && export REAL_CXX=g++-10 && make distrib && \
|
||||
make install && make clean
|
||||
|
||||
RUN git clone https://github.com/vanhauser-thc/afl-cov afl-cov
|
||||
RUN cd afl-cov && make install
|
||||
|
||||
RUN echo 'alias joe="jupp --wordwrap"' >> ~/.bashrc
|
||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 0
|
||||
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 0
|
||||
|
||||
ENV LLVM_CONFIG=llvm-config-14
|
||||
ENV AFL_SKIP_CPUFREQ=1
|
||||
ENV AFL_TRY_AFFINITY=1
|
||||
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
|
||||
|
||||
RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov /afl-cov
|
||||
RUN cd /afl-cov && make install && cd ..
|
||||
|
||||
COPY . /AFLplusplus
|
||||
WORKDIR /AFLplusplus
|
||||
|
||||
RUN export CC=gcc-12 && export CXX=g++-12 && make clean && \
|
||||
make distrib && make install && make clean
|
||||
|
||||
RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc'
|
||||
RUN echo '. /etc/bash_completion' >> ~/.bashrc
|
||||
RUN echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc
|
||||
RUN echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc
|
||||
ENV IS_DOCKER="1"
|
||||
|
||||
# Disabled as there are now better alternatives
|
||||
#COPY --from=aflplusplus/afl-dyninst /usr/local/lib/libdyninstAPI_RT.so /usr/local/lib/libdyninstAPI_RT.so
|
||||
#COPY --from=aflplusplus/afl-dyninst /afl-dyninst/libAflDyninst.so /usr/local/lib/libAflDyninst.so
|
||||
|
515
GNUmakefile
515
GNUmakefile
@ -10,7 +10,7 @@
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
@ -24,18 +24,44 @@ BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH = $(PREFIX)/share/doc/afl
|
||||
MISC_PATH = $(PREFIX)/share/afl
|
||||
MAN_PATH = $(PREFIX)/man/man8
|
||||
MAN_PATH = $(PREFIX)/share/man/man8
|
||||
|
||||
PROGNAME = afl
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
# PROGS intentionally omit afl-as, which gets installed elsewhere.
|
||||
|
||||
PROGS = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
|
||||
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config afl-persistent-config afl-cc
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
|
||||
ASAN_OPTIONS=detect_leaks=0
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
ARCH = $(shell uname -m)
|
||||
|
||||
$(info [*] Compiling afl++ for OS $(SYS) on ARCH $(ARCH))
|
||||
|
||||
ifdef NO_SPLICING
|
||||
override CFLAGS_OPT += -DNO_SPLICING
|
||||
endif
|
||||
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
override CFLAGS += $(ASAN_CFLAGS)
|
||||
LDFLAGS += $(ASAN_LDFLAGS)
|
||||
endif
|
||||
ifdef UBSAN_BUILD
|
||||
$(info Compiling UBSAN version of binaries)
|
||||
override CFLAGS += -fsanitize=undefined -fno-omit-frame-pointer
|
||||
override LDFLAGS += -fsanitize=undefined
|
||||
endif
|
||||
ifdef MSAN_BUILD
|
||||
$(info Compiling MSAN version of binaries)
|
||||
CC := clang
|
||||
override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer
|
||||
override LDFLAGS += -fsanitize=memory
|
||||
endif
|
||||
|
||||
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=full
|
||||
@ -50,30 +76,42 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
|
||||
endif
|
||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
|
||||
#endif
|
||||
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
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"
|
||||
#CFLAGS_OPT += -march=native
|
||||
SPECIAL_PERFORMANCE += -march=native
|
||||
endif
|
||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
# ifndef SOURCE_DATE_EPOCH
|
||||
# HAVE_MARCHNATIVE = 1
|
||||
# CFLAGS_OPT += -march=native
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
# OS X does not like _FORTIFY_SOURCE=2
|
||||
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
||||
ifndef DEBUG
|
||||
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
||||
endif
|
||||
else
|
||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||
LDFLAGS += $(SDK_LD)
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname)" "SunOS"
|
||||
CFLAGS_OPT += -Wno-format-truncation
|
||||
LDFLAGS=-lkstat
|
||||
ifeq "$(SYS)" "SunOS"
|
||||
CFLAGS_OPT += -Wno-format-truncation
|
||||
LDFLAGS = -lkstat -lrt
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(info Compiling static version of binaries, disabling python though)
|
||||
# Disable python for static compilation to simplify things
|
||||
PYTHON_OK=0
|
||||
PYTHON_OK = 0
|
||||
PYFLAGS=
|
||||
PYTHON_INCLUDE=/
|
||||
PYTHON_INCLUDE = /
|
||||
|
||||
CFLAGS_OPT += -static
|
||||
LDFLAGS += -lm -lpthread -lz -lutil
|
||||
@ -81,50 +119,62 @@ endif
|
||||
|
||||
ifdef PROFILING
|
||||
$(info Compiling with profiling information, for analysis: gprof ./afl-fuzz gmon.out > prof.txt)
|
||||
CFLAGS_OPT += -pg -DPROFILING=1
|
||||
LDFLAGS += -pg
|
||||
override CFLAGS_OPT += -pg -DPROFILING=1
|
||||
override LDFLAGS += -pg
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname -m)" "x86_64"
|
||||
ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386"
|
||||
ifneq "$(shell uname -m)" "amd64"
|
||||
ifneq "$(shell uname -m)" "i86pc"
|
||||
ifdef INTROSPECTION
|
||||
$(info Compiling with introspection documentation)
|
||||
override CFLAGS_OPT += -DINTROSPECTION=1
|
||||
endif
|
||||
|
||||
ifneq "$(ARCH)" "x86_64"
|
||||
ifneq "$(patsubst i%86,i386,$(ARCH))" "i386"
|
||||
ifneq "$(ARCH)" "amd64"
|
||||
ifneq "$(ARCH)" "i86pc"
|
||||
AFL_NO_X86=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
|
||||
override CFLAGS += -Wall -g -Wno-pointer-sign -Wmissing-declarations\
|
||||
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
||||
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
||||
|
||||
ifeq "$(shell uname -s)" "FreeBSD"
|
||||
override CFLAGS += -I /usr/local/include/
|
||||
LDFLAGS += -L /usr/local/lib/
|
||||
ifdef DEBUG
|
||||
$(info Compiling DEBUG version of binaries)
|
||||
override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
|
||||
else
|
||||
CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname -s)" "DragonFly"
|
||||
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wno-pointer-arith \
|
||||
-fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
||||
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
||||
# -fstack-protector
|
||||
|
||||
ifeq "$(SYS)" "FreeBSD"
|
||||
override CFLAGS += -I /usr/local/include/
|
||||
LDFLAGS += -L /usr/local/lib/
|
||||
override LDFLAGS += -L /usr/local/lib/
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname -s)" "OpenBSD"
|
||||
ifeq "$(SYS)" "DragonFly"
|
||||
override CFLAGS += -I /usr/local/include/
|
||||
override LDFLAGS += -L /usr/local/lib/
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
override CFLAGS += -I /usr/local/include/ -mno-retpoline
|
||||
LDFLAGS += -Wl,-z,notext -L /usr/local/lib/
|
||||
override LDFLAGS += -Wl,-z,notext -L /usr/local/lib/
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname -s)" "NetBSD"
|
||||
ifeq "$(SYS)" "NetBSD"
|
||||
override CFLAGS += -I /usr/pkg/include/
|
||||
LDFLAGS += -L /usr/pkg/lib/
|
||||
override LDFLAGS += -L /usr/pkg/lib/
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname -s)" "Haiku"
|
||||
ifeq "$(SYS)" "Haiku"
|
||||
SHMAT_OK=0
|
||||
override CFLAGS += -DUSEMMAP=1 -Wno-error=format -fPIC
|
||||
LDFLAGS += -Wno-deprecated-declarations -lgnu
|
||||
SPECIAL_PERFORMANCE += -DUSEMMAP=1
|
||||
override CFLAGS += -DUSEMMAP=1 -Wno-error=format
|
||||
override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
|
||||
#SPECIAL_PERFORMANCE += -DUSEMMAP=1
|
||||
endif
|
||||
|
||||
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
||||
@ -195,24 +245,23 @@ else
|
||||
BUILD_DATE ?= $(shell date "+%Y-%m-%d")
|
||||
endif
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
ifneq "$(filter Linux GNU%,$(SYS))" ""
|
||||
override LDFLAGS += -ldl -lrt -lm
|
||||
endif
|
||||
|
||||
ifneq "$(findstring FreeBSD, $(shell uname))" ""
|
||||
ifneq "$(findstring FreeBSD, $(SYS))" ""
|
||||
override CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
override LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifneq "$(findstring NetBSD, $(shell uname))" ""
|
||||
ifneq "$(findstring NetBSD, $(SYS))" ""
|
||||
override CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
override LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
TEST_CC = afl-gcc
|
||||
else
|
||||
TEST_CC = afl-clang
|
||||
ifneq "$(findstring OpenBSD, $(SYS))" ""
|
||||
override CFLAGS += -pthread
|
||||
override LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
@ -239,57 +288,74 @@ ifeq "$(shell command -v svn >/dev/null && svn proplist . 2>/dev/null && echo 1
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() { return 0;}' | $(CC) $(CFLAGS) -fsanitize=address -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
ASAN_CFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
|
||||
ASAN_CFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer -DASAN_BUILD
|
||||
ASAN_LDFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
|
||||
endif
|
||||
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
override CFLAGS+=$(ASAN_CFLAGS)
|
||||
LDFLAGS+=$(ASAN_LDFLAGS)
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
override CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -Wno-deprecated-declarations -lrt
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
ifdef TEST_MMAP
|
||||
SHMAT_OK=0
|
||||
override CFLAGS += -DUSEMMAP=1
|
||||
LDFLAGS += -Wno-deprecated-declarations -lrt
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
|
||||
.PHONY: all
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
|
||||
-$(MAKE) -C utils/aflpp_driver
|
||||
|
||||
.PHONY: llvm
|
||||
llvm:
|
||||
-$(MAKE) -j4 -f GNUmakefile.llvm
|
||||
@test -e afl-cc || { echo "[-] Compiling afl-cc failed. You seem not to have a working compiler." ; exit 1; }
|
||||
|
||||
.PHONY: gcc_plugin
|
||||
gcc_plugin:
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
endif
|
||||
|
||||
.PHONY: man
|
||||
man: $(MANPAGES)
|
||||
|
||||
.PHONY: test
|
||||
test: tests
|
||||
|
||||
.PHONY: tests
|
||||
tests: source-only
|
||||
@cd test ; ./test.sh
|
||||
@cd test ; ./test-all.sh
|
||||
@rm -f test/errors
|
||||
|
||||
.PHONY: performance-tests
|
||||
performance-tests: performance-test
|
||||
.PHONY: test-performance
|
||||
test-performance: performance-test
|
||||
|
||||
.PHONY: performance-test
|
||||
performance-test: source-only
|
||||
@cd test ; ./test-performance.sh
|
||||
|
||||
|
||||
# hint: make targets are also listed in the top level README.md
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "HELP --- the following make targets exist:"
|
||||
@echo "=========================================="
|
||||
@echo "all: just the main afl++ binaries"
|
||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap"
|
||||
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap"
|
||||
@echo "all: the main afl++ binaries and llvm/gcc instrumentation"
|
||||
@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: nyx_mode, libdislocator, libtokencap"
|
||||
@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 "install: installs everything you have compiled with the build option above"
|
||||
@echo "clean: cleans everything compiled (not downloads when on a checkout)"
|
||||
@echo "deepclean: cleans everything including downloads"
|
||||
@echo "uninstall: uninstall afl++ from the system"
|
||||
@echo "code-format: format the code, do this before you commit and send a PR please!"
|
||||
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
|
||||
@echo "unit: perform unit tests (based on cmocka and GNU linker)"
|
||||
@ -302,71 +368,62 @@ help:
|
||||
@echo "=========================================="
|
||||
@echo STATIC - compile AFL++ static
|
||||
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||
@echo PROFILING - compile afl-fuzz with profiling information
|
||||
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
|
||||
@echo NO_PYTHON - disable python support
|
||||
@echo NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
|
||||
@echo NO_NYX - disable building nyx mode dependencies
|
||||
@echo 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 "=========================================="
|
||||
@echo e.g.: make ASAN_BUILD=1
|
||||
|
||||
.PHONY: test_x86
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_x86:
|
||||
@echo "[*] Checking for the default compiler cc..."
|
||||
@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
|
||||
@echo "[*] Testing the PATH environment variable..."
|
||||
@test "$${PATH}" != "$${PATH#.:}" && { echo "Please remove current directory '.' from PATH to avoid recursion of 'as', thanks!"; echo; exit 1; } || :
|
||||
@echo "[*] Checking for the ability to compile x86 code..."
|
||||
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
|
||||
@echo 'int main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) $(LDFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
|
||||
@rm -f .test1
|
||||
|
||||
else
|
||||
|
||||
test_x86:
|
||||
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: test_shm
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: test_python
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
|
||||
test_python:
|
||||
@rm -f .test 2> /dev/null
|
||||
@echo "[+] $(PYTHON_VERSION) support seems to be working."
|
||||
|
||||
else
|
||||
|
||||
test_python:
|
||||
@echo "[-] You seem to need to install the package python3-dev, python2-dev or python-dev (and perhaps python[23]-apt), but it is optional so we continue"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: ready
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile."
|
||||
|
||||
afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
|
||||
|
||||
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
ln -sf afl-as as
|
||||
@ln -sf afl-as as
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
|
||||
@ -378,23 +435,25 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
|
||||
.PHONY: document
|
||||
document: afl-fuzz-document
|
||||
|
||||
# document all mutations and only do one run (use with only one input file!)
|
||||
document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
|
||||
afl-fuzz-document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
|
||||
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
|
||||
@ -432,126 +491,185 @@ unit_preallocable: test/unittests/unit_preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_preallocable
|
||||
|
||||
.PHONY: unit_clean
|
||||
unit_clean:
|
||||
@rm -f ./test/unittests/unit_preallocable ./test/unittests/unit_list ./test/unittests/unit_maybe_alloc test/unittests/*.o
|
||||
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
|
||||
unit: unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
|
||||
|
||||
.PHONY: unit
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
unit: unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
|
||||
else
|
||||
|
||||
unit:
|
||||
@echo [-] unit tests are skipped on Darwin \(lacks GNU linker feature --wrap\)
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: code-format
|
||||
code-format:
|
||||
./.custom-format.py -i src/*.c
|
||||
./.custom-format.py -i include/*.h
|
||||
./.custom-format.py -i libdislocator/*.c
|
||||
./.custom-format.py -i libtokencap/*.c
|
||||
./.custom-format.py -i llvm_mode/*.c
|
||||
./.custom-format.py -i llvm_mode/*.h
|
||||
./.custom-format.py -i llvm_mode/*.cc
|
||||
./.custom-format.py -i gcc_plugin/*.c
|
||||
#./.custom-format.py -i gcc_plugin/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i custom_mutators/*/*.c
|
||||
./.custom-format.py -i custom_mutators/*/*.h
|
||||
./.custom-format.py -i examples/*/*.c
|
||||
./.custom-format.py -i examples/*/*.h
|
||||
./.custom-format.py -i instrumentation/*.h
|
||||
./.custom-format.py -i instrumentation/*.cc
|
||||
./.custom-format.py -i instrumentation/*.c
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
@#./.custom-format.py -i custom_mutators/*/*.c* # destroys libfuzzer :-(
|
||||
@#./.custom-format.py -i custom_mutators/*/*.h # destroys honggfuzz :-(
|
||||
./.custom-format.py -i utils/*/*.c*
|
||||
./.custom-format.py -i utils/*/*.h
|
||||
./.custom-format.py -i test/*.c
|
||||
./.custom-format.py -i qemu_mode/patches/*.h
|
||||
./.custom-format.py -i frida_mode/src/*.c
|
||||
./.custom-format.py -i frida_mode/include/*.h
|
||||
-./.custom-format.py -i frida_mode/src/*/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.h
|
||||
./.custom-format.py -i qbdi_mode/*.c
|
||||
./.custom-format.py -i qbdi_mode/*.cpp
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
./.custom-format.py -i qemu_mode/libqasan/*.c
|
||||
./.custom-format.py -i qemu_mode/libqasan/*.h
|
||||
|
||||
|
||||
.PHONY: test_build
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
|
||||
test_build: afl-cc afl-gcc afl-as afl-showmap
|
||||
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
|
||||
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo
|
||||
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
|
||||
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
|
||||
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
|
||||
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
# @rm -f test-instr
|
||||
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
|
||||
# gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option." ) || \
|
||||
# ( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
|
||||
# @echo
|
||||
# @echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
|
||||
else
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
test_build: afl-cc afl-as afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all_done
|
||||
all_done: test_build
|
||||
@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
|
||||
@test -e afl-cc && echo "[+] Main compiler 'afl-cc' successfully built!" || { echo "[-] Main compiler 'afl-cc' failed to build, set up a working build environment first!" ; exit 1 ; }
|
||||
@test -e cmplog-instructions-pass.so && echo "[+] LLVM mode for 'afl-cc' successfully built!" || echo "[-] LLVM mode for 'afl-cc' failed to build, likely you either don't have llvm installed, or you need to set LLVM_CONFIG, to point to e.g. llvm-config-11. See instrumentation/README.llvm.md how to do this. Highly recommended!"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
|
||||
@if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
.NOTPARALLEL: clean all
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(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-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-*
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C examples/afl_network_proxy clean
|
||||
$(MAKE) -C examples/socket_fuzzing clean
|
||||
$(MAKE) -C examples/argv_fuzzing clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
rm -rf qemu_mode/qemu-3.1.1
|
||||
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
|
||||
-$(MAKE) -f GNUmakefile.llvm clean
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||
-$(MAKE) -C utils/libdislocator clean
|
||||
-$(MAKE) -C utils/libtokencap clean
|
||||
$(MAKE) -C utils/aflpp_driver clean
|
||||
-$(MAKE) -C utils/afl_network_proxy clean
|
||||
-$(MAKE) -C utils/socket_fuzzing clean
|
||||
-$(MAKE) -C utils/argv_fuzzing clean
|
||||
-$(MAKE) -C utils/plot_ui clean
|
||||
-$(MAKE) -C qemu_mode/unsigaction clean
|
||||
-$(MAKE) -C qemu_mode/libcompcov clean
|
||||
-$(MAKE) -C qemu_mode/libqasan 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"
|
||||
test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl 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 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
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf coresight_mode/coresight_trace
|
||||
rm -rf qemu_mode/qemuafl
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
endif
|
||||
|
||||
.PHONY: deepclean
|
||||
deepclean: clean
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf coresight_mode/coresight-trace
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
git reset --hard >/dev/null 2>&1 || true
|
||||
rm -rf qemu_mode/qemuafl
|
||||
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
git checkout coresight_mode/coresight-trace
|
||||
git checkout unicorn_mode/unicornafl
|
||||
git checkout qemu_mode/qemuafl
|
||||
git checkout nyx_mode/libnyx
|
||||
git checkout nyx_mode/packer
|
||||
git checkout nyx_mode/QEMU-Nyx
|
||||
endif
|
||||
|
||||
.PHONY: distrib
|
||||
distrib: all
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/afl_network_proxy
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
-$(MAKE) -j4 -f GNUmakefile.llvm
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
endif
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
-$(MAKE) -C utils/afl_network_proxy
|
||||
-$(MAKE) -C utils/socket_fuzzing
|
||||
-$(MAKE) -C utils/argv_fuzzing
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
-$(MAKE) -C frida_mode
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
-$(MAKE) -C coresight_mode
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifndef NO_NYX
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
endif
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
endif
|
||||
|
||||
binary-only: all
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/afl_network_proxy
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
.PHONY: binary-only
|
||||
binary-only: test_shm test_python ready $(PROGS)
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
-$(MAKE) -C utils/afl_network_proxy
|
||||
-$(MAKE) -C utils/socket_fuzzing
|
||||
-$(MAKE) -C utils/argv_fuzzing
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
-$(MAKE) -C frida_mode
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
-$(MAKE) -C coresight_mode
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifndef NO_NYX
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
endif
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
endif
|
||||
|
||||
.PHONY: source-only
|
||||
source-only: all
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
#$(MAKE) -C examples/afl_network_proxy
|
||||
#$(MAKE) -C examples/socket_fuzzing
|
||||
#$(MAKE) -C examples/argv_fuzzing
|
||||
-$(MAKE) -j4 -f GNUmakefile.llvm
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
endif
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifndef NO_NYX
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
endif
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@ -572,30 +690,53 @@ source-only: all
|
||||
@echo .SH LICENSE >> $@
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
.PHONY: install
|
||||
install: all $(MANPAGES)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
@rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
|
||||
@for i in afl-llvm-dict2file.so afl-llvm-lto-instrumentlist.so afl-llvm-pass.so cmplog-instructions-pass.so cmplog-routines-pass.so cmplog-switches-pass.so compare-transform-pass.so libcompcov.so libdislocator.so libnyx.so libqasan.so libtokencap.so SanitizerCoverageLTO.so SanitizerCoveragePCGUARD.so split-compares-pass.so split-switches-pass.so; do echo rm -fv $${DESTDIR}$(HELPER_PATH)/$${i}; done
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi
|
||||
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
|
||||
if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
|
||||
if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
|
||||
|
||||
mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
@if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f utils/plot_ui/afl-plot-ui ]; then install -m 755 utils/plot_ui/afl-plot-ui $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libqasan.so ]; then set -e; install -m 755 libqasan.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); 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 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/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
|
||||
-$(MAKE) -f GNUmakefile.llvm install
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin install
|
||||
endif
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang++
|
||||
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
|
||||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
|
||||
|
||||
.PHONY: 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}$(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
|
||||
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
||||
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
||||
-rmdir $${DESTDIR}$(BIN_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(HELPER_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(MISC_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(DOC_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(MAN_PATH) 2>/dev/null
|
||||
|
198
GNUmakefile.gcc_plugin
Normal file
198
GNUmakefile.gcc_plugin
Normal file
@ -0,0 +1,198 @@
|
||||
#
|
||||
# american fuzzy lop++ - GCC plugin instrumentation
|
||||
# -----------------------------------------------
|
||||
#
|
||||
# Written by Austin Seipp <aseipp@pobox.com> and
|
||||
# Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski and
|
||||
# Heiko Eißfeldt <heiko@hexco.de>
|
||||
#
|
||||
# GCC integration design is based on the LLVM design, which comes
|
||||
# from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#TEST_MMAP=1
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
||||
BIN_PATH ?= $(PREFIX)/bin
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MAN_PATH ?= $(PREFIX)/share/man/man8
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
CFLAGS_SAFE := -Wall -Iinclude -Wno-pointer-sign \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
||||
-Wno-unused-function
|
||||
override CFLAGS += $(CFLAGS_SAFE)
|
||||
|
||||
CXXFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
CXXEFLAGS := $(CXXFLAGS) -Wall -std=c++11
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
|
||||
ifeq "clang" "$(CC)"
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
ifeq "clang++" "$(CXX)"
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
ifeq "$(findstring Foundation,$(shell $(CC) --version))" ""
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
PLUGIN_BASE = "$(shell $(CC) -print-file-name=plugin)"
|
||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I$(PLUGIN_BASE)/include -I$(PLUGIN_BASE)
|
||||
HASH=\#
|
||||
|
||||
GCCVER = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
|
||||
GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
override CFLAGS_SAFE += -DUSEMMAP=1
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
override CFLAGS_SAFE += -DUSEMMAP=1
|
||||
endif
|
||||
|
||||
ifneq "$(SYS)" "Haiku"
|
||||
ifneq "$(SYS)" "OpenBSD"
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
else
|
||||
CFLAGS_SAFE += -DUSEMMAP=1
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
CC = egcc
|
||||
CXX = eg++
|
||||
PLUGIN_FLAGS += -I/usr/local/include
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "DragonFly"
|
||||
PLUGIN_FLAGS += -I/usr/local/include
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "SunOS"
|
||||
PLUGIN_FLAGS += -I/usr/include/gmp
|
||||
endif
|
||||
|
||||
|
||||
PROGS = ./afl-gcc-pass.so ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
|
||||
|
||||
.PHONY: all
|
||||
all: test_shm test_deps $(PROGS) test_build all_done
|
||||
|
||||
.PHONY: test_shm
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
else
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
endif
|
||||
|
||||
.PHONY: test_deps
|
||||
test_deps:
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@command -v $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
# @echo "[*] Checking for gcc for plugin support..."
|
||||
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
||||
@echo "[*] Checking for gcc plugin development header files..."
|
||||
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
||||
@echo "[*] Checking for './afl-showmap'..."
|
||||
@test -f ./afl-showmap || ( echo "[-] Oops, can't find './afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
afl-common.o: ./src/afl-common.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||
|
||||
./afl-compiler-rt.o: instrumentation/afl-compiler-rt.o.c
|
||||
$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
|
||||
|
||||
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
|
||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
|
||||
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
|
||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
||||
@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
|
||||
./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
|
||||
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
|
||||
ln -sf afl-cc afl-gcc-fast
|
||||
ln -sf afl-cc afl-g++-fast
|
||||
ln -sf afl-cc.8 afl-gcc-fast.8
|
||||
ln -sf afl-cc.8 afl-g++-fast.8
|
||||
|
||||
.PHONY: test_build
|
||||
test_build: $(PROGS)
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
.PHONY: all_done
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use './afl-gcc-fast' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ./$@
|
||||
@echo .SH NAME >> ./$@
|
||||
@echo .B $* >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH SYNOPSIS >> ./$@
|
||||
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH OPTIONS >> ./$@
|
||||
@echo .nf >> ./$@
|
||||
@./$* -h 2>&1 | tail -n +4 >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH AUTHOR >> ./$@
|
||||
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
|
||||
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH LICENSE >> ./$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ./$@
|
||||
ln -sf afl-cc.8 ./afl-g++-fast.8
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc-fast
|
||||
ln -sf afl-c++ $${DESTDIR}$(BIN_PATH)/afl-g++-fast
|
||||
ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
|
||||
install -m 755 ./afl-gcc-pass.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 -T instrumentation/README.gcc_plugin.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||
rm -f $(PROGS) afl-common.o ./afl-g++-fast ./afl-g*-fast.8 instrumentation/*.o
|
529
GNUmakefile.llvm
Normal file
529
GNUmakefile.llvm
Normal file
@ -0,0 +1,529 @@
|
||||
# american fuzzy lop++ - LLVM instrumentation
|
||||
# -----------------------------------------
|
||||
#
|
||||
# Written by Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski
|
||||
#
|
||||
# LLVM integration design comes from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
#TEST_MMAP=1
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
||||
BIN_PATH ?= $(PREFIX)/bin
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MISC_PATH ?= $(PREFIX)/share/afl
|
||||
MAN_PATH ?= $(PREFIX)/share/man/man8
|
||||
|
||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
ifeq "$(HAS_OPT)" "1"
|
||||
$(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
||||
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 )
|
||||
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[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_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_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
|
||||
LLVM_LTO = 0
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_UNSUPPORTED)" "1"
|
||||
$(error llvm_mode only supports llvm from version 3.8 onwards)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_TOO_NEW)" "1"
|
||||
$(warning you are using an in-development llvm version - this might break llvm_mode!)
|
||||
endif
|
||||
|
||||
LLVM_TOO_OLD=1
|
||||
|
||||
ifeq "$(LLVM_MAJOR)" "9"
|
||||
$(info [+] llvm_mode detected llvm 9, enabling neverZero implementation)
|
||||
LLVM_TOO_OLD=0
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_NEW_API)" "1"
|
||||
$(info [+] llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
|
||||
LLVM_STDCXX = c++14
|
||||
LLVM_TOO_OLD=0
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_TOO_OLD)" "1"
|
||||
$(info [!] llvm_mode detected an old version of llvm, upgrade to at least 9 or preferable 11!)
|
||||
$(shell sleep 1)
|
||||
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"
|
||||
$(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation)
|
||||
LLVM_LTO = 1
|
||||
#TEST_MMAP = 1
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_LTO)" "0"
|
||||
$(info [+] llvm_mode detected llvm < 11 or llvm 15, afl-lto LTO will not be build.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# We were using llvm-config --bindir to get the location of clang, but
|
||||
# this seems to be busted on some distros, so using the one in $PATH is
|
||||
# probably better.
|
||||
|
||||
CC = $(LLVM_BINDIR)/clang
|
||||
CXX = $(LLVM_BINDIR)/clang++
|
||||
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
# however we must ensure that this is not a "CC=gcc make"
|
||||
ifeq "$(shell command -v $(CC) 2> /dev/null)" ""
|
||||
# we do not have a valid CC variable so we try alternatives
|
||||
ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1"
|
||||
# we found one in the local install directory, lets use these
|
||||
CC = $(BIN_DIR)/clang
|
||||
else
|
||||
# hope for the best
|
||||
$(warning we have trouble finding clang - llvm-config is not helping us)
|
||||
CC = clang
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e $(CXX) || echo 1 )" "1"
|
||||
# however we must ensure that this is not a "CXX=g++ make"
|
||||
ifeq "$(shell command -v $(CXX) 2> /dev/null)" ""
|
||||
# we do not have a valid CXX variable so we try alternatives
|
||||
ifeq "$(shell test -e '$(BIN_DIR)/clang++' && echo 1)" "1"
|
||||
# we found one in the local install directory, lets use these
|
||||
CXX = $(BIN_DIR)/clang++
|
||||
else
|
||||
# hope for the best
|
||||
$(warning we have trouble finding clang++ - llvm-config is not helping us)
|
||||
CXX = clang++
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# sanity check.
|
||||
# Are versions of clang --version and llvm-config --version equal?
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
# I disable this because it does not make sense with what we did before (marc)
|
||||
# We did exactly set these 26 lines above with these values, and it would break
|
||||
# "CC=gcc make" etc. usages
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
CC_SAVE := $(LLVM_BINDIR)/clang
|
||||
else
|
||||
CC_SAVE := $(CC)
|
||||
endif
|
||||
ifeq "$(findstring clang, $(shell $(CXX) --version 2>/dev/null))" ""
|
||||
CXX_SAVE := $(LLVM_BINDIR)/clang++
|
||||
else
|
||||
CXX_SAVE := $(CXX)
|
||||
endif
|
||||
|
||||
CLANG_BIN := $(CC_SAVE)
|
||||
CLANGPP_BIN := $(CXX_SAVE)
|
||||
|
||||
ifeq "$(CC_SAVE)" "$(LLVM_BINDIR)/clang"
|
||||
USE_BINDIR = 1
|
||||
else
|
||||
ifeq "$(CXX_SAVE)" "$(LLVM_BINDIR)/clang++"
|
||||
USE_BINDIR = 1
|
||||
else
|
||||
USE_BINDIR = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
# On old platform we cannot compile with clang because std++ libraries are too
|
||||
# old. For these we need to use gcc/g++, so if we find REAL_CC and REAL_CXX
|
||||
# variable we override the compiler variables here
|
||||
ifneq "$(REAL_CC)" ""
|
||||
CC = $(REAL_CC)
|
||||
endif
|
||||
ifneq "$(REAL_CXX)" ""
|
||||
CXX = $(REAL_CXX)
|
||||
endif
|
||||
|
||||
#
|
||||
# Now it can happen that CC points to clang - but there is no clang on the
|
||||
# system. Then we fall back to cc
|
||||
#
|
||||
ifeq "$(shell command -v $(CC) 2>/dev/null)" ""
|
||||
CC = cc
|
||||
endif
|
||||
ifeq "$(shell command -v $(CXX) 2>/dev/null)" ""
|
||||
CXX = c++
|
||||
endif
|
||||
|
||||
|
||||
# After we set CC/CXX we can start makefile magic tests
|
||||
|
||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
# CFLAGS_OPT = -march=native
|
||||
#endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=full
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=thin
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" ""
|
||||
AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld
|
||||
else
|
||||
$(warning ld.lld not found, cannot enable LTO mode)
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
endif
|
||||
else
|
||||
$(warning clang option -flto is not working - maybe LLVMgold.so not found - cannot enable LTO mode)
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
AFL_CLANG_FUSELD=
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FUSELD=1
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(LLVM_BINDIR)/ld.lld -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_LDPATH=1
|
||||
endif
|
||||
else
|
||||
$(warning -fuse-ld is not working, cannot enable LTO mode)
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fdebug-prefix-map=$(CURDIR)=llvm_mode -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_DEBUG_PREFIX = -fdebug-prefix-map="$(CURDIR)=llvm_mode"
|
||||
else
|
||||
AFL_CLANG_DEBUG_PREFIX =
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
||||
CFLAGS_SAFE := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sign -I ./include/ -I ./instrumentation/ \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
|
||||
-DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \
|
||||
-Wno-deprecated -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
|
||||
-DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
|
||||
-DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \
|
||||
-DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
|
||||
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function \
|
||||
$(AFL_CLANG_DEBUG_PREFIX)
|
||||
override CFLAGS += $(CFLAGS_SAFE)
|
||||
|
||||
ifdef AFL_TRACE_PC
|
||||
$(info Compile option AFL_TRACE_PC is deprecated, just set AFL_LLVM_INSTRUMENT=PCGUARD to activate when compiling targets )
|
||||
endif
|
||||
|
||||
CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
|
||||
override CXXFLAGS += -Wall -g -I ./include/ \
|
||||
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros \
|
||||
-DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR)
|
||||
|
||||
ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" ""
|
||||
CLANG_CFL = -I$(shell $(LLVM_CONFIG) --includedir)
|
||||
endif
|
||||
ifneq "$(LLVM_CONFIG)" ""
|
||||
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
|
||||
endif
|
||||
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations
|
||||
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
|
||||
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(SYS)" "Darwin"
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
override LLVM_HAVE_LTO := 0
|
||||
override LLVM_LTO := 0
|
||||
else
|
||||
CLANG_CPPFL += -Wl,-znodelete
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
|
||||
CLANG_CPPFL += -mno-retpoline
|
||||
CFLAGS += -mno-retpoline
|
||||
# Needed for unwind symbols
|
||||
LDFLAGS += -lc++abi -lpthread
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS_SAFE += -DUSEMMAP=1
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS_SAFE += -DUSEMMAP=1
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
|
||||
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so
|
||||
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
ifeq "$(LLVMVER)" ""
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE_XCODE)" "00"
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifeq "$(NO_BUILD)" "1"
|
||||
TARGETS = test_shm $(PROGS_ALWAYS) afl-cc.8
|
||||
else
|
||||
TARGETS = test_shm test_deps $(PROGS) afl-cc.8 test_build all_done
|
||||
endif
|
||||
|
||||
LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?)
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGETS)
|
||||
|
||||
.PHONY: test_shm
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
else
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
endif
|
||||
|
||||
.PHONY: no_build
|
||||
no_build:
|
||||
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
||||
|
||||
.PHONY: test_deps
|
||||
test_deps:
|
||||
@echo "[*] Checking for working 'llvm-config'..."
|
||||
ifneq "$(LLVM_APPLE_XCODE)" "1"
|
||||
@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-11 or something like that.)"; exit 1 )
|
||||
endif
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
@echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'"
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
@echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)"
|
||||
else
|
||||
@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
|
||||
endif
|
||||
@echo "[*] Checking for './afl-showmap'..."
|
||||
@test -f ./afl-showmap || ( echo "[-] Oops, can't find './afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
instrumentation/afl-common.o: ./src/afl-common.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||
|
||||
./afl-cc: src/afl-cc.c instrumentation/afl-common.o
|
||||
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< instrumentation/afl-common.o -o $@ -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR) $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" -lm
|
||||
@ln -sf afl-cc ./afl-c++
|
||||
@ln -sf afl-cc ./afl-gcc
|
||||
@ln -sf afl-cc ./afl-g++
|
||||
@ln -sf afl-cc ./afl-clang
|
||||
@ln -sf afl-cc ./afl-clang++
|
||||
@ln -sf afl-cc ./afl-clang-fast
|
||||
@ln -sf afl-cc ./afl-clang-fast++
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
@ln -sf afl-cc ./afl-clang-lto
|
||||
@ln -sf afl-cc ./afl-clang-lto++
|
||||
@ln -sf afl-cc ./afl-lto
|
||||
@ln -sf afl-cc ./afl-lto++
|
||||
endif
|
||||
endif
|
||||
|
||||
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
|
||||
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||
|
||||
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
||||
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
|
||||
endif
|
||||
$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
|
||||
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
ifeq "$(LLVM_10_OK)" "1"
|
||||
-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
|
||||
endif
|
||||
|
||||
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
endif
|
||||
|
||||
./afl-ld-lto: src/afl-ld-lto.c
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
endif
|
||||
|
||||
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
|
||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||
endif
|
||||
|
||||
# laf
|
||||
./split-switches-pass.so: instrumentation/split-switches-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
./compare-transform-pass.so: instrumentation/compare-transform-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
./split-compares-pass.so: instrumentation/split-compares-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
# /laf
|
||||
|
||||
./cmplog-routines-pass.so: instrumentation/cmplog-routines-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
|
||||
./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
|
||||
./cmplog-switches-pass.so: instrumentation/cmplog-switches-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
|
||||
afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
|
||||
.PHONY: document
|
||||
document:
|
||||
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt.o
|
||||
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
|
||||
./afl-compiler-rt.o: instrumentation/afl-compiler-rt.o.c
|
||||
$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
|
||||
|
||||
./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
|
||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
|
||||
./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
|
||||
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
|
||||
@$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
|
||||
|
||||
.PHONY: test_build
|
||||
test_build: $(PROGS)
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
.PHONY: all_done
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use './afl-cc' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
.PHONY: install
|
||||
install: all
|
||||
@install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
@if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi
|
||||
@rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o
|
||||
@if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
|
||||
@if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi
|
||||
@if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi
|
||||
set -e; install -m 644 ./dynamic_list.txt $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 instrumentation/README.*.md $${DESTDIR}$(DOC_PATH)/
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > ./$@
|
||||
@echo .SH NAME >> ./$@
|
||||
@printf "%s" ".B $* \- " >> ./$@
|
||||
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ./$@
|
||||
@echo .B $* >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH SYNOPSIS >> ./$@
|
||||
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH OPTIONS >> ./$@
|
||||
@echo .nf >> ./$@
|
||||
@./$* -h 2>&1 | tail -n +4 >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH AUTHOR >> ./$@
|
||||
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
|
||||
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
|
||||
@echo >> ./$@
|
||||
@echo .SH LICENSE >> ./$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ./$@
|
||||
@ln -sf afl-cc.8 ./afl-c++.8
|
||||
@ln -sf afl-cc.8 ./afl-clang-fast.8
|
||||
@ln -sf afl-cc.8 ./afl-clang-fast++.8
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
@ln -sf afl-cc.8 ./afl-clang-lto.8
|
||||
@ln -sf afl-cc.8 ./afl-clang-lto++.8
|
||||
@ln -sf afl-cc.8 ./afl-lto.8
|
||||
@ln -sf afl-cc.8 ./afl-lto++.8
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
||||
rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-compiler-rt*.o ./afl-llvm-rt*.o instrumentation/*.o
|
@ -1 +0,0 @@
|
||||
docs/QuickStartGuide.md
|
935
README.md
935
README.md
@ -1,763 +1,258 @@
|
||||
# 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: [4.01c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
Release Version: [2.66c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
GitHub version: 4.02a
|
||||
|
||||
Github Version: 2.66d
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
||||
includes all necessary/interesting changes from Google's afl 2.56b
|
||||
AFL++ is maintained by:
|
||||
|
||||
Originally developed by Michal "lcamtuf" Zalewski.
|
||||
* Marc "van Hauser" Heuse <mh@mh-sec.de>
|
||||
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
|
||||
* Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
* Dominik Maier <mail@dmnk.co>
|
||||
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
|
||||
|
||||
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
Originally developed by Michał "lcamtuf" Zalewski.
|
||||
|
||||
afl++ is maintained by:
|
||||
* Marc "van Hauser" Heuse <mh@mh-sec.de>,
|
||||
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
* Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
* Dominik Maier <mail@dmnk.co>.
|
||||
AFL++ is a superior fork to Google's AFL - more speed, more and better
|
||||
mutations, more and better instrumentation, custom module support, etc.
|
||||
|
||||
Note that although afl now has a Google afl repository [https://github.com/Google/afl](https://github.com/Google/afl),
|
||||
it is unlikely to receive any notable enhancements: [https://twitter.com/Dor3s/status/1154737061787660288](https://twitter.com/Dor3s/status/1154737061787660288)
|
||||
You are free to copy, modify, and distribute AFL++ with attribution under the
|
||||
terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
|
||||
|
||||
## The enhancements compared to the original stock afl
|
||||
## Getting started
|
||||
|
||||
Many improvements were made over the official afl release - which did not
|
||||
get any feature improvements since November 2017.
|
||||
Here is some information to get you started:
|
||||
|
||||
Among other changes afl++ has a more performant llvm_mode, supports
|
||||
llvm up to version 11, QEMU 3.1, more speed and crashfixes for QEMU,
|
||||
better *BSD and Android support and much, much more.
|
||||
* 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
|
||||
[Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and
|
||||
[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
|
||||
[features](docs/features.md).
|
||||
* If you want to use AFL++ for your academic work, check the
|
||||
[papers page](https://aflplus.plus/papers/) on the website.
|
||||
* To cite our work, look at the [Cite](#cite) section.
|
||||
* For comparisons, use the fuzzbench `aflplusplus` setup, or use
|
||||
`afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
|
||||
default configuration on Google's
|
||||
[fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
||||
|
||||
Additionally the following features and patches have been integrated:
|
||||
## Building and installing AFL++
|
||||
|
||||
* AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||
To have AFL++ easily available with everything compiled, pull the image directly
|
||||
from the Docker Hub (available for both x86_64 and arm64):
|
||||
|
||||
* The new excellent MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
|
||||
|
||||
* InsTrim, a very effective CFG llvm_mode instrumentation implementation for large targets: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim)
|
||||
|
||||
* C. Holler's afl-fuzz Python mutator module and llvm_mode instrument file support: [https://github.com/choller/afl](https://github.com/choller/afl)
|
||||
|
||||
* Custom mutator by a library (instead of Python) by kyakdan
|
||||
|
||||
* Unicorn mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
|
||||
|
||||
* LAF-Intel or CompCov support for llvm_mode, qemu_mode and unicorn_mode
|
||||
|
||||
* NeverZero patch for afl-gcc, llvm_mode, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
|
||||
|
||||
* Persistent mode and deferred forkserver for qemu_mode
|
||||
|
||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||
|
||||
* Radamsa mutator (as a custom mutator).
|
||||
|
||||
* QBDI mode to fuzz android native libraries via QBDI framework
|
||||
|
||||
* 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)
|
||||
|
||||
* LLVM mode Ngram coverage by Adrian Herrera [https://github.com/adrianherrera/afl-ngram-pass](https://github.com/adrianherrera/afl-ngram-pass)
|
||||
|
||||
A more thorough list is available in the [PATCHES](docs/PATCHES.md) file.
|
||||
|
||||
| Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode |
|
||||
| ----------------------- |:-------:|:---------:|:----------:|:----------------:|:------------:|
|
||||
| NeverZero | x | x(1) | (2) | x | x |
|
||||
| Persistent mode | | x | x | x86[_64]/arm[64] | x |
|
||||
| LAF-Intel / CompCov | | x | | x86[_64]/arm[64] | x86[_64]/arm |
|
||||
| CmpLog | | x | | x86[_64]/arm[64] | |
|
||||
| Instrument file list | | x | x | (x)(3) | |
|
||||
| Non-colliding coverage | | x(4) | | (x)(5) | |
|
||||
| InsTrim | | x | | | |
|
||||
| Ngram prev_loc coverage | | x(6) | | | |
|
||||
| Context coverage | | x | | | |
|
||||
| Snapshot LKM support | | x | | (x)(5) | |
|
||||
|
||||
neverZero:
|
||||
|
||||
(1) default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
|
||||
|
||||
(2) GCC creates non-performant code, hence it is disabled in gcc_plugin
|
||||
|
||||
(3) partially via AFL_CODE_START/AFL_CODE_END
|
||||
|
||||
(4) Only for LLVM >= 11 and not all targets compile
|
||||
|
||||
(5) upcoming, development in the branch
|
||||
|
||||
(6) not compatible with LTO instrumentation and needs at least LLVM >= 4.1
|
||||
|
||||
So all in all this is the best-of afl that is currently out there :-)
|
||||
|
||||
For new versions and additional information, check out:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
||||
To compare notes with other users or get notified about major new features,
|
||||
send a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
|
||||
See [docs/QuickStartGuide.md](docs/QuickStartGuide.md) if you don't have time to
|
||||
read this file.
|
||||
|
||||
## Branches
|
||||
|
||||
The following branches exist:
|
||||
|
||||
* [master/trunk](https://github.com/AFLplusplus/AFLplusplus/) : stable state of afl++ - it is synced from dev from time to
|
||||
time when we are satisfied with it's stability
|
||||
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of afl++ - bleeding edge and you might catch a
|
||||
checkout which does not compile or has a bug. *We only accept PRs in dev!!*
|
||||
* (any other) : experimental branches to work on specific features or testing
|
||||
new functionality or changes.
|
||||
|
||||
For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab.
|
||||
|
||||
## Google Summer of Code 2020 (and any other students and enthusiast developers)
|
||||
|
||||
We are happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)! :-)
|
||||
|
||||
We have several ideas we would like to see in AFL++ to make it even better.
|
||||
However, we already work on so many things that we do not have the time for
|
||||
all the big ideas.
|
||||
|
||||
This can be your way to support and contribute to AFL++ - extend it to
|
||||
something cool.
|
||||
|
||||
We have an idea list in [docs/ideas.md](docs/ideas.md).
|
||||
|
||||
For everyone who wants to contribute (and send pull requests) please read
|
||||
[CONTRIBUTING.md](CONTRIBUTING.md) before your submit.
|
||||
|
||||
## Building and installing afl++
|
||||
|
||||
An easy way to install afl++ with everything compiled is available via docker:
|
||||
You can use the [Dockerfile](Dockerfile) (which has gcc-10 and clang-11 -
|
||||
hence afl-clang-lto is available!) or just pull directly from the docker hub:
|
||||
```shell
|
||||
docker pull aflplusplus/aflplusplus
|
||||
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
|
||||
```
|
||||
This container is automatically generated when a push to master happens.
|
||||
You will find your target source code in /src in the container.
|
||||
|
||||
If you want to build afl++ yourself you have many options.
|
||||
The easiest is to build and install everything:
|
||||
This image is automatically published when a push to the stable branch happens
|
||||
(see [branches](#branches)). If you use the command above, you will find your
|
||||
target source code in `/src` in the container.
|
||||
|
||||
```shell
|
||||
sudo apt install build-essential libtool-bin python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools llvm
|
||||
make distrib
|
||||
sudo make install
|
||||
```
|
||||
It is recommended to install the newest available gcc and clang and llvm-dev
|
||||
possible in your distribution!
|
||||
Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current
|
||||
development state of AFL++.
|
||||
|
||||
Note that "make distrib" also builds llvm_mode, qemu_mode, unicorn_mode and
|
||||
more. If you just want plain afl then do "make all", however compiling and
|
||||
using at least llvm_mode is highly recommended for much better results -
|
||||
hence in this case
|
||||
To build AFL++ yourself - *which we recommend* - continue at
|
||||
[docs/INSTALL.md](docs/INSTALL.md).
|
||||
|
||||
```shell
|
||||
make source-only
|
||||
```
|
||||
is what you should choose.
|
||||
## Quick start: Fuzzing with AFL++
|
||||
|
||||
These build targets exist:
|
||||
*NOTE: Before you start, please read about the
|
||||
[common sense risks of fuzzing](docs/fuzzing_in_depth.md#0-common-sense-risks).*
|
||||
|
||||
* all: just the main afl++ binaries
|
||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap
|
||||
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap
|
||||
* distrib: everything (for both binary-only and source code fuzzing)
|
||||
* man: creates simple man pages from the help option of the programs
|
||||
* install: installs everything you have compiled with the build options above
|
||||
* clean: cleans everything compiled, not downloads (unless not on a checkout)
|
||||
* deepclean: cleans everything including downloads
|
||||
* code-format: format the code, do this before you commit and send a PR please!
|
||||
* tests: runs test cases to ensure that all features are still working as they should
|
||||
* unit: perform unit tests (based on cmocka)
|
||||
* help: shows these build options
|
||||
This is a quick start for fuzzing targets with the source code available. To
|
||||
read about the process in detail, see
|
||||
[docs/fuzzing_in_depth.md](docs/fuzzing_in_depth.md).
|
||||
|
||||
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the
|
||||
afl++ binaries by passing the STATIC=1 argument to make:
|
||||
To learn about fuzzing other targets, see:
|
||||
* Binary-only targets:
|
||||
[docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md)
|
||||
* Network services:
|
||||
[docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service)
|
||||
* GUI programs:
|
||||
[docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program)
|
||||
|
||||
```shell
|
||||
make all STATIC=1
|
||||
```
|
||||
Step-by-step quick start:
|
||||
|
||||
These build options exist:
|
||||
1. Compile the program or library to be fuzzed using `afl-cc`. A common way to
|
||||
do this would be:
|
||||
|
||||
* STATIC - compile AFL++ static
|
||||
* ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||
* PROFILING - compile with profiling information (gprof)
|
||||
* NO_PYTHON - disable python support
|
||||
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g. Debian)
|
||||
```
|
||||
CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared
|
||||
make clean all
|
||||
```
|
||||
|
||||
e.g.: make ASAN_BUILD=1
|
||||
2. Get a small but valid input file that makes sense to the program. When
|
||||
fuzzing verbose syntax (SQL, HTTP, etc.), create a dictionary as described in
|
||||
[dictionaries/README.md](dictionaries/README.md), too.
|
||||
|
||||
## Challenges of guided fuzzing
|
||||
3. If the program reads from stdin, run `afl-fuzz` like so:
|
||||
|
||||
Fuzzing is one of the most powerful and proven strategies for identifying
|
||||
security issues in real-world software; it is responsible for the vast
|
||||
majority of remote code execution and privilege escalation bugs found to date
|
||||
in security-critical software.
|
||||
```
|
||||
./afl-fuzz -i seeds_dir -o output_dir -- \
|
||||
/path/to/tested/program [...program's cmdline...]
|
||||
```
|
||||
|
||||
Unfortunately, fuzzing is also relatively shallow; blind, random mutations
|
||||
make it very unlikely to reach certain code paths in the tested code, leaving
|
||||
some vulnerabilities firmly outside the reach of this technique.
|
||||
To add a dictionary, add `-x /path/to/dictionary.txt` to afl-fuzz.
|
||||
|
||||
There have been numerous attempts to solve this problem. One of the early
|
||||
approaches - pioneered by Tavis Ormandy - is corpus distillation. The method
|
||||
relies on coverage signals to select a subset of interesting seeds from a
|
||||
massive, high-quality corpus of candidate files, and then fuzz them by
|
||||
traditional means. The approach works exceptionally well but requires such
|
||||
a corpus to be readily available. In addition, block coverage measurements
|
||||
provide only a very simplistic understanding of the program state and are less
|
||||
useful for guiding the fuzzing effort in the long haul.
|
||||
If the program takes input from a file, you can put `@@` in the program's
|
||||
command line; AFL++ will put an auto-generated file name in there for you.
|
||||
|
||||
Other, more sophisticated research has focused on techniques such as program
|
||||
flow analysis ("concolic execution"), symbolic execution, or static analysis.
|
||||
All these methods are extremely promising in experimental settings, but tend
|
||||
to suffer from reliability and performance problems in practical uses - and
|
||||
currently do not offer a viable alternative to "dumb" fuzzing techniques.
|
||||
4. Investigate anything shown in red in the fuzzer UI by promptly consulting
|
||||
[docs/afl-fuzz_approach.md#understanding-the-status-screen](docs/afl-fuzz_approach.md#understanding-the-status-screen).
|
||||
|
||||
5. You will find found crashes and hangs in the subdirectories `crashes/` and
|
||||
`hangs/` in the `-o output_dir` directory. You can replay the crashes by
|
||||
feeding them to the target, e.g. if your target is using stdin:
|
||||
|
||||
## The afl-fuzz approach
|
||||
```
|
||||
cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]
|
||||
```
|
||||
|
||||
American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple
|
||||
but rock-solid instrumentation-guided genetic algorithm. It uses a modified
|
||||
form of edge coverage to effortlessly pick up subtle, local-scale changes to
|
||||
program control flow.
|
||||
You can generate cores or use gdb directly to follow up the crashes.
|
||||
|
||||
Simplifying a bit, the overall algorithm can be summed up as:
|
||||
|
||||
1) Load user-supplied initial test cases into the queue,
|
||||
|
||||
2) Take the next input file from the queue,
|
||||
|
||||
3) Attempt to trim the test case to the smallest size that doesn't alter
|
||||
the measured behavior of the program,
|
||||
|
||||
4) Repeatedly mutate the file using a balanced and well-researched variety
|
||||
of traditional fuzzing strategies,
|
||||
|
||||
5) If any of the generated mutations resulted in a new state transition
|
||||
recorded by the instrumentation, add mutated output as a new entry in the
|
||||
queue.
|
||||
|
||||
6) Go to 2.
|
||||
|
||||
The discovered test cases are also periodically culled to eliminate ones that
|
||||
have been obsoleted by newer, higher-coverage finds; and undergo several other
|
||||
instrumentation-driven effort minimization steps.
|
||||
|
||||
As a side result of the fuzzing process, the tool creates a small,
|
||||
self-contained corpus of interesting test cases. These are extremely useful
|
||||
for seeding other, labor- or resource-intensive testing regimes - for example,
|
||||
for stress-testing browsers, office applications, graphics suites, or
|
||||
closed-source tools.
|
||||
|
||||
The fuzzer is thoroughly tested to deliver out-of-the-box performance far
|
||||
superior to blind fuzzing or coverage-only tools.
|
||||
|
||||
|
||||
## Instrumenting programs for use with AFL
|
||||
|
||||
PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++
|
||||
instead of afl-gcc/afl-g++ is much faster and has many cool features.
|
||||
See llvm_mode/ - however few code does not compile with llvm.
|
||||
We support llvm versions 3.4 to 11.
|
||||
|
||||
When source code is available, instrumentation can be injected by a companion
|
||||
tool that works as a drop-in replacement for gcc or clang in any standard build
|
||||
process for third-party code.
|
||||
|
||||
The instrumentation has a fairly modest performance impact; in conjunction with
|
||||
other optimizations implemented by afl-fuzz, most programs can be fuzzed as fast
|
||||
or even faster than possible with traditional tools.
|
||||
|
||||
The correct way to recompile the target program may vary depending on the
|
||||
specifics of the build process, but a nearly-universal approach would be:
|
||||
|
||||
```shell
|
||||
CC=/path/to/afl/afl-gcc ./configure
|
||||
make clean all
|
||||
```
|
||||
|
||||
For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`.
|
||||
|
||||
The clang wrappers (afl-clang and afl-clang++) can be used in the same way;
|
||||
clang users may also opt to leverage a higher-performance instrumentation mode,
|
||||
as described in [llvm_mode/README.md](llvm_mode/README.md).
|
||||
Clang/LLVM has a much better performance and works with LLVM version 3.4 to 11.
|
||||
|
||||
Using the LAF Intel performance enhancements are also recommended, see
|
||||
[llvm_mode/README.laf-intel.md](llvm_mode/README.laf-intel.md)
|
||||
|
||||
Using partial instrumentation is also recommended, see
|
||||
[llvm_mode/README.instrument_file.md](llvm_mode/README.instrument_file.md)
|
||||
|
||||
When testing libraries, you need to find or write a simple program that reads
|
||||
data from stdin or from a file and passes it to the tested library. In such a
|
||||
case, it is essential to link this executable against a static version of the
|
||||
instrumented library or to make sure that the correct .so file is loaded at
|
||||
runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static
|
||||
build, usually possible via:
|
||||
|
||||
```shell
|
||||
CC=/path/to/afl/afl-gcc ./configure --disable-shared
|
||||
```
|
||||
|
||||
Setting `AFL_HARDEN=1` when calling 'make' will cause the CC wrapper to
|
||||
automatically enable code hardening options that make it easier to detect
|
||||
simple memory bugs. Libdislocator, a helper library included with AFL (see
|
||||
[libdislocator/README.md](libdislocator/README.md)) can help uncover heap corruption issues, too.
|
||||
|
||||
PS. ASAN users are advised to review [docs/notes_for_asan.md](docs/notes_for_asan.md)
|
||||
file for important caveats.
|
||||
|
||||
|
||||
## Instrumenting binary-only apps
|
||||
|
||||
When source code is *NOT* available, the fuzzer offers experimental support for
|
||||
fast, on-the-fly instrumentation of black-box binaries. This is accomplished
|
||||
with a version of QEMU running in the lesser-known "user space emulation" mode.
|
||||
|
||||
QEMU is a project separate from AFL, but you can conveniently build the
|
||||
feature by doing:
|
||||
|
||||
```shell
|
||||
cd qemu_mode
|
||||
./build_qemu_support.sh
|
||||
```
|
||||
|
||||
For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md).
|
||||
|
||||
If possible you should use the persistent mode, see [qemu_mode/README.persistent.md](qemu_mode/README.persistent.md).
|
||||
|
||||
The mode is approximately 2-5x slower than compile-time instrumentation, is
|
||||
less conducive to parallelization, and may have some other quirks.
|
||||
|
||||
If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for
|
||||
your binary, then you can use afl-fuzz normally and it will have twice
|
||||
the speed compared to qemu_mode.
|
||||
|
||||
A more comprehensive description of these and other options can be found in
|
||||
[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md)
|
||||
|
||||
## Good examples and writeups
|
||||
|
||||
Here are some good writeups to show how to effectively use AFL++:
|
||||
|
||||
* [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
|
||||
* [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/)
|
||||
* [https://securitylab.github.com/research/fuzzing-challenges-solutions-1](https://securitylab.github.com/research/fuzzing-challenges-solutions-1)
|
||||
* [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
|
||||
|
||||
If you are interested in fuzzing structured data (where you define what the
|
||||
structure is), these two links have you covered:
|
||||
* [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/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
|
||||
|
||||
If you find other good ones, please send them to us :-)
|
||||
|
||||
## Power schedules
|
||||
|
||||
The power schedules were copied from Marcel Böhme's excellent AFLfast
|
||||
implementation and expand on the ability to discover new paths and
|
||||
therefore may increase the code coverage.
|
||||
|
||||
The available schedules are:
|
||||
|
||||
- explore (default, original AFL)
|
||||
- exploit (original AFL)
|
||||
- fast (AFLfast)
|
||||
- coe (AFLfast)
|
||||
- quad (AFLfast)
|
||||
- lin (AFLfast)
|
||||
- rare (afl++ experimental)
|
||||
- mmopt (afl++ experimental)
|
||||
- seek (afl++ experimental)
|
||||
|
||||
In parallel mode (-M/-S, several instances with the shared queue), we suggest to
|
||||
run the main node using the explore or fast schedule (-p explore) and the secondary
|
||||
nodes with a combination of cut-off-exponential (-p coe), exponential (-p fast),
|
||||
explore (-p explore) and mmopt (-p mmopt) schedules. If a schedule does
|
||||
not perform well for a target, restart the secondary nodes with a different schedule.
|
||||
|
||||
In single mode, using -p fast is usually slightly more beneficial than the
|
||||
default explore mode.
|
||||
(We don't want to change the default behavior of afl, so "fast" has not been
|
||||
made the default mode).
|
||||
|
||||
More details can be found in the paper published at the 23rd ACM Conference on
|
||||
Computer and Communications Security [CCS'16](https://www.sigsac.org/ccs/CCS2016/accepted-papers/)
|
||||
|
||||
## Choosing initial test cases
|
||||
|
||||
To operate correctly, the fuzzer requires one or more starting file that
|
||||
contains a good example of the input data normally expected by the targeted
|
||||
application. There are two basic rules:
|
||||
|
||||
- Keep the files small. Under 1 kB is ideal, although not strictly necessary.
|
||||
For a discussion of why size matters, see [perf_tips.md](docs/perf_tips.md).
|
||||
|
||||
- Use multiple test cases only if they are functionally different from
|
||||
each other. There is no point in using fifty different vacation photos
|
||||
to fuzz an image library.
|
||||
|
||||
You can find many good examples of starting files in the testcases/ subdirectory
|
||||
that comes with this tool.
|
||||
|
||||
PS. If a large corpus of data is available for screening, you may want to use
|
||||
the afl-cmin utility to identify a subset of functionally distinct files that
|
||||
exercise different code paths in the target binary.
|
||||
|
||||
|
||||
## Fuzzing binaries
|
||||
|
||||
The fuzzing process itself is carried out by the afl-fuzz utility. This program
|
||||
requires a read-only directory with initial test cases, a separate place to
|
||||
store its findings, plus a path to the binary to test.
|
||||
|
||||
For target binaries that accept input directly from stdin, the usual syntax is:
|
||||
|
||||
```shell
|
||||
./afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...]
|
||||
```
|
||||
|
||||
For programs that take input from a file, use '@@' to mark the location in
|
||||
the target's command line where the input file name should be placed. The
|
||||
fuzzer will substitute this for you:
|
||||
|
||||
```shell
|
||||
./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@
|
||||
```
|
||||
|
||||
You can also use the -f option to have the mutated data written to a specific
|
||||
file. This is useful if the program expects a particular file extension or so.
|
||||
|
||||
Non-instrumented binaries can be fuzzed in the QEMU mode (add -Q in the command
|
||||
line) or in a traditional, blind-fuzzer mode (specify -n).
|
||||
|
||||
You can use -t and -m to override the default timeout and memory limit for the
|
||||
executed process; rare examples of targets that may need these settings touched
|
||||
include compilers and video decoders.
|
||||
|
||||
Tips for optimizing fuzzing performance are discussed in [perf_tips.md](docs/perf_tips.md).
|
||||
|
||||
Note that afl-fuzz starts by performing an array of deterministic fuzzing
|
||||
steps, which can take several days, but tend to produce neat test cases. If you
|
||||
want quick & dirty results right away - akin to zzuf and other traditional
|
||||
fuzzers - add the -d option to the command line.
|
||||
|
||||
## Interpreting output
|
||||
|
||||
See the [docs/status_screen.md](docs/status_screen.md) file for information on
|
||||
how to interpret the displayed stats and monitor the health of the process. Be
|
||||
sure to consult this file especially if any UI elements are highlighted in red.
|
||||
|
||||
The fuzzing process will continue until you press Ctrl-C. At a minimum, you want
|
||||
to allow the fuzzer to complete one queue cycle, which may take anywhere from a
|
||||
couple of hours to a week or so.
|
||||
|
||||
There are three subdirectories created within the output directory and updated
|
||||
in real-time:
|
||||
|
||||
- queue/ - test cases for every distinctive execution path, plus all the
|
||||
starting files given by the user. This is the synthesized corpus
|
||||
mentioned in section 2.
|
||||
|
||||
Before using this corpus for any other purposes, you can shrink
|
||||
it to a smaller size using the afl-cmin tool. The tool will find
|
||||
a smaller subset of files offering equivalent edge coverage.
|
||||
|
||||
- crashes/ - unique test cases that cause the tested program to receive a
|
||||
fatal signal (e.g., SIGSEGV, SIGILL, SIGABRT). The entries are
|
||||
grouped by the received signal.
|
||||
|
||||
- hangs/ - unique test cases that cause the tested program to time out. The
|
||||
default time limit before something is classified as a hang is
|
||||
the larger of 1 second and the value of the -t parameter.
|
||||
The value can be fine-tuned by setting AFL_HANG_TMOUT, but this
|
||||
is rarely necessary.
|
||||
|
||||
Crashes and hangs are considered "unique" if the associated execution paths
|
||||
involve any state transitions not seen in previously-recorded faults. If a
|
||||
single bug can be reached in multiple ways, there will be some count inflation
|
||||
early in the process, but this should quickly taper off.
|
||||
|
||||
The file names for crashes and hangs are correlated with the parent, non-faulting
|
||||
queue entries. This should help with debugging.
|
||||
|
||||
When you can't reproduce a crash found by afl-fuzz, the most likely cause is
|
||||
that you are not setting the same memory limit as used by the tool. Try:
|
||||
|
||||
```shell
|
||||
LIMIT_MB=50
|
||||
( ulimit -Sv $[LIMIT_MB << 10]; /path/to/tested_binary ... )
|
||||
```
|
||||
|
||||
Change LIMIT_MB to match the -m parameter passed to afl-fuzz. On OpenBSD,
|
||||
also change -Sv to -Sd.
|
||||
|
||||
Any existing output directory can be also used to resume aborted jobs; try:
|
||||
|
||||
```shell
|
||||
./afl-fuzz -i- -o existing_output_dir [...etc...]
|
||||
```
|
||||
|
||||
If you have gnuplot installed, you can also generate some pretty graphs for any
|
||||
active fuzzing task using afl-plot. For an example of how this looks like,
|
||||
see [http://lcamtuf.coredump.cx/afl/plot/](http://lcamtuf.coredump.cx/afl/plot/).
|
||||
|
||||
## Parallelized fuzzing
|
||||
|
||||
Every instance of afl-fuzz takes up roughly one core. This means that on
|
||||
multi-core systems, parallelization is necessary to fully utilize the hardware.
|
||||
For tips on how to fuzz a common target on multiple cores or multiple networked
|
||||
machines, please refer to [docs/parallel_fuzzing.md](docs/parallel_fuzzing.md).
|
||||
|
||||
The parallel fuzzing mode also offers a simple way for interfacing AFL to other
|
||||
fuzzers, to symbolic or concolic execution engines, and so forth; again, see the
|
||||
last section of [docs/parallel_fuzzing.md](docs/parallel_fuzzing.md) for tips.
|
||||
|
||||
## Fuzzer dictionaries
|
||||
|
||||
By default, afl-fuzz mutation engine is optimized for compact data formats -
|
||||
say, images, multimedia, compressed data, regular expression syntax, or shell
|
||||
scripts. It is somewhat less suited for languages with particularly verbose and
|
||||
redundant verbiage - notably including HTML, SQL, or JavaScript.
|
||||
|
||||
To avoid the hassle of building syntax-aware tools, afl-fuzz provides a way to
|
||||
seed the fuzzing process with an optional dictionary of language keywords,
|
||||
magic headers, or other special tokens associated with the targeted data type
|
||||
-- and use that to reconstruct the underlying grammar on the go:
|
||||
|
||||
[http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html](http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html)
|
||||
|
||||
To use this feature, you first need to create a dictionary in one of the two
|
||||
formats discussed in [dictionaries/README.md](dictionaries/README.md);
|
||||
and then point the fuzzer to it via the -x option in the command line.
|
||||
|
||||
(Several common dictionaries are already provided in that subdirectory, too.)
|
||||
|
||||
There is no way to provide more structured descriptions of the underlying
|
||||
syntax, but the fuzzer will likely figure out some of this based on the
|
||||
instrumentation feedback alone. This actually works in practice, say:
|
||||
|
||||
[http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html](http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html)
|
||||
|
||||
PS. Even when no explicit dictionary is given, afl-fuzz will try to extract
|
||||
existing syntax tokens in the input corpus by watching the instrumentation
|
||||
very closely during deterministic byte flips. This works for some types of
|
||||
parsers and grammars but isn't nearly as good as the -x mode.
|
||||
|
||||
If a dictionary is really hard to come by, another option is to let AFL run
|
||||
for a while and then use the token capture library that comes as a companion
|
||||
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
|
||||
|
||||
## Crash triage
|
||||
|
||||
The coverage-based grouping of crashes usually produces a small data set that
|
||||
can be quickly triaged manually or with a very simple GDB or Valgrind script.
|
||||
Every crash is also traceable to its parent non-crashing test case in the
|
||||
queue, making it easier to diagnose faults.
|
||||
|
||||
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
|
||||
code analysis work. To assist with this task, afl-fuzz supports a very unique
|
||||
"crash exploration" mode enabled with the -C flag.
|
||||
|
||||
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 paths that can be reached in the program while keeping it in the
|
||||
crashing state.
|
||||
|
||||
Mutations that do not result in a crash are rejected; so are any changes that
|
||||
do not affect the execution path.
|
||||
|
||||
The output is a small corpus of files that can be very rapidly examined to see
|
||||
what degree of control the attacker has over the faulting address, or whether
|
||||
it is possible to get past an initial out-of-bounds read - and see what lies
|
||||
beneath.
|
||||
|
||||
Oh, one more thing: for test case minimization, give afl-tmin a try. The tool
|
||||
can be operated in a very simple way:
|
||||
|
||||
```shell
|
||||
./afl-tmin -i test_case -o minimized_result -- /path/to/program [...]
|
||||
```
|
||||
|
||||
The tool works with crashing and non-crashing test cases alike. In the crash
|
||||
mode, it will happily accept instrumented and non-instrumented binaries. In the
|
||||
non-crashing mode, the minimizer relies on standard AFL instrumentation to make
|
||||
the file simpler without altering the execution path.
|
||||
|
||||
The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with
|
||||
afl-fuzz.
|
||||
|
||||
Another recent addition to 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 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 complex file formats. More info about its operation can be found
|
||||
near the end of [docs/technical_details.md](docs/technical_details.md).
|
||||
|
||||
## Going beyond crashes
|
||||
|
||||
Fuzzing is a wonderful and underutilized technique for discovering non-crashing
|
||||
design and implementation errors, too. Quite a few interesting bugs have been
|
||||
found by modifying the target programs to call abort() when say:
|
||||
|
||||
- Two bignum libraries produce different outputs when given the same
|
||||
fuzzer-generated input,
|
||||
|
||||
- An image library produces different outputs when asked to decode the same
|
||||
input image several times in a row,
|
||||
|
||||
- A serialization / deserialization library fails to produce stable outputs
|
||||
when iteratively serializing and deserializing fuzzer-supplied data,
|
||||
|
||||
- A compression library produces an output inconsistent with the input file
|
||||
when asked to compress and then decompress a particular blob.
|
||||
|
||||
Implementing these or similar sanity checks usually takes very little time;
|
||||
if you are the maintainer of a particular package, you can make this code
|
||||
conditional with `#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` (a flag also
|
||||
shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL).
|
||||
|
||||
## Common-sense risks
|
||||
|
||||
Please keep in mind that, similarly to many other computationally-intensive
|
||||
tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
|
||||
|
||||
- Your CPU will run hot and will need adequate cooling. In most cases, if
|
||||
cooling is insufficient or stops working properly, CPU speeds will be
|
||||
automatically throttled. That said, especially when fuzzing on less
|
||||
suitable hardware (laptops, smartphones, etc), it's not entirely impossible
|
||||
for something to blow up.
|
||||
|
||||
- Targeted programs may end up erratically grabbing gigabytes of memory or
|
||||
filling up disk space with junk files. AFL tries to enforce basic memory
|
||||
limits, but can't prevent each and every possible mishap. The bottom line
|
||||
is that you shouldn't be fuzzing on systems where the prospect of data loss
|
||||
is not an acceptable risk.
|
||||
|
||||
- Fuzzing involves billions of reads and writes to the filesystem. On modern
|
||||
systems, this will be usually heavily cached, resulting in fairly modest
|
||||
"physical" I/O - but there are many factors that may alter this equation.
|
||||
It is your responsibility to monitor for potential trouble; with very heavy
|
||||
I/O, the lifespan of many HDDs and SSDs may be reduced.
|
||||
|
||||
A good way to monitor disk I/O on Linux is the 'iostat' command:
|
||||
|
||||
```shell
|
||||
$ iostat -d 3 -x -k [...optional disk ID...]
|
||||
```
|
||||
|
||||
## Known limitations & areas for improvement
|
||||
|
||||
Here are some of the most important caveats for AFL:
|
||||
|
||||
- AFL detects faults by checking for the first spawned process dying due to
|
||||
a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for
|
||||
these signals may need to have the relevant code commented out. In the same
|
||||
vein, faults in child processes spawned by the fuzzed target may evade
|
||||
detection unless you manually add some code to catch that.
|
||||
|
||||
- As with any other brute-force tool, the fuzzer offers limited coverage if
|
||||
encryption, checksums, cryptographic signatures, or compression are used to
|
||||
wholly wrap the actual data format to be tested.
|
||||
|
||||
To work around this, you can comment out the relevant checks (see
|
||||
examples/libpng_no_checksum/ for inspiration); if this is not possible,
|
||||
you can also write a postprocessor, one of the hooks of custom mutators.
|
||||
See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
|
||||
`AFL_CUSTOM_MUTATOR_LIBRARY`
|
||||
|
||||
- There are some unfortunate trade-offs with ASAN and 64-bit binaries. This
|
||||
isn't due to any specific fault of afl-fuzz; see [docs/notes_for_asan.md](docs/notes_for_asan.md)
|
||||
for tips.
|
||||
|
||||
- There is no direct support for fuzzing network services, background
|
||||
daemons, or interactive apps that require UI interaction to work. You may
|
||||
need to make simple code changes to make them behave in a more traditional
|
||||
way. Preeny may offer a relatively simple option, too - see:
|
||||
[https://github.com/zardus/preeny](https://github.com/zardus/preeny)
|
||||
|
||||
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)
|
||||
|
||||
- AFL doesn't output human-readable coverage data. If you want to monitor
|
||||
coverage, use afl-cov from Michael Rash: [https://github.com/mrash/afl-cov](https://github.com/mrash/afl-cov)
|
||||
|
||||
- Occasionally, sentient machines rise against their creators. If this
|
||||
happens to you, please consult [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/).
|
||||
|
||||
Beyond this, see INSTALL for platform-specific tips.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Many of the improvements to the original afl and afl++ wouldn't be possible
|
||||
without feedback, bug reports, or patches from:
|
||||
|
||||
```
|
||||
Jann Horn Hanno Boeck
|
||||
Felix Groebert Jakub Wilk
|
||||
Richard W. M. Jones Alexander Cherepanov
|
||||
Tom Ritter Hovik Manucharyan
|
||||
Sebastian Roschke Eberhard Mattes
|
||||
Padraig Brady Ben Laurie
|
||||
@dronesec Luca Barbato
|
||||
Tobias Ospelt Thomas Jarosch
|
||||
Martin Carpenter Mudge Zatko
|
||||
Joe Zbiciak Ryan Govostes
|
||||
Michael Rash William Robinet
|
||||
Jonathan Gray Filipe Cabecinhas
|
||||
Nico Weber Jodie Cunningham
|
||||
Andrew Griffiths Parker Thompson
|
||||
Jonathan Neuschaefer Tyler Nighswander
|
||||
Ben Nagy Samir Aguiar
|
||||
Aidan Thornton Aleksandar Nikolich
|
||||
Sam Hakim Laszlo Szekeres
|
||||
David A. Wheeler Turo Lamminen
|
||||
Andreas Stieger Richard Godbee
|
||||
Louis Dassy teor2345
|
||||
Alex Moneger Dmitry Vyukov
|
||||
Keegan McAllister Kostya Serebryany
|
||||
Richo Healey Martijn Bogaard
|
||||
rc0r Jonathan Foote
|
||||
Christian Holler Dominique Pelle
|
||||
Jacek Wielemborek Leo Barnes
|
||||
Jeremy Barnes Jeff Trull
|
||||
Guillaume Endignoux ilovezfs
|
||||
Daniel Godas-Lopez Franjo Ivancic
|
||||
Austin Seipp Daniel Komaromy
|
||||
Daniel Binderman Jonathan Metzman
|
||||
Vegard Nossum Jan Kneschke
|
||||
Kurt Roeckx Marcel Boehme
|
||||
Van-Thuan Pham Abhik Roychoudhury
|
||||
Joshua J. Drake Toby Hutton
|
||||
Rene Freingruber Sergey Davidoff
|
||||
Sami Liedes Craig Young
|
||||
Andrzej Jackowski Daniel Hodson
|
||||
Nathan Voss Dominik Maier
|
||||
Andrea Biondo Vincent Le Garrec
|
||||
Khaled Yakdan Kuang-che Wu
|
||||
Josephine Calliotte Konrad Welc
|
||||
```
|
||||
|
||||
Thank you!
|
||||
(For people sending pull requests - please add yourself to this list :-)
|
||||
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
|
||||
|
||||
Questions? Concerns? Bug reports? The contributors can be reached via
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
Questions? Concerns? Bug reports?
|
||||
|
||||
There is also a mailing list for the afl project; to join, send a mail to
|
||||
<afl-users+subscribe@googlegroups.com>. Or, if you prefer to browse
|
||||
archives first, try: [https://groups.google.com/group/afl-users](https://groups.google.com/group/afl-users)
|
||||
* The contributors can be reached via (e.g., by creating an issue):
|
||||
[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
|
||||
question missing, submit it via
|
||||
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
||||
* 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
|
||||
notes with other users or to get notified about major new features, send an
|
||||
email to <afl-users+subscribe@googlegroups.com>, but note that this is not
|
||||
managed by us.
|
||||
|
||||
## Branches
|
||||
|
||||
The following branches exist:
|
||||
|
||||
* [release](https://github.com/AFLplusplus/AFLplusplus/tree/release): the latest
|
||||
release
|
||||
* [stable/trunk](https://github.com/AFLplusplus/AFLplusplus/): stable state of
|
||||
AFL++ - it is synced from dev from time to time when we are satisfied with its
|
||||
stability
|
||||
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state
|
||||
of AFL++ - bleeding edge and you might catch a checkout which does not compile
|
||||
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
|
||||
functionality or changes.
|
||||
|
||||
## Help wanted
|
||||
|
||||
We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it
|
||||
even better. However, we already work on so many things that we do not have the
|
||||
time for all the big ideas.
|
||||
|
||||
This can be your way to support and contribute to AFL++ - extend it to do
|
||||
something cool.
|
||||
|
||||
For everyone who wants to contribute (and send pull requests), please read our
|
||||
[contributing guidelines](CONTRIBUTING.md) before you submit.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Many of the improvements to the original AFL and AFL++ wouldn't be possible
|
||||
without feedback, bug reports, or patches from our contributors.
|
||||
|
||||
Thank you! (For people sending pull requests - please add yourself to this list
|
||||
:-)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>List of contributors</summary>
|
||||
|
||||
```
|
||||
Jann Horn Hanno Boeck
|
||||
Felix Groebert Jakub Wilk
|
||||
Richard W. M. Jones Alexander Cherepanov
|
||||
Tom Ritter Hovik Manucharyan
|
||||
Sebastian Roschke Eberhard Mattes
|
||||
Padraig Brady Ben Laurie
|
||||
@dronesec Luca Barbato
|
||||
Tobias Ospelt Thomas Jarosch
|
||||
Martin Carpenter Mudge Zatko
|
||||
Joe Zbiciak Ryan Govostes
|
||||
Michael Rash William Robinet
|
||||
Jonathan Gray Filipe Cabecinhas
|
||||
Nico Weber Jodie Cunningham
|
||||
Andrew Griffiths Parker Thompson
|
||||
Jonathan Neuschaefer Tyler Nighswander
|
||||
Ben Nagy Samir Aguiar
|
||||
Aidan Thornton Aleksandar Nikolich
|
||||
Sam Hakim Laszlo Szekeres
|
||||
David A. Wheeler Turo Lamminen
|
||||
Andreas Stieger Richard Godbee
|
||||
Louis Dassy teor2345
|
||||
Alex Moneger Dmitry Vyukov
|
||||
Keegan McAllister Kostya Serebryany
|
||||
Richo Healey Martijn Bogaard
|
||||
rc0r Jonathan Foote
|
||||
Christian Holler Dominique Pelle
|
||||
Jacek Wielemborek Leo Barnes
|
||||
Jeremy Barnes Jeff Trull
|
||||
Guillaume Endignoux ilovezfs
|
||||
Daniel Godas-Lopez Franjo Ivancic
|
||||
Austin Seipp Daniel Komaromy
|
||||
Daniel Binderman Jonathan Metzman
|
||||
Vegard Nossum Jan Kneschke
|
||||
Kurt Roeckx Marcel Boehme
|
||||
Van-Thuan Pham Abhik Roychoudhury
|
||||
Joshua J. Drake Toby Hutton
|
||||
Rene Freingruber Sergey Davidoff
|
||||
Sami Liedes Craig Young
|
||||
Andrzej Jackowski Daniel Hodson
|
||||
Nathan Voss Dominik Maier
|
||||
Andrea Biondo Vincent Le Garrec
|
||||
Khaled Yakdan Kuang-che Wu
|
||||
Josephine Calliotte Konrad Welc
|
||||
Thomas Rooijakkers David Carlier
|
||||
Ruben ten Hove Joey Jiao
|
||||
fuzzah @intrigus-lgtm
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Cite
|
||||
|
||||
If you use AFL++ in scientific work, consider citing
|
||||
[our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi)
|
||||
presented at WOOT'20:
|
||||
|
||||
Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>BibTeX</summary>
|
||||
|
||||
```bibtex
|
||||
@inproceedings {AFLplusplus-Woot20,
|
||||
author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse},
|
||||
title = {{AFL++}: Combining Incremental Steps of Fuzzing Research},
|
||||
booktitle = {14th {USENIX} Workshop on Offensive Technologies ({WOOT} 20)},
|
||||
year = {2020},
|
||||
publisher = {{USENIX} Association},
|
||||
month = aug,
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
48
TODO.md
48
TODO.md
@ -1,32 +1,36 @@
|
||||
# TODO list for AFL++
|
||||
|
||||
## Roadmap 2.66+
|
||||
## Should
|
||||
|
||||
- AFL_MAP_SIZE for qemu_mode and unicorn_mode
|
||||
- namespace for targets? e.g. network
|
||||
- learn from honggfuzz (mutations, maybe ptrace?)
|
||||
- CPU affinity for many cores? There seems to be an issue > 96 cores
|
||||
- makefiles should show provide a build summary success/failure
|
||||
- better documentation for custom mutators
|
||||
- better autodetection of shifting runtime timeout values
|
||||
- Update afl->pending_not_fuzzed for MOpt
|
||||
- afl-plot to support multiple plot_data
|
||||
- parallel builds for source-only targets
|
||||
- get rid of check_binary, replace with more forkserver communication
|
||||
|
||||
## Maybe
|
||||
|
||||
- forkserver tells afl-fuzz if cmplog is supported and if so enable
|
||||
it by default, with AFL_CMPLOG_NO=1 (?) set to skip?
|
||||
- afl_custom_fuzz_splice_optin()
|
||||
- afl_custom_splice()
|
||||
- cmdline option from-to range for mutations
|
||||
|
||||
## Further down the road
|
||||
|
||||
afl-fuzz:
|
||||
- ascii_only mode for mutation output - or use a custom mutator for this?
|
||||
- setting min_len/max_len/start_offset/end_offset limits for mutation output
|
||||
|
||||
llvm_mode:
|
||||
- LTO - imitate sancov
|
||||
|
||||
gcc_plugin:
|
||||
- (wait for submission then decide)
|
||||
- laf-intel
|
||||
- better instrumentation (seems to be better with gcc-9+)
|
||||
|
||||
qemu_mode:
|
||||
- update to 5.x (if the performance bug if gone)
|
||||
QEMU mode/FRIDA mode:
|
||||
- non colliding instrumentation
|
||||
- rename qemu specific envs to AFL_QEMU (AFL_ENTRYPOINT, AFL_CODE_START/END,
|
||||
AFL_COMPCOV_LEVEL?)
|
||||
- add AFL_QEMU_EXITPOINT (maybe multiple?), maybe pointless as we have
|
||||
- add AFL_QEMU_EXITPOINT (maybe multiple?), maybe pointless as there is
|
||||
persistent mode
|
||||
- add/implement AFL_QEMU_INST_LIBLIST and AFL_QEMU_NOINST_PROGRAM
|
||||
- add/implement AFL_QEMU_INST_REGIONS as a list of _START/_END addresses
|
||||
|
||||
## Ideas
|
||||
|
||||
- LTO/sancov: write current edge to prev_loc and use that information when
|
||||
using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow up
|
||||
edge numbers that both following cmp paths have been found and then disable
|
||||
working on this edge id -> cmplog_intelligence branch
|
||||
- use cmplog colorization taint result for havoc locations?
|
||||
|
166
afl-cmin
166
afl-cmin
@ -106,6 +106,7 @@ function usage() {
|
||||
" -f file - location read by the fuzzed program (stdin)\n" \
|
||||
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
||||
" -t msec - run time limit for child process (none)\n" \
|
||||
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
||||
" -Q - use binary-only instrumentation (QEMU mode)\n" \
|
||||
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
|
||||
"\n" \
|
||||
@ -113,13 +114,19 @@ function usage() {
|
||||
" -C - keep crashing inputs, reject everything else\n" \
|
||||
" -e - solve for edge coverage only, ignore hit counts\n" \
|
||||
"\n" \
|
||||
"For additional tips, please consult docs/README.md\n" \
|
||||
"For additional tips, please consult README.md\n" \
|
||||
"\n" \
|
||||
"Environment variables used:\n" \
|
||||
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
|
||||
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
|
||||
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
|
||||
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
|
||||
"AFL_PATH: path for the afl-showmap binary\n" \
|
||||
"AFL_SKIP_BIN_CHECK: skip check for target binary\n" \
|
||||
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n"
|
||||
"AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \
|
||||
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" \
|
||||
"AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \
|
||||
"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
|
||||
"printed to stdout\n" \
|
||||
"AFL_SKIP_BIN_CHECK: skip afl instrumentation checks for target binary\n"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -128,14 +135,22 @@ function exists_and_is_executable(binarypath) {
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
if (0 != system( "test -t 1")) {
|
||||
redirected = 1
|
||||
} else {
|
||||
redirected = 0
|
||||
}
|
||||
|
||||
print "corpus minimization tool for afl++ (awk version)\n"
|
||||
|
||||
# defaults
|
||||
extra_par = ""
|
||||
AFL_CMIN_CRASHES_ONLY = ""
|
||||
|
||||
# process options
|
||||
Opterr = 1 # default is to diagnose
|
||||
Optind = 1 # skip ARGV[0]
|
||||
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCQU?")) != -1) {
|
||||
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCOQU?")) != -1) {
|
||||
if (_go_c == "i") {
|
||||
if (!Optarg) usage()
|
||||
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||
@ -168,24 +183,28 @@ BEGIN {
|
||||
continue
|
||||
} else
|
||||
if (_go_c == "C") {
|
||||
ENVIRON["AFL_CMIN_CRASHES_ONLY"] = 1
|
||||
AFL_CMIN_CRASHES_ONLY = "AFL_CMIN_CRASHES_ONLY=1 "
|
||||
continue
|
||||
} else
|
||||
if (_go_c == "e") {
|
||||
extra_par = extra_par " -e"
|
||||
continue
|
||||
} else
|
||||
if (_go_c == "O") {
|
||||
if (frida_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||
extra_par = extra_par " -O"
|
||||
frida_mode = 1
|
||||
continue
|
||||
} else
|
||||
if (_go_c == "Q") {
|
||||
if (qemu_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||
extra_par = extra_par " -Q"
|
||||
if ( !mem_limit_given ) mem_limit = "250"
|
||||
qemu_mode = 1
|
||||
continue
|
||||
} else
|
||||
if (_go_c == "U") {
|
||||
if (unicorn_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||
extra_par = extra_par " -U"
|
||||
if ( !mem_limit_given ) mem_limit = "250"
|
||||
unicorn_mode = 1
|
||||
continue
|
||||
} else
|
||||
@ -195,7 +214,7 @@ BEGIN {
|
||||
usage()
|
||||
} # while options
|
||||
|
||||
if (!mem_limit) mem_limit = 200
|
||||
if (!mem_limit) mem_limit = "none"
|
||||
if (!timeout) timeout = "none"
|
||||
|
||||
# get program args
|
||||
@ -204,7 +223,7 @@ BEGIN {
|
||||
for (; Optind < ARGC; Optind++) {
|
||||
prog_args[i++] = ARGV[Optind]
|
||||
if (i > 1)
|
||||
prog_args_string = prog_args_string" "ARGV[Optind]
|
||||
prog_args_string = prog_args_string" '"ARGV[Optind]"'"
|
||||
}
|
||||
|
||||
# sanity checks
|
||||
@ -240,7 +259,7 @@ BEGIN {
|
||||
if (!stdin_file) {
|
||||
found_atat = 0
|
||||
for (prog_args_ind in prog_args) {
|
||||
if ("@@" == prog_args[prog_args_ind]) {
|
||||
if (match(prog_args[prog_args_ind], "@@") != 0) {
|
||||
found_atat = 1
|
||||
break
|
||||
}
|
||||
@ -272,7 +291,7 @@ BEGIN {
|
||||
target_bin = tnew
|
||||
}
|
||||
|
||||
if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !unicorn_mode) {
|
||||
if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
|
||||
if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
|
||||
print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
|
||||
exit 1
|
||||
@ -284,9 +303,13 @@ BEGIN {
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (0 == system( "test -d "in_dir"/queue" )) {
|
||||
in_dir = in_dir "/queue"
|
||||
}
|
||||
#if (0 == system( "test -d "in_dir"/default" )) {
|
||||
# in_dir = in_dir "/default"
|
||||
#}
|
||||
#
|
||||
#if (0 == system( "test -d "in_dir"/queue" )) {
|
||||
# in_dir = in_dir "/queue"
|
||||
#}
|
||||
|
||||
system("rm -rf "trace_dir" 2>/dev/null");
|
||||
system("rm "out_dir"/id[:_]* 2>/dev/null")
|
||||
@ -309,14 +332,18 @@ BEGIN {
|
||||
close( stdin_file )
|
||||
}
|
||||
|
||||
if (!ENVIRON["AFL_PATH"]) {
|
||||
if (0 == system("test -f afl-cmin")) {
|
||||
# First we look in PATH
|
||||
if (0 == system("command -v afl-showmap >/dev/null 2>&1")) {
|
||||
"command -v afl-showmap 2>/dev/null" | getline showmap
|
||||
} else {
|
||||
# then we look in the current directory
|
||||
if (0 == system("test -x ./afl-showmap")) {
|
||||
showmap = "./afl-showmap"
|
||||
} else {
|
||||
"command -v afl-showmap 2>/dev/null" | getline showmap
|
||||
if (ENVIRON["AFL_PATH"]) {
|
||||
showmap = ENVIRON["AFL_PATH"] "/afl-showmap"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showmap = ENVIRON["AFL_PATH"] "/afl-showmap"
|
||||
}
|
||||
|
||||
if (!showmap || 0 != system("test -x "showmap )) {
|
||||
@ -335,56 +362,65 @@ BEGIN {
|
||||
} else {
|
||||
stat_format = "-f '%z %N'" # *BSD, MacOS
|
||||
}
|
||||
cmdline = "cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} \\; | sort -k1n -k2r"
|
||||
cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format") | sort -k1n -k2r"
|
||||
cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r)"
|
||||
#cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r"
|
||||
#cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r"
|
||||
#cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"
|
||||
while (cmdline | getline) {
|
||||
sub(/^[0-9]+ (\.\/)?/,"",$0)
|
||||
infilesSmallToBig[i++] = $0
|
||||
infilesSmallToBigFull[i] = $0
|
||||
sub(/.*\//, "", $0)
|
||||
infilesSmallToBig[i] = $0
|
||||
infilesSmallToBigMap[infilesSmallToBig[i]] = infilesSmallToBigFull[i]
|
||||
infilesSmallToBigFullMap[infilesSmallToBigFull[i]] = infilesSmallToBig[i]
|
||||
i++
|
||||
}
|
||||
in_count = i
|
||||
|
||||
first_file = infilesSmallToBig[0]
|
||||
first_file = infilesSmallToBigFull[0]
|
||||
|
||||
# Make sure that we're not dealing with a directory.
|
||||
#if (0 == system("test -d ""\""in_dir"/"first_file"\"")) {
|
||||
# print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr"
|
||||
# exit 1
|
||||
#}
|
||||
|
||||
if (0 == system("test -d "in_dir"/"first_file)) {
|
||||
print "[-] Error: The input directory contains subdirectories - please fix." > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (0 == system("ln "in_dir"/"first_file" "trace_dir"/.link_test")) {
|
||||
system(">\""in_dir"/.afl-cmin.test\"")
|
||||
if (0 == system("ln \""in_dir"/.afl-cmin.test\" "trace_dir"/.link_test")) {
|
||||
cp_tool = "ln"
|
||||
} else {
|
||||
cp_tool = "cp"
|
||||
}
|
||||
system("rm -f \""in_dir"/.afl-cmin.test\"")
|
||||
|
||||
# Make sure that we can actually get anything out of afl-showmap before we
|
||||
# waste too much time.
|
||||
if (!ENVIRON["AFL_SKIP_BIN_CHECK"]) {
|
||||
# Make sure that we can actually get anything out of afl-showmap before we
|
||||
# waste too much time.
|
||||
|
||||
print "[*] Testing the target binary..."
|
||||
print "[*] Testing the target binary..."
|
||||
|
||||
if (!stdin_file) {
|
||||
system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
|
||||
} else {
|
||||
system("cp "in_dir"/"first_file" "stdin_file)
|
||||
system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -A \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
|
||||
}
|
||||
|
||||
first_count = 0
|
||||
|
||||
runtest = trace_dir"/.run_test"
|
||||
while ((getline < runtest) > 0) {
|
||||
++first_count
|
||||
}
|
||||
|
||||
if (first_count) {
|
||||
print "[+] OK, "first_count" tuples recorded."
|
||||
} else {
|
||||
print "[-] Error: no instrumentation output detected (perhaps crash or timeout)." > "/dev/stderr"
|
||||
if (!ENVIRON["AFL_KEEP_TRACES"]) {
|
||||
system("rm -rf "trace_dir" 2>/dev/null")
|
||||
if (!stdin_file) {
|
||||
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
|
||||
} else {
|
||||
system("cp \""in_dir"/"first_file"\" "stdin_file)
|
||||
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
|
||||
}
|
||||
|
||||
first_count = 0
|
||||
|
||||
runtest = trace_dir"/.run_test"
|
||||
while ((getline < runtest) > 0) {
|
||||
++first_count
|
||||
}
|
||||
|
||||
if (first_count) {
|
||||
print "[+] OK, "first_count" tuples recorded."
|
||||
} else {
|
||||
print "[-] Error: no instrumentation output detected (perhaps crash or timeout)." > "/dev/stderr"
|
||||
if (!ENVIRON["AFL_KEEP_TRACES"]) {
|
||||
system("rm -rf "trace_dir" 2>/dev/null")
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Let's roll!
|
||||
@ -398,14 +434,16 @@ BEGIN {
|
||||
cur = 0;
|
||||
if (!stdin_file) {
|
||||
print " Processing "in_count" files (forkserver mode)..."
|
||||
retval = system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
|
||||
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
|
||||
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
|
||||
} else {
|
||||
print " Processing "in_count" files (forkserver mode)..."
|
||||
retval = system( "AFL_CMIN_ALLOW_ANY=1 \""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string" </dev/null")
|
||||
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null"
|
||||
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
print "[!]Exit code != 0 received from afl-showmap, terminating..."
|
||||
if (retval && !AFL_CMIN_CRASHES_ONLY) {
|
||||
print "[!] Exit code "retval" != 0 received from afl-showmap, terminating..."
|
||||
|
||||
if (!ENVIRON["AFL_KEEP_TRACES"]) {
|
||||
system("rm -rf "trace_dir" 2>/dev/null")
|
||||
@ -431,7 +469,8 @@ BEGIN {
|
||||
while (cur < in_count) {
|
||||
fn = infilesSmallToBig[cur]
|
||||
++cur
|
||||
printf "\r Processing file "cur"/"in_count
|
||||
if (redirected == 0) { printf "\r Processing file "cur"/"in_count }
|
||||
else { print " Processing file "cur"/"in_count }
|
||||
# create path for the trace file from afl-showmap
|
||||
tracefile_path = trace_dir"/"fn
|
||||
# gather all keys, and count them
|
||||
@ -470,7 +509,9 @@ BEGIN {
|
||||
key = field[nrFields]
|
||||
|
||||
++tcnt;
|
||||
printf "\r Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..."
|
||||
if (redirected == 0) { printf "\r Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
|
||||
else { print " Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
|
||||
|
||||
if (key in keyAlreadyKnown) {
|
||||
continue
|
||||
}
|
||||
@ -485,7 +526,8 @@ BEGIN {
|
||||
|
||||
# copy file unless already done
|
||||
if (! (fn in file_already_copied)) {
|
||||
system(cp_tool" "in_dir"/"fn" "out_dir"/"fn)
|
||||
realfile = infilesSmallToBigMap[fn]
|
||||
system(cp_tool" \""in_dir"/"realfile"\" \""out_dir"/"fn"\"")
|
||||
file_already_copied[fn] = ""
|
||||
++out_count
|
||||
#printf "tuple nr %d (%d cnt=%d) -> %s\n",tcnt,key,key_count[key],fn > trace_dir"/.log"
|
||||
|
@ -11,7 +11,7 @@
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# This tool tries to find the smallest subset of files in the input directory
|
||||
# that still trigger the full range of instrumentation data points seen in
|
||||
@ -45,7 +45,7 @@ echo
|
||||
|
||||
# Process command-line options...
|
||||
|
||||
MEM_LIMIT=200
|
||||
MEM_LIMIT=none
|
||||
TIMEOUT=none
|
||||
|
||||
unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
|
||||
@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
|
||||
|
||||
export AFL_QUIET=1
|
||||
|
||||
while getopts "+i:o:f:m:t:eQUCh" opt; do
|
||||
while getopts "+i:o:f:m:t:eOQUCh" opt; do
|
||||
|
||||
case "$opt" in
|
||||
|
||||
@ -83,14 +83,16 @@ while getopts "+i:o:f:m:t:eQUCh" opt; do
|
||||
"C")
|
||||
export AFL_CMIN_CRASHES_ONLY=1
|
||||
;;
|
||||
"O")
|
||||
EXTRA_PAR="$EXTRA_PAR -O"
|
||||
FRIDA_MODE=1
|
||||
;;
|
||||
"Q")
|
||||
EXTRA_PAR="$EXTRA_PAR -Q"
|
||||
test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250
|
||||
QEMU_MODE=1
|
||||
;;
|
||||
"U")
|
||||
EXTRA_PAR="$EXTRA_PAR -U"
|
||||
test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250
|
||||
UNICORN_MODE=1
|
||||
;;
|
||||
"?")
|
||||
@ -120,6 +122,7 @@ Execution control settings:
|
||||
-f file - location read by the fuzzed program (stdin)
|
||||
-m megs - memory limit for child process ($MEM_LIMIT MB)
|
||||
-t msec - run time limit for child process (none)
|
||||
-O - use binary-only instrumentation (FRIDA mode)
|
||||
-Q - use binary-only instrumentation (QEMU mode)
|
||||
-U - use unicorn-based instrumentation (Unicorn mode)
|
||||
|
||||
@ -128,11 +131,12 @@ Minimization settings:
|
||||
-C - keep crashing inputs, reject everything else
|
||||
-e - solve for edge coverage only, ignore hit counts
|
||||
|
||||
For additional tips, please consult docs/README.md.
|
||||
For additional tips, please consult README.md.
|
||||
|
||||
Environment variables used:
|
||||
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
|
||||
AFL_PATH: path for the afl-showmap binary
|
||||
AFL_NO_FORKSRV: run target via execve instead of using the forkserver
|
||||
AFL_PATH: last resort location to find the afl-showmap binary
|
||||
AFL_SKIP_BIN_CHECK: skip check for target binary
|
||||
_EOF_
|
||||
exit 1
|
||||
@ -211,7 +215,7 @@ if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
|
||||
|
||||
fi
|
||||
|
||||
if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
|
||||
if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
|
||||
|
||||
if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then
|
||||
echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2
|
||||
@ -225,6 +229,7 @@ if [ ! -d "$IN_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test -d "$IN_DIR/default" && IN_DIR="$IN_DIR/default"
|
||||
test -d "$IN_DIR/queue" && IN_DIR="$IN_DIR/queue"
|
||||
|
||||
find "$OUT_DIR" -name 'id[:_]*' -maxdepth 1 -exec rm -- {} \; 2>/dev/null
|
||||
@ -244,10 +249,21 @@ if [ ! "$STDIN_FILE" = "" ]; then
|
||||
touch "$STDIN_FILE" || exit 1
|
||||
fi
|
||||
|
||||
if [ "$AFL_PATH" = "" ]; then
|
||||
SHOWMAP="${0%/afl-cmin.bash}/afl-showmap"
|
||||
SHOWMAP=`command -v afl-showmap 2>/dev/null`
|
||||
|
||||
if [ -z "$SHOWMAP" ]; then
|
||||
TMP="${0%/afl-cmin.bash}/afl-showmap"
|
||||
if [ -x "$TMP" ]; then
|
||||
SHOWMAP=$TMP
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$SHOWMAP" -a -x "./afl-showmap" ]; then
|
||||
SHOWMAP="./afl-showmap"
|
||||
else
|
||||
SHOWMAP="$AFL_PATH/afl-showmap"
|
||||
if [ -n "$AFL_PATH" ]; then
|
||||
SHOWMAP="$AFL_PATH/afl-showmap"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$SHOWMAP" ]; then
|
||||
@ -294,7 +310,7 @@ if [ "$STDIN_FILE" = "" ]; then
|
||||
else
|
||||
|
||||
cp "$IN_DIR/$FIRST_FILE" "$STDIN_FILE"
|
||||
AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -A "$STDIN_FILE" -- "$@" </dev/null
|
||||
AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
|
||||
|
||||
fi
|
||||
|
||||
@ -344,7 +360,7 @@ echo "[*] Obtaining traces for input files in '$IN_DIR'..."
|
||||
|
||||
cp "$IN_DIR/$fn" "$STDIN_FILE"
|
||||
|
||||
"$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -A "$STDIN_FILE" -- "$@" </dev/null
|
||||
"$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
|
||||
|
||||
done
|
||||
|
||||
|
133
afl-persistent-config
Executable file
133
afl-persistent-config
Executable file
@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
# written by jhertz
|
||||
#
|
||||
|
||||
test "$1" = "-h" -o "$1" = "-hh" && {
|
||||
echo 'afl-persistent-config'
|
||||
echo
|
||||
echo $0
|
||||
echo
|
||||
echo afl-persistent-config has no command line options
|
||||
echo
|
||||
echo afl-persistent-config permanently reconfigures the system to a high performance fuzzing state.
|
||||
echo "WARNING: this reduces the security of the system!"
|
||||
echo
|
||||
echo Note that there is also afl-system-config which sets additional runtime
|
||||
echo configuration options.
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo
|
||||
echo "WARNING: This scripts makes permanent configuration changes to the system to"
|
||||
echo " increase the performance for fuzzing. As a result, the system also"
|
||||
echo " becomes less secure against attacks! If you use this script, setup"
|
||||
echo " strong firewall rules and only make SSH available as a network"
|
||||
echo " service!"
|
||||
echo
|
||||
echo -n "Type \"YES\" to continue: "
|
||||
read ANSWER
|
||||
if [[ "$ANSWER" != "YES" ]]; then
|
||||
echo Input was not YES, aborting ...
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
PLATFORM=`uname -s`
|
||||
|
||||
# check that we're on Mac
|
||||
if [[ "$PLATFORM" = "Darwin" ]] ; then
|
||||
|
||||
# check if UID == 0
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
echo "You need to be root to do this. E.g. use \"sudo\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check if SIP is disabled
|
||||
if [[ ! $(csrutil status | grep "disabled") ]]; then
|
||||
echo "SIP needs to be disabled. Restart and press Command-R at reboot, Utilities => Terminal => enter \"csrutil disable\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checks passed."
|
||||
|
||||
echo "Installing /Library/LaunchDaemons/shm_setup.plist"
|
||||
|
||||
cat << EOF > /Library/LaunchDaemons/shm_setup.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>shmemsetup</string>
|
||||
<key>UserName</key>
|
||||
<string>root</string>
|
||||
<key>GroupName</key>
|
||||
<string>wheel</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/sbin/sysctl</string>
|
||||
<string>-w</string>
|
||||
<string>kern.sysv.shmmax=524288000</string>
|
||||
<string>kern.sysv.shmmin=1</string>
|
||||
<string>kern.sysv.shmmni=128</string>
|
||||
<string>kern.sysv.shmseg=48</string>
|
||||
<string>kern.sysv.shmall=131072000</string>
|
||||
</array>
|
||||
<key>KeepAlive</key>
|
||||
<false/>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo "Reboot and enjoy your fuzzing"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$PLATFORM" = "Linux" ]] ; then
|
||||
|
||||
# check if UID == 0
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
echo "You need to be root to do this. E.g. use \"sudo\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checks passed."
|
||||
|
||||
test -d /etc/sysctl.d || echo Error: /etc/sysctl.d directory not found, cannot install shmem config
|
||||
test -d /etc/sysctl.d -a '!' -e /etc/sysctl.d/99-fuzzing && {
|
||||
echo "Installing /etc/sysctl.d/99-fuzzing"
|
||||
cat << EOF > /etc/sysctl.d/99-fuzzing
|
||||
kernel.core_uses_pid=0
|
||||
kernel.core_pattern=core
|
||||
kernel.randomize_va_space=0
|
||||
kernel.sched_child_runs_first=1
|
||||
kernel.sched_autogroup_enabled=1
|
||||
kernel.sched_migration_cost_ns=50000000
|
||||
kernel.sched_latency_ns=250000000
|
||||
EOF
|
||||
}
|
||||
|
||||
egrep -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
|
||||
egrep -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
|
||||
egrep '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | egrep -q hardened_usercopy=off || {
|
||||
echo "Configuring performance boot options"
|
||||
LINE=`egrep '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
|
||||
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
|
||||
}
|
||||
}
|
||||
|
||||
echo
|
||||
echo "Reboot and enjoy your fuzzing"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "Error: Unknown platform \"$PLATFORM\", currently supported are Linux and MacOS."
|
||||
exit 1
|
202
afl-plot
202
afl-plot
@ -12,7 +12,7 @@
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
get_abs_path() {
|
||||
@ -22,16 +22,28 @@ get_abs_path() {
|
||||
echo "progress plotting utility for afl-fuzz by Michal Zalewski"
|
||||
echo
|
||||
|
||||
if [ ! "$#" = "2" ]; then
|
||||
GRAPHICAL="0"
|
||||
|
||||
if [ "$1" = "-g" ] || [ "$1" = "--graphical" ]; then
|
||||
GRAPHICAL="1"
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$#" != "2" ]; then
|
||||
|
||||
cat 1>&2 <<_EOF_
|
||||
$0 afl_state_dir graph_output_dir
|
||||
$0 [ -g | --graphical ] afl_state_dir graph_output_dir
|
||||
|
||||
This program generates gnuplot images from afl-fuzz output data. Usage:
|
||||
This program generates gnuplot images from afl-fuzz output data.
|
||||
|
||||
The afl_state_dir parameter should point to an existing state directory for any
|
||||
active or stopped instance of afl-fuzz; while graph_output_dir should point to
|
||||
an empty directory where this tool can write the resulting plots to.
|
||||
Usage:
|
||||
|
||||
afl_state_dir should point to an existing state directory for any
|
||||
active or stopped instance of afl-fuzz
|
||||
graph_output_dir should point to an empty directory where this
|
||||
tool can write the resulting plots to
|
||||
-g, --graphical (optional) display the plots in a graphical window
|
||||
(you should have built afl-plot-ui to use this option)
|
||||
|
||||
The program will put index.html and three PNG images in the output directory;
|
||||
you should be able to view it with any web browser of your choice.
|
||||
@ -68,6 +80,15 @@ if [ ! -f "$inputdir/plot_data" ]; then
|
||||
|
||||
fi
|
||||
|
||||
LINES=`cat "$inputdir/plot_data" | wc -l`
|
||||
|
||||
if [ "$LINES" -lt 3 ]; then
|
||||
|
||||
echo "[-] Error: plot_data carries too little data, let it run longer." 1>&2
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
BANNER="`cat "$inputdir/fuzzer_stats" 2> /dev/null | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`"
|
||||
|
||||
test "$BANNER" = "" && BANNER="(none)"
|
||||
@ -90,21 +111,13 @@ if [ ! -d "$outputdir" ]; then
|
||||
|
||||
fi
|
||||
|
||||
rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png"
|
||||
rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png"
|
||||
mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null
|
||||
|
||||
echo "[*] Generating plots..."
|
||||
|
||||
(
|
||||
|
||||
cat <<_EOF_
|
||||
set terminal png truecolor enhanced size 1000,300 butt
|
||||
|
||||
set output '$outputdir/high_freq.png'
|
||||
|
||||
set xdata time
|
||||
set timefmt '%s'
|
||||
set format x "%b %d\n%H:%M"
|
||||
GNUPLOT_SETUP="
|
||||
#set xdata time
|
||||
#set timefmt '%s'
|
||||
#set format x \"%b %d\n%H:%M\"
|
||||
set tics font 'small'
|
||||
unset mxtics
|
||||
unset mytics
|
||||
@ -118,29 +131,167 @@ set key outside
|
||||
set autoscale xfixmin
|
||||
set autoscale xfixmax
|
||||
|
||||
plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'total paths' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
|
||||
'' using 1:3 with filledcurve x1 title 'current path' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
|
||||
'' using 1:5 with lines title 'pending paths' linecolor rgb '#0090ff' linewidth 3, \\
|
||||
set xlabel \"relative time in seconds\" font \"small\"
|
||||
"
|
||||
|
||||
PLOT_HF="
|
||||
set terminal png truecolor enhanced size 1000,300 butt
|
||||
set output '$outputdir/high_freq.png'
|
||||
|
||||
$GNUPLOT_SETUP
|
||||
|
||||
plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'corpus count' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
|
||||
'' using 1:3 with filledcurve x1 title 'current fuzz item' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
|
||||
'' using 1:5 with lines title 'pending items' linecolor rgb '#0090ff' linewidth 3, \\
|
||||
'' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\
|
||||
'' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3
|
||||
"
|
||||
|
||||
PLOT_LF="
|
||||
set terminal png truecolor enhanced size 1000,200 butt
|
||||
set output '$outputdir/low_freq.png'
|
||||
|
||||
$GNUPLOT_SETUP
|
||||
|
||||
plot '$inputdir/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\
|
||||
'' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\
|
||||
'' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\
|
||||
'' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3
|
||||
"
|
||||
|
||||
PLOT_ES="
|
||||
set terminal png truecolor enhanced size 1000,200 butt
|
||||
set output '$outputdir/exec_speed.png'
|
||||
|
||||
$GNUPLOT_SETUP
|
||||
|
||||
plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
|
||||
'$inputdir/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
|
||||
"
|
||||
|
||||
PLOT_EG="
|
||||
set terminal png truecolor enhanced size 1000,300 butt
|
||||
set output '$outputdir/edges.png'
|
||||
|
||||
$GNUPLOT_SETUP
|
||||
|
||||
plot '$inputdir/plot_data' using 1:13 with lines title ' edges' linecolor rgb '#0090ff' linewidth 3
|
||||
"
|
||||
|
||||
if [ "$#" = "2" ] && [ "$GRAPHICAL" = "1" ]; then
|
||||
|
||||
afl-plot-ui -h > /dev/null 2>&1
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
|
||||
cat 1>&2 <<_EOF_
|
||||
You do not seem to have the afl-plot-ui utility installed. If you have installed afl-plot-ui, make sure the afl-plot-ui executable is in your PATH.
|
||||
If you are still facing any problems, please open an issue at https://github.com/AFLplusplus/AFLplusplus/issues.
|
||||
|
||||
No plots have been generated. Please rerun without the "-g" or "--graphical" flag to generate the plots.
|
||||
_EOF_
|
||||
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
rm -rf "$outputdir/.tmp"
|
||||
mkdir -p "$outputdir/.tmp"
|
||||
mkfifo "$outputdir/.tmp/win_ids" || exit 1
|
||||
|
||||
afl-plot-ui > "$outputdir/.tmp/win_ids" &
|
||||
W_IDS=$(cat "$outputdir/.tmp/win_ids")
|
||||
|
||||
rm -rf "$outputdir/.tmp"
|
||||
|
||||
W_ID1=$(echo "$W_IDS" | head -n 1)
|
||||
W_ID2=$(echo "$W_IDS" | head -n 2 | tail -n 1)
|
||||
W_ID3=$(echo "$W_IDS" | head -n 3 | tail -n 1)
|
||||
W_ID4=$(echo "$W_IDS" | tail -n 1)
|
||||
|
||||
echo "[*] Generating plots..."
|
||||
|
||||
(
|
||||
|
||||
cat << _EOF_
|
||||
|
||||
$PLOT_HF
|
||||
set term x11 window "$W_ID3"
|
||||
set output
|
||||
replot
|
||||
pause mouse close
|
||||
|
||||
_EOF_
|
||||
|
||||
) | gnuplot
|
||||
) | gnuplot 2> /dev/null &
|
||||
|
||||
(
|
||||
|
||||
cat << _EOF_
|
||||
|
||||
$PLOT_LF
|
||||
set term x11 window "$W_ID4"
|
||||
set output
|
||||
replot
|
||||
pause mouse close
|
||||
|
||||
_EOF_
|
||||
|
||||
) | gnuplot 2> /dev/null &
|
||||
|
||||
(
|
||||
|
||||
cat << _EOF_
|
||||
|
||||
$PLOT_ES
|
||||
set term x11 window "$W_ID2"
|
||||
set output
|
||||
replot
|
||||
pause mouse close
|
||||
|
||||
_EOF_
|
||||
|
||||
) | gnuplot 2> /dev/null &
|
||||
|
||||
(
|
||||
|
||||
cat << _EOF_
|
||||
|
||||
$PLOT_EG
|
||||
set term x11 window "$W_ID1"
|
||||
set output
|
||||
replot
|
||||
pause mouse close
|
||||
|
||||
_EOF_
|
||||
|
||||
) | gnuplot 2> /dev/null &
|
||||
|
||||
sleep 1
|
||||
|
||||
else
|
||||
|
||||
echo "[*] Generating plots..."
|
||||
|
||||
(
|
||||
|
||||
cat << _EOF_
|
||||
|
||||
$PLOT_HF
|
||||
|
||||
$PLOT_LF
|
||||
|
||||
$PLOT_ES
|
||||
|
||||
$PLOT_EG
|
||||
|
||||
_EOF_
|
||||
|
||||
) | gnuplot
|
||||
|
||||
echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot-h\" to know more."
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -s "$outputdir/exec_speed.png" ]; then
|
||||
|
||||
@ -158,6 +309,7 @@ cat >"$outputdir/index.html" <<_EOF_
|
||||
<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
<img src="edges.png" width=1000 height=300>
|
||||
<img src="high_freq.png" width=1000 height=300><p>
|
||||
<img src="low_freq.png" width=1000 height=200><p>
|
||||
<img src="exec_speed.png" width=1000 height=200>
|
||||
@ -169,7 +321,7 @@ _EOF_
|
||||
# sensitive, this seems like a reasonable trade-off.
|
||||
|
||||
chmod 755 "$outputdir"
|
||||
chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/index.html"
|
||||
chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html"
|
||||
|
||||
echo "[+] All done - enjoy your charts!"
|
||||
|
||||
|
@ -1,45 +1,59 @@
|
||||
#!/bin/sh
|
||||
test "$1" = "-h" && {
|
||||
test "$1" = "-h" -o "$1" = "-hh" && {
|
||||
echo 'afl-system-config by Marc Heuse <mh@mh-sec.de>'
|
||||
echo
|
||||
echo $0
|
||||
echo
|
||||
echo afl-system-config has no command line options
|
||||
echo
|
||||
echo afl-system reconfigures the system to a high performance fuzzing state
|
||||
echo WARNING: this reduces the security of the system
|
||||
echo afl-system-config reconfigures the system to a high performance fuzzing state.
|
||||
echo "WARNING: this reduces the security of the system!"
|
||||
echo
|
||||
exit 1
|
||||
echo Note that there is also afl-persistent-config which sets additional permanent
|
||||
echo configuration options.
|
||||
exit 0
|
||||
}
|
||||
|
||||
DONE=
|
||||
PLATFORM=`uname -s`
|
||||
echo This reconfigures the system to have a better fuzzing performance.
|
||||
echo "WARNING: this reduces the security of the system!"
|
||||
echo
|
||||
if [ '!' "$EUID" = 0 ] && [ '!' `id -u` = 0 ] ; then
|
||||
echo "Warning: you need to be root to run this!"
|
||||
# we do not exit as other mechanisms exist that allows to do this than
|
||||
# being root. let the errors speak for themselves.
|
||||
fi
|
||||
sleep 1
|
||||
if [ "$PLATFORM" = "Linux" ] ; then
|
||||
{
|
||||
sysctl -w kernel.core_pattern=core
|
||||
sysctl -w kernel.core_uses_pid=0
|
||||
# Arch Linux requires core_pattern to be empty :(
|
||||
test -e /etc/arch-release && sysctl -w kernel.core_pattern=
|
||||
test -e /etc/arch-release || sysctl -w kernel.core_pattern=core
|
||||
sysctl -w kernel.randomize_va_space=0
|
||||
sysctl -w kernel.sched_child_runs_first=1
|
||||
sysctl -w kernel.sched_autogroup_enabled=1
|
||||
sysctl -w kernel.sched_migration_cost_ns=50000000
|
||||
sysctl -w kernel.sched_latency_ns=250000000
|
||||
sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null
|
||||
sysctl -w kernel.sched_latency_ns=250000000 2>/dev/null
|
||||
echo never > /sys/kernel/mm/transparent_hugepage/enabled
|
||||
test -e /sys/devices/system/cpu/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/scaling_governor
|
||||
test -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor
|
||||
test -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||
test -e /sys/devices/system/cpu/intel_pstate/no_turbo && echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo
|
||||
test -e /sys/devices/system/cpu/cpufreq/boost && echo 1 > /sys/devices/system/cpu/cpufreq/boost
|
||||
test -e /sys/devices/system/cpu/intel_pstate/max_perf_pct && echo 100 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
|
||||
test -n "$(which auditctl)" && auditctl -a never,task >/dev/null 2>&1
|
||||
} > /dev/null
|
||||
echo Settings applied.
|
||||
echo
|
||||
dmesg | egrep -q 'nospectre_v2|spectre_v2=off' || {
|
||||
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
|
||||
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"'
|
||||
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
|
||||
echo
|
||||
}
|
||||
echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "FreeBSD" ] ; then
|
||||
@ -48,36 +62,76 @@ if [ "$PLATFORM" = "FreeBSD" ] ; then
|
||||
sysctl kern.elf64.aslr.enable=0
|
||||
} > /dev/null
|
||||
echo Settings applied.
|
||||
echo
|
||||
cat <<EOF
|
||||
In order to suppress core file generation during fuzzing it is recommended to set
|
||||
me:\\
|
||||
:coredumpsize=0:
|
||||
in the ~/.login_conf file for the user used for fuzzing.
|
||||
EOF
|
||||
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
|
||||
echo ' sysctl hw.ibrs_disable=1'
|
||||
echo 'Setting kern.pmap.pg_ps_enabled=0 into /boot/loader.conf might be helpful too.'
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "OpenBSD" ] ; then
|
||||
echo
|
||||
doas sysctl vm.malloc_conf=
|
||||
echo 'Freecheck on allocation in particular can be detrimental to performance.'
|
||||
echo 'Also we might not want necessarily to abort at any allocation failure.'
|
||||
echo 'System security features cannot be disabled on OpenBSD.'
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "DragonFly" ] ; then
|
||||
#/sbin/sysctl kern.corefile=/dev/null
|
||||
#echo Settings applied.
|
||||
cat <<EOF
|
||||
In order to suppress core file generation during fuzzing it is recommended to set
|
||||
me:\\
|
||||
:coredumpsize=0:
|
||||
in the ~/.login_conf file for the user used for fuzzing.
|
||||
EOF
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "NetBSD" ] ; then
|
||||
{
|
||||
#echo It is recommended to enable unprivileged users to set cpu affinity
|
||||
#echo to be able to use afl-gotcpu meaningfully.
|
||||
/sbin/sysctl -w security.models.extensions.user_set_cpu_affinity=1
|
||||
} > /dev/null
|
||||
echo Settings applied.
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "Darwin" ] ; then
|
||||
sysctl kern.sysv.shmmax=524288000
|
||||
sysctl kern.sysv.shmmin=1
|
||||
sysctl kern.sysv.shmseg=48
|
||||
sysctl kern.sysv.shmall=131072000
|
||||
echo Settings applied.
|
||||
echo
|
||||
if [ $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ] ; then
|
||||
echo We unload the default crash reporter here
|
||||
echo
|
||||
echo Unloading the default crash reporter
|
||||
SL=/System/Library; PL=com.apple.ReportCrash
|
||||
launchctl unload -w ${SL}/LaunchAgents/${PL}.plist
|
||||
sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist
|
||||
echo Settings applied.
|
||||
else
|
||||
echo Nothing to do.
|
||||
launchctl unload -w ${SL}/LaunchAgents/${PL}.plist >/dev/null 2>&1
|
||||
sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1
|
||||
echo
|
||||
fi
|
||||
echo It is recommended to disable System Integrity Protection for increased performance.
|
||||
echo
|
||||
DONE=1
|
||||
fi
|
||||
if [ "$PLATFORM" = "Haiku" ] ; then
|
||||
DEBUG_SERVER_DIR=~/config/settings/system/debug_server
|
||||
[ ! -d ${DEBUG_SERVER_DIR} ] && mkdir -p ${DEBUG_SERVER_DIR}
|
||||
SETTINGS=${DEBUG_SERVER_DIR}/settings
|
||||
[ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
|
||||
echo We change the debug_server default_action from user to silently kill; \
|
||||
[ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
|
||||
echo Settings applied.; echo; \
|
||||
}
|
||||
DONE=1
|
||||
fi
|
||||
test -z "$DONE" && echo Error: Unknown platform: $PLATFORM
|
||||
test -z "$AFL_TMPDIR" && echo Also use AFL_TMPDIR and point it to a tmpfs for the input file caching
|
||||
exit 0
|
||||
|
111
afl-whatsup
111
afl-whatsup
@ -6,13 +6,13 @@
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# 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");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# This tool summarizes the status of any locally-running synchronized
|
||||
# instances of afl-fuzz.
|
||||
@ -20,33 +20,42 @@
|
||||
|
||||
echo "$0 status check tool for afl-fuzz by Michal Zalewski"
|
||||
echo
|
||||
test "$1" = "-h" && {
|
||||
echo $0 [-s] output_directory
|
||||
test "$1" = "-h" -o "$1" = "-hh" && {
|
||||
echo "Usage: $0 [-s] [-d] afl_output_directory"
|
||||
echo
|
||||
echo Options:
|
||||
echo -s - skip details and output summary results only
|
||||
echo " -s - skip details and output summary results only"
|
||||
echo " -d - include dead fuzzer stats"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$1" = "-s" ]; then
|
||||
unset SUMMARY_ONLY
|
||||
unset PROCESS_DEAD
|
||||
|
||||
SUMMARY_ONLY=1
|
||||
DIR="$2"
|
||||
while [ "$1" = "-s" -o "$1" = "-d" ]; do
|
||||
|
||||
else
|
||||
if [ "$1" = "-s" ]; then
|
||||
SUMMARY_ONLY=1
|
||||
fi
|
||||
|
||||
unset SUMMARY_ONLY
|
||||
DIR="$1"
|
||||
if [ "$1" = "-d" ]; then
|
||||
PROCESS_DEAD=1
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
DIR="$1"
|
||||
|
||||
if [ "$DIR" = "" ]; then
|
||||
|
||||
echo "Usage: $0 [ -s ] afl_sync_dir" 1>&2
|
||||
echo "Usage: $0 [-s] [-d] afl_output_directory" 1>&2
|
||||
echo 1>&2
|
||||
echo "The -s option causes the tool to skip all the per-fuzzer trivia and show" 1>&2
|
||||
echo "just the summary results. See docs/parallel_fuzzing.md for additional tips." 1>&2
|
||||
echo Options: 1>&2
|
||||
echo " -s - skip details and output summary results only" 1>&2
|
||||
echo " -d - include dead fuzzer stats" 1>&2
|
||||
echo 1>&2
|
||||
exit 1
|
||||
|
||||
@ -82,9 +91,9 @@ TOTAL_CRASHES=0
|
||||
TOTAL_PFAV=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_PATH="${RED}none seen yet${NC}"
|
||||
FMT_FIND="${RED}none seen yet${NC}"
|
||||
FMT_CRASH="none seen yet"
|
||||
FMT_HANG="none seen yet"
|
||||
|
||||
@ -99,7 +108,7 @@ fi
|
||||
fmt_duration()
|
||||
{
|
||||
DUR_STRING=
|
||||
if [ $1 -eq 0 ]; then
|
||||
if [ $1 -le 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -109,7 +118,11 @@ fmt_duration()
|
||||
local minutes=$(((duration / 60) % 60))
|
||||
local seconds=$((duration % 60))
|
||||
|
||||
if [ $days -gt 0 ]; then
|
||||
if [ $duration -le 0 ]; then
|
||||
DUR_STRING="0 seconds"
|
||||
elif [ $duration -eq 1 ]; then
|
||||
DUR_STRING="1 second"
|
||||
elif [ $days -gt 0 ]; then
|
||||
DUR_STRING="$days days, $hours hours"
|
||||
elif [ $hours -gt 0 ]; then
|
||||
DUR_STRING="$hours hours, $minutes minutes"
|
||||
@ -122,14 +135,14 @@ fmt_duration()
|
||||
|
||||
FIRST=true
|
||||
TOTAL_WCOP=
|
||||
TOTAL_LAST_PATH=0
|
||||
TOTAL_LAST_FIND=0
|
||||
|
||||
for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
|
||||
. "$TMP"
|
||||
|
||||
RUN_UNIX=$((CUR_TIME - start_time))
|
||||
RUN_UNIX=$run_time
|
||||
RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24))
|
||||
RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24))
|
||||
|
||||
@ -156,24 +169,31 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
fi
|
||||
|
||||
DEAD_CNT=$((DEAD_CNT + 1))
|
||||
continue
|
||||
last_find=0
|
||||
|
||||
if [ "$PROCESS_DEAD" = "" ]; then
|
||||
|
||||
continue
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
ALIVE_CNT=$((ALIVE_CNT + 1))
|
||||
|
||||
EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||
PATH_PERC=$((cur_path * 100 / paths_total))
|
||||
EXEC_SEC=0
|
||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||
|
||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||
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_PFAV=$((TOTAL_PFAV + pending_favs))
|
||||
|
||||
if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then
|
||||
TOTAL_LAST_PATH=$last_path
|
||||
if [ "$last_find" -gt "$TOTAL_LAST_FIND" ]; then
|
||||
TOTAL_LAST_FIND=$last_find
|
||||
fi
|
||||
|
||||
if [ "$SUMMARY_ONLY" = "" ]; then
|
||||
@ -184,11 +204,13 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
echo " ${RED}timeout_ratio $TIMEOUT_PERC%${NC}"
|
||||
fi
|
||||
|
||||
if [ $EXEC_SEC -lt 100 ]; then
|
||||
if [ $EXEC_SEC -eq 0 ]; then
|
||||
echo " ${YELLOW}no data yet, 0 execs/sec${NC}"
|
||||
elif [ $EXEC_SEC -lt 100 ]; then
|
||||
echo " ${RED}slow execution, $EXEC_SEC execs/sec${NC}"
|
||||
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_hang && FMT_HANG=$DUR_STRING
|
||||
FMT_CWOP="not available"
|
||||
@ -198,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}"
|
||||
}
|
||||
|
||||
echo " last_path : $FMT_PATH"
|
||||
echo " last_find : $FMT_FIND"
|
||||
echo " last_crash : $FMT_CRASH"
|
||||
echo " last_hang : $FMT_HANG"
|
||||
echo " cycles_wo_finds : $FMT_CWOP"
|
||||
@ -207,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}')
|
||||
|
||||
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"
|
||||
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
|
||||
|
||||
echo
|
||||
@ -221,7 +243,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
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
|
||||
# Formatting for total execution
|
||||
FMT_EXECS="0 millions"
|
||||
@ -241,17 +263,28 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
|
||||
TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
|
||||
|
||||
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
|
||||
|
||||
if [ "$PROCESS_DEAD" = "" ]; then
|
||||
|
||||
TXT="excluded from stats"
|
||||
|
||||
else
|
||||
|
||||
TXT="included in stats"
|
||||
ALIVE_CNT=$(($ALIVE_CNT - $DEAD_CNT))
|
||||
|
||||
fi
|
||||
|
||||
echo "Summary stats"
|
||||
echo "============="
|
||||
echo
|
||||
echo " Fuzzers alive : $ALIVE_CNT"
|
||||
|
||||
if [ ! "$DEAD_CNT" = "0" ]; then
|
||||
echo " Dead or remote : $DEAD_CNT (excluded from stats)"
|
||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||
fi
|
||||
|
||||
echo " Total run time : $FMT_TIME"
|
||||
@ -260,15 +293,15 @@ echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
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
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
fi
|
||||
|
||||
echo " Crashes found : $TOTAL_CRASHES locally unique"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
echo "Cycles without finds : $TOTAL_WCOP"
|
||||
echo " Time without finds : $TOTAL_LAST_PATH"
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
@ -28,9 +28,9 @@ if not os.getenv("AFL_INST_LIBS"):
|
||||
os.environ["AFL_CODE_END"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode + pe.OPTIONAL_HEADER.SizeOfCode)
|
||||
|
||||
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]:
|
||||
os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so")
|
||||
os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so") + ",WINEARCH=win64"
|
||||
else:
|
||||
os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so")
|
||||
os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so") + ",WINEARCH=win32"
|
||||
|
||||
if os.getenv("WINECOV_QEMU_PATH"):
|
||||
qemu_path = os.getenv("WINECOV_QEMU_PATH")
|
||||
@ -68,7 +68,12 @@ else:
|
||||
argv = sys.argv[1:]
|
||||
for i in range(len(argv)):
|
||||
if ".cur_input" in argv[i]:
|
||||
argv[i] = subprocess.run([os.path.join(os.path.dirname(wine_path), "winepath"), "--windows", argv[i]], universal_newlines=True, stdout=subprocess.PIPE).stdout
|
||||
# Get the Wine translated path using the winepath tool
|
||||
arg_translated = subprocess.run([os.path.join(os.path.dirname(wine_path), "winepath"), "--windows", argv[i]], universal_newlines=True, stdout=subprocess.PIPE).stdout
|
||||
# Remove the spurious LF at the end of the path
|
||||
if len(arg_translated) > 0 and arg_translated[-1] == '\n':
|
||||
arg_translated = arg_translated[:-1]
|
||||
argv[i] = arg_translated
|
||||
break
|
||||
|
||||
print("[afl-wine-trace] exec:", " ".join([qemu_path, wine_path] + argv))
|
||||
|
2
coresight_mode/.gitignore
vendored
Normal file
2
coresight_mode/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.local
|
||||
glibc*
|
62
coresight_mode/GNUmakefile
Normal file
62
coresight_mode/GNUmakefile
Normal file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env make
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2021 Ricerca Security, Inc. All rights reserved.
|
||||
|
||||
SHELL:=bash
|
||||
PREFIX?=$(shell pwd)/.local
|
||||
|
||||
CS_TRACE:=coresight-trace
|
||||
|
||||
PATCHELF?=$(PREFIX)/bin/patchelf
|
||||
|
||||
PATCH_DIR:=patches
|
||||
|
||||
GLIBC_VER:=2.33
|
||||
GLIBC_NAME:=glibc-$(GLIBC_VER)
|
||||
GLIBC_URL_BASE:=http://ftp.gnu.org/gnu/glibc
|
||||
GLIBC_LDSO?=$(PREFIX)/lib/ld-linux-aarch64.so.1
|
||||
|
||||
OUTPUT?="$(TARGET).patched"
|
||||
|
||||
all: build
|
||||
|
||||
build:
|
||||
git submodule update --init --recursive $(CS_TRACE)
|
||||
$(MAKE) -C $(CS_TRACE)
|
||||
cp $(CS_TRACE)/cs-proxy ../afl-cs-proxy
|
||||
|
||||
patch: | $(PATCHELF) $(GLIBC_LDSO)
|
||||
@if test -z "$(TARGET)"; then echo "TARGET is not set"; exit 1; fi
|
||||
$(PATCHELF) \
|
||||
--set-interpreter $(GLIBC_LDSO) \
|
||||
--set-rpath $(dir $(GLIBC_LDSO)) \
|
||||
--output $(OUTPUT) \
|
||||
$(TARGET)
|
||||
|
||||
$(PATCHELF): patchelf
|
||||
git submodule update --init $<
|
||||
cd $< && \
|
||||
./bootstrap.sh && \
|
||||
./configure --prefix=$(PREFIX) && \
|
||||
$(MAKE) && \
|
||||
$(MAKE) check && \
|
||||
$(MAKE) install
|
||||
|
||||
$(GLIBC_LDSO): | $(GLIBC_NAME).tar.xz
|
||||
tar -xf $(GLIBC_NAME).tar.xz
|
||||
for file in $(shell find $(PATCH_DIR) -maxdepth 1 -type f); do \
|
||||
patch -p1 < $$file ; \
|
||||
done
|
||||
mkdir -p $(GLIBC_NAME)/build
|
||||
cd $(GLIBC_NAME)/build && \
|
||||
../configure --prefix=$(PREFIX) && \
|
||||
$(MAKE) && \
|
||||
$(MAKE) install
|
||||
|
||||
$(GLIBC_NAME).tar.xz:
|
||||
wget -O $@ $(GLIBC_URL_BASE)/$@
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(CS_TRACE) clean
|
||||
|
||||
.PHONY: all build patch clean
|
21
coresight_mode/Makefile
Normal file
21
coresight_mode/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env make
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2021 Ricerca Security, Inc. All rights reserved.
|
||||
|
||||
all:
|
||||
@echo trying to use GNU make...
|
||||
@gmake all || echo please install GNUmake
|
||||
|
||||
build:
|
||||
@echo trying to use GNU make...
|
||||
@gmake build || echo please install GNUmake
|
||||
|
||||
patch:
|
||||
@echo trying to use GNU make...
|
||||
@gmake patch || echo please install GNUmake
|
||||
|
||||
clean:
|
||||
@echo trying to use GNU make...
|
||||
@gmake clean || echo please install GNUmake
|
||||
|
||||
.PHONY: all build patch clean
|
70
coresight_mode/README.md
Normal file
70
coresight_mode/README.md
Normal file
@ -0,0 +1,70 @@
|
||||
# AFL++ CoreSight mode
|
||||
|
||||
CoreSight mode enables binary-only fuzzing on ARM64 Linux using CoreSight (ARM's hardware tracing technology).
|
||||
|
||||
NOTE: CoreSight mode is in the early development stage. Not applicable for production use.
|
||||
Currently the following hardware boards are supported:
|
||||
* NVIDIA Jetson TX2 (NVIDIA Parker)
|
||||
* NVIDIA Jetson Nano (NVIDIA Tegra X1)
|
||||
* GIGABYTE R181-T90 (Marvell ThunderX2 CN99XX)
|
||||
|
||||
## Getting started
|
||||
|
||||
Please read the [RICSec/coresight-trace README](https://github.com/RICSecLab/coresight-trace/blob/master/README.md) and check the prerequisites (capstone) before getting started.
|
||||
|
||||
CoreSight mode supports the AFL++ fork server mode to reduce `exec` system call
|
||||
overhead. To support it for binary-only fuzzing, it needs to modify the target
|
||||
ELF binary to re-link to the patched glibc. We employ this design from
|
||||
[PTrix](https://github.com/junxzm1990/afl-pt).
|
||||
|
||||
Check out all the git submodules in the `cs_mode` directory:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### Build coresight-trace
|
||||
|
||||
There are some notes on building coresight-trace. Refer to the [README](https://github.com/RICSecLab/coresight-trace/blob/master/README.md) for the details. Run make in the `cs_mode` directory:
|
||||
|
||||
```bash
|
||||
make build
|
||||
```
|
||||
|
||||
Make sure `cs-proxy` is placed in the AFL++ root directory as `afl-cs-proxy`.
|
||||
|
||||
### Patch COTS binary
|
||||
|
||||
The fork server mode requires patchelf and the patched glibc. The dependency build can be done by just run make:
|
||||
|
||||
```bash
|
||||
make patch TARGET=$BIN
|
||||
```
|
||||
|
||||
The above make command builds and installs the dependencies to `$PREFIX` (default to `$PWD/.local`) at the first time. Then, it runs `patchelf` to `$BIN` with output `$OUTPUT` (`$BIN.patched` by default).
|
||||
|
||||
### Run afl-fuzz
|
||||
|
||||
Run `afl-fuzz` with `-A` option to use CoreSight mode.
|
||||
|
||||
```bash
|
||||
sudo afl-fuzz -A -i input -o output -- $OUTPUT @@
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
There are AFL++ CoreSight mode-specific environment variables for run-time configuration.
|
||||
|
||||
* `AFL_CS_CUSTOM_BIN` overrides the proxy application path. `afl-cs-proxy` will be used if not defined.
|
||||
|
||||
* `AFLCS_COV` specifies coverage type on CoreSight trace decoding. `edge` and `path` is supported. The default value is `edge`.
|
||||
* `AFLCS_UDMABUF` is the u-dma-buf device number used to store trace data in the DMA region. The default value is `0`.
|
||||
|
||||
## TODO List
|
||||
|
||||
* Eliminate modified glibc dependency
|
||||
* Support parallel fuzzing
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This project has received funding from the Acquisition, Technology & Logistics Agency (ATLA) under the National Security Technology Research Promotion Fund 2021 (JPJ004596).
|
1
coresight_mode/coresight-trace
Submodule
1
coresight_mode/coresight-trace
Submodule
Submodule coresight_mode/coresight-trace added at fe8b26ea4b
1
coresight_mode/patchelf
Submodule
1
coresight_mode/patchelf
Submodule
Submodule coresight_mode/patchelf added at be0cc30a59
117
coresight_mode/patches/0001-Add-AFL-forkserver.patch
Normal file
117
coresight_mode/patches/0001-Add-AFL-forkserver.patch
Normal file
@ -0,0 +1,117 @@
|
||||
diff --git a/glibc-2.33/elf/rtld.c b/glibc-2.33/elf/rtld.c
|
||||
index 596b6ac3..2ee270d4 100644
|
||||
--- a/glibc-2.33/elf/rtld.c
|
||||
+++ b/glibc-2.33/elf/rtld.c
|
||||
@@ -169,6 +169,99 @@ uintptr_t __pointer_chk_guard_local
|
||||
strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
|
||||
#endif
|
||||
|
||||
+#define AFLCS_RTLD 1
|
||||
+
|
||||
+#if AFLCS_RTLD
|
||||
+
|
||||
+#include <sys/shm.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <dlfcn.h>
|
||||
+#include <signal.h>
|
||||
+
|
||||
+#include <asm/unistd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#define FORKSRV_FD 198
|
||||
+
|
||||
+#define AFLCS_ENABLE "__AFLCS_ENABLE"
|
||||
+
|
||||
+/* We use this additional AFLCS_# AFLCS_#+1 pair to communicate with proxy */
|
||||
+#define AFLCS_FORKSRV_FD (FORKSRV_FD - 3)
|
||||
+#define AFLCS_RTLD_SNIPPET do { __cs_start_forkserver(); } while(0)
|
||||
+
|
||||
+/* Fork server logic, invoked before we return from _dl_start. */
|
||||
+
|
||||
+static void __cs_start_forkserver(void) {
|
||||
+ int status;
|
||||
+ pid_t child_pid;
|
||||
+ static char tmp[4] = {0, 0, 0, 0};
|
||||
+
|
||||
+ if (!getenv(AFLCS_ENABLE)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (write(AFLCS_FORKSRV_FD + 1, tmp, 4) != 4) {
|
||||
+ _exit(-1);
|
||||
+ }
|
||||
+
|
||||
+ /* All right, let's await orders... */
|
||||
+ while (1) {
|
||||
+ /* Whoops, parent dead? */
|
||||
+ if (read(AFLCS_FORKSRV_FD, tmp, 4) != 4) {
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+
|
||||
+ child_pid = INLINE_SYSCALL(clone, 5,
|
||||
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,
|
||||
+ NULL, NULL, &THREAD_SELF->tid);
|
||||
+ if (child_pid < 0) {
|
||||
+ _exit(4);
|
||||
+ }
|
||||
+ if (!child_pid) {
|
||||
+ /* Child process. Wait for parent start tracing */
|
||||
+ kill(getpid(), SIGSTOP);
|
||||
+ /* Close descriptors and run free. */
|
||||
+ close(AFLCS_FORKSRV_FD);
|
||||
+ close(AFLCS_FORKSRV_FD + 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Parent. */
|
||||
+ if (write(AFLCS_FORKSRV_FD + 1, &child_pid, 4) != 4) {
|
||||
+ _exit(5);
|
||||
+ }
|
||||
+
|
||||
+ /* Wait until SIGCONT is signaled. */
|
||||
+ if (waitpid(child_pid, &status, WCONTINUED) < 0) {
|
||||
+ _exit(6);
|
||||
+ }
|
||||
+ if (!WIFCONTINUED(status)) {
|
||||
+ /* Relay status to proxy. */
|
||||
+ if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) {
|
||||
+ _exit(7);
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ while (1) {
|
||||
+ /* Get status. */
|
||||
+ if (waitpid(child_pid, &status, WUNTRACED) < 0) {
|
||||
+ _exit(8);
|
||||
+ }
|
||||
+ /* Relay status to proxy. */
|
||||
+ if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) {
|
||||
+ _exit(9);
|
||||
+ }
|
||||
+ if (!(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)) {
|
||||
+ /* The child process is exited. */
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif /* AFLCS_RTLD */
|
||||
+
|
||||
/* Check that AT_SECURE=0, or that the passed name does not contain
|
||||
directories and is not overly long. Reject empty names
|
||||
unconditionally. */
|
||||
@@ -588,6 +681,12 @@ _dl_start (void *arg)
|
||||
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
|
||||
#endif
|
||||
|
||||
+ /* AFL-CS-START */
|
||||
+#if AFLCS_RTLD
|
||||
+ AFLCS_RTLD_SNIPPET;
|
||||
+#endif
|
||||
+ /* AFL-CS-END */
|
||||
+
|
||||
return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
|
||||
}
|
||||
}
|
121
custom_mutators/Android.bp
Normal file
121
custom_mutators/Android.bp
Normal file
@ -0,0 +1,121 @@
|
||||
cc_library_shared {
|
||||
name: "libfuzzer-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-fpermissive",
|
||||
"-std=c++11",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-unused-variable",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"libfuzzer/FuzzerCrossOver.cpp",
|
||||
"libfuzzer/FuzzerDataFlowTrace.cpp",
|
||||
"libfuzzer/FuzzerDriver.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsDlsym.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsWeak.cpp",
|
||||
"libfuzzer/FuzzerExtFunctionsWindows.cpp",
|
||||
"libfuzzer/FuzzerExtraCounters.cpp",
|
||||
"libfuzzer/FuzzerFork.cpp",
|
||||
"libfuzzer/FuzzerIO.cpp",
|
||||
"libfuzzer/FuzzerIOPosix.cpp",
|
||||
"libfuzzer/FuzzerIOWindows.cpp",
|
||||
"libfuzzer/FuzzerLoop.cpp",
|
||||
"libfuzzer/FuzzerMerge.cpp",
|
||||
"libfuzzer/FuzzerMutate.cpp",
|
||||
"libfuzzer/FuzzerSHA1.cpp",
|
||||
"libfuzzer/FuzzerTracePC.cpp",
|
||||
"libfuzzer/FuzzerUtil.cpp",
|
||||
"libfuzzer/FuzzerUtilDarwin.cpp",
|
||||
"libfuzzer/FuzzerUtilFuchsia.cpp",
|
||||
"libfuzzer/FuzzerUtilLinux.cpp",
|
||||
"libfuzzer/FuzzerUtilPosix.cpp",
|
||||
"libfuzzer/FuzzerUtilWindows.cpp",
|
||||
"libfuzzer/libfuzzer.cpp",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
/*cc_library_shared {
|
||||
name: "honggfuzz-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-Wl,-Bsymbolic",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"honggfuzz/honggfuzz.c",
|
||||
"honggfuzz/mangle.c",
|
||||
// "../src/afl-perfomance.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}*/
|
||||
|
||||
cc_library_shared {
|
||||
name: "radamsa-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-unused-function",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"radamsa/libradamsa.c",
|
||||
"radamsa/radamsa-mutator.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "symcc-mutator",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-O0",
|
||||
"-funroll-loops",
|
||||
"-fPIC",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-pointer-sign",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"symcc/symcc.c",
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libafl_headers",
|
||||
],
|
||||
}
|
||||
|
||||
subdirs = [
|
||||
"libprotobuf-mutator-example",
|
||||
]
|
@ -1,4 +1,30 @@
|
||||
# production ready custom mutators
|
||||
# Custom Mutators
|
||||
|
||||
Custom mutators enhance and alter the mutation strategies of AFL++.
|
||||
For further information and documentation on how to write your own, read [the docs](../docs/custom_mutators.md).
|
||||
|
||||
## Examples
|
||||
|
||||
The `./examples` folder contains examples for custom mutators in python and C.
|
||||
|
||||
## Rust
|
||||
|
||||
In `./rust`, you will find rust bindings, including a simple example in `./rust/example` and an example for structured fuzzing, based on lain, in`./rust/example_lain`.
|
||||
|
||||
## The AFL++ Grammar Mutator
|
||||
|
||||
If you use git to clone AFL++, then the following will incorporate our
|
||||
excellent grammar custom mutator:
|
||||
|
||||
```sh
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
Read the README in the [Grammar-Mutator] repository on how to use it.
|
||||
|
||||
[Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator
|
||||
|
||||
## Production-Ready Custom Mutators
|
||||
|
||||
This directory holds ready to use custom mutators.
|
||||
Just type "make" in the individual subdirectories.
|
||||
@ -10,3 +36,25 @@ Use with e.g.
|
||||
and add `AFL_CUSTOM_MUTATOR_ONLY=1` if you only want to use the custom mutator.
|
||||
|
||||
Multiple custom mutators can be used by separating their paths with `:` in the environment variable.
|
||||
|
||||
## 3rd Party Custom Mutators
|
||||
|
||||
### Superion Mutators
|
||||
|
||||
Adrian Tiron ported the Superion grammar fuzzer to AFL++, it is WIP and
|
||||
requires cmake (among other things):
|
||||
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
|
||||
|
||||
### libprotobuf Mutators
|
||||
|
||||
There are two WIP protobuf projects, that require work to be working though:
|
||||
|
||||
transforms protobuf raw:
|
||||
https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator
|
||||
|
||||
has a transform function you need to fill for your protobuf format, however
|
||||
needs to be ported to the updated AFL++ custom mutator API (not much work):
|
||||
https://github.com/thebabush/afl-libprotobuf-mutator
|
||||
|
||||
same as above but is for current AFL++:
|
||||
https://github.com/P1umer/AFLplusplus-protobuf-mutator
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Examples for the custom mutator
|
||||
|
||||
These are example and helper files for the custom mutator feature.
|
||||
See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information
|
||||
See [docs/custom_mutators.md](../../docs/custom_mutators.md) for more information
|
||||
|
||||
Note that if you compile with python3.7 you must use python3 scripts, and if
|
||||
you use python2.7 to compile python2 scripts!
|
@ -12,12 +12,13 @@ import random, re, io
|
||||
# The XmlMutatorMin class #
|
||||
###########################
|
||||
|
||||
|
||||
class XmlMutatorMin:
|
||||
|
||||
"""
|
||||
Optionals parameters:
|
||||
seed Seed used by the PRNG (default: "RANDOM")
|
||||
verbose Verbosity (default: False)
|
||||
Optionals parameters:
|
||||
seed Seed used by the PRNG (default: "RANDOM")
|
||||
verbose Verbosity (default: False)
|
||||
"""
|
||||
|
||||
def __init__(self, seed="RANDOM", verbose=False):
|
||||
@ -41,7 +42,12 @@ class XmlMutatorMin:
|
||||
self.tree = None
|
||||
|
||||
# High-level mutators (no database needed)
|
||||
hl_mutators_delete = ["del_node_and_children", "del_node_but_children", "del_attribute", "del_content"] # Delete items
|
||||
hl_mutators_delete = [
|
||||
"del_node_and_children",
|
||||
"del_node_but_children",
|
||||
"del_attribute",
|
||||
"del_content",
|
||||
] # Delete items
|
||||
hl_mutators_fuzz = ["fuzz_attribute"] # Randomly change attribute values
|
||||
|
||||
# Exposed mutators
|
||||
@ -74,7 +80,9 @@ class XmlMutatorMin:
|
||||
|
||||
""" Serialize a XML document. Basic wrapper around lxml.tostring() """
|
||||
|
||||
return ET.tostring(tree, with_tail=False, xml_declaration=True, encoding=tree.docinfo.encoding)
|
||||
return ET.tostring(
|
||||
tree, with_tail=False, xml_declaration=True, encoding=tree.docinfo.encoding
|
||||
)
|
||||
|
||||
def __ver(self, version):
|
||||
|
||||
@ -161,7 +169,7 @@ class XmlMutatorMin:
|
||||
# Randomly pick one the function calls
|
||||
(func, args) = random.choice(l)
|
||||
# Split by "," and randomly pick one of the arguments
|
||||
value = random.choice(args.split(','))
|
||||
value = random.choice(args.split(","))
|
||||
# Remove superfluous characters
|
||||
unclean_value = value
|
||||
value = value.strip(" ").strip("'")
|
||||
@ -170,49 +178,49 @@ class XmlMutatorMin:
|
||||
value = attrib_value
|
||||
|
||||
# For each type, define some possible replacement values
|
||||
choices_number = ( \
|
||||
"0", \
|
||||
"11111", \
|
||||
"-128", \
|
||||
"2", \
|
||||
"-1", \
|
||||
"1/3", \
|
||||
"42/0", \
|
||||
"1094861636 idiv 1.0", \
|
||||
"-1123329771506872 idiv 3.8", \
|
||||
"17=$numericRTF", \
|
||||
str(3 + random.randrange(0, 100)), \
|
||||
)
|
||||
choices_number = (
|
||||
"0",
|
||||
"11111",
|
||||
"-128",
|
||||
"2",
|
||||
"-1",
|
||||
"1/3",
|
||||
"42/0",
|
||||
"1094861636 idiv 1.0",
|
||||
"-1123329771506872 idiv 3.8",
|
||||
"17=$numericRTF",
|
||||
str(3 + random.randrange(0, 100)),
|
||||
)
|
||||
|
||||
choices_letter = ( \
|
||||
"P" * (25 * random.randrange(1, 100)), \
|
||||
"%s%s%s%s%s%s", \
|
||||
"foobar", \
|
||||
)
|
||||
choices_letter = (
|
||||
"P" * (25 * random.randrange(1, 100)),
|
||||
"%s%s%s%s%s%s",
|
||||
"foobar",
|
||||
)
|
||||
|
||||
choices_alnum = ( \
|
||||
"Abc123", \
|
||||
"020F0302020204030204", \
|
||||
"020F0302020204030204" * (random.randrange(5, 20)), \
|
||||
)
|
||||
choices_alnum = (
|
||||
"Abc123",
|
||||
"020F0302020204030204",
|
||||
"020F0302020204030204" * (random.randrange(5, 20)),
|
||||
)
|
||||
|
||||
# Fuzz the value
|
||||
if random.choice((True,False)) and value == "":
|
||||
if random.choice((True, False)) and value == "":
|
||||
|
||||
# Empty
|
||||
new_value = value
|
||||
|
||||
elif random.choice((True,False)) and value.isdigit():
|
||||
elif random.choice((True, False)) and value.isdigit():
|
||||
|
||||
# Numbers
|
||||
new_value = random.choice(choices_number)
|
||||
|
||||
elif random.choice((True,False)) and value.isalpha():
|
||||
elif random.choice((True, False)) and value.isalpha():
|
||||
|
||||
# Letters
|
||||
new_value = random.choice(choices_letter)
|
||||
|
||||
elif random.choice((True,False)) and value.isalnum():
|
||||
elif random.choice((True, False)) and value.isalnum():
|
||||
|
||||
# Alphanumeric
|
||||
new_value = random.choice(choices_alnum)
|
||||
@ -232,22 +240,25 @@ class XmlMutatorMin:
|
||||
|
||||
# Log something
|
||||
if self.verbose:
|
||||
print("Fuzzing attribute #%i '%s' of tag #%i '%s'" % (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag))
|
||||
print(
|
||||
"Fuzzing attribute #%i '%s' of tag #%i '%s'"
|
||||
% (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag)
|
||||
)
|
||||
|
||||
# Modify the attribute
|
||||
rand_elem.set(rand_attrib, new_value.decode("utf-8"))
|
||||
|
||||
def __del_node_and_children(self):
|
||||
|
||||
""" High-level minimizing mutator
|
||||
Delete a random node and its children (i.e. delete a random tree) """
|
||||
"""High-level minimizing mutator
|
||||
Delete a random node and its children (i.e. delete a random tree)"""
|
||||
|
||||
self.__del_node(True)
|
||||
|
||||
def __del_node_but_children(self):
|
||||
|
||||
""" High-level minimizing mutator
|
||||
Delete a random node but its children (i.e. link them to the parent of the deleted node) """
|
||||
"""High-level minimizing mutator
|
||||
Delete a random node but its children (i.e. link them to the parent of the deleted node)"""
|
||||
|
||||
self.__del_node(False)
|
||||
|
||||
@ -270,7 +281,10 @@ class XmlMutatorMin:
|
||||
# Log something
|
||||
if self.verbose:
|
||||
but_or_and = "and" if delete_children else "but"
|
||||
print("Deleting tag #%i '%s' %s its children" % (rand_elem_id, rand_elem.tag, but_or_and))
|
||||
print(
|
||||
"Deleting tag #%i '%s' %s its children"
|
||||
% (rand_elem_id, rand_elem.tag, but_or_and)
|
||||
)
|
||||
|
||||
if delete_children is False:
|
||||
# Link children of the random (soon to be deleted) node to its parent
|
||||
@ -282,8 +296,8 @@ class XmlMutatorMin:
|
||||
|
||||
def __del_content(self):
|
||||
|
||||
""" High-level minimizing mutator
|
||||
Delete the attributes and children of a random node """
|
||||
"""High-level minimizing mutator
|
||||
Delete the attributes and children of a random node"""
|
||||
|
||||
# Select a node to modify
|
||||
(rand_elem_id, rand_elem) = self.__pick_element()
|
||||
@ -297,8 +311,8 @@ class XmlMutatorMin:
|
||||
|
||||
def __del_attribute(self):
|
||||
|
||||
""" High-level minimizing mutator
|
||||
Delete a random attribute from a random node """
|
||||
"""High-level minimizing mutator
|
||||
Delete a random attribute from a random node"""
|
||||
|
||||
# Select a node to modify
|
||||
(rand_elem_id, rand_elem) = self.__pick_element()
|
||||
@ -318,7 +332,10 @@ class XmlMutatorMin:
|
||||
|
||||
# Log something
|
||||
if self.verbose:
|
||||
print("Deleting attribute #%i '%s' of tag #%i '%s'" % (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag))
|
||||
print(
|
||||
"Deleting attribute #%i '%s' of tag #%i '%s'"
|
||||
% (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag)
|
||||
)
|
||||
|
||||
# Delete the attribute
|
||||
rand_elem.attrib.pop(rand_attrib)
|
||||
@ -329,4 +346,3 @@ class XmlMutatorMin:
|
||||
|
||||
# High-level mutation
|
||||
self.__exec_among(self, self.hl_mutators_all, min, max)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
'''
|
||||
"""
|
||||
Module containing functions shared between multiple AFL modules
|
||||
|
||||
@author: Christian Holler (:decoder)
|
||||
@ -12,7 +12,7 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
@contact: choller@mozilla.com
|
||||
'''
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import random
|
||||
@ -23,18 +23,18 @@ import re
|
||||
def randel(l):
|
||||
if not l:
|
||||
return None
|
||||
return l[random.randint(0, len(l)-1)]
|
||||
return l[random.randint(0, len(l) - 1)]
|
||||
|
||||
|
||||
def randel_pop(l):
|
||||
if not l:
|
||||
return None
|
||||
return l.pop(random.randint(0, len(l)-1))
|
||||
return l.pop(random.randint(0, len(l) - 1))
|
||||
|
||||
|
||||
def write_exc_example(data, exc):
|
||||
exc_name = re.sub(r'[^a-zA-Z0-9]', '_', repr(exc))
|
||||
exc_name = re.sub(r"[^a-zA-Z0-9]", "_", repr(exc))
|
||||
|
||||
if not os.path.exists(exc_name):
|
||||
with open(exc_name, 'w') as f:
|
||||
with open(exc_name, "w") as f:
|
||||
f.write(data)
|
@ -13,7 +13,7 @@
|
||||
#define BUF_VAR(type, name) \
|
||||
type * name##_buf; \
|
||||
size_t name##_size;
|
||||
/* this filles in `&structptr->something_buf, &structptr->something_size`. */
|
||||
/* this fills in `&structptr->something_buf, &structptr->something_size`. */
|
||||
#define BUF_PARAMS(struct, name) \
|
||||
(void **)&struct->name##_buf, &struct->name##_size
|
||||
|
||||
@ -324,8 +324,8 @@ static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
|
||||
}
|
||||
|
||||
/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
|
||||
static inline void swap_bufs(void **buf1, size_t *size1, void **buf2,
|
||||
size_t *size2) {
|
||||
static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2,
|
||||
size_t *size2) {
|
||||
|
||||
void * scratch_buf = *buf1;
|
||||
size_t scratch_size = *size1;
|
@ -349,12 +349,15 @@ uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param filename_new_queue File name of the new queue entry
|
||||
* @param filename_orig_queue File name of the original queue entry
|
||||
* @return if the file contents was modified return 1 (True), 0 (False)
|
||||
* otherwise
|
||||
*/
|
||||
void afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
/* Additional analysis on the original or new test case */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
'''
|
||||
"""
|
||||
Example Python Module for AFLFuzz
|
||||
|
||||
@author: Christian Holler (:decoder)
|
||||
@ -12,7 +12,7 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
@contact: choller@mozilla.com
|
||||
'''
|
||||
"""
|
||||
|
||||
import random
|
||||
|
||||
@ -26,12 +26,12 @@ COMMANDS = [
|
||||
|
||||
|
||||
def init(seed):
|
||||
'''
|
||||
"""
|
||||
Called once when AFLFuzz starts up. Used to seed our RNG.
|
||||
|
||||
@type seed: int
|
||||
@param seed: A 32-bit random value
|
||||
'''
|
||||
"""
|
||||
random.seed(seed)
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ def deinit():
|
||||
|
||||
|
||||
def fuzz(buf, add_buf, max_size):
|
||||
'''
|
||||
"""
|
||||
Called per fuzzing iteration.
|
||||
|
||||
@type buf: bytearray
|
||||
@ -55,13 +55,14 @@ def fuzz(buf, add_buf, max_size):
|
||||
|
||||
@rtype: bytearray
|
||||
@return: A new bytearray containing the mutated data
|
||||
'''
|
||||
"""
|
||||
ret = bytearray(100)
|
||||
|
||||
ret[:3] = random.choice(COMMANDS)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# Uncomment and implement the following methods if you want to use a custom
|
||||
# trimming algorithm. See also the documentation for a better API description.
|
||||
|
@ -45,6 +45,7 @@
|
||||
1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
|
||||
and return the original `len`.
|
||||
|
||||
NOTE: the following is currently NOT true, we abort in this case!
|
||||
2) If you want to skip this test case altogether and have AFL generate a
|
||||
new one, return 0 or set `*out_buf = NULL`.
|
||||
Use this sparingly - it's faster than running the target program
|
||||
@ -53,14 +54,14 @@
|
||||
3) If you want to modify the test case, allocate an appropriately-sized
|
||||
buffer, move the data into that buffer, make the necessary changes, and
|
||||
then return the new pointer as out_buf. Return an appropriate len
|
||||
afterwards.
|
||||
afterwards.
|
||||
|
||||
Note that the buffer will *not* be freed for you. To avoid memory leaks,
|
||||
you need to free it or reuse it on subsequent calls (as shown below).
|
||||
|
||||
*** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
|
||||
|
||||
Aight. The example below shows a simple postprocessor that tries to make
|
||||
Alright. The example below shows a simple postprocessor that tries to make
|
||||
sure that all input files start with "GIF89a".
|
||||
|
||||
PS. If you don't like C, you can try out the unix-based wrapper from
|
||||
@ -83,7 +84,7 @@ typedef struct post_state {
|
||||
|
||||
} post_state_t;
|
||||
|
||||
void *afl afl_custom_init(void *afl) {
|
||||
void *afl_custom_init(void *afl) {
|
||||
|
||||
post_state_t *state = malloc(sizeof(post_state_t));
|
||||
if (!state) {
|
||||
@ -94,7 +95,13 @@ void *afl afl_custom_init(void *afl) {
|
||||
}
|
||||
|
||||
state->buf = calloc(sizeof(unsigned char), 4096);
|
||||
if (!state->buf) { return NULL; }
|
||||
if (!state->buf) {
|
||||
|
||||
free(state);
|
||||
perror("calloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -54,7 +54,13 @@ void *afl_custom_init(void *afl) {
|
||||
}
|
||||
|
||||
state->buf = calloc(sizeof(unsigned char), 4096);
|
||||
if (!state->buf) { return NULL; }
|
||||
if (!state->buf) {
|
||||
|
||||
free(state);
|
||||
perror("calloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
'''
|
||||
"""
|
||||
Simple Chunk Cross-Over Replacement Module for AFLFuzz
|
||||
|
||||
@author: Christian Holler (:decoder)
|
||||
@ -12,24 +12,24 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
@contact: choller@mozilla.com
|
||||
'''
|
||||
"""
|
||||
|
||||
import random
|
||||
|
||||
|
||||
def init(seed):
|
||||
'''
|
||||
"""
|
||||
Called once when AFLFuzz starts up. Used to seed our RNG.
|
||||
|
||||
@type seed: int
|
||||
@param seed: A 32-bit random value
|
||||
'''
|
||||
"""
|
||||
# Seed our RNG
|
||||
random.seed(seed)
|
||||
|
||||
|
||||
def fuzz(buf, add_buf, max_size):
|
||||
'''
|
||||
"""
|
||||
Called per fuzzing iteration.
|
||||
|
||||
@type buf: bytearray
|
||||
@ -44,7 +44,7 @@ def fuzz(buf, add_buf, max_size):
|
||||
|
||||
@rtype: bytearray
|
||||
@return: A new bytearray containing the mutated data
|
||||
'''
|
||||
"""
|
||||
# Make a copy of our input buffer for returning
|
||||
ret = bytearray(buf)
|
||||
|
||||
@ -58,7 +58,9 @@ def fuzz(buf, add_buf, max_size):
|
||||
rand_dst_idx = random.randint(0, len(buf))
|
||||
|
||||
# Make the chunk replacement
|
||||
ret[rand_dst_idx:rand_dst_idx + fragment_len] = add_buf[rand_src_idx:rand_src_idx + fragment_len]
|
||||
ret[rand_dst_idx : rand_dst_idx + fragment_len] = add_buf[
|
||||
rand_src_idx : rand_src_idx + fragment_len
|
||||
]
|
||||
|
||||
# Return data
|
||||
return ret
|
@ -8,7 +8,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _FIXED_CHAR
|
||||
#define 0x41
|
||||
#define _FIXED_CHAR 0x41
|
||||
#endif
|
||||
|
||||
typedef struct my_mutator {
|
@ -27,7 +27,7 @@ def log(text):
|
||||
|
||||
def init(seed):
|
||||
"""
|
||||
Called once when AFL starts up. Seed is used to identify the AFL instance in log files
|
||||
Called once when AFL starts up. Seed is used to identify the AFL instance in log files
|
||||
"""
|
||||
|
||||
global __mutator__
|
||||
@ -72,7 +72,10 @@ def fuzz(buf, add_buf, max_size):
|
||||
if via_buffer:
|
||||
try:
|
||||
__mutator__.init_from_string(buf_str)
|
||||
log("fuzz(): Mutator successfully initialized with AFL buffer (%d bytes)" % len(buf_str))
|
||||
log(
|
||||
"fuzz(): Mutator successfully initialized with AFL buffer (%d bytes)"
|
||||
% len(buf_str)
|
||||
)
|
||||
except Exception:
|
||||
via_buffer = False
|
||||
log("fuzz(): Can't initialize mutator with AFL buffer")
|
||||
@ -104,7 +107,7 @@ def fuzz(buf, add_buf, max_size):
|
||||
|
||||
|
||||
# Main (for debug)
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
|
||||
__log__ = True
|
||||
__log_file__ = "/dev/stdout"
|
||||
@ -112,7 +115,9 @@ if __name__ == '__main__':
|
||||
|
||||
init(__seed__)
|
||||
|
||||
in_1 = bytearray("<foo ddd='eeee'>ffff<a b='c' d='456' eee='ffffff'>zzzzzzzzzzzz</a><b yyy='YYY' zzz='ZZZ'></b></foo>")
|
||||
in_1 = bytearray(
|
||||
"<foo ddd='eeee'>ffff<a b='c' d='456' eee='ffffff'>zzzzzzzzzzzz</a><b yyy='YYY' zzz='ZZZ'></b></foo>"
|
||||
)
|
||||
in_2 = bytearray("<abc abc123='456' abcCBA='ppppppppppppppppppppppppppppp'/>")
|
||||
out = fuzz(in_1, in_2)
|
||||
print(out)
|
1
custom_mutators/gramatron/JSONC_VERSION
Normal file
1
custom_mutators/gramatron/JSONC_VERSION
Normal file
@ -0,0 +1 @@
|
||||
af8dd4a307e7b837f9fa2959549548ace4afe08b
|
49
custom_mutators/gramatron/README.md
Normal file
49
custom_mutators/gramatron/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# GramaTron
|
||||
|
||||
GramaTron is a coverage-guided fuzzer that uses grammar automatons to perform
|
||||
grammar-aware fuzzing. Technical details about our framework are available in
|
||||
the [ISSTA'21 paper](https://nebelwelt.net/files/21ISSTA.pdf). The artifact to
|
||||
reproduce the experiments presented in the paper are present in `artifact/`.
|
||||
Instructions to run a sample campaign and incorporate new grammars is presented
|
||||
below:
|
||||
|
||||
## Compiling
|
||||
|
||||
Execute `./build_gramatron_mutator.sh`.
|
||||
|
||||
## Running
|
||||
|
||||
You have to set the grammar file to use with `GRAMATRON_AUTOMATION`:
|
||||
|
||||
```
|
||||
export AFL_DISABLE_TRIM=1
|
||||
export AFL_CUSTOM_MUTATOR_ONLY=1
|
||||
export AFL_CUSTOM_MUTATOR_LIBRARY=./gramatron.so
|
||||
export GRAMATRON_AUTOMATION=grammars/ruby/source_automata.json
|
||||
afl-fuzz -i in -o out -- ./target
|
||||
```
|
||||
|
||||
## Adding and testing a new grammar
|
||||
|
||||
- Specify in a JSON format for CFG. Examples are correspond `source.json` files.
|
||||
- Run the automaton generation script (in `src/gramfuzz-mutator/preprocess`)
|
||||
which will place the generated automaton in the same folder.
|
||||
|
||||
```
|
||||
./preprocess/prep_automaton.sh <grammar_file> <start_symbol> [stack_limit]
|
||||
|
||||
E.g., ./preprocess/prep_automaton.sh ~/grammars/ruby/source.json PROGRAM
|
||||
```
|
||||
|
||||
- If the grammar has no self-embedding rules, then you do not need to pass the
|
||||
stack limit parameter. However, if it does have self-embedding rules, then you
|
||||
need to pass the stack limit parameter. We recommend starting with `5` and
|
||||
then increasing it if you need more complexity.
|
||||
- To sanity-check that the automaton is generating inputs as expected, you can
|
||||
use the `test` binary housed in `src/gramfuzz-mutator`.
|
||||
|
||||
```
|
||||
./test SanityCheck <automaton_file>
|
||||
|
||||
E.g., ./test SanityCheck ~/grammars/ruby/source_automata.json
|
||||
```
|
149
custom_mutators/gramatron/build_gramatron_mutator.sh
Executable file
149
custom_mutators/gramatron/build_gramatron_mutator.sh
Executable file
@ -0,0 +1,149 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# american fuzzy lop++ - gramatron build script
|
||||
# ------------------------------------------------
|
||||
#
|
||||
# Originally written by Nathan Voss <njvoss99@gmail.com>
|
||||
#
|
||||
# Adapted from code by Andrew Griffiths <agriffiths@google.com> and
|
||||
# Michal Zalewski
|
||||
#
|
||||
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
||||
#
|
||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# This script downloads, patches, and builds a version of Unicorn with
|
||||
# minor tweaks to allow Unicorn-emulated binaries to be run under
|
||||
# afl-fuzz.
|
||||
#
|
||||
# The modifications reside in patches/*. The standalone Unicorn library
|
||||
# will be written to /usr/lib/libunicornafl.so, and the Python bindings
|
||||
# will be installed system-wide.
|
||||
#
|
||||
# You must make sure that Unicorn Engine is not already installed before
|
||||
# running this script. If it is, please uninstall it first.
|
||||
|
||||
JSONC_VERSION="$(cat ./JSONC_VERSION)"
|
||||
JSONC_REPO="https://github.com/json-c/json-c"
|
||||
|
||||
echo "================================================="
|
||||
echo "Gramatron Mutator build script"
|
||||
echo "================================================="
|
||||
echo
|
||||
|
||||
echo "[*] Performing basic sanity checks..."
|
||||
|
||||
PLT=`uname -s`
|
||||
|
||||
if [ ! -f "../../config.h" ]; then
|
||||
|
||||
echo "[-] Error: key files not found - wrong working directory?"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -f "../../src/afl-performance.o" ]; then
|
||||
|
||||
echo "[-] Error: you must build afl-fuzz first and not do a \"make clean\""
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
PYTHONBIN=`command -v python3 || command -v python || command -v python2 || echo python3`
|
||||
MAKECMD=make
|
||||
TARCMD=tar
|
||||
|
||||
if [ "$PLT" = "Darwin" ]; then
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=tar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "FreeBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
PREREQ_NOTFOUND=
|
||||
for i in git $MAKECMD $TARCMD; do
|
||||
|
||||
T=`command -v "$i" 2>/dev/null`
|
||||
|
||||
if [ "$T" = "" ]; then
|
||||
|
||||
echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
|
||||
PREREQ_NOTFOUND=1
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
test -z "$CC" && export CC=cc
|
||||
|
||||
if echo "$CC" | grep -qF /afl-; then
|
||||
|
||||
echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
|
||||
PREREQ_NOTFOUND=1
|
||||
|
||||
fi
|
||||
|
||||
if [ "$PREREQ_NOTFOUND" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[+] All checks passed!"
|
||||
|
||||
echo "[*] Making sure json-c is checked out"
|
||||
|
||||
git status 1>/dev/null 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[*] initializing json-c submodule"
|
||||
git submodule init || exit 1
|
||||
git submodule update ./json-c 2>/dev/null # ignore errors
|
||||
else
|
||||
echo "[*] cloning json-c"
|
||||
test -d json-c/.git || {
|
||||
CNT=1
|
||||
while [ '!' -d json-c/.git -a "$CNT" -lt 4 ]; do
|
||||
echo "Trying to clone json-c (attempt $CNT/3)"
|
||||
git clone "$JSONC_REPO"
|
||||
CNT=`expr "$CNT" + 1`
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
test -d json-c/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||
echo "[+] Got json-c."
|
||||
|
||||
test -e json-c/.libs/libjson-c.a || {
|
||||
cd "json-c" || exit 1
|
||||
echo "[*] Checking out $JSONC_VERSION"
|
||||
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
||||
git checkout "$JSONC_VERSION" || exit 1
|
||||
sh autogen.sh || exit 1
|
||||
export CFLAGS=-fPIC
|
||||
./configure --disable-shared || exit 1
|
||||
make || exit 1
|
||||
cd ..
|
||||
}
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "[+] Json-c successfully prepared!"
|
||||
echo "[+] Builing gramatron now."
|
||||
$CC -O3 -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o gramatron.so -shared -I. -I/prg/dev/include gramfuzz.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c ../../src/afl-performance.o json-c/.libs/libjson-c.a || exit 1
|
||||
echo
|
||||
echo "[+] gramatron successfully built!"
|
336
custom_mutators/gramatron/gramfuzz-helpers.c
Normal file
336
custom_mutators/gramatron/gramfuzz-helpers.c
Normal file
@ -0,0 +1,336 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "afl-fuzz.h"
|
||||
#include "gramfuzz.h"
|
||||
|
||||
/*Slices from beginning till idx*/
|
||||
Array *slice(Array *input, int idx) {
|
||||
|
||||
// printf("\nSlice idx:%d", idx);
|
||||
terminal *origptr;
|
||||
terminal *term_ptr;
|
||||
Array * sliced = (Array *)malloc(sizeof(Array));
|
||||
initArray(sliced, input->size);
|
||||
// Populate dynamic array members
|
||||
if (idx == 0) { return sliced; }
|
||||
for (int x = 0; x < idx; x++) {
|
||||
|
||||
origptr = &input->start[x];
|
||||
insertArray(sliced, origptr->state, origptr->symbol, origptr->symbol_len,
|
||||
origptr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
return sliced;
|
||||
|
||||
}
|
||||
|
||||
/* Slices from idx till end*/
|
||||
Array *slice_inverse(Array *input, int idx) {
|
||||
|
||||
// printf("\nSlice idx:%d", idx);
|
||||
terminal *origptr;
|
||||
terminal *term_ptr;
|
||||
Array * sliced = (Array *)malloc(sizeof(Array));
|
||||
initArray(sliced, input->size);
|
||||
for (int x = idx; x < input->used; x++) {
|
||||
|
||||
origptr = &input->start[x];
|
||||
insertArray(sliced, origptr->state, origptr->symbol, origptr->symbol_len,
|
||||
origptr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
return sliced;
|
||||
|
||||
}
|
||||
|
||||
/*Carves with `start` included and `end` excluded*/
|
||||
Array *carve(Array *input, int start, int end) {
|
||||
|
||||
terminal *origptr;
|
||||
terminal *term_ptr;
|
||||
Array * sliced = (Array *)malloc(sizeof(Array));
|
||||
initArray(sliced, input->size);
|
||||
for (int x = start; x < end; x++) {
|
||||
|
||||
origptr = &input->start[x];
|
||||
insertArray(sliced, origptr->state, origptr->symbol, origptr->symbol_len,
|
||||
origptr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
return sliced;
|
||||
|
||||
}
|
||||
|
||||
/*Concats prefix + feature *mult*/
|
||||
void concatPrefixFeature(Array *prefix, Array *feature) {
|
||||
|
||||
// XXX: Currently we have hardcoded the multiplication threshold for adding
|
||||
// the recursive feature. Might want to fix it to choose a random number upper
|
||||
// bounded by a static value instead.
|
||||
terminal *featureptr;
|
||||
int len = rand_below(global_afl, RECUR_THRESHOLD);
|
||||
for (int x = 0; x < len; x++) {
|
||||
|
||||
for (int y = 0; y < feature->used; y++) {
|
||||
|
||||
featureptr = &feature->start[y];
|
||||
insertArray(prefix, featureptr->state, featureptr->symbol,
|
||||
featureptr->symbol_len, featureptr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void concatPrefixFeatureBench(Array *prefix, Array *feature) {
|
||||
|
||||
// XXX: Currently we have hardcoded the multiplication threshold for adding
|
||||
// the recursive feature. Might want to fix it to choose a random number upper
|
||||
// bounded by a static value instead.
|
||||
terminal *featureptr;
|
||||
int len =
|
||||
5; // 5 is the number of times we compare performing random recursion.
|
||||
for (int x = 0; x < len; x++) {
|
||||
|
||||
for (int y = 0; y < feature->used; y++) {
|
||||
|
||||
featureptr = &feature->start[y];
|
||||
insertArray(prefix, featureptr->state, featureptr->symbol,
|
||||
featureptr->symbol_len, featureptr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Array *spliceGF(Array *orig, Array *toSplice, int idx) {
|
||||
|
||||
terminal *toSplicePtr;
|
||||
terminal *tempPtr;
|
||||
// Iterate through the splice candidate from the `idx` till end
|
||||
for (int x = idx; x < toSplice->used; x++) {
|
||||
|
||||
toSplicePtr = &toSplice->start[x];
|
||||
insertArray(orig, toSplicePtr->state, toSplicePtr->symbol,
|
||||
toSplicePtr->symbol_len, toSplicePtr->trigger_idx);
|
||||
|
||||
}
|
||||
|
||||
return orig;
|
||||
|
||||
}
|
||||
|
||||
Array *gen_input(state *pda, Array *input) {
|
||||
|
||||
state * state_ptr;
|
||||
trigger * trigger_ptr;
|
||||
terminal *term_ptr;
|
||||
int offset = 0;
|
||||
int randval, error;
|
||||
// Generating an input for the first time
|
||||
if (input == NULL) {
|
||||
|
||||
input = (Array *)calloc(1, sizeof(Array));
|
||||
initArray(input, INIT_SIZE);
|
||||
curr_state = init_state;
|
||||
|
||||
}
|
||||
|
||||
while (curr_state != final_state) {
|
||||
|
||||
// Retrieving the state from the pda
|
||||
state_ptr = pda + curr_state;
|
||||
|
||||
// Get a random trigger
|
||||
randval = rand_below(global_afl, state_ptr->trigger_len);
|
||||
trigger_ptr = (state_ptr->ptr) + randval;
|
||||
|
||||
// Insert into the dynamic array
|
||||
insertArray(input, curr_state, trigger_ptr->term, trigger_ptr->term_len,
|
||||
randval);
|
||||
curr_state = trigger_ptr->dest;
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
return input;
|
||||
|
||||
}
|
||||
|
||||
Array *gen_input_count(state *pda, Array *input, int *mut_count) {
|
||||
|
||||
state * state_ptr;
|
||||
trigger * trigger_ptr;
|
||||
terminal *term_ptr;
|
||||
int offset = 0;
|
||||
int randval, error;
|
||||
// Generating an input for the first time
|
||||
if (input == NULL) {
|
||||
|
||||
input = (Array *)calloc(1, sizeof(Array));
|
||||
initArray(input, INIT_SIZE);
|
||||
curr_state = init_state;
|
||||
|
||||
}
|
||||
|
||||
while (curr_state != final_state) {
|
||||
|
||||
*mut_count += 1;
|
||||
// Retrieving the state from the pda
|
||||
state_ptr = pda + curr_state;
|
||||
|
||||
// Get a random trigger
|
||||
randval = rand_below(global_afl, state_ptr->trigger_len);
|
||||
trigger_ptr = (state_ptr->ptr) + randval;
|
||||
|
||||
// Insert into the dynamic array
|
||||
insertArray(input, curr_state, trigger_ptr->term, trigger_ptr->term_len,
|
||||
randval);
|
||||
curr_state = trigger_ptr->dest;
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
return input;
|
||||
|
||||
}
|
||||
|
||||
/*Creates a candidate from walk with state hashmap and
|
||||
* recursion hashmap
|
||||
*/
|
||||
|
||||
Candidate *gen_candidate(Array *input) {
|
||||
|
||||
terminal * term_ptr;
|
||||
IdxMap_new *idxmapPtr;
|
||||
// Declare the State Hash Table
|
||||
IdxMap_new *idxmapStart =
|
||||
(IdxMap_new *)malloc(sizeof(IdxMap_new) * numstates);
|
||||
for (int x = 0; x < numstates; x++) {
|
||||
|
||||
idxmapPtr = &idxmapStart[x];
|
||||
utarray_new(idxmapPtr->nums, &ut_int_icd);
|
||||
|
||||
}
|
||||
|
||||
char * trigger;
|
||||
int state;
|
||||
char * key;
|
||||
Candidate *candidate = (Candidate *)malloc(sizeof(Candidate));
|
||||
candidate->walk = input;
|
||||
int offset = 0, error;
|
||||
|
||||
// Generate statemap for splicing
|
||||
while (offset < input->used) {
|
||||
|
||||
term_ptr = &input->start[offset];
|
||||
state = term_ptr->state;
|
||||
// char *statenum = state + 1;
|
||||
// int num = atoi(statenum);
|
||||
idxmapPtr = &idxmapStart[state];
|
||||
utarray_push_back(idxmapPtr->nums, &offset);
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
candidate->statemap = idxmapStart;
|
||||
return candidate;
|
||||
|
||||
}
|
||||
|
||||
char *get_state(char *trigger) {
|
||||
|
||||
// Get the state from transition
|
||||
int trigger_idx = 0;
|
||||
printf("\nTrigger:%s", trigger);
|
||||
char *state = (char *)malloc(sizeof(char) * 10);
|
||||
while (trigger[trigger_idx] != '_') {
|
||||
|
||||
state[trigger_idx] = trigger[trigger_idx];
|
||||
trigger_idx += 1;
|
||||
|
||||
}
|
||||
|
||||
printf("\nTrigger Idx:%d", trigger_idx);
|
||||
state[trigger_idx] = '\0';
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
void print_repr(Array *input, char *prefix) {
|
||||
|
||||
size_t offset = 0;
|
||||
terminal *term_ptr;
|
||||
char geninput[input->used * 100];
|
||||
if (!input->used) {
|
||||
|
||||
printf("\n=============");
|
||||
printf("\n%s:%s", prefix, "");
|
||||
printf("\n=============");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// This is done to create a null-terminated initial string
|
||||
term_ptr = &input->start[offset];
|
||||
strcpy(geninput, term_ptr->symbol);
|
||||
offset += 1;
|
||||
|
||||
while (offset < input->used) {
|
||||
|
||||
term_ptr = &input->start[offset];
|
||||
strcat(geninput, term_ptr->symbol);
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
printf("\n=============");
|
||||
printf("\n%s:%s", prefix, geninput);
|
||||
printf("\n=============");
|
||||
|
||||
}
|
||||
|
||||
// int main(int argc, char*argv[]) {
|
||||
|
||||
// char *mode;
|
||||
// if (argc == 1) {
|
||||
|
||||
// printf("\nUsage: ./gramfuzzer <mode>");
|
||||
// return -1;
|
||||
// }
|
||||
// if (argc >= 2) {
|
||||
|
||||
// mode = argv[1];
|
||||
// printf("\nMode:%s", mode);
|
||||
// }
|
||||
// if (! strcmp(mode, "Generate")) {
|
||||
|
||||
// GenInputBenchmark();
|
||||
// }
|
||||
// else if (! strcmp(mode, "RandomMutation")) {
|
||||
|
||||
// RandomMutationBenchmark();
|
||||
// }
|
||||
// else if (! strcmp(mode, "Splice")) {
|
||||
|
||||
// SpliceMutationBenchmark();
|
||||
// }
|
||||
// else if (! strcmp(mode, "Recursive")) {
|
||||
|
||||
// RandomRecursiveBenchmark();
|
||||
// }
|
||||
// else {
|
||||
|
||||
// printf("\nUnrecognized mode");
|
||||
// return -1;
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
247
custom_mutators/gramatron/gramfuzz-mutators.c
Normal file
247
custom_mutators/gramatron/gramfuzz-mutators.c
Normal file
@ -0,0 +1,247 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "afl-fuzz.h"
|
||||
#include "gramfuzz.h"
|
||||
|
||||
Array *performRandomMutation(state *pda, Array *input) {
|
||||
|
||||
terminal *term_ptr;
|
||||
// terminal *prev_ptr;
|
||||
Array *mutated;
|
||||
Array *sliced;
|
||||
|
||||
// Get offset at which to generate new input and slice it
|
||||
int idx = rand_below(global_afl, input->used);
|
||||
sliced = slice(input, idx);
|
||||
// print_repr(sliced, "Slice");
|
||||
|
||||
// prev_ptr = & input->start[idx - 1];
|
||||
// printf("\nState:%s Symbol:%s", prev_ptr->state, prev_ptr->symbol);
|
||||
// Reset current state to that of the slice's last member
|
||||
term_ptr = &input->start[idx];
|
||||
curr_state = term_ptr->state;
|
||||
// printf("\nState:%s Symbol:%s", curr_state, term_ptr->symbol);
|
||||
|
||||
// Set the next available cell to the one adjacent to this chosen point
|
||||
mutated = gen_input(pda, sliced);
|
||||
return mutated;
|
||||
|
||||
}
|
||||
|
||||
// Tries to perform splice operation between two automaton walks
|
||||
UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL};
|
||||
|
||||
Array *performSpliceOne(Array *originput, IdxMap_new *statemap_orig,
|
||||
Array *splicecand) {
|
||||
|
||||
UT_array * stateptr, *pairs;
|
||||
intpair_t ip;
|
||||
intpair_t *cand;
|
||||
|
||||
terminal *term_ptr;
|
||||
Array * prefix;
|
||||
int state;
|
||||
|
||||
// Initialize the dynamic holding the splice indice pairs
|
||||
utarray_new(pairs, &intpair_icd);
|
||||
// print_repr(originput, "Orig");
|
||||
// print_repr(splicecand, "SpliceCand");
|
||||
|
||||
// Iterate through the splice candidate identifying potential splice points
|
||||
// and pushing pair (orig_idx, splice_idx) to a dynamic array
|
||||
for (int x = 0; x < splicecand->used; x++) {
|
||||
|
||||
term_ptr = &splicecand->start[x];
|
||||
stateptr = statemap_orig[term_ptr->state].nums;
|
||||
int length = utarray_len(stateptr);
|
||||
if (length) {
|
||||
|
||||
int *splice_idx = (int *)utarray_eltptr(stateptr, rand_below(global_afl, length));
|
||||
ip.orig_idx = *splice_idx;
|
||||
ip.splice_idx = x;
|
||||
utarray_push_back(pairs, &ip);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Pick a random pair
|
||||
int length = utarray_len(pairs);
|
||||
cand = (intpair_t *)utarray_eltptr(pairs, rand_below(global_afl, length));
|
||||
// printf("\n Orig_idx:%d Splice_idx:%d", cand->orig_idx, cand->splice_idx);
|
||||
|
||||
// Perform the splicing
|
||||
prefix = slice(originput, cand->orig_idx);
|
||||
Array *spliced = spliceGF(prefix, splicecand, cand->splice_idx);
|
||||
// print_repr(spliced, "Spliced");
|
||||
//
|
||||
utarray_free(pairs);
|
||||
|
||||
return spliced;
|
||||
|
||||
}
|
||||
|
||||
UT_array **get_dupes(Array *input, int *recur_len) {
|
||||
|
||||
// Variables related to finding duplicates
|
||||
int offset = 0;
|
||||
int state;
|
||||
terminal * term_ptr;
|
||||
IdxMap_new *idxMapPtr;
|
||||
UT_array ** recurIdx;
|
||||
|
||||
// Declare the Recursive Map Table
|
||||
IdxMap_new *idxmapStart =
|
||||
(IdxMap_new *)malloc(sizeof(IdxMap_new) * numstates);
|
||||
//
|
||||
// UT_array *(recurIdx[numstates]);
|
||||
recurIdx = malloc(sizeof(UT_array *) * numstates);
|
||||
|
||||
for (int x = 0; x < numstates; x++) {
|
||||
|
||||
idxMapPtr = &idxmapStart[x];
|
||||
utarray_new(idxMapPtr->nums, &ut_int_icd);
|
||||
|
||||
}
|
||||
|
||||
// Obtain frequency distribution of states
|
||||
while (offset < input->used) {
|
||||
|
||||
term_ptr = &input->start[offset];
|
||||
state = term_ptr->state;
|
||||
// int num = atoi(state + 1);
|
||||
idxMapPtr = &idxmapStart[state];
|
||||
utarray_push_back(idxMapPtr->nums, &offset);
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
// Retrieve the duplicated states
|
||||
offset = 0;
|
||||
while (offset < numstates) {
|
||||
|
||||
idxMapPtr = &idxmapStart[offset];
|
||||
int length = utarray_len(idxMapPtr->nums);
|
||||
if (length >= 2) {
|
||||
|
||||
recurIdx[*recur_len] = idxMapPtr->nums;
|
||||
*recur_len += 1;
|
||||
|
||||
}
|
||||
|
||||
// else {
|
||||
|
||||
// utarray_free(idxMapPtr->nums);
|
||||
// }
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
if (*recur_len) {
|
||||
|
||||
// Declare the return struct
|
||||
// We use this struct so that we save the reference to IdxMap_new and free
|
||||
// it after we have used it in doMult
|
||||
// Get_Dupes_Ret* getdupesret =
|
||||
// (Get_Dupes_Ret*)malloc(sizeof(Get_Dupes_Ret));
|
||||
return recurIdx;
|
||||
// getdupesret->idxmap = idxmapStart;
|
||||
// getdupesret->recurIdx = recurIdx;
|
||||
// return getdupesret;
|
||||
|
||||
} else {
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Array *doMult(Array *input, UT_array **recur, int recurlen) {
|
||||
|
||||
int offset = 0;
|
||||
int idx = rand_below(global_afl, recurlen);
|
||||
UT_array *recurMap = recur[idx];
|
||||
UT_array *recurPtr;
|
||||
Array * prefix;
|
||||
Array * postfix;
|
||||
Array * feature;
|
||||
|
||||
// Choose two indices to get the recursive feature
|
||||
int recurIndices = utarray_len(recurMap);
|
||||
int firstIdx = 0;
|
||||
int secondIdx = 0;
|
||||
getTwoIndices(recurMap, recurIndices, &firstIdx, &secondIdx);
|
||||
|
||||
// Perform the recursive mut
|
||||
// print_repr(input, "Orig");
|
||||
prefix = slice(input, firstIdx);
|
||||
// print_repr(prefix, "Prefix");
|
||||
if (firstIdx < secondIdx) {
|
||||
|
||||
feature = carve(input, firstIdx, secondIdx);
|
||||
|
||||
} else {
|
||||
|
||||
feature = carve(input, secondIdx, firstIdx);
|
||||
|
||||
}
|
||||
|
||||
// print_repr(feature, "Feature");
|
||||
concatPrefixFeature(prefix, feature);
|
||||
|
||||
// GC allocated structures
|
||||
free(feature->start);
|
||||
free(feature);
|
||||
// for(int x = 0; x < recurlen; x++) {
|
||||
|
||||
// utarray_free(recur[x]);
|
||||
// }
|
||||
// free(recur);
|
||||
// print_repr(prefix, "Concat");
|
||||
return spliceGF(prefix, input, secondIdx);
|
||||
|
||||
}
|
||||
|
||||
void getTwoIndices(UT_array *recur, int recurlen, int *firstIdx,
|
||||
int *secondIdx) {
|
||||
|
||||
int ArrayRecurIndices[recurlen];
|
||||
int offset = 0, *p;
|
||||
// Unroll into an array
|
||||
for (p = (int *)utarray_front(recur); p != NULL;
|
||||
p = (int *)utarray_next(recur, p)) {
|
||||
|
||||
ArrayRecurIndices[offset] = *p;
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
/*Source:
|
||||
* https://www.geeksforgeeks.org/shuffle-a-given-array-using-fisher-yates-shuffle-algorithm/
|
||||
*/
|
||||
for (int i = offset - 1; i > 0; i--) {
|
||||
|
||||
// Pick a random index from 0 to i
|
||||
int j = rand_below(global_afl, i + 1);
|
||||
|
||||
// Swap arr[i] with the element at random index
|
||||
swap(&ArrayRecurIndices[i], &ArrayRecurIndices[j]);
|
||||
|
||||
}
|
||||
|
||||
*firstIdx = ArrayRecurIndices[0];
|
||||
*secondIdx = ArrayRecurIndices[1];
|
||||
|
||||
}
|
||||
|
||||
void swap(int *a, int *b) {
|
||||
|
||||
int temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
|
||||
}
|
||||
|
268
custom_mutators/gramatron/gramfuzz-util.c
Normal file
268
custom_mutators/gramatron/gramfuzz-util.c
Normal file
@ -0,0 +1,268 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "afl-fuzz.h"
|
||||
#include "gramfuzz.h"
|
||||
#ifdef _GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Dynamic Array for adding to the input repr
|
||||
* */
|
||||
void initArray(Array *a, size_t initialSize) {
|
||||
|
||||
a->start = (terminal *)calloc(1, sizeof(terminal) * initialSize);
|
||||
a->used = 0;
|
||||
a->size = initialSize;
|
||||
a->inputlen = 0;
|
||||
|
||||
}
|
||||
|
||||
void insertArray(Array *a, int state, char *symbol, size_t symbol_len,
|
||||
int trigger_idx) {
|
||||
|
||||
// a->used is the number of used entries, because a->array[a->used++] updates
|
||||
// a->used only *after* the array has been accessed. Therefore a->used can go
|
||||
// up to a->size
|
||||
terminal *term_ptr;
|
||||
if (a->used == a->size) {
|
||||
|
||||
a->size = a->size * sizeof(terminal);
|
||||
a->start = (terminal *)realloc(a->start, a->size * sizeof(terminal));
|
||||
|
||||
}
|
||||
|
||||
// Add the element
|
||||
term_ptr = &a->start[a->used];
|
||||
term_ptr->state = state;
|
||||
term_ptr->symbol = symbol;
|
||||
term_ptr->symbol_len = symbol_len;
|
||||
term_ptr->trigger_idx = trigger_idx;
|
||||
|
||||
// Increment the pointer
|
||||
a->used += 1;
|
||||
a->inputlen += symbol_len;
|
||||
|
||||
}
|
||||
|
||||
void freeArray(Array *a) {
|
||||
|
||||
terminal *ptr;
|
||||
for (int x = 0; x < a->used; x++) {
|
||||
|
||||
ptr = &a->start[x];
|
||||
free(ptr);
|
||||
|
||||
}
|
||||
|
||||
a->start = NULL;
|
||||
a->used = a->size = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Dynamic array for adding indices of states/recursive features
|
||||
* Source:
|
||||
* https://stackoverflow.com/questions/3536153/c-dynamically-growing-array
|
||||
*/
|
||||
void initArrayIdx(IdxMap *a, size_t initialSize) {
|
||||
|
||||
a->array = (int *)malloc(initialSize * sizeof(int));
|
||||
a->used = 0;
|
||||
a->size = initialSize;
|
||||
|
||||
}
|
||||
|
||||
void insertArrayIdx(IdxMap *a, int idx) {
|
||||
|
||||
// a->used is the number of used entries, because a->array[a->used++] updates
|
||||
// a->used only *after* the array has been accessed. Therefore a->used can go
|
||||
// up to a->size
|
||||
if (a->used == a->size) {
|
||||
|
||||
a->size *= 2;
|
||||
a->array = (int *)realloc(a->array, a->size * sizeof(int));
|
||||
|
||||
}
|
||||
|
||||
a->array[a->used++] = idx;
|
||||
|
||||
}
|
||||
|
||||
void freeArrayIdx(IdxMap *a) {
|
||||
|
||||
free(a->array);
|
||||
a->array = NULL;
|
||||
a->used = a->size = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Dynamic array for adding potential splice points
|
||||
*/
|
||||
void initArraySplice(SpliceCandArray *a, size_t initialSize) {
|
||||
|
||||
a->start = (SpliceCand *)malloc(initialSize * sizeof(SpliceCand));
|
||||
a->used = 0;
|
||||
a->size = initialSize;
|
||||
|
||||
}
|
||||
|
||||
void insertArraySplice(SpliceCandArray *a, Candidate *candidate, int idx) {
|
||||
|
||||
// a->used is the number of used entries, because a->array[a->used++] updates
|
||||
// a->used only *after* the array has been accessed. Therefore a->used can go
|
||||
// up to a->size
|
||||
SpliceCand *candptr;
|
||||
if (a->used == a->size) {
|
||||
|
||||
a->size = a->size * sizeof(SpliceCand);
|
||||
a->start = (SpliceCand *)realloc(a->start, a->size * sizeof(SpliceCand));
|
||||
|
||||
}
|
||||
|
||||
// Add the element
|
||||
candptr = &a->start[a->used];
|
||||
candptr->splice_cand = candidate;
|
||||
candptr->idx = idx;
|
||||
a->used += 1;
|
||||
|
||||
}
|
||||
|
||||
void freeArraySplice(IdxMap *a) {
|
||||
|
||||
free(a->array);
|
||||
a->array = NULL;
|
||||
a->used = a->size = 0;
|
||||
|
||||
}
|
||||
|
||||
int fact(int n) {
|
||||
|
||||
int i, f = 1;
|
||||
for (i = 1; i <= n; i++) {
|
||||
|
||||
f *= i;
|
||||
|
||||
}
|
||||
|
||||
return f;
|
||||
|
||||
}
|
||||
|
||||
/* Uses the walk to create the input in-memory */
|
||||
u8 *unparse_walk(Array *input) {
|
||||
|
||||
terminal *term_ptr;
|
||||
int offset = 0;
|
||||
u8 * unparsed = (u8 *)malloc(input->inputlen + 1);
|
||||
term_ptr = &input->start[offset];
|
||||
strcpy(unparsed, term_ptr->symbol);
|
||||
offset += 1;
|
||||
while (offset < input->used) {
|
||||
|
||||
term_ptr = &input->start[offset];
|
||||
strcat(unparsed, term_ptr->symbol);
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
return unparsed;
|
||||
|
||||
}
|
||||
|
||||
/*Dump the input representation into a file*/
|
||||
void write_input(Array *input, u8 *fn) {
|
||||
|
||||
FILE *fp;
|
||||
// If file already exists, then skip creating the file
|
||||
if (access(fn, F_OK) != -1) { return; }
|
||||
|
||||
fp = fopen(fn, "wbx+");
|
||||
// If the input has already been flushed, then skip silently
|
||||
if (fp == NULL) {
|
||||
|
||||
fprintf(stderr, "\n File '%s' could not be open, exiting\n", fn);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
// Write the length parameters
|
||||
fwrite(&input->used, sizeof(size_t), 1, fp);
|
||||
fwrite(&input->size, sizeof(size_t), 1, fp);
|
||||
fwrite(&input->inputlen, sizeof(size_t), 1, fp);
|
||||
|
||||
// Write the dynamic array to file
|
||||
fwrite(input->start, input->size * sizeof(terminal), 1, fp);
|
||||
// printf("\nUsed:%zu Size:%zu Inputlen:%zu", input->used, input->size,
|
||||
// input->inputlen);
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
|
||||
Array *parse_input(state *pda, FILE *fp) {
|
||||
|
||||
terminal *term;
|
||||
state * state_ptr;
|
||||
trigger * trigger;
|
||||
int trigger_idx;
|
||||
Array * input = (Array *)calloc(1, sizeof(Array));
|
||||
|
||||
// Read the length parameters
|
||||
fread(&input->used, sizeof(size_t), 1, fp);
|
||||
fread(&input->size, sizeof(size_t), 1, fp);
|
||||
fread(&input->inputlen, sizeof(size_t), 1, fp);
|
||||
|
||||
terminal *start_ptr = (terminal *)calloc(input->size, sizeof(terminal));
|
||||
if (!start_ptr) {
|
||||
|
||||
fprintf(stderr, "alloc failed!\n");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
// Read the dynamic array to memory
|
||||
fread(start_ptr, input->size * sizeof(terminal), 1, fp);
|
||||
// Update the pointers to the terminals since they would have
|
||||
// changed
|
||||
int idx = 0;
|
||||
while (idx < input->used) {
|
||||
|
||||
terminal *term = &start_ptr[idx];
|
||||
// Find the state
|
||||
state_ptr = pda + term->state;
|
||||
// Find the trigger and update the terminal address
|
||||
trigger_idx = term->trigger_idx;
|
||||
trigger = (state_ptr->ptr) + trigger_idx;
|
||||
term->symbol = trigger->term;
|
||||
idx += 1;
|
||||
|
||||
}
|
||||
|
||||
input->start = start_ptr;
|
||||
// printf("\nUsed:%zu Size:%zu Inputlen:%zu", input->used, input->size,
|
||||
// input->inputlen);
|
||||
|
||||
return input;
|
||||
|
||||
}
|
||||
|
||||
// Read the input representation into memory
|
||||
Array *read_input(state *pda, u8 *fn) {
|
||||
|
||||
FILE *fp;
|
||||
fp = fopen(fn, "rb");
|
||||
if (fp == NULL) {
|
||||
|
||||
fprintf(stderr, "\n File '%s' does not exist, exiting\n", fn);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
Array *res = parse_input(pda, fp);
|
||||
fclose(fp);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
429
custom_mutators/gramatron/gramfuzz.c
Normal file
429
custom_mutators/gramatron/gramfuzz.c
Normal file
@ -0,0 +1,429 @@
|
||||
// This simple example just creates random buffer <= 100 filled with 'A'
|
||||
// needs -I /path/to/AFLplusplus/include
|
||||
//#include "custom_mutator_helpers.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
#include "gramfuzz.h"
|
||||
|
||||
#define MUTATORS 4 // Specify the total number of mutators
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
|
||||
u8 * mutator_buf;
|
||||
u8 * unparsed_input;
|
||||
Array *mutated_walk;
|
||||
Array *orig_walk;
|
||||
|
||||
IdxMap_new *statemap; // Keeps track of the statemap
|
||||
UT_array ** recurIdx;
|
||||
// Get_Dupes_Ret* getdupesret; // Recursive feature map
|
||||
int recurlen;
|
||||
|
||||
int mut_alloced;
|
||||
int orig_alloced;
|
||||
int mut_idx; // Signals the current mutator being used, used to cycle through
|
||||
// each mutator
|
||||
|
||||
unsigned int seed;
|
||||
|
||||
} my_mutator_t;
|
||||
|
||||
state *create_pda(u8 *automaton_file) {
|
||||
|
||||
struct json_object *parsed_json;
|
||||
state * pda;
|
||||
json_object * source_obj, *attr;
|
||||
int arraylen, ii, ii2, trigger_len, error;
|
||||
|
||||
printf("\n[GF] Automaton file passed:%s", automaton_file);
|
||||
// parsed_json =
|
||||
// json_object_from_file("./gramfuzz/php_gnf_processed_full.json");
|
||||
parsed_json = json_object_from_file(automaton_file);
|
||||
|
||||
// Getting final state
|
||||
source_obj = json_object_object_get(parsed_json, "final_state");
|
||||
printf("\t\nFinal=%s\n", json_object_get_string(source_obj));
|
||||
final_state = atoi(json_object_get_string(source_obj));
|
||||
|
||||
// Getting initial state
|
||||
source_obj = json_object_object_get(parsed_json, "init_state");
|
||||
init_state = atoi(json_object_get_string(source_obj));
|
||||
printf("\tInit=%s\n", json_object_get_string(source_obj));
|
||||
|
||||
// Getting number of states
|
||||
source_obj = json_object_object_get(parsed_json, "numstates");
|
||||
numstates = atoi(json_object_get_string(source_obj)) + 1;
|
||||
printf("\tNumStates=%d\n", numstates);
|
||||
|
||||
// Allocate state space for each pda state
|
||||
pda = (state *)calloc(atoi(json_object_get_string(source_obj)) + 1,
|
||||
sizeof(state));
|
||||
|
||||
// Getting PDA representation
|
||||
source_obj = json_object_object_get(parsed_json, "pda");
|
||||
enum json_type type;
|
||||
json_object_object_foreach(source_obj, key, val) {
|
||||
|
||||
state * state_ptr;
|
||||
trigger *trigger_ptr;
|
||||
int offset;
|
||||
|
||||
// Get the correct offset into the pda to store state information
|
||||
state_ptr = pda;
|
||||
offset = atoi(key);
|
||||
state_ptr += offset;
|
||||
// Store state string
|
||||
state_ptr->state_name = offset;
|
||||
|
||||
// Create trigger array of structs
|
||||
trigger_len = json_object_array_length(val);
|
||||
state_ptr->trigger_len = trigger_len;
|
||||
trigger_ptr = (trigger *)calloc(trigger_len, sizeof(trigger));
|
||||
state_ptr->ptr = trigger_ptr;
|
||||
|
||||
for (ii = 0; ii < trigger_len; ii++) {
|
||||
|
||||
json_object *obj = json_object_array_get_idx(val, ii);
|
||||
// Get all the trigger trigger attributes
|
||||
attr = json_object_array_get_idx(obj, 0);
|
||||
(trigger_ptr)->id = strdup(json_object_get_string(attr));
|
||||
|
||||
attr = json_object_array_get_idx(obj, 1);
|
||||
trigger_ptr->dest = atoi(json_object_get_string(attr));
|
||||
|
||||
attr = json_object_array_get_idx(obj, 2);
|
||||
if (!strcmp("\\n", json_object_get_string(attr))) {
|
||||
|
||||
trigger_ptr->term = strdup("\n");
|
||||
|
||||
} else {
|
||||
|
||||
trigger_ptr->term = strdup(json_object_get_string(attr));
|
||||
|
||||
}
|
||||
|
||||
trigger_ptr->term_len = strlen(trigger_ptr->term);
|
||||
trigger_ptr++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete the JSON object
|
||||
json_object_put(parsed_json);
|
||||
|
||||
return pda;
|
||||
|
||||
}
|
||||
|
||||
my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
|
||||
if (!data) {
|
||||
|
||||
perror("afl_custom_init alloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
|
||||
|
||||
perror("mutator_buf alloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
data->afl = afl;
|
||||
global_afl = afl; // dirty
|
||||
data->seed = seed;
|
||||
|
||||
data->mut_alloced = 0;
|
||||
data->orig_alloced = 0;
|
||||
data->mut_idx = 0;
|
||||
data->recurlen = 0;
|
||||
|
||||
// data->mutator_buf = NULL;
|
||||
// data->unparsed_input = NULL;
|
||||
// data->mutated_walk = NULL;
|
||||
// data->orig_walk = NULL;
|
||||
//
|
||||
// data->statemap = NULL; // Keeps track of the statemap
|
||||
// data->recur_idx = NULL; // Will keep track of recursive feature indices
|
||||
// u32 recur_len = 0; // The number of recursive features
|
||||
// data->mutator_buf = NULL;
|
||||
|
||||
char *automaton_file = getenv("GRAMATRON_AUTOMATION");
|
||||
if (automaton_file) {
|
||||
|
||||
pda = create_pda(automaton_file);
|
||||
|
||||
} else {
|
||||
|
||||
fprintf(stderr,
|
||||
"\nError: GrammaTron needs an automation json file set in "
|
||||
"GRAMATRON_AUTOMATION\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
|
||||
size_t max_size) {
|
||||
|
||||
u8 *unparsed_input;
|
||||
|
||||
// Pick a mutator
|
||||
// int choice = rand() % MUTATORS;
|
||||
// data->mut_idx = 1;
|
||||
// GC old mutant
|
||||
if (data->mut_alloced) {
|
||||
|
||||
free(data->mutated_walk->start);
|
||||
free(data->mutated_walk);
|
||||
data->mut_alloced = 0;
|
||||
|
||||
};
|
||||
|
||||
// printf("\nChoice:%d", choice);
|
||||
|
||||
if (data->mut_idx == 0) { // Perform random mutation
|
||||
data->mutated_walk = performRandomMutation(pda, data->orig_walk);
|
||||
data->mut_alloced = 1;
|
||||
|
||||
} else if (data->mut_idx == 1 &&
|
||||
|
||||
data->recurlen) { // Perform recursive mutation
|
||||
data->mutated_walk =
|
||||
doMult(data->orig_walk, data->recurIdx, data->recurlen);
|
||||
data->mut_alloced = 1;
|
||||
|
||||
} else if (data->mut_idx == 2) { // Perform splice mutation
|
||||
|
||||
// we cannot use the supplied splice data so choose a new random file
|
||||
u32 tid = rand_below(global_afl, data->afl->queued_items);
|
||||
struct queue_entry *q = data->afl->queue_buf[tid];
|
||||
|
||||
// Read the input representation for the splice candidate
|
||||
u8 * automaton_fn = alloc_printf("%s.aut", q->fname);
|
||||
Array *spliceCandidate = read_input(pda, automaton_fn);
|
||||
|
||||
if (spliceCandidate) {
|
||||
|
||||
data->mutated_walk =
|
||||
performSpliceOne(data->orig_walk, data->statemap, spliceCandidate);
|
||||
data->mut_alloced = 1;
|
||||
free(spliceCandidate->start);
|
||||
free(spliceCandidate);
|
||||
|
||||
} else {
|
||||
|
||||
data->mutated_walk = gen_input(pda, NULL);
|
||||
data->mut_alloced = 1;
|
||||
|
||||
}
|
||||
|
||||
ck_free(automaton_fn);
|
||||
|
||||
} else { // Generate an input from scratch
|
||||
|
||||
data->mutated_walk = gen_input(pda, NULL);
|
||||
data->mut_alloced = 1;
|
||||
|
||||
}
|
||||
|
||||
// Cycle to the next mutator
|
||||
if (data->mut_idx == MUTATORS - 1)
|
||||
data->mut_idx =
|
||||
0; // Wrap around if we have reached end of the mutator list
|
||||
else
|
||||
data->mut_idx += 1;
|
||||
|
||||
// Unparse the mutated automaton walk
|
||||
if (data->unparsed_input) { free(data->unparsed_input); }
|
||||
data->unparsed_input = unparse_walk(data->mutated_walk);
|
||||
*out_buf = data->unparsed_input;
|
||||
|
||||
return data->mutated_walk->inputlen;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the automaton-based representation for the corresponding input
|
||||
*
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param filename_new_queue File name of the new queue entry
|
||||
* @param filename_orig_queue File name of the original queue entry
|
||||
*/
|
||||
u8 afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
// get the filename
|
||||
u8 * automaton_fn, *unparsed_input;
|
||||
Array *new_input;
|
||||
s32 fd;
|
||||
|
||||
automaton_fn = alloc_printf("%s.aut", filename_new_queue);
|
||||
// Check if this method is being called during initialization
|
||||
|
||||
// fprintf(stderr, "new: %s, old: %s, auto: %s\n",
|
||||
// filename_new_queue,filename_orig_queue,automaton_fn);
|
||||
|
||||
if (filename_orig_queue) {
|
||||
|
||||
write_input(data->mutated_walk, automaton_fn);
|
||||
|
||||
} else {
|
||||
|
||||
new_input = gen_input(pda, NULL);
|
||||
write_input(new_input, automaton_fn);
|
||||
|
||||
// Update the placeholder file
|
||||
if (unlink(filename_new_queue)) {
|
||||
|
||||
PFATAL("Unable to delete '%s'", filename_new_queue);
|
||||
|
||||
}
|
||||
|
||||
unparsed_input = unparse_walk(new_input);
|
||||
fd = open(filename_new_queue, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) { PFATAL("Failed to update file '%s'", filename_new_queue); }
|
||||
int written = write(fd, unparsed_input, new_input->inputlen + 1);
|
||||
close(fd);
|
||||
|
||||
free(new_input->start);
|
||||
free(new_input);
|
||||
free(unparsed_input);
|
||||
|
||||
}
|
||||
|
||||
ck_free(automaton_fn);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the corresponding tree representation for the candidate that is to be
|
||||
* mutated
|
||||
*
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param filename File name of the test case in the queue entry
|
||||
* @return Return True(1) if the fuzzer will fuzz the queue entry, and
|
||||
* False(0) otherwise.
|
||||
*/
|
||||
uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
|
||||
|
||||
// get the filename
|
||||
u8 * automaton_fn = alloc_printf("%s.aut", filename);
|
||||
IdxMap_new *statemap_ptr;
|
||||
terminal * term_ptr;
|
||||
int state;
|
||||
|
||||
// TODO: I don't think we need to update pointers when reading back
|
||||
// Probably build two different versions of read_input one for flushing
|
||||
// inputs to disk and the other that
|
||||
if (data->orig_alloced) {
|
||||
|
||||
free(data->orig_walk->start);
|
||||
free(data->orig_walk);
|
||||
data->orig_alloced = 0;
|
||||
|
||||
}
|
||||
|
||||
if (data->statemap) {
|
||||
|
||||
for (int x = 0; x < numstates; x++) {
|
||||
|
||||
utarray_free(data->statemap[x].nums);
|
||||
|
||||
}
|
||||
|
||||
free(data->statemap);
|
||||
|
||||
}
|
||||
|
||||
if (data->recurIdx) {
|
||||
|
||||
data->recurlen = 0;
|
||||
free(data->recurIdx);
|
||||
|
||||
}
|
||||
|
||||
data->orig_walk = read_input(pda, automaton_fn);
|
||||
data->orig_alloced = 1;
|
||||
|
||||
// Create statemap for the fuzz candidate
|
||||
IdxMap_new *statemap_start =
|
||||
(IdxMap_new *)malloc(sizeof(IdxMap_new) * numstates);
|
||||
for (int x = 0; x < numstates; x++) {
|
||||
|
||||
statemap_ptr = &statemap_start[x];
|
||||
utarray_new(statemap_ptr->nums, &ut_int_icd);
|
||||
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
while (offset < data->orig_walk->used) {
|
||||
|
||||
term_ptr = &data->orig_walk->start[offset];
|
||||
state = term_ptr->state;
|
||||
statemap_ptr = &statemap_start[state];
|
||||
utarray_push_back(statemap_ptr->nums, &offset);
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
data->statemap = statemap_start;
|
||||
|
||||
// Create recursive feature map (if it exists)
|
||||
data->recurIdx = malloc(sizeof(UT_array *) * numstates);
|
||||
// Retrieve the duplicated states
|
||||
offset = 0;
|
||||
while (offset < numstates) {
|
||||
|
||||
statemap_ptr = &data->statemap[offset];
|
||||
int length = utarray_len(statemap_ptr->nums);
|
||||
if (length >= 2) {
|
||||
|
||||
data->recurIdx[data->recurlen] = statemap_ptr->nums;
|
||||
data->recurlen += 1;
|
||||
|
||||
}
|
||||
|
||||
offset += 1;
|
||||
|
||||
}
|
||||
|
||||
// data->getdupesret = get_dupes(data->orig_walk, &data->recurlen);
|
||||
|
||||
ck_free(automaton_fn);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitialize everything
|
||||
*
|
||||
* @param data The data ptr from afl_custom_init
|
||||
*/
|
||||
|
||||
void afl_custom_deinit(my_mutator_t *data) {
|
||||
|
||||
free(data->mutator_buf);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
255
custom_mutators/gramatron/gramfuzz.h
Normal file
255
custom_mutators/gramatron/gramfuzz.h
Normal file
@ -0,0 +1,255 @@
|
||||
#ifndef _GRAMFUZZ_H
|
||||
|
||||
#define _GRAMFUZZ_H
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <unistd.h>
|
||||
#include "hashmap.h"
|
||||
#include "uthash.h"
|
||||
#include "utarray.h"
|
||||
|
||||
#define INIT_INPUTS 100 // No. of initial inputs to be generated
|
||||
|
||||
// Set this as `numstates` + 1 where `numstates` is retrieved from gen automata
|
||||
// json #define STATES 63
|
||||
|
||||
#define INIT_SIZE 100 // Initial size of the dynamic array holding the input
|
||||
|
||||
#define SPLICE_CORPUS 10000
|
||||
#define RECUR_THRESHOLD 6
|
||||
#define SIZE_THRESHOLD 2048
|
||||
|
||||
#define FLUSH_INTERVAL \
|
||||
3600 // Inputs that gave new coverage will be dumped every FLUSH_INTERVAL
|
||||
// seconds
|
||||
|
||||
afl_state_t *global_afl;
|
||||
|
||||
typedef struct trigger {
|
||||
|
||||
char * id;
|
||||
int dest;
|
||||
char * term;
|
||||
size_t term_len;
|
||||
|
||||
} trigger;
|
||||
|
||||
typedef struct state {
|
||||
|
||||
int state_name; // Integer State name
|
||||
int trigger_len; // Number of triggers associated with this state
|
||||
trigger *ptr; // Pointer to beginning of the list of triggers
|
||||
|
||||
} state;
|
||||
|
||||
typedef struct terminal {
|
||||
|
||||
int state;
|
||||
int trigger_idx;
|
||||
size_t symbol_len;
|
||||
char * symbol;
|
||||
|
||||
} terminal;
|
||||
|
||||
typedef struct buckethash {
|
||||
|
||||
int freq;
|
||||
|
||||
} buckethash;
|
||||
|
||||
int init_state;
|
||||
int curr_state;
|
||||
int final_state;
|
||||
int numstates;
|
||||
|
||||
/*****************
|
||||
/ DYNAMIC ARRAY FOR WALKS
|
||||
*****************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
size_t used;
|
||||
size_t size;
|
||||
size_t inputlen;
|
||||
terminal *start;
|
||||
|
||||
} Array;
|
||||
|
||||
/*****************
|
||||
/ DYNAMIC ARRAY FOR STATEMAPS/RECURSION MAPS
|
||||
*****************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
int * array;
|
||||
size_t used;
|
||||
size_t size;
|
||||
|
||||
} IdxMap;
|
||||
|
||||
typedef struct {
|
||||
|
||||
UT_array *nums;
|
||||
|
||||
} IdxMap_new;
|
||||
|
||||
typedef struct {
|
||||
|
||||
IdxMap_new *idxmap;
|
||||
UT_array ** recurIdx;
|
||||
|
||||
} Get_Dupes_Ret;
|
||||
|
||||
/* Candidate Struct */
|
||||
typedef struct {
|
||||
|
||||
Array * walk;
|
||||
IdxMap_new *statemap;
|
||||
|
||||
} Candidate;
|
||||
|
||||
/* Splice Mutation helpers*/
|
||||
typedef struct {
|
||||
|
||||
Candidate *splice_cand;
|
||||
int idx;
|
||||
|
||||
} SpliceCand;
|
||||
|
||||
typedef struct {
|
||||
|
||||
SpliceCand *start;
|
||||
size_t used;
|
||||
size_t size;
|
||||
|
||||
} SpliceCandArray;
|
||||
|
||||
// Initialize dynamic array for potential splice points
|
||||
SpliceCand potential[SPLICE_CORPUS];
|
||||
|
||||
typedef struct {
|
||||
|
||||
int orig_idx;
|
||||
int splice_idx;
|
||||
|
||||
} intpair_t;
|
||||
|
||||
// Initialize dynamic array for potential splice points
|
||||
// SpliceCand potential[SPLICE_CORPUS];
|
||||
// IdxMap_new* rcuridx[STATES];
|
||||
|
||||
/* Prototypes*/
|
||||
Array * slice(Array *, int);
|
||||
state * create_pda(u8 *);
|
||||
Array * gen_input(state *, Array *);
|
||||
Array * gen_input_count(state *, Array *, int *);
|
||||
int updatebucket(map_t, int);
|
||||
void itoa(int, char *, int);
|
||||
void strrreverse(char *, char *);
|
||||
void dbg_hashmap(map_t);
|
||||
void print_repr(Array *, char *);
|
||||
int isSatisfied(map_t);
|
||||
char * get_state(char *);
|
||||
Candidate *gen_candidate(Array *);
|
||||
|
||||
Array *spliceGF(Array *, Array *, int);
|
||||
Array *performSpliceOne(Array *, IdxMap_new *, Array *);
|
||||
/* Mutation Methods*/
|
||||
Array * performRandomMutation(state *, Array *);
|
||||
Array * performRandomMutationCount(state *, Array *, int *);
|
||||
Array * performSpliceMutationBench(state *, Array *, Candidate **);
|
||||
UT_array **get_dupes(Array *, int *);
|
||||
Array * doMult(Array *, UT_array **, int);
|
||||
Array * doMultBench(Array *, UT_array **, int);
|
||||
|
||||
/* Benchmarks*/
|
||||
void SpaceBenchmark(char *);
|
||||
void GenInputBenchmark(char *, char *);
|
||||
void RandomMutationBenchmark(char *, char *);
|
||||
void MutationAggrBenchmark(char *, char *);
|
||||
void SpliceMutationBenchmark(char *, char *);
|
||||
void SpliceMutationBenchmarkOne(char *, char *);
|
||||
void RandomRecursiveBenchmark(char *, char *);
|
||||
|
||||
/* Testers */
|
||||
void SanityCheck(char *);
|
||||
|
||||
/*Helpers*/
|
||||
void initArray(Array *, size_t);
|
||||
void insertArray(Array *, int, char *, size_t, int);
|
||||
void freeArray(Array *);
|
||||
void initArrayIdx(IdxMap *, size_t);
|
||||
void insertArrayIdx(IdxMap *, int);
|
||||
void freeArrayIdx(IdxMap *);
|
||||
void initArraySplice(SpliceCandArray *, size_t);
|
||||
void insertArraySplice(SpliceCandArray *, Candidate *, int);
|
||||
void freeArraySplice(IdxMap *);
|
||||
void getTwoIndices(UT_array *, int, int *, int *);
|
||||
void swap(int *, int *);
|
||||
Array *slice_inverse(Array *, int);
|
||||
void concatPrefixFeature(Array *, Array *);
|
||||
void concatPrefixFeatureBench(Array *, Array *);
|
||||
Array *carve(Array *, int, int);
|
||||
int fact(int);
|
||||
|
||||
void add_to_corpus(struct json_object *, Array *);
|
||||
struct json_object *term_to_json(terminal *);
|
||||
|
||||
/* Gramatron specific prototypes */
|
||||
u8 * unparse_walk(Array *);
|
||||
Array *performSpliceGF(state *, Array *, afl_state_t *);
|
||||
void dump_input(u8 *, char *, int *);
|
||||
void write_input(Array *, u8 *);
|
||||
Array *read_input(state *, u8 *);
|
||||
state *pda;
|
||||
|
||||
// // AFL-specific struct
|
||||
// typedef uint8_t u8;
|
||||
// typedef uint16_t u16;
|
||||
// typedef uint32_t u32;
|
||||
// #ifdef __x86_64__
|
||||
// typedef unsigned long long u64;
|
||||
// #else
|
||||
// typedef uint64_t u64;
|
||||
// #endif /* ^__x86_64__ */
|
||||
//
|
||||
// struct queue_entry {
|
||||
|
||||
// Array* walk; /* Pointer to the automaton walk*/
|
||||
// u32 walk_len; /* Number of tokens in the input*/
|
||||
// Candidate* cand; /* Preprocessed info about the
|
||||
// candidate to allow for faster mutations*/
|
||||
//
|
||||
// u8* fname; /* File name for the test case */
|
||||
// u32 len; /* Input length */
|
||||
// UT_array** recur_idx; /* Keeps track of recursive feature
|
||||
// indices*/
|
||||
//
|
||||
// u32 recur_len; /* The number of recursive features*/
|
||||
//
|
||||
// u8 cal_failed, /* Calibration failed? */
|
||||
// trim_done, /* Trimmed? */
|
||||
// was_fuzzed, /* Had any fuzzing done yet? */
|
||||
// passed_det, /* Deterministic stages passed? */
|
||||
// has_new_cov, /* Triggers new coverage? */
|
||||
// var_behavior, /* Variable behavior? */
|
||||
// favored, /* Currently favored? */
|
||||
// fs_redundant; /* Marked as redundant in the fs? */
|
||||
//
|
||||
// u32 bitmap_size, /* Number of bits set in bitmap */
|
||||
// exec_cksum; /* Checksum of the execution trace */
|
||||
//
|
||||
// u64 exec_us, /* Execution time (us) */
|
||||
// handicap, /* Number of queue cycles behind */
|
||||
// depth; /* Path depth */
|
||||
//
|
||||
// u8* trace_mini; /* Trace bytes, if kept */
|
||||
// u32 tc_ref; /* Trace bytes ref count */
|
||||
//
|
||||
// struct queue_entry *next, /* Next element, if any */
|
||||
// *next_100; /* 100 elements ahead */
|
||||
//
|
||||
// };
|
||||
|
||||
#endif
|
||||
|
606
custom_mutators/gramatron/grammars/js/source.json
Normal file
606
custom_mutators/gramatron/grammars/js/source.json
Normal file
@ -0,0 +1,606 @@
|
||||
{
|
||||
"ARGLIST": [
|
||||
"EXPR ',' ARGLIST",
|
||||
"EXPR",
|
||||
"EXPR ',' ARGLIST",
|
||||
"EXPR"
|
||||
],
|
||||
"ARGS": [
|
||||
"'()'",
|
||||
"'(' ARGLIST ')'",
|
||||
"'()'",
|
||||
"'(' ARGLIST ')'"
|
||||
],
|
||||
"ARITHMETICOPERATION": [
|
||||
"EXPR '/' EXPR",
|
||||
"EXPR '*' EXPR",
|
||||
"EXPR '+' EXPR",
|
||||
"EXPR '-' EXPR",
|
||||
"EXPR '%' EXPR",
|
||||
"EXPR '**' EXPR",
|
||||
"EXPR '++'"
|
||||
],
|
||||
"ARRAY": [
|
||||
"'[' ARRAYCONTENT ']'",
|
||||
"'[]'"
|
||||
],
|
||||
"ARRAYCONTENT": [
|
||||
"EXPR ',' ARRAYCONTENT",
|
||||
"EXPR"
|
||||
],
|
||||
"BOOLEAN": [
|
||||
"'true'",
|
||||
"'false'"
|
||||
],
|
||||
"BYTEWISEOPERATION": [
|
||||
"EXPR '&' EXPR",
|
||||
"EXPR '|' EXPR"
|
||||
],
|
||||
"COMPARISONOPERATION": [
|
||||
"EXPR '<' EXPR"
|
||||
],
|
||||
"DECIMALDIGITS": [
|
||||
"'20'",
|
||||
"'1234'",
|
||||
"'66'",
|
||||
"'234_9'",
|
||||
"'99999999999999999999'"
|
||||
],
|
||||
"DECIMALNUMBER": [
|
||||
"DECIMALDIGITS"
|
||||
],
|
||||
"EXPR": [
|
||||
"'(' EXPR ')'",
|
||||
"VAR",
|
||||
"'delete' SP EXPR",
|
||||
"'new' SP IDENTIFIER ARGS",
|
||||
"LITERAL",
|
||||
"IDENTIFIER",
|
||||
"METHODCALL",
|
||||
"'(' ARITHMETICOPERATION ')'",
|
||||
"'(' COMPARISONOPERATION ')'",
|
||||
"'(' BYTEWISEOPERATION ')'",
|
||||
"'(' LOGICALOPERATION ')'"
|
||||
],
|
||||
"IDENTIFIER": [
|
||||
"'Object'",
|
||||
"VAR",
|
||||
"'Function'",
|
||||
"'main'",
|
||||
"'opt'",
|
||||
"'Boolean'",
|
||||
"'Symbol'",
|
||||
"'JSON'",
|
||||
"'Error'",
|
||||
"'EvalError'",
|
||||
"'RangeError'",
|
||||
"'ReferenceError'",
|
||||
"'SyntaxError'",
|
||||
"'TypeError'",
|
||||
"'URIError'",
|
||||
"'this'",
|
||||
"'Number'",
|
||||
"'Math'",
|
||||
"'Date'",
|
||||
"'String'",
|
||||
"'RegExp'",
|
||||
"'Array'",
|
||||
"'Int8Array'",
|
||||
"'Uint8Array'",
|
||||
"'Uint8ClampedArray'",
|
||||
"'Int16Array'",
|
||||
"'Uint16Array'",
|
||||
"'Int32Array'",
|
||||
"'Uint32Array'",
|
||||
"'Float32Array'",
|
||||
"'Float64Array'",
|
||||
"'DataView'",
|
||||
"'ArrayBuffer'",
|
||||
"'Map'",
|
||||
"'Set'",
|
||||
"'WeakMap'",
|
||||
"'WeakSet'",
|
||||
"'Promise'",
|
||||
"'AsyncFunction'",
|
||||
"'asyncGenerator'",
|
||||
"'Reflect'",
|
||||
"'Proxy'",
|
||||
"'Intl'",
|
||||
"'Intl.Collator'",
|
||||
"'Intl.DateTimeFormat'",
|
||||
"'Intl.NumberFormat'",
|
||||
"'Intl.PluralRules'",
|
||||
"'WebAssembly'",
|
||||
"'WebAssembly.Module'",
|
||||
"'WebAssembly.Instance'",
|
||||
"'WebAssembly.Memory'",
|
||||
"'WebAssembly.Table'",
|
||||
"'WebAssembly.CompileError'",
|
||||
"'WebAssembly.LinkError'",
|
||||
"'WebAssembly.RuntimeError'",
|
||||
"'arguments'",
|
||||
"'Infinity'",
|
||||
"'NaN'",
|
||||
"'undefined'",
|
||||
"'null'",
|
||||
"'console'",
|
||||
"' '"
|
||||
],
|
||||
"IDENTIFIERLIST": [
|
||||
"IDENTIFIER ',' IDENTIFIERLIST",
|
||||
"'(' IDENTIFIERLIST '),' IDENTIFIERLIST",
|
||||
"IDENTIFIER"
|
||||
],
|
||||
"JSBLOCK": [
|
||||
"JSSTATEMENT",
|
||||
"JSSTATEMENT JSBLOCK"
|
||||
],
|
||||
"JSSTATEMENT": [
|
||||
"STATEMENT NEWLINE"
|
||||
],
|
||||
"LITERAL": [
|
||||
"'null'",
|
||||
"BOOLEAN",
|
||||
"NUMBER",
|
||||
"ARRAY"
|
||||
],
|
||||
"LOGICALOPERATION": [
|
||||
"EXPR '&&' EXPR",
|
||||
"EXPR '||' EXPR"
|
||||
],
|
||||
"METHODCALL": [
|
||||
"OBJECT PROPERTY METHODCALL1"
|
||||
],
|
||||
"METHODCALL1": [
|
||||
"'.' METHOD_NAME ARGS METHODCALL1",
|
||||
"' '"
|
||||
],
|
||||
"METHOD_NAME": [
|
||||
"IDENTIFIER",
|
||||
"'print'",
|
||||
"'eval'",
|
||||
"'uneval'",
|
||||
"'isFinite'",
|
||||
"'isNaN'",
|
||||
"'parseFloat'",
|
||||
"'parseInt'",
|
||||
"'decodeURI'",
|
||||
"'decodeURIComponent'",
|
||||
"'encodeURI'",
|
||||
"'encodeURIComponent'",
|
||||
"'escape'",
|
||||
"'unescape'",
|
||||
"'assign'",
|
||||
"'create'",
|
||||
"'defineProperty'",
|
||||
"'defineProperties'",
|
||||
"'entries'",
|
||||
"'freeze'",
|
||||
"'getOwnPropertyDescriptor'",
|
||||
"'getOwnPropertyDescriptors'",
|
||||
"'getOwnPropertyNames'",
|
||||
"'getOwnPropertySymbols'",
|
||||
"'getPrototypeOf'",
|
||||
"'is'",
|
||||
"'isExtensible'",
|
||||
"'isFrozen'",
|
||||
"'isSealed'",
|
||||
"'keys'",
|
||||
"'preventExtensions'",
|
||||
"'seal'",
|
||||
"'setPrototypeOf'",
|
||||
"'values'",
|
||||
"'__defineGetter__'",
|
||||
"'__defineSetter__'",
|
||||
"'__lookupGetter__'",
|
||||
"'__lookupSetter__'",
|
||||
"'hasOwnProperty'",
|
||||
"'isPrototypeOf'",
|
||||
"'propertyIsEnumerable'",
|
||||
"'toSource'",
|
||||
"'toLocaleString'",
|
||||
"'toString'",
|
||||
"'unwatch'",
|
||||
"'valueOf'",
|
||||
"'watch'",
|
||||
"'apply'",
|
||||
"'bind'",
|
||||
"'call'",
|
||||
"'isGenerator'",
|
||||
"'valueOf'",
|
||||
"'for'",
|
||||
"'keyFor'",
|
||||
"'stringify'",
|
||||
"'isInteger'",
|
||||
"'isSafeInteger'",
|
||||
"'toInteger'",
|
||||
"'toExponential'",
|
||||
"'toFixed'",
|
||||
"'toLocaleString'",
|
||||
"'toPrecision'",
|
||||
"'abs'",
|
||||
"'acos'",
|
||||
"'acosh'",
|
||||
"'asin'",
|
||||
"'asinh'",
|
||||
"'atan'",
|
||||
"'atanh'",
|
||||
"'atan2'",
|
||||
"'cbrt'",
|
||||
"'ceil'",
|
||||
"'clz32'",
|
||||
"'cos'",
|
||||
"'cosh'",
|
||||
"'exp'",
|
||||
"'expm1'",
|
||||
"'floor'",
|
||||
"'fround'",
|
||||
"'hypot'",
|
||||
"'imul'",
|
||||
"'log'",
|
||||
"'log1p'",
|
||||
"'log10'",
|
||||
"'log2'",
|
||||
"'max'",
|
||||
"'min'",
|
||||
"'pow'",
|
||||
"'random'",
|
||||
"'round'",
|
||||
"'sign'",
|
||||
"'sin'",
|
||||
"'sinh'",
|
||||
"'sqrt'",
|
||||
"'tan'",
|
||||
"'tanh'",
|
||||
"'trunc'",
|
||||
"'now'",
|
||||
"'parse'",
|
||||
"'UTC'",
|
||||
"'getDate'",
|
||||
"'getDay'",
|
||||
"'getFullYear'",
|
||||
"'getHours'",
|
||||
"'getMilliseconds'",
|
||||
"'getMinutes'",
|
||||
"'getMonth'",
|
||||
"'getSeconds'",
|
||||
"'getTime'",
|
||||
"'getTimezoneOffset'",
|
||||
"'getUTCDate'",
|
||||
"'getUTCDay'",
|
||||
"'getUTCFullYear'",
|
||||
"'getUTCHours'",
|
||||
"'getUTCMilliseconds'",
|
||||
"'getUTCMinutes'",
|
||||
"'getUTCMonth'",
|
||||
"'getUTCSeconds'",
|
||||
"'getYear'",
|
||||
"'setDate'",
|
||||
"'setFullYear'",
|
||||
"'setHours'",
|
||||
"'setMilliseconds'",
|
||||
"'setMinutes'",
|
||||
"'setMonth'",
|
||||
"'setSeconds'",
|
||||
"'setTime'",
|
||||
"'setUTCDate'",
|
||||
"'setUTCFullYear'",
|
||||
"'setUTCHours'",
|
||||
"'setUTCMilliseconds'",
|
||||
"'setUTCMinutes'",
|
||||
"'setUTCMonth'",
|
||||
"'setUTCSeconds'",
|
||||
"'setYear'",
|
||||
"'toDateString'",
|
||||
"'toISOString'",
|
||||
"'toJSON'",
|
||||
"'toGMTString'",
|
||||
"'toLocaleDateString'",
|
||||
"'toLocaleFormat'",
|
||||
"'toLocaleString'",
|
||||
"'toLocaleTimeString'",
|
||||
"'toTimeString'",
|
||||
"'toUTCString'",
|
||||
"'indexOf'",
|
||||
"'substring'",
|
||||
"'charAt'",
|
||||
"'strcmp'",
|
||||
"'fromCharCode'",
|
||||
"'fromCodePoint'",
|
||||
"'raw'",
|
||||
"'charCodeAt'",
|
||||
"'slice'",
|
||||
"'codePointAt'",
|
||||
"'concat'",
|
||||
"'includes'",
|
||||
"'endsWith'",
|
||||
"'lastIndexOf'",
|
||||
"'localeCompare'",
|
||||
"'match'",
|
||||
"'normalize'",
|
||||
"'padEnd'",
|
||||
"'padStart'",
|
||||
"'quote'",
|
||||
"'repeat'",
|
||||
"'replace'",
|
||||
"'search'",
|
||||
"'split'",
|
||||
"'startsWith'",
|
||||
"'substr'",
|
||||
"'toLocaleLowerCase'",
|
||||
"'toLocaleUpperCase'",
|
||||
"'toLowerCase'",
|
||||
"'toUpperCase'",
|
||||
"'trim'",
|
||||
"'trimleft'",
|
||||
"'trimright'",
|
||||
"'anchor'",
|
||||
"'big'",
|
||||
"'blink'",
|
||||
"'bold'",
|
||||
"'fixed'",
|
||||
"'fontcolor'",
|
||||
"'fontsize'",
|
||||
"'italics'",
|
||||
"'link'",
|
||||
"'small'",
|
||||
"'strike'",
|
||||
"'sub'",
|
||||
"'sup'",
|
||||
"'compile'",
|
||||
"'exec'",
|
||||
"'test'",
|
||||
"'from'",
|
||||
"'isArray'",
|
||||
"'of'",
|
||||
"'copyWithin'",
|
||||
"'fill'",
|
||||
"'pop'",
|
||||
"'push'",
|
||||
"'reverse'",
|
||||
"'shift'",
|
||||
"'sort'",
|
||||
"'splice'",
|
||||
"'unshift'",
|
||||
"'concat'",
|
||||
"'join'",
|
||||
"'every'",
|
||||
"'filter'",
|
||||
"'findIndex'",
|
||||
"'forEach'",
|
||||
"'map'",
|
||||
"'reduce'",
|
||||
"'reduceRight'",
|
||||
"'some'",
|
||||
"'move'",
|
||||
"'getInt8'",
|
||||
"'getUint8'",
|
||||
"'getInt16'",
|
||||
"'getUint16'",
|
||||
"'getInt32'",
|
||||
"'getUint32'",
|
||||
"'getFloat32'",
|
||||
"'getFloat64'",
|
||||
"'setInt8'",
|
||||
"'setUint8'",
|
||||
"'setInt16'",
|
||||
"'setUint16'",
|
||||
"'setInt32'",
|
||||
"'setUint32'",
|
||||
"'setFloat32'",
|
||||
"'setFloat64'",
|
||||
"'isView'",
|
||||
"'transfer'",
|
||||
"'clear'",
|
||||
"'get'",
|
||||
"'has'",
|
||||
"'set'",
|
||||
"'add'",
|
||||
"'splat'",
|
||||
"'check'",
|
||||
"'extractLane'",
|
||||
"'replaceLane'",
|
||||
"'load'",
|
||||
"'load1'",
|
||||
"'load2'",
|
||||
"'load3'",
|
||||
"'store'",
|
||||
"'store1'",
|
||||
"'store2'",
|
||||
"'store3'",
|
||||
"'addSaturate'",
|
||||
"'div'",
|
||||
"'mul'",
|
||||
"'neg'",
|
||||
"'reciprocalApproximation'",
|
||||
"'reciprocalSqrtApproximation'",
|
||||
"'subSaturate'",
|
||||
"'shuffle'",
|
||||
"'swizzle'",
|
||||
"'maxNum'",
|
||||
"'minNum'",
|
||||
"'select'",
|
||||
"'equal'",
|
||||
"'notEqual'",
|
||||
"'lessThan'",
|
||||
"'lessThanOrEqual'",
|
||||
"'greaterThan'",
|
||||
"'greaterThanOrEqual'",
|
||||
"'and'",
|
||||
"'or'",
|
||||
"'xor'",
|
||||
"'not'",
|
||||
"'shiftLeftByScalar'",
|
||||
"'shiftRightByScalar'",
|
||||
"'allTrue'",
|
||||
"'anyTrue'",
|
||||
"'fromFloat32x4'",
|
||||
"'fromFloat32x4Bits'",
|
||||
"'fromFloat64x2Bits'",
|
||||
"'fromInt32x4'",
|
||||
"'fromInt32x4Bits'",
|
||||
"'fromInt16x8Bits'",
|
||||
"'fromInt8x16Bits'",
|
||||
"'fromUint32x4'",
|
||||
"'fromUint32x4Bits'",
|
||||
"'fromUint16x8Bits'",
|
||||
"'fromUint8x16Bits'",
|
||||
"'neg'",
|
||||
"'compareExchange'",
|
||||
"'exchange'",
|
||||
"'wait'",
|
||||
"'wake'",
|
||||
"'isLockFree'",
|
||||
"'all'",
|
||||
"'race'",
|
||||
"'reject'",
|
||||
"'resolve'",
|
||||
"'catch'",
|
||||
"'then'",
|
||||
"'finally'",
|
||||
"'next'",
|
||||
"'throw'",
|
||||
"'close'",
|
||||
"'send'",
|
||||
"'apply'",
|
||||
"'construct'",
|
||||
"'deleteProperty'",
|
||||
"'ownKeys'",
|
||||
"'getCanonicalLocales'",
|
||||
"'supportedLocalesOf'",
|
||||
"'resolvedOptions'",
|
||||
"'formatToParts'",
|
||||
"'resolvedOptions'",
|
||||
"'instantiate'",
|
||||
"'instantiateStreaming'",
|
||||
"'compileStreaming'",
|
||||
"'validate'",
|
||||
"'customSections'",
|
||||
"'exports'",
|
||||
"'imports'",
|
||||
"'grow'",
|
||||
"'super'",
|
||||
"'in'",
|
||||
"'instanceof'",
|
||||
"' '"
|
||||
],
|
||||
"NEWLINE": [
|
||||
"'\\n'"
|
||||
],
|
||||
"NUMBER": [
|
||||
"'1/2'",
|
||||
"'1E2'",
|
||||
"'1E02'",
|
||||
"'1E+02'",
|
||||
"'-1'",
|
||||
"'-1.00'",
|
||||
"'-1/2'",
|
||||
"'-1E2'",
|
||||
"'-1E02'",
|
||||
"'-1E+02'",
|
||||
"'1/0'",
|
||||
"'0/0'",
|
||||
"'-2147483648/-1'",
|
||||
"'-9223372036854775808/-1'",
|
||||
"'-0'",
|
||||
"'-0.0'",
|
||||
"'+0'"
|
||||
],
|
||||
"OBJECT": [
|
||||
"IDENTIFIER"
|
||||
],
|
||||
"PROGRAM": [
|
||||
"JSBLOCK"
|
||||
],
|
||||
"PROPERTY": [
|
||||
"'.length' PROPERTY",
|
||||
"'.prototype' PROPERTY",
|
||||
"'.constructor' PROPERTY",
|
||||
"'.__proto__' PROPERTY",
|
||||
"'.__noSuchMethod__' PROPERTY",
|
||||
"'.__count__' PROPERTY",
|
||||
"'.__parent__' PROPERTY",
|
||||
"'.arguments' PROPERTY",
|
||||
"'.arity' PROPERTY",
|
||||
"'.caller' PROPERTY",
|
||||
"'.name' PROPERTY",
|
||||
"'.displayName' PROPERTY",
|
||||
"'.iterator' PROPERTY",
|
||||
"'.asyncIterator' PROPERTY",
|
||||
"'.match' PROPERTY",
|
||||
"'.replace' PROPERTY",
|
||||
"'.search' PROPERTY",
|
||||
"'.split' PROPERTY",
|
||||
"'.hasInstance' PROPERTY",
|
||||
"'.isConcatSpreadable' PROPERTY",
|
||||
"'.unscopables' PROPERTY",
|
||||
"'.species' PROPERTY",
|
||||
"'.toPrimitive' PROPERTY",
|
||||
"'.toStringTag' PROPERTY",
|
||||
"'.fileName' PROPERTY",
|
||||
"'.lineNumber' PROPERTY",
|
||||
"'.columnNumber' PROPERTY",
|
||||
"'.message' PROPERTY",
|
||||
"'.name' PROPERTY",
|
||||
"'.EPSILON' PROPERTY",
|
||||
"'.MAX_SAFE_INTEGER' PROPERTY",
|
||||
"'.MAX_VALUE' PROPERTY",
|
||||
"'.MIN_SAFE_INTEGER' PROPERTY",
|
||||
"'.MIN_VALUE' PROPERTY",
|
||||
"'.NaN' PROPERTY",
|
||||
"'.NEGATIVE_INFINITY' PROPERTY",
|
||||
"'.POSITIVE_INFINITY' PROPERTY",
|
||||
"'.E' PROPERTY",
|
||||
"'.LN2' PROPERTY",
|
||||
"'.LN10' PROPERTY",
|
||||
"'.LOG2E' PROPERTY",
|
||||
"'.LOG10E' PROPERTY",
|
||||
"'.PI' PROPERTY",
|
||||
"'.SQRT1_2' PROPERTY",
|
||||
"'.SQRT2' PROPERTY",
|
||||
"'.flags' PROPERTY",
|
||||
"'.global' PROPERTY",
|
||||
"'.ignoreCase' PROPERTY",
|
||||
"'.multiline' PROPERTY",
|
||||
"'.source' PROPERTY",
|
||||
"'.sticky' PROPERTY",
|
||||
"'.unicode' PROPERTY",
|
||||
"'.buffer' PROPERTY",
|
||||
"'.byteLength' PROPERTY",
|
||||
"'.byteOffset' PROPERTY",
|
||||
"'.BYTES_PER_ELEMENT' PROPERTY",
|
||||
"'.compare' PROPERTY",
|
||||
"'.format' PROPERTY",
|
||||
"'.callee' PROPERTY",
|
||||
"'.caller' PROPERTY",
|
||||
"'.memory' PROPERTY",
|
||||
"'.exports' PROPERTY",
|
||||
"' '"
|
||||
],
|
||||
"SP": [
|
||||
"' '"
|
||||
],
|
||||
"STATEMENT": [
|
||||
"EXPR ';'",
|
||||
"'var' SP VAR '=' EXPR ';'",
|
||||
"'let' SP VAR '=' EXPR ';'",
|
||||
"VAR '=' EXPR ';'",
|
||||
"VAR PROPERTY '=' EXPR ';'",
|
||||
"VAR '[' DECIMALNUMBER ']' '=' EXPR ';'",
|
||||
"'const' SP VAR '=' EXPR ';'",
|
||||
"'typeof' SP EXPR ';'",
|
||||
"'void' SP EXPR ';'",
|
||||
"'return' SP EXPR ';'",
|
||||
"VAR ':'"
|
||||
],
|
||||
"VAR": [
|
||||
"'a'",
|
||||
"'b'",
|
||||
"'c'",
|
||||
"'d'",
|
||||
"'e'",
|
||||
"'f'",
|
||||
"'g'",
|
||||
"'h'"
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
8707
custom_mutators/gramatron/grammars/php/source.json
Normal file
8707
custom_mutators/gramatron/grammars/php/source.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1195
custom_mutators/gramatron/grammars/ruby/source.json
Normal file
1195
custom_mutators/gramatron/grammars/ruby/source.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
434
custom_mutators/gramatron/hashmap.c
Normal file
434
custom_mutators/gramatron/hashmap.c
Normal file
@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Generic map implementation.
|
||||
*/
|
||||
#include "hashmap.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define INITIAL_SIZE (256)
|
||||
#define MAX_CHAIN_LENGTH (8)
|
||||
|
||||
/* We need to keep keys and values */
|
||||
typedef struct _hashmap_element {
|
||||
|
||||
char *key;
|
||||
int in_use;
|
||||
any_t data;
|
||||
|
||||
} hashmap_element;
|
||||
|
||||
/* A hashmap has some maximum size and current size,
|
||||
* as well as the data to hold. */
|
||||
typedef struct _hashmap_map {
|
||||
|
||||
int table_size;
|
||||
int size;
|
||||
hashmap_element *data;
|
||||
|
||||
} hashmap_map;
|
||||
|
||||
/*
|
||||
* Return an empty hashmap, or NULL on failure.
|
||||
*/
|
||||
map_t hashmap_new() {
|
||||
|
||||
hashmap_map *m = (hashmap_map *)malloc(sizeof(hashmap_map));
|
||||
if (!m) goto err;
|
||||
|
||||
m->data = (hashmap_element *)calloc(INITIAL_SIZE, sizeof(hashmap_element));
|
||||
if (!m->data) goto err;
|
||||
|
||||
m->table_size = INITIAL_SIZE;
|
||||
m->size = 0;
|
||||
|
||||
return m;
|
||||
err:
|
||||
if (m) hashmap_free(m);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* The implementation here was originally done by Gary S. Brown. I have
|
||||
borrowed the tables directly, and made some minor changes to the
|
||||
crc32-function (including changing the interface). //ylo */
|
||||
|
||||
/* ============================================================= */
|
||||
/* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
|
||||
/* code or tables extracted from it, as desired without restriction. */
|
||||
/* */
|
||||
/* First, the polynomial itself and its table of feedback terms. The */
|
||||
/* polynomial is */
|
||||
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
|
||||
/* */
|
||||
/* Note that we take it "backwards" and put the highest-order term in */
|
||||
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
|
||||
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
|
||||
/* the MSB being 1. */
|
||||
/* */
|
||||
/* Note that the usual hardware shift register implementation, which */
|
||||
/* is what we're using (we're merely optimizing it by doing eight-bit */
|
||||
/* chunks at a time) shifts bits into the lowest-order term. In our */
|
||||
/* implementation, that means shifting towards the right. Why do we */
|
||||
/* do it this way? Because the calculated CRC must be transmitted in */
|
||||
/* order from highest-order term to lowest-order term. UARTs transmit */
|
||||
/* characters in order from LSB to MSB. By storing the CRC this way, */
|
||||
/* we hand it to the UART in the order low-byte to high-byte; the UART */
|
||||
/* sends each low-bit to hight-bit; and the result is transmission bit */
|
||||
/* by bit from highest- to lowest-order term without requiring any bit */
|
||||
/* shuffling on our part. Reception works similarly. */
|
||||
/* */
|
||||
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
|
||||
/* */
|
||||
/* The table can be generated at runtime if desired; code to do so */
|
||||
/* is shown later. It might not be obvious, but the feedback */
|
||||
/* terms simply represent the results of eight shift/xor opera- */
|
||||
/* tions for all combinations of data and CRC register values. */
|
||||
/* */
|
||||
/* The values must be right-shifted by eight bits by the "updcrc" */
|
||||
/* logic; the shift must be unsigned (bring in zeroes). On some */
|
||||
/* hardware you could probably optimize the shift in assembler by */
|
||||
/* using byte-swap instructions. */
|
||||
/* polynomial $edb88320 */
|
||||
/* */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static unsigned long crc32_tab[] = {
|
||||
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL};
|
||||
|
||||
/* Return a 32-bit CRC of the contents of the buffer. */
|
||||
|
||||
unsigned long crc32(const unsigned char *s, unsigned int len) {
|
||||
|
||||
unsigned int i;
|
||||
unsigned long crc32val;
|
||||
|
||||
crc32val = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
|
||||
|
||||
}
|
||||
|
||||
return crc32val;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Hashing function for a string
|
||||
*/
|
||||
unsigned int hashmap_hash_int(hashmap_map *m, char *keystring) {
|
||||
|
||||
unsigned long key = crc32((unsigned char *)(keystring), strlen(keystring));
|
||||
|
||||
/* Robert Jenkins' 32 bit Mix Function */
|
||||
key += (key << 12);
|
||||
key ^= (key >> 22);
|
||||
key += (key << 4);
|
||||
key ^= (key >> 9);
|
||||
key += (key << 10);
|
||||
key ^= (key >> 2);
|
||||
key += (key << 7);
|
||||
key ^= (key >> 12);
|
||||
|
||||
/* Knuth's Multiplicative Method */
|
||||
key = (key >> 3) * 2654435761;
|
||||
|
||||
return key % m->table_size;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the integer of the location in data
|
||||
* to store the point to the item, or MAP_FULL.
|
||||
*/
|
||||
int hashmap_hash(map_t in, char *key) {
|
||||
|
||||
int curr;
|
||||
int i;
|
||||
|
||||
/* Cast the hashmap */
|
||||
hashmap_map *m = (hashmap_map *)in;
|
||||
|
||||
/* If full, return immediately */
|
||||
if (m->size >= (m->table_size / 2)) return MAP_FULL;
|
||||
|
||||
/* Find the best index */
|
||||
curr = hashmap_hash_int(m, key);
|
||||
|
||||
/* Linear probing */
|
||||
for (i = 0; i < MAX_CHAIN_LENGTH; i++) {
|
||||
|
||||
if (m->data[curr].in_use == 0) return curr;
|
||||
|
||||
if (m->data[curr].in_use == 1 && (strcmp(m->data[curr].key, key) == 0))
|
||||
return curr;
|
||||
|
||||
curr = (curr + 1) % m->table_size;
|
||||
|
||||
}
|
||||
|
||||
return MAP_FULL;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Doubles the size of the hashmap, and rehashes all the elements
|
||||
*/
|
||||
int hashmap_rehash(map_t in) {
|
||||
|
||||
int i;
|
||||
int old_size;
|
||||
hashmap_element *curr;
|
||||
|
||||
/* Setup the new elements */
|
||||
hashmap_map * m = (hashmap_map *)in;
|
||||
hashmap_element *temp =
|
||||
(hashmap_element *)calloc(2 * m->table_size, sizeof(hashmap_element));
|
||||
if (!temp) return MAP_OMEM;
|
||||
|
||||
/* Update the array */
|
||||
curr = m->data;
|
||||
m->data = temp;
|
||||
|
||||
/* Update the size */
|
||||
old_size = m->table_size;
|
||||
m->table_size = 2 * m->table_size;
|
||||
m->size = 0;
|
||||
|
||||
/* Rehash the elements */
|
||||
for (i = 0; i < old_size; i++) {
|
||||
|
||||
int status;
|
||||
|
||||
if (curr[i].in_use == 0) continue;
|
||||
|
||||
status = hashmap_put(m, curr[i].key, curr[i].data);
|
||||
if (status != MAP_OK) return status;
|
||||
|
||||
}
|
||||
|
||||
free(curr);
|
||||
|
||||
return MAP_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a pointer to the hashmap with some key
|
||||
*/
|
||||
int hashmap_put(map_t in, char *key, any_t value) {
|
||||
|
||||
int index;
|
||||
hashmap_map *m;
|
||||
|
||||
/* Cast the hashmap */
|
||||
m = (hashmap_map *)in;
|
||||
|
||||
/* Find a place to put our value */
|
||||
index = hashmap_hash(in, key);
|
||||
while (index == MAP_FULL) {
|
||||
|
||||
if (hashmap_rehash(in) == MAP_OMEM) { return MAP_OMEM; }
|
||||
index = hashmap_hash(in, key);
|
||||
|
||||
}
|
||||
|
||||
/* Set the data */
|
||||
m->data[index].data = value;
|
||||
m->data[index].key = key;
|
||||
m->data[index].in_use = 1;
|
||||
m->size++;
|
||||
|
||||
return MAP_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get your pointer out of the hashmap with a key
|
||||
*/
|
||||
int hashmap_get(map_t in, char *key, any_t *arg) {
|
||||
|
||||
int curr;
|
||||
int i;
|
||||
hashmap_map *m;
|
||||
|
||||
/* Cast the hashmap */
|
||||
m = (hashmap_map *)in;
|
||||
|
||||
/* Find data location */
|
||||
curr = hashmap_hash_int(m, key);
|
||||
|
||||
/* Linear probing, if necessary */
|
||||
for (i = 0; i < MAX_CHAIN_LENGTH; i++) {
|
||||
|
||||
int in_use = m->data[curr].in_use;
|
||||
if (in_use == 1) {
|
||||
|
||||
if (strcmp(m->data[curr].key, key) == 0) {
|
||||
|
||||
*arg = (m->data[curr].data);
|
||||
return MAP_OK;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
curr = (curr + 1) % m->table_size;
|
||||
|
||||
}
|
||||
|
||||
*arg = NULL;
|
||||
|
||||
/* Not found */
|
||||
return MAP_MISSING;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate the function parameter over each element in the hashmap. The
|
||||
* additional any_t argument is passed to the function as its first
|
||||
* argument and the hashmap element is the second.
|
||||
*/
|
||||
int hashmap_iterate(map_t in, PFany f, any_t item) {
|
||||
|
||||
int i;
|
||||
|
||||
/* Cast the hashmap */
|
||||
hashmap_map *m = (hashmap_map *)in;
|
||||
|
||||
/* On empty hashmap, return immediately */
|
||||
if (hashmap_length(m) <= 0) return MAP_MISSING;
|
||||
|
||||
/* Linear probing */
|
||||
for (i = 0; i < m->table_size; i++)
|
||||
if (m->data[i].in_use != 0) {
|
||||
|
||||
any_t data = (any_t)(m->data[i].data);
|
||||
int status = f(item, data);
|
||||
if (status != MAP_OK) { return status; }
|
||||
|
||||
}
|
||||
|
||||
return MAP_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an element with that key from the map
|
||||
*/
|
||||
int hashmap_remove(map_t in, char *key) {
|
||||
|
||||
int i;
|
||||
int curr;
|
||||
hashmap_map *m;
|
||||
|
||||
/* Cast the hashmap */
|
||||
m = (hashmap_map *)in;
|
||||
|
||||
/* Find key */
|
||||
curr = hashmap_hash_int(m, key);
|
||||
|
||||
/* Linear probing, if necessary */
|
||||
for (i = 0; i < MAX_CHAIN_LENGTH; i++) {
|
||||
|
||||
int in_use = m->data[curr].in_use;
|
||||
if (in_use == 1) {
|
||||
|
||||
if (strcmp(m->data[curr].key, key) == 0) {
|
||||
|
||||
/* Blank out the fields */
|
||||
m->data[curr].in_use = 0;
|
||||
m->data[curr].data = NULL;
|
||||
m->data[curr].key = NULL;
|
||||
|
||||
/* Reduce the size */
|
||||
m->size--;
|
||||
return MAP_OK;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
curr = (curr + 1) % m->table_size;
|
||||
|
||||
}
|
||||
|
||||
/* Data not found */
|
||||
return MAP_MISSING;
|
||||
|
||||
}
|
||||
|
||||
/* Deallocate the hashmap */
|
||||
void hashmap_free(map_t in) {
|
||||
|
||||
hashmap_map *m = (hashmap_map *)in;
|
||||
free(m->data);
|
||||
free(m);
|
||||
|
||||
}
|
||||
|
||||
/* Return the length of the hashmap */
|
||||
int hashmap_length(map_t in) {
|
||||
|
||||
hashmap_map *m = (hashmap_map *)in;
|
||||
if (m != NULL)
|
||||
return m->size;
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
83
custom_mutators/gramatron/hashmap.h
Normal file
83
custom_mutators/gramatron/hashmap.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Generic hashmap manipulation functions
|
||||
*
|
||||
* Originally by Elliot C Back -
|
||||
* http://elliottback.com/wp/hashmap-implementation-in-c/
|
||||
*
|
||||
* Modified by Pete Warden to fix a serious performance problem, support strings
|
||||
* as keys and removed thread synchronization - http://petewarden.typepad.com
|
||||
*/
|
||||
#ifndef __HASHMAP_H__
|
||||
#define __HASHMAP_H__
|
||||
|
||||
#define MAP_MISSING -3 /* No such element */
|
||||
#define MAP_FULL -2 /* Hashmap is full */
|
||||
#define MAP_OMEM -1 /* Out of Memory */
|
||||
#define MAP_OK 0 /* OK */
|
||||
|
||||
/*
|
||||
* any_t is a pointer. This allows you to put arbitrary structures in
|
||||
* the hashmap.
|
||||
*/
|
||||
typedef void *any_t;
|
||||
|
||||
/*
|
||||
* PFany is a pointer to a function that can take two any_t arguments
|
||||
* and return an integer. Returns status code..
|
||||
*/
|
||||
typedef int (*PFany)(any_t, any_t);
|
||||
|
||||
/*
|
||||
* map_t is a pointer to an internally maintained data structure.
|
||||
* Clients of this package do not need to know how hashmaps are
|
||||
* represented. They see and manipulate only map_t's.
|
||||
*/
|
||||
typedef any_t map_t;
|
||||
|
||||
/*
|
||||
* Return an empty hashmap. Returns NULL if empty.
|
||||
*/
|
||||
extern map_t hashmap_new();
|
||||
|
||||
/*
|
||||
* Iteratively call f with argument (item, data) for
|
||||
* each element data in the hashmap. The function must
|
||||
* return a map status code. If it returns anything other
|
||||
* than MAP_OK the traversal is terminated. f must
|
||||
* not reenter any hashmap functions, or deadlock may arise.
|
||||
*/
|
||||
extern int hashmap_iterate(map_t in, PFany f, any_t item);
|
||||
|
||||
/*
|
||||
* Add an element to the hashmap. Return MAP_OK or MAP_OMEM.
|
||||
*/
|
||||
extern int hashmap_put(map_t in, char *key, any_t value);
|
||||
|
||||
/*
|
||||
* Get an element from the hashmap. Return MAP_OK or MAP_MISSING.
|
||||
*/
|
||||
extern int hashmap_get(map_t in, char *key, any_t *arg);
|
||||
|
||||
/*
|
||||
* Remove an element from the hashmap. Return MAP_OK or MAP_MISSING.
|
||||
*/
|
||||
extern int hashmap_remove(map_t in, char *key);
|
||||
|
||||
/*
|
||||
* Get any element. Return MAP_OK or MAP_MISSING.
|
||||
* remove - should the element be removed from the hashmap
|
||||
*/
|
||||
extern int hashmap_get_one(map_t in, any_t *arg, int remove);
|
||||
|
||||
/*
|
||||
* Free the hashmap
|
||||
*/
|
||||
extern void hashmap_free(map_t in);
|
||||
|
||||
/*
|
||||
* Get the current size of a hashmap
|
||||
*/
|
||||
extern int hashmap_length(map_t in);
|
||||
|
||||
#endif
|
||||
|
1
custom_mutators/gramatron/json-c
Submodule
1
custom_mutators/gramatron/json-c
Submodule
Submodule custom_mutators/gramatron/json-c added at 11546bfd07
275
custom_mutators/gramatron/preprocess/construct_automata.py
Normal file
275
custom_mutators/gramatron/preprocess/construct_automata.py
Normal file
@ -0,0 +1,275 @@
|
||||
import sys
|
||||
import json
|
||||
import re
|
||||
from collections import defaultdict
|
||||
# import pygraphviz as pgv
|
||||
|
||||
gram_data = None
|
||||
state_count = 1
|
||||
pda = []
|
||||
worklist = []
|
||||
state_stacks = {}
|
||||
|
||||
# === If user provides upper bound on the stack size during FSA creation ===
|
||||
# Specifies the upper bound to which the stack is allowed to grow
|
||||
# If for any generated state, the stack size is >= stack_limit then this
|
||||
# state is not expanded further.
|
||||
stack_limit = None
|
||||
# Holds the set of unexpanded rules owing to the user-passed stack constraint limit
|
||||
unexpanded_rules = set()
|
||||
|
||||
def main(grammar, limit):
|
||||
global worklist, gram_data, stack_limit
|
||||
current = '0'
|
||||
stack_limit = limit
|
||||
if stack_limit:
|
||||
print ('[X] Operating in bounded stack mode')
|
||||
|
||||
with open(grammar, 'r') as fd:
|
||||
gram_data = json.load(fd)
|
||||
start_symbol = gram_data["Start"][0]
|
||||
worklist.append([current, [start_symbol]])
|
||||
# print (grammar)
|
||||
filename = (grammar.split('/')[-1]).split('.')[0]
|
||||
|
||||
|
||||
while worklist:
|
||||
# Take an element from the worklist
|
||||
# print ('================')
|
||||
# print ('Worklist:', worklist)
|
||||
element = worklist.pop(0)
|
||||
prep_transitions(element)
|
||||
|
||||
pda_file = filename + '_transition.json'
|
||||
graph_file = filename + '.png'
|
||||
# print ('XXXXXXXXXXXXXXXX')
|
||||
# print ('PDA file:%s Png graph file:%s' % (pda_file, graph_file))
|
||||
# XXX Commented out because visualization of current version of PHP causes segfault
|
||||
# Create the graph and dump the transitions to a file
|
||||
# create_graph(filename)
|
||||
transformed = postprocess()
|
||||
with open(filename + '_automata.json', 'w+') as fd:
|
||||
json.dump(transformed, fd)
|
||||
with open(filename + '_transition.json', 'w+') as fd:
|
||||
json.dump(pda, fd)
|
||||
if not unexpanded_rules:
|
||||
print ('[X] No unexpanded rules, absolute FSA formed')
|
||||
exit(0)
|
||||
else:
|
||||
print ('[X] Certain rules were not expanded due to stack size limit. Inexact approximation has been created and the disallowed rules have been put in {}_disallowed.json'.format(filename))
|
||||
print ('[X] Number of unexpanded rules:', len(unexpanded_rules))
|
||||
with open(filename + '_disallowed.json', 'w+') as fd:
|
||||
json.dump(list(unexpanded_rules), fd)
|
||||
|
||||
def create_graph(filename):
|
||||
'''
|
||||
Creates a DOT representation of the PDA
|
||||
'''
|
||||
global pda
|
||||
G = pgv.AGraph(strict = False, directed = True)
|
||||
for transition in pda:
|
||||
print ('Transition:', transition)
|
||||
G.add_edge(transition['source'], transition['dest'],
|
||||
label = 'Term:{}'.format(transition['terminal']))
|
||||
G.layout(prog = 'dot')
|
||||
print ('Do it up 2')
|
||||
G.draw(filename + '.png')
|
||||
|
||||
def prep_transitions(element):
|
||||
'''
|
||||
Generates transitions
|
||||
'''
|
||||
global gram_data, state_count, pda, worklist, state_stacks, stack_limit, unexpanded_rules
|
||||
state = element[0]
|
||||
try:
|
||||
nonterminal = element[1][0]
|
||||
except IndexError:
|
||||
# Final state was encountered, pop from worklist without doing anything
|
||||
return
|
||||
rules = gram_data[nonterminal]
|
||||
count = 1
|
||||
for rule in rules:
|
||||
isRecursive = False
|
||||
# print ('Current state:', state)
|
||||
terminal, ss, termIsRegex = tokenize(rule)
|
||||
transition = get_template()
|
||||
transition['trigger'] = '_'.join([state, str(count)])
|
||||
transition['source'] = state
|
||||
transition['dest'] = str(state_count)
|
||||
transition['ss'] = ss
|
||||
transition['terminal'] = terminal
|
||||
transition['rule'] = "{} -> {}".format(nonterminal, rule )
|
||||
if termIsRegex:
|
||||
transition['termIsRegex'] = True
|
||||
|
||||
# Creating a state stack for the new state
|
||||
try:
|
||||
state_stack = state_stacks[state][:]
|
||||
except:
|
||||
state_stack = []
|
||||
if len(state_stack):
|
||||
state_stack.pop(0)
|
||||
if ss:
|
||||
for symbol in ss[::-1]:
|
||||
state_stack.insert(0, symbol)
|
||||
transition['stack'] = state_stack
|
||||
|
||||
# Check if a recursive transition state being created, if so make a backward
|
||||
# edge and don't add anything to the worklist
|
||||
# print (state_stacks)
|
||||
if state_stacks:
|
||||
for state_element, stack in state_stacks.items():
|
||||
# print ('Stack:', sorted(stack))
|
||||
# print ('State stack:', sorted(state_stack))
|
||||
if sorted(stack) == sorted(state_stack):
|
||||
transition['dest'] = state_element
|
||||
# print ('Recursive:', transition)
|
||||
pda.append(transition)
|
||||
count += 1
|
||||
isRecursive = True
|
||||
break
|
||||
# If a recursive transition exercised don't add the same transition as a new
|
||||
# edge, continue onto the next transitions
|
||||
if isRecursive:
|
||||
continue
|
||||
|
||||
# If the generated state has a stack size > stack_limit then that state is abandoned
|
||||
# and not added to the FSA or the worklist for further expansion
|
||||
if stack_limit:
|
||||
if (len(transition['stack']) > stack_limit):
|
||||
unexpanded_rules.add(transition['rule'])
|
||||
continue
|
||||
|
||||
# Create transitions for the non-recursive relations and add to the worklist
|
||||
# print ('Normal:', transition)
|
||||
# print ('State2:', state)
|
||||
pda.append(transition)
|
||||
worklist.append([transition['dest'], transition['stack']])
|
||||
state_stacks[transition['dest']] = state_stack
|
||||
state_count += 1
|
||||
count += 1
|
||||
|
||||
def tokenize(rule):
|
||||
'''
|
||||
Gets the terminal and the corresponding stack symbols from a rule in GNF form
|
||||
'''
|
||||
pattern = re.compile("([r])*\'([\s\S]+)\'([\s\S]*)")
|
||||
terminal = None
|
||||
ss = None
|
||||
termIsRegex = False
|
||||
match = pattern.match(rule)
|
||||
if match.group(1):
|
||||
termIsRegex = True
|
||||
if match.group(2):
|
||||
terminal = match.group(2)
|
||||
else:
|
||||
raise AssertionError("Rule is not in GNF form")
|
||||
|
||||
if match.group(3):
|
||||
ss = (match.group(3)).split()
|
||||
|
||||
return terminal, ss, termIsRegex
|
||||
|
||||
def get_template():
|
||||
transition_template = {
|
||||
'trigger':None,
|
||||
'source': None,
|
||||
'dest': None,
|
||||
'termIsRegex': False,
|
||||
'terminal' : None,
|
||||
'stack': []
|
||||
}
|
||||
return transition_template
|
||||
|
||||
def postprocess():
|
||||
'''
|
||||
Creates a representation to be passed on to the C-module
|
||||
'''
|
||||
global pda
|
||||
final_struct = {}
|
||||
memoized = defaultdict(list)
|
||||
# Supporting data structures for if stack limit is imposed
|
||||
culled_pda = []
|
||||
culled_final = []
|
||||
num_transitions = 0 # Keep track of number of transitions
|
||||
|
||||
|
||||
states, final, initial = _get_states()
|
||||
|
||||
print (initial)
|
||||
assert len(initial) == 1, 'More than one init state found'
|
||||
|
||||
# Cull transitions to states which were not expanded owing to the stack limit
|
||||
if stack_limit:
|
||||
|
||||
blocklist = []
|
||||
for final_state in final:
|
||||
for transition in pda:
|
||||
if (transition["dest"] == final_state) and (len(transition["stack"]) > 0):
|
||||
blocklist.append(transition["dest"])
|
||||
continue
|
||||
else:
|
||||
culled_pda.append(transition)
|
||||
|
||||
culled_final = [state for state in final if state not in blocklist]
|
||||
|
||||
assert len(culled_final) == 1, 'More than one final state found'
|
||||
|
||||
for transition in culled_pda:
|
||||
state = transition["source"]
|
||||
if transition["dest"] in blocklist:
|
||||
continue
|
||||
num_transitions += 1
|
||||
memoized[state].append([transition["trigger"], transition["dest"],
|
||||
transition["terminal"]])
|
||||
final_struct["init_state"] = initial
|
||||
final_struct["final_state"] = culled_final[0]
|
||||
# The reason we do this is because when states are culled, the indexing is
|
||||
# still relative to the actual number of states hence we keep numstates recorded
|
||||
# as the original number of states
|
||||
print ('[X] Actual Number of states:', len(memoized.keys()))
|
||||
print ('[X] Number of transitions:', num_transitions)
|
||||
print ('[X] Original Number of states:', len(states))
|
||||
final_struct["numstates"] = len(states)
|
||||
final_struct["pda"] = memoized
|
||||
return final_struct
|
||||
|
||||
# Running FSA construction in exact approximation mode and postprocessing it like so
|
||||
for transition in pda:
|
||||
state = transition["source"]
|
||||
memoized[state].append([transition["trigger"], transition["dest"],
|
||||
transition["terminal"]])
|
||||
|
||||
final_struct["init_state"] = initial
|
||||
final_struct["final_state"] = final[0]
|
||||
print ('[X] Actual Number of states:', len(memoized.keys()))
|
||||
final_struct["numstates"] = len(memoized.keys())
|
||||
final_struct["pda"] = memoized
|
||||
return final_struct
|
||||
|
||||
|
||||
def _get_states():
|
||||
source = set()
|
||||
dest = set()
|
||||
global pda
|
||||
for transition in pda:
|
||||
source.add(transition["source"])
|
||||
dest.add(transition["dest"])
|
||||
source_copy = source.copy()
|
||||
source_copy.update(dest)
|
||||
return list(source_copy), list(dest.difference(source)), str(''.join(list(source.difference(dest))))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description = 'Script to convert GNF grammar to PDA')
|
||||
parser.add_argument(
|
||||
'--gf',
|
||||
type = str,
|
||||
help = 'Location of GNF grammar')
|
||||
parser.add_argument(
|
||||
'--limit',
|
||||
type = int,
|
||||
default = None,
|
||||
help = 'Specify the upper bound for the stack size')
|
||||
args = parser.parse_args()
|
||||
main(args.gf, args.limit)
|
289
custom_mutators/gramatron/preprocess/gnf_converter.py
Normal file
289
custom_mutators/gramatron/preprocess/gnf_converter.py
Normal file
@ -0,0 +1,289 @@
|
||||
import sys
|
||||
import re
|
||||
import copy
|
||||
import json
|
||||
from string import ascii_uppercase
|
||||
from itertools import combinations
|
||||
from collections import defaultdict
|
||||
|
||||
NONTERMINALSET = []
|
||||
COUNT = 1
|
||||
|
||||
def main(grammar_file, out, start):
|
||||
grammar = None
|
||||
# If grammar file is a preprocessed NT file, then skip preprocessing
|
||||
if '.json' in grammar_file:
|
||||
with open(grammar_file, 'r') as fd:
|
||||
grammar = json.load(fd)
|
||||
elif '.g4' in grammar_file:
|
||||
with open(grammar_file, 'r') as fd:
|
||||
data = fd.readlines()
|
||||
grammar = preprocess(data)
|
||||
else:
|
||||
raise('Unknwown file format passed. Accepts (.g4/.json)')
|
||||
|
||||
with open('debug_preprocess.json', 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
grammar = remove_unit(grammar) # eliminates unit productions
|
||||
with open('debug_unit.json', 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
grammar = remove_mixed(grammar) # eliminate terminals existing with non-terminals
|
||||
with open('debug_mixed.json', 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
grammar = break_rules(grammar) # eliminate rules with more than two non-terminals
|
||||
with open('debug_break.json', 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
grammar = gnf(grammar)
|
||||
|
||||
# Dump GNF form of the grammar with only reachable rules
|
||||
# reachable_grammar = get_reachable(grammar, start)
|
||||
# with open('debug_gnf_reachable.json', 'w+') as fd:
|
||||
# json.dump(reachable_grammar, fd)
|
||||
with open('debug_gnf.json', 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
|
||||
grammar["Start"] = [start]
|
||||
with open(out, 'w+') as fd:
|
||||
json.dump(grammar, fd)
|
||||
|
||||
def get_reachable(grammar, start):
|
||||
'''
|
||||
Returns a grammar without dead rules
|
||||
'''
|
||||
reachable_nt = set()
|
||||
worklist = list()
|
||||
processed = set()
|
||||
reachable_grammar = dict()
|
||||
worklist.append(start)
|
||||
|
||||
while worklist:
|
||||
nt = worklist.pop(0)
|
||||
processed.add(nt)
|
||||
reachable_grammar[nt] = grammar[nt]
|
||||
rules = grammar[nt]
|
||||
for rule in rules:
|
||||
tokens = gettokens(rule)
|
||||
for token in tokens:
|
||||
if not isTerminal(token):
|
||||
if token not in processed:
|
||||
worklist.append(token)
|
||||
return reachable_grammar
|
||||
|
||||
|
||||
def gettokens(rule):
|
||||
pattern = re.compile("([^\s\"\']+)|\"([^\"]*)\"|\'([^\']*)\'")
|
||||
return [matched.group(0) for matched in pattern.finditer(rule)]
|
||||
|
||||
def gnf(grammar):
|
||||
old_grammar = copy.deepcopy(grammar)
|
||||
new_grammar = defaultdict(list)
|
||||
isgnf = False
|
||||
while not isgnf:
|
||||
for lhs, rules in old_grammar.items():
|
||||
for rule in rules:
|
||||
tokens = gettokens(rule)
|
||||
if len(tokens) == 1 and isTerminal(rule):
|
||||
new_grammar[lhs].append(rule)
|
||||
continue
|
||||
startoken = tokens[0]
|
||||
endrule = tokens[1:]
|
||||
if not isTerminal(startoken):
|
||||
newrules = []
|
||||
extendrules = old_grammar[startoken]
|
||||
for extension in extendrules:
|
||||
temprule = endrule[:]
|
||||
temprule.insert(0, extension)
|
||||
newrules.append(temprule)
|
||||
for newnew in newrules:
|
||||
new_grammar[lhs].append(' '.join(newnew))
|
||||
else:
|
||||
new_grammar[lhs].append(rule)
|
||||
isgnf = True
|
||||
for lhs, rules in new_grammar.items():
|
||||
for rule in rules:
|
||||
# if "\' \'" or isTerminal(rule):
|
||||
tokens = gettokens(rule)
|
||||
if len(tokens) == 1 and isTerminal(rule):
|
||||
continue
|
||||
startoken = tokens[0]
|
||||
if not isTerminal(startoken):
|
||||
isgnf = False
|
||||
break
|
||||
if not isgnf:
|
||||
old_grammar = copy.deepcopy(new_grammar)
|
||||
new_grammar = defaultdict(list)
|
||||
return new_grammar
|
||||
|
||||
|
||||
def preprocess(data):
|
||||
productions = []
|
||||
production = []
|
||||
for line in data:
|
||||
if line != '\n':
|
||||
production.append(line)
|
||||
else:
|
||||
productions.append(production)
|
||||
production = []
|
||||
final_rule_set = {}
|
||||
for production in productions:
|
||||
rules = []
|
||||
init = production[0]
|
||||
nonterminal = init.split(':')[0]
|
||||
rules.append(strip_chars(init.split(':')[1]).strip('| '))
|
||||
for production_rule in production[1:]:
|
||||
rules.append(strip_chars(production_rule.split('|')[0]))
|
||||
final_rule_set[nonterminal] = rules
|
||||
# for line in data:
|
||||
# if line != '\n':
|
||||
# production.append(line)
|
||||
return final_rule_set
|
||||
|
||||
def remove_unit(grammar):
|
||||
nounitproductions = False
|
||||
old_grammar = copy.deepcopy(grammar)
|
||||
new_grammar = defaultdict(list)
|
||||
while not nounitproductions:
|
||||
for lhs, rules in old_grammar.items():
|
||||
for rhs in rules:
|
||||
# Checking if the rule is a unit production rule
|
||||
if len(gettokens(rhs)) == 1:
|
||||
if not isTerminal(rhs):
|
||||
new_grammar[lhs].extend([rule for rule in old_grammar[rhs]])
|
||||
else:
|
||||
new_grammar[lhs].append(rhs)
|
||||
else:
|
||||
new_grammar[lhs].append(rhs)
|
||||
# Checking there are no unit productions left in the grammar
|
||||
nounitproductions = True
|
||||
for lhs, rules in new_grammar.items():
|
||||
for rhs in rules:
|
||||
if len(gettokens(rhs)) == 1:
|
||||
if not isTerminal(rhs):
|
||||
nounitproductions = False
|
||||
break
|
||||
if not nounitproductions:
|
||||
break
|
||||
# Unit productions are still there in the grammar -- repeat the process
|
||||
if not nounitproductions:
|
||||
old_grammar = copy.deepcopy(new_grammar)
|
||||
new_grammar = defaultdict(list)
|
||||
return new_grammar
|
||||
|
||||
def isTerminal(rule):
|
||||
# pattern = re.compile("([r]*\'[\s\S]+\')")
|
||||
pattern = re.compile("\'(.*?)\'")
|
||||
match = pattern.match(rule)
|
||||
if match:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def remove_mixed(grammar):
|
||||
'''
|
||||
Remove rules where there are terminals mixed in with non-terminals
|
||||
'''
|
||||
new_grammar = defaultdict(list)
|
||||
for lhs, rules in grammar.items():
|
||||
for rhs in rules:
|
||||
# tokens = rhs.split(' ')
|
||||
regen_rule = []
|
||||
tokens = gettokens(rhs)
|
||||
if len(gettokens(rhs)) == 1:
|
||||
new_grammar[lhs].append(rhs)
|
||||
continue
|
||||
for token in tokens:
|
||||
# Identify if there is a terminal in the RHS
|
||||
if isTerminal(token):
|
||||
# Check if a corresponding nonterminal already exists
|
||||
nonterminal = terminal_exist(token, new_grammar)
|
||||
if nonterminal:
|
||||
regen_rule.append(nonterminal)
|
||||
else:
|
||||
new_nonterm = get_nonterminal()
|
||||
new_grammar[new_nonterm].append(token)
|
||||
regen_rule.append(new_nonterm)
|
||||
else:
|
||||
regen_rule.append(token)
|
||||
new_grammar[lhs].append(' '.join(regen_rule))
|
||||
return new_grammar
|
||||
|
||||
def break_rules(grammar):
|
||||
new_grammar = defaultdict(list)
|
||||
old_grammar = copy.deepcopy(grammar)
|
||||
nomulti = False
|
||||
while not nomulti:
|
||||
for lhs, rules in old_grammar.items():
|
||||
for rhs in rules:
|
||||
tokens = gettokens(rhs)
|
||||
if len(tokens) > 2 and (not isTerminal(rhs)):
|
||||
split = tokens[:-1]
|
||||
nonterminal = terminal_exist(' '.join(split), new_grammar)
|
||||
if nonterminal:
|
||||
newrule = ' '.join([nonterminal, tokens[-1]])
|
||||
new_grammar[lhs].append(newrule)
|
||||
else:
|
||||
nonterminal = get_nonterminal()
|
||||
new_grammar[nonterminal].append(' '.join(split))
|
||||
newrule = ' '.join([nonterminal, tokens[-1]])
|
||||
new_grammar[lhs].append(newrule)
|
||||
else:
|
||||
new_grammar[lhs].append(rhs)
|
||||
nomulti = True
|
||||
for lhs, rules in new_grammar.items():
|
||||
for rhs in rules:
|
||||
# tokens = rhs.split(' ')
|
||||
tokens = gettokens(rhs)
|
||||
if len(tokens) > 2 and (not isTerminal(rhs)):
|
||||
nomulti = False
|
||||
break
|
||||
if not nomulti:
|
||||
old_grammar = copy.deepcopy(new_grammar)
|
||||
new_grammar = defaultdict(list)
|
||||
return new_grammar
|
||||
|
||||
def strip_chars(rule):
|
||||
return rule.strip('\n\t ')
|
||||
|
||||
def get_nonterminal():
|
||||
global NONTERMINALSET
|
||||
if NONTERMINALSET:
|
||||
return NONTERMINALSET.pop(0)
|
||||
else:
|
||||
_repopulate()
|
||||
return NONTERMINALSET.pop(0)
|
||||
|
||||
def _repopulate():
|
||||
global COUNT
|
||||
global NONTERMINALSET
|
||||
NONTERMINALSET = [''.join(x) for x in list(combinations(ascii_uppercase, COUNT))]
|
||||
COUNT += 1
|
||||
|
||||
def terminal_exist(token, grammar):
|
||||
for nonterminal, rules in grammar.items():
|
||||
if token in rules:
|
||||
return nonterminal
|
||||
return None
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description = 'Script to convert grammar to GNF form')
|
||||
parser.add_argument(
|
||||
'--gf',
|
||||
type = str,
|
||||
required = True,
|
||||
help = 'Location of grammar file')
|
||||
parser.add_argument(
|
||||
'--out',
|
||||
type = str,
|
||||
required = True,
|
||||
help = 'Location of output file')
|
||||
parser.add_argument(
|
||||
'--start',
|
||||
type = str,
|
||||
required = True,
|
||||
help = 'Start token')
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.gf, args.out, args.start)
|
38
custom_mutators/gramatron/preprocess/prep_automaton.sh
Executable file
38
custom_mutators/gramatron/preprocess/prep_automaton.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script creates a FSA describing the input grammar *.g4
|
||||
|
||||
if [ ! "$#" -lt 4 ]; then
|
||||
echo "Usage: ./prep_pda.sh <grammar_file> <start> [stack_limit]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GRAMMAR_FILE=$1
|
||||
GRAMMAR_DIR="$(dirname $GRAMMAR_FILE)"
|
||||
START="$2"
|
||||
STACK_LIMIT="$3"
|
||||
|
||||
# Get filename
|
||||
FILE=$(basename -- "$GRAMMAR_FILE")
|
||||
echo "File:$FILE"
|
||||
FILENAME="${FILE%.*}"
|
||||
echo "Name:$FILENAME"
|
||||
|
||||
|
||||
# Create the GNF form of the grammar
|
||||
CMD="python gnf_converter.py --gf $GRAMMAR_FILE --out ${FILENAME}.json --start $START"
|
||||
$CMD
|
||||
|
||||
# Generate grammar automaton
|
||||
# Check if user provided a stack limit
|
||||
if [ -z "${STACK_LIMIT}" ]; then
|
||||
CMD="python3 construct_automata.py --gf ${FILENAME}.json"
|
||||
else
|
||||
CMD="python construct_automata.py --gf ${FILENAME}.json --limit ${STACK_LIMIT}"
|
||||
fi
|
||||
echo $CMD
|
||||
$CMD
|
||||
|
||||
# Move PDA to the source dir of the grammar
|
||||
echo "Copying ${FILENAME}_automata.json to $GRAMMAR_DIR"
|
||||
mv "${FILENAME}_automata.json" $GRAMMAR_DIR/
|
154
custom_mutators/gramatron/test.c
Normal file
154
custom_mutators/gramatron/test.c
Normal file
@ -0,0 +1,154 @@
|
||||
/* This is the testing module for Gramatron
|
||||
*/
|
||||
#include "afl-fuzz.h"
|
||||
#include "gramfuzz.h"
|
||||
|
||||
#define NUMINPUTS 50
|
||||
|
||||
state *create_pda(u8 *automaton_file) {
|
||||
|
||||
struct json_object *parsed_json;
|
||||
state * pda;
|
||||
json_object * source_obj, *attr;
|
||||
int arraylen, ii, ii2, trigger_len, error;
|
||||
|
||||
printf("\n[GF] Automaton file passed:%s", automaton_file);
|
||||
// parsed_json =
|
||||
// json_object_from_file("./gramfuzz/php_gnf_processed_full.json");
|
||||
parsed_json = json_object_from_file(automaton_file);
|
||||
|
||||
// Getting final state
|
||||
source_obj = json_object_object_get(parsed_json, "final_state");
|
||||
printf("\t\nFinal=%s\n", json_object_get_string(source_obj));
|
||||
final_state = atoi(json_object_get_string(source_obj));
|
||||
|
||||
// Getting initial state
|
||||
source_obj = json_object_object_get(parsed_json, "init_state");
|
||||
init_state = atoi(json_object_get_string(source_obj));
|
||||
printf("\tInit=%s\n", json_object_get_string(source_obj));
|
||||
|
||||
// Getting number of states
|
||||
source_obj = json_object_object_get(parsed_json, "numstates");
|
||||
numstates = atoi(json_object_get_string(source_obj)) + 1;
|
||||
printf("\tNumStates=%d\n", numstates);
|
||||
|
||||
// Allocate state space for each pda state
|
||||
pda = (state *)calloc(atoi(json_object_get_string(source_obj)) + 1,
|
||||
sizeof(state));
|
||||
|
||||
// Getting PDA representation
|
||||
source_obj = json_object_object_get(parsed_json, "pda");
|
||||
enum json_type type;
|
||||
json_object_object_foreach(source_obj, key, val) {
|
||||
|
||||
state * state_ptr;
|
||||
trigger *trigger_ptr;
|
||||
int offset;
|
||||
|
||||
// Get the correct offset into the pda to store state information
|
||||
state_ptr = pda;
|
||||
offset = atoi(key);
|
||||
state_ptr += offset;
|
||||
|
||||
// Store state string
|
||||
state_ptr->state_name = offset;
|
||||
|
||||
// Create trigger array of structs
|
||||
trigger_len = json_object_array_length(val);
|
||||
state_ptr->trigger_len = trigger_len;
|
||||
trigger_ptr = (trigger *)calloc(trigger_len, sizeof(trigger));
|
||||
state_ptr->ptr = trigger_ptr;
|
||||
printf("\nName:%d Trigger:%d", offset, trigger_len);
|
||||
|
||||
for (ii = 0; ii < trigger_len; ii++) {
|
||||
|
||||
json_object *obj = json_object_array_get_idx(val, ii);
|
||||
// Get all the trigger trigger attributes
|
||||
attr = json_object_array_get_idx(obj, 0);
|
||||
(trigger_ptr)->id = strdup(json_object_get_string(attr));
|
||||
|
||||
attr = json_object_array_get_idx(obj, 1);
|
||||
trigger_ptr->dest = atoi(json_object_get_string(attr));
|
||||
|
||||
attr = json_object_array_get_idx(obj, 2);
|
||||
if (!strcmp("\\n", json_object_get_string(attr))) {
|
||||
|
||||
trigger_ptr->term = strdup("\n");
|
||||
|
||||
} else {
|
||||
|
||||
trigger_ptr->term = strdup(json_object_get_string(attr));
|
||||
|
||||
}
|
||||
|
||||
trigger_ptr->term_len = strlen(trigger_ptr->term);
|
||||
trigger_ptr++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete the JSON object
|
||||
json_object_put(parsed_json);
|
||||
|
||||
return pda;
|
||||
|
||||
}
|
||||
|
||||
void SanityCheck(char *automaton_path) {
|
||||
|
||||
state * pda = create_pda(automaton_path);
|
||||
int count = 0, state;
|
||||
Get_Dupes_Ret *getdupesret;
|
||||
IdxMap_new * statemap;
|
||||
IdxMap_new * statemap_ptr;
|
||||
terminal * term_ptr;
|
||||
|
||||
while (count < NUMINPUTS) {
|
||||
|
||||
// Perform input generation
|
||||
Array *generated = gen_input(pda, NULL);
|
||||
print_repr(generated, "Gen");
|
||||
count += 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
char * mode;
|
||||
char * automaton_path;
|
||||
char * output_dir = NULL;
|
||||
struct timeval tv;
|
||||
struct timeval tz;
|
||||
// gettimeofday(&tv, &tz);
|
||||
srand(1337);
|
||||
if (argc == 3) {
|
||||
|
||||
mode = argv[1];
|
||||
automaton_path = strdup(argv[2]);
|
||||
printf("\nMode:%s Path:%s", mode, automaton_path);
|
||||
|
||||
} else {
|
||||
|
||||
printf("\nUsage: ./test <mode> <automaton_path>");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (!strcmp(mode, "SanityCheck")) {
|
||||
|
||||
SanityCheck(automaton_path);
|
||||
|
||||
} else {
|
||||
|
||||
printf("\nUnrecognized mode");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
57
custom_mutators/gramatron/test.h
Normal file
57
custom_mutators/gramatron/test.h
Normal file
@ -0,0 +1,57 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <json-c/json.h>
|
||||
#include <unistd.h>
|
||||
#include "hashmap.h"
|
||||
#include "uthash.h"
|
||||
#include "utarray.h"
|
||||
|
||||
#define INIT_SIZE 100 // Initial size of the dynamic array holding the input
|
||||
|
||||
typedef struct terminal {
|
||||
|
||||
int state;
|
||||
int trigger_idx;
|
||||
size_t symbol_len;
|
||||
char * symbol;
|
||||
|
||||
} terminal;
|
||||
|
||||
typedef struct trigger {
|
||||
|
||||
char * id;
|
||||
int dest;
|
||||
char * term;
|
||||
size_t term_len;
|
||||
|
||||
} trigger;
|
||||
|
||||
typedef struct state {
|
||||
|
||||
int state_name; // Integer State name
|
||||
int trigger_len; // Number of triggers associated with this state
|
||||
trigger *ptr; // Pointer to beginning of the list of triggers
|
||||
|
||||
} state;
|
||||
|
||||
typedef struct {
|
||||
|
||||
size_t used;
|
||||
size_t size;
|
||||
size_t inputlen;
|
||||
terminal *start;
|
||||
|
||||
} Array;
|
||||
|
||||
int init_state;
|
||||
int curr_state;
|
||||
int final_state;
|
||||
|
||||
state *create_pda(char *);
|
||||
Array *gen_input(state *, Array *);
|
||||
void print_repr(Array *, char *);
|
||||
void initArray(Array *, size_t);
|
||||
void insertArray(Array *, int, char *, size_t, int);
|
||||
|
392
custom_mutators/gramatron/utarray.h
Normal file
392
custom_mutators/gramatron/utarray.h
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* a dynamic array implementation using macros
|
||||
*/
|
||||
#ifndef UTARRAY_H
|
||||
#define UTARRAY_H
|
||||
|
||||
#define UTARRAY_VERSION 2.1.0
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <string.h> /* memset, etc */
|
||||
#include <stdlib.h> /* exit */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define UTARRAY_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define UTARRAY_UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef oom
|
||||
#error \
|
||||
"The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code."
|
||||
#define utarray_oom() oom()
|
||||
#endif
|
||||
|
||||
#ifndef utarray_oom
|
||||
#define utarray_oom() exit(-1)
|
||||
#endif
|
||||
|
||||
typedef void(ctor_f)(void *dst, const void *src);
|
||||
typedef void(dtor_f)(void *elt);
|
||||
typedef void(init_f)(void *elt);
|
||||
typedef struct {
|
||||
|
||||
size_t sz;
|
||||
init_f *init;
|
||||
ctor_f *copy;
|
||||
dtor_f *dtor;
|
||||
|
||||
} UT_icd;
|
||||
|
||||
typedef struct {
|
||||
|
||||
unsigned i, n; /* i: index of next available slot, n: num slots */
|
||||
UT_icd icd; /* initializer, copy and destructor functions */
|
||||
char * d; /* n slots of size icd->sz*/
|
||||
|
||||
} UT_array;
|
||||
|
||||
#define utarray_init(a, _icd) \
|
||||
do { \
|
||||
\
|
||||
memset(a, 0, sizeof(UT_array)); \
|
||||
(a)->icd = *(_icd); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_done(a) \
|
||||
do { \
|
||||
\
|
||||
if ((a)->n) { \
|
||||
\
|
||||
if ((a)->icd.dtor) { \
|
||||
\
|
||||
unsigned _ut_i; \
|
||||
for (_ut_i = 0; _ut_i < (a)->i; _ut_i++) { \
|
||||
\
|
||||
(a)->icd.dtor(utarray_eltptr(a, _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
free((a)->d); \
|
||||
\
|
||||
} \
|
||||
(a)->n = 0; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_new(a, _icd) \
|
||||
do { \
|
||||
\
|
||||
(a) = (UT_array *)malloc(sizeof(UT_array)); \
|
||||
if ((a) == NULL) { utarray_oom(); } \
|
||||
utarray_init(a, _icd); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_free(a) \
|
||||
do { \
|
||||
\
|
||||
utarray_done(a); \
|
||||
free(a); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_reserve(a, by) \
|
||||
do { \
|
||||
\
|
||||
if (((a)->i + (by)) > (a)->n) { \
|
||||
\
|
||||
char *utarray_tmp; \
|
||||
while (((a)->i + (by)) > (a)->n) { \
|
||||
\
|
||||
(a)->n = ((a)->n ? (2 * (a)->n) : 8); \
|
||||
\
|
||||
} \
|
||||
utarray_tmp = (char *)realloc((a)->d, (a)->n * (a)->icd.sz); \
|
||||
if (utarray_tmp == NULL) { utarray_oom(); } \
|
||||
(a)->d = utarray_tmp; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_push_back(a, p) \
|
||||
do { \
|
||||
\
|
||||
utarray_reserve(a, 1); \
|
||||
if ((a)->icd.copy) { \
|
||||
\
|
||||
(a)->icd.copy(_utarray_eltptr(a, (a)->i++), p); \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
memcpy(_utarray_eltptr(a, (a)->i++), p, (a)->icd.sz); \
|
||||
\
|
||||
}; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_pop_back(a) \
|
||||
do { \
|
||||
\
|
||||
if ((a)->icd.dtor) { \
|
||||
\
|
||||
(a)->icd.dtor(_utarray_eltptr(a, --((a)->i))); \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
(a)->i--; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_extend_back(a) \
|
||||
do { \
|
||||
\
|
||||
utarray_reserve(a, 1); \
|
||||
if ((a)->icd.init) { \
|
||||
\
|
||||
(a)->icd.init(_utarray_eltptr(a, (a)->i)); \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
memset(_utarray_eltptr(a, (a)->i), 0, (a)->icd.sz); \
|
||||
\
|
||||
} \
|
||||
(a)->i++; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_len(a) ((a)->i)
|
||||
|
||||
#define utarray_eltptr(a, j) (((j) < (a)->i) ? _utarray_eltptr(a, j) : NULL)
|
||||
#define _utarray_eltptr(a, j) ((a)->d + ((a)->icd.sz * (j)))
|
||||
|
||||
#define utarray_insert(a, p, j) \
|
||||
do { \
|
||||
\
|
||||
if ((j) > (a)->i) utarray_resize(a, j); \
|
||||
utarray_reserve(a, 1); \
|
||||
if ((j) < (a)->i) { \
|
||||
\
|
||||
memmove(_utarray_eltptr(a, (j) + 1), _utarray_eltptr(a, j), \
|
||||
((a)->i - (j)) * ((a)->icd.sz)); \
|
||||
\
|
||||
} \
|
||||
if ((a)->icd.copy) { \
|
||||
\
|
||||
(a)->icd.copy(_utarray_eltptr(a, j), p); \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
memcpy(_utarray_eltptr(a, j), p, (a)->icd.sz); \
|
||||
\
|
||||
}; \
|
||||
(a)->i++; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_inserta(a, w, j) \
|
||||
do { \
|
||||
\
|
||||
if (utarray_len(w) == 0) break; \
|
||||
if ((j) > (a)->i) utarray_resize(a, j); \
|
||||
utarray_reserve(a, utarray_len(w)); \
|
||||
if ((j) < (a)->i) { \
|
||||
\
|
||||
memmove(_utarray_eltptr(a, (j) + utarray_len(w)), _utarray_eltptr(a, j), \
|
||||
((a)->i - (j)) * ((a)->icd.sz)); \
|
||||
\
|
||||
} \
|
||||
if ((a)->icd.copy) { \
|
||||
\
|
||||
unsigned _ut_i; \
|
||||
for (_ut_i = 0; _ut_i < (w)->i; _ut_i++) { \
|
||||
\
|
||||
(a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), \
|
||||
_utarray_eltptr(w, _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
memcpy(_utarray_eltptr(a, j), _utarray_eltptr(w, 0), \
|
||||
utarray_len(w) * ((a)->icd.sz)); \
|
||||
\
|
||||
} \
|
||||
(a)->i += utarray_len(w); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_resize(dst, num) \
|
||||
do { \
|
||||
\
|
||||
unsigned _ut_i; \
|
||||
if ((dst)->i > (unsigned)(num)) { \
|
||||
\
|
||||
if ((dst)->icd.dtor) { \
|
||||
\
|
||||
for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \
|
||||
\
|
||||
(dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} else if ((dst)->i < (unsigned)(num)) { \
|
||||
\
|
||||
utarray_reserve(dst, (num) - (dst)->i); \
|
||||
if ((dst)->icd.init) { \
|
||||
\
|
||||
for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \
|
||||
\
|
||||
(dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} else { \
|
||||
\
|
||||
memset(_utarray_eltptr(dst, (dst)->i), 0, \
|
||||
(dst)->icd.sz *((num) - (dst)->i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
(dst)->i = (num); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_concat(dst, src) \
|
||||
do { \
|
||||
\
|
||||
utarray_inserta(dst, src, utarray_len(dst)); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_erase(a, pos, len) \
|
||||
do { \
|
||||
\
|
||||
if ((a)->icd.dtor) { \
|
||||
\
|
||||
unsigned _ut_i; \
|
||||
for (_ut_i = 0; _ut_i < (len); _ut_i++) { \
|
||||
\
|
||||
(a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
if ((a)->i > ((pos) + (len))) { \
|
||||
\
|
||||
memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \
|
||||
((a)->i - ((pos) + (len))) * (a)->icd.sz); \
|
||||
\
|
||||
} \
|
||||
(a)->i -= (len); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_renew(a, u) \
|
||||
do { \
|
||||
\
|
||||
if (a) \
|
||||
utarray_clear(a); \
|
||||
else \
|
||||
utarray_new(a, u); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_clear(a) \
|
||||
do { \
|
||||
\
|
||||
if ((a)->i > 0) { \
|
||||
\
|
||||
if ((a)->icd.dtor) { \
|
||||
\
|
||||
unsigned _ut_i; \
|
||||
for (_ut_i = 0; _ut_i < (a)->i; _ut_i++) { \
|
||||
\
|
||||
(a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
(a)->i = 0; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_sort(a, cmp) \
|
||||
do { \
|
||||
\
|
||||
qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define utarray_find(a, v, cmp) bsearch((v), (a)->d, (a)->i, (a)->icd.sz, cmp)
|
||||
|
||||
#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a, 0)) : NULL)
|
||||
#define utarray_next(a, e) \
|
||||
(((e) == NULL) ? utarray_front(a) \
|
||||
: (((a)->i != utarray_eltidx(a, e) + 1) \
|
||||
? _utarray_eltptr(a, utarray_eltidx(a, e) + 1) \
|
||||
: NULL))
|
||||
#define utarray_prev(a, e) \
|
||||
(((e) == NULL) ? utarray_back(a) \
|
||||
: ((utarray_eltidx(a, e) != 0) \
|
||||
? _utarray_eltptr(a, utarray_eltidx(a, e) - 1) \
|
||||
: NULL))
|
||||
#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a, (a)->i - 1)) : NULL)
|
||||
#define utarray_eltidx(a, e) (((char *)(e) - (a)->d) / (a)->icd.sz)
|
||||
|
||||
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||
static void utarray_str_cpy(void *dst, const void *src) {
|
||||
|
||||
char **_src = (char **)src, **_dst = (char **)dst;
|
||||
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
||||
|
||||
}
|
||||
|
||||
static void utarray_str_dtor(void *elt) {
|
||||
|
||||
char **eltc = (char **)elt;
|
||||
if (*eltc != NULL) free(*eltc);
|
||||
|
||||
}
|
||||
|
||||
static const UT_icd ut_str_icd UTARRAY_UNUSED = {
|
||||
|
||||
sizeof(char *), NULL, utarray_str_cpy, utarray_str_dtor};
|
||||
static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int), NULL, NULL, NULL};
|
||||
static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void *), NULL, NULL,
|
||||
NULL};
|
||||
|
||||
#endif /* UTARRAY_H */
|
||||
|
1611
custom_mutators/gramatron/uthash.h
Normal file
1611
custom_mutators/gramatron/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
1
custom_mutators/grammar_mutator/GRAMMAR_VERSION
Normal file
1
custom_mutators/grammar_mutator/GRAMMAR_VERSION
Normal file
@ -0,0 +1 @@
|
||||
ff4e5a2
|
6
custom_mutators/grammar_mutator/README.md
Normal file
6
custom_mutators/grammar_mutator/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Grammar-Mutator
|
||||
|
||||
This is just a stub directory that will clone the real grammar mutator
|
||||
directory.
|
||||
|
||||
Execute `./build_grammar_mutator.sh` to set everything up.
|
141
custom_mutators/grammar_mutator/build_grammar_mutator.sh
Executable file
141
custom_mutators/grammar_mutator/build_grammar_mutator.sh
Executable file
@ -0,0 +1,141 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# american fuzzy lop++ - unicorn mode build script
|
||||
# ------------------------------------------------
|
||||
#
|
||||
# Originally written by Nathan Voss <njvoss99@gmail.com>
|
||||
#
|
||||
# Adapted from code by Andrew Griffiths <agriffiths@google.com> and
|
||||
# Michal Zalewski
|
||||
#
|
||||
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
||||
#
|
||||
# CompareCoverage and NeverZero counters by Andrea Fioraldi
|
||||
# <andreafioraldi@gmail.com>
|
||||
#
|
||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# This script downloads, patches, and builds a version of Unicorn with
|
||||
# minor tweaks to allow Unicorn-emulated binaries to be run under
|
||||
# afl-fuzz.
|
||||
#
|
||||
# The modifications reside in patches/*. The standalone Unicorn library
|
||||
# will be written to /usr/lib/libunicornafl.so, and the Python bindings
|
||||
# will be installed system-wide.
|
||||
#
|
||||
# You must make sure that Unicorn Engine is not already installed before
|
||||
# running this script. If it is, please uninstall it first.
|
||||
|
||||
GRAMMAR_VERSION="$(cat ./GRAMMAR_VERSION)"
|
||||
GRAMMAR_REPO="https://github.com/AFLplusplus/grammar-mutator"
|
||||
|
||||
echo "================================================="
|
||||
echo "Grammar Mutator build script"
|
||||
echo "================================================="
|
||||
echo
|
||||
|
||||
echo "[*] Performing basic sanity checks..."
|
||||
|
||||
PLT=`uname -s`
|
||||
|
||||
if [ ! -f "../../config.h" ]; then
|
||||
|
||||
echo "[-] Error: key files not found - wrong working directory?"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
|
||||
PYTHONBIN=`command -v python3 || command -v python || command -v python2 || echo python3`
|
||||
MAKECMD=make
|
||||
TARCMD=tar
|
||||
|
||||
if [ "$PLT" = "Darwin" ]; then
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=tar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "FreeBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
PREREQ_NOTFOUND=
|
||||
for i in git $MAKECMD $TARCMD; do
|
||||
|
||||
T=`command -v "$i" 2>/dev/null`
|
||||
|
||||
if [ "$T" = "" ]; then
|
||||
|
||||
echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
|
||||
PREREQ_NOTFOUND=1
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if echo "$CC" | grep -qF /afl-; then
|
||||
|
||||
echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
|
||||
PREREQ_NOTFOUND=1
|
||||
|
||||
fi
|
||||
|
||||
if [ "$PREREQ_NOTFOUND" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[+] All checks passed!"
|
||||
|
||||
echo "[*] Making sure grammar mutator is checked out"
|
||||
|
||||
git status 1>/dev/null 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[*] initializing grammar mutator submodule"
|
||||
git submodule init || exit 1
|
||||
git submodule update ./grammar_mutator 2>/dev/null # ignore errors
|
||||
else
|
||||
echo "[*] cloning grammar mutator"
|
||||
test -d grammar_mutator/.git || {
|
||||
CNT=1
|
||||
while [ '!' -d grammar_mutator/.git -a "$CNT" -lt 4 ]; do
|
||||
echo "Trying to clone grammar_mutator (attempt $CNT/3)"
|
||||
git clone "$GRAMMAR_REPO"
|
||||
CNT=`expr "$CNT" + 1`
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
test -f grammar_mutator/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||
echo "[+] Got grammar mutator."
|
||||
|
||||
cd "grammar_mutator" || exit 1
|
||||
echo "[*] Checking out $GRAMMAR_VERSION"
|
||||
git pull >/dev/null 2>&1
|
||||
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
||||
git checkout "$GRAMMAR_VERSION" || exit 1
|
||||
echo "[*] Downloading antlr..."
|
||||
wget -c https://www.antlr.org/download/antlr-4.8-complete.jar
|
||||
cd ..
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "[+] All successfully prepared!"
|
||||
echo "[!] To build for your grammar just do:"
|
||||
echo " cd grammar_mutator"
|
||||
echo " make GRAMMAR_FILE=/path/to/your/grammar"
|
||||
echo "[+] You will find a JSON and RUBY grammar in grammar_mutator/grammars to play with."
|
||||
echo
|
1
custom_mutators/grammar_mutator/grammar_mutator
Submodule
1
custom_mutators/grammar_mutator/grammar_mutator
Submodule
Submodule custom_mutators/grammar_mutator/grammar_mutator added at ff4e5a265d
50
custom_mutators/grammar_mutator/update_grammar_ref.sh
Executable file
50
custom_mutators/grammar_mutator/update_grammar_ref.sh
Executable file
@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
##################################################
|
||||
# AFL++ tool to update a git ref.
|
||||
# Usage: ./<script>.sh <new commit hash>
|
||||
# If no commit hash was provided, it'll take HEAD.
|
||||
##################################################
|
||||
|
||||
TOOL="grammar mutator"
|
||||
VERSION_FILE='./GRAMMAR_VERSION'
|
||||
REPO_FOLDER='./grammar_mutator'
|
||||
THIS_SCRIPT=`basename $0`
|
||||
BRANCH="stable"
|
||||
|
||||
NEW_VERSION="$1"
|
||||
|
||||
if [ "$NEW_VERSION" = "-h" ]; then
|
||||
echo "Internal script to update bound $TOOL version."
|
||||
echo
|
||||
echo "Usage: $THIS_SCRIPT <new commit hash>"
|
||||
echo "If no commit hash is provided, will use HEAD."
|
||||
echo "-h to show this help screen."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git submodule init && git submodule update ./grammar_mutator || exit 1
|
||||
cd "$REPO_FOLDER" || exit 1
|
||||
git fetch origin $BRANCH 1>/dev/null || exit 1
|
||||
git stash 1>/dev/null 2>/dev/null
|
||||
git stash drop 1>/dev/null 2>/dev/null
|
||||
git checkout $BRANCH
|
||||
|
||||
if [ -z "$NEW_VERSION" ]; then
|
||||
# No version provided, take HEAD.
|
||||
NEW_VERSION=$(git rev-parse --short HEAD)
|
||||
fi
|
||||
|
||||
if [ -z "$NEW_VERSION" ]; then
|
||||
echo "Error getting version."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git checkout "$NEW_VERSION" || exit 1
|
||||
|
||||
cd ..
|
||||
|
||||
rm "$VERSION_FILE"
|
||||
echo "$NEW_VERSION" > "$VERSION_FILE"
|
||||
|
||||
echo "Done. New $TOOL version is $NEW_VERSION."
|
17
custom_mutators/honggfuzz/Makefile
Normal file
17
custom_mutators/honggfuzz/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
CFLAGS = -O3 -funroll-loops -fPIC -Wl,-Bsymbolic
|
||||
|
||||
all: honggfuzz-mutator.so
|
||||
|
||||
honggfuzz-mutator.so: honggfuzz.c input.h mangle.c ../../src/afl-performance.c
|
||||
$(CC) $(CFLAGS) -I../../include -I. -shared -o honggfuzz-mutator.so honggfuzz.c mangle.c ../../src/afl-performance.c
|
||||
|
||||
update:
|
||||
@# seriously? --unlink is a dud option? sigh ...
|
||||
rm -f mangle.c mangle.h honggfuzz.h
|
||||
wget --unlink https://github.com/google/honggfuzz/raw/master/mangle.c
|
||||
wget --unlink https://github.com/google/honggfuzz/raw/master/mangle.h
|
||||
wget --unlink https://github.com/google/honggfuzz/raw/master/honggfuzz.h
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ *.so core
|
12
custom_mutators/honggfuzz/README.md
Normal file
12
custom_mutators/honggfuzz/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# custum mutator: honggfuzz mangle
|
||||
|
||||
this is the honggfuzz mutator in mangle.c as a custom mutator
|
||||
module for AFL++. It is the original mangle.c, mangle.h and honggfuzz.h
|
||||
with a lot of mocking around it :-)
|
||||
|
||||
just type `make` to build
|
||||
|
||||
```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/honggfuzz/honggfuzz-mutator.so afl-fuzz ...```
|
||||
|
||||
> Original repository: https://github.com/google/honggfuzz
|
||||
> Source commit: d0fbcb0373c32436b8fb922e6937da93b17291f5
|
22
custom_mutators/honggfuzz/custom_mutator_helpers.h
Normal file
22
custom_mutators/honggfuzz/custom_mutator_helpers.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef CUSTOM_MUTATOR_HELPERS
|
||||
#define CUSTOM_MUTATOR_HELPERS
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "afl-fuzz.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define INITIAL_GROWTH_SIZE (64)
|
||||
|
||||
/* Use in a struct: creates a name_buf and a name_size variable. */
|
||||
#define BUF_VAR(type, name) \
|
||||
type * name##_buf; \
|
||||
size_t name##_size;
|
||||
/* this filles in `&structptr->something_buf, &structptr->something_size`. */
|
||||
#define BUF_PARAMS(struct, name) \
|
||||
(void **)&struct->name##_buf, &struct->name##_size
|
||||
|
||||
#undef INITIAL_GROWTH_SIZE
|
||||
|
||||
#endif
|
||||
|
146
custom_mutators/honggfuzz/honggfuzz.c
Normal file
146
custom_mutators/honggfuzz/honggfuzz.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "custom_mutator_helpers.h"
|
||||
#include "mangle.h"
|
||||
|
||||
#define NUMBER_OF_MUTATIONS 5
|
||||
|
||||
uint8_t * queue_input;
|
||||
size_t queue_input_size;
|
||||
afl_state_t * afl_struct;
|
||||
run_t run;
|
||||
honggfuzz_t global;
|
||||
struct _dynfile_t dynfile;
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
run_t * run;
|
||||
u8 * mutator_buf;
|
||||
unsigned int seed;
|
||||
unsigned int extras_cnt, a_extras_cnt;
|
||||
|
||||
} my_mutator_t;
|
||||
|
||||
my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
|
||||
if (!data) {
|
||||
|
||||
perror("afl_custom_init alloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
|
||||
|
||||
free(data);
|
||||
perror("mutator_buf alloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
run.dynfile = &dynfile;
|
||||
run.global = &global;
|
||||
data->afl = afl;
|
||||
data->seed = seed;
|
||||
data->run = &run;
|
||||
afl_struct = afl;
|
||||
|
||||
run.global->mutate.maxInputSz = MAX_FILE;
|
||||
run.global->mutate.mutationsPerRun = NUMBER_OF_MUTATIONS;
|
||||
run.mutationsPerRun = NUMBER_OF_MUTATIONS;
|
||||
run.global->timing.lastCovUpdate = 6;
|
||||
|
||||
// global->feedback.cmpFeedback
|
||||
// global->feedback.cmpFeedbackMap
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/* When a new queue entry is added we check if there are new dictionary
|
||||
entries to add to honggfuzz structure */
|
||||
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
if (run.global->mutate.dictionaryCnt >= 1024) return;
|
||||
|
||||
while (data->extras_cnt < data->afl->extras_cnt &&
|
||||
run.global->mutate.dictionaryCnt < 1024) {
|
||||
|
||||
memcpy(run.global->mutate.dictionary[run.global->mutate.dictionaryCnt].val,
|
||||
data->afl->extras[data->extras_cnt].data,
|
||||
data->afl->extras[data->extras_cnt].len);
|
||||
run.global->mutate.dictionary[run.global->mutate.dictionaryCnt].len =
|
||||
data->afl->extras[data->extras_cnt].len;
|
||||
run.global->mutate.dictionaryCnt++;
|
||||
data->extras_cnt++;
|
||||
|
||||
}
|
||||
|
||||
while (data->a_extras_cnt < data->afl->a_extras_cnt &&
|
||||
run.global->mutate.dictionaryCnt < 1024) {
|
||||
|
||||
memcpy(run.global->mutate.dictionary[run.global->mutate.dictionaryCnt].val,
|
||||
data->afl->a_extras[data->a_extras_cnt].data,
|
||||
data->afl->a_extras[data->a_extras_cnt].len);
|
||||
run.global->mutate.dictionary[run.global->mutate.dictionaryCnt].len =
|
||||
data->afl->a_extras[data->a_extras_cnt].len;
|
||||
run.global->mutate.dictionaryCnt++;
|
||||
data->a_extras_cnt++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* we could set only_printable if is_ascii is set ... let's see
|
||||
uint8_t afl_custom_queue_get(void *data, const uint8_t *filename) {
|
||||
|
||||
//run.global->cfg.only_printable = ...
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* here we run the honggfuzz mutator, which is really good */
|
||||
|
||||
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
|
||||
size_t max_size) {
|
||||
|
||||
/* set everything up, costly ... :( */
|
||||
memcpy(data->mutator_buf, buf, buf_size);
|
||||
queue_input = data->mutator_buf;
|
||||
run.dynfile->data = data->mutator_buf;
|
||||
queue_input_size = buf_size;
|
||||
run.dynfile->size = buf_size;
|
||||
*out_buf = data->mutator_buf;
|
||||
|
||||
/* the mutation */
|
||||
mangle_mangleContent(&run, NUMBER_OF_MUTATIONS);
|
||||
|
||||
/* return size of mutated data */
|
||||
return run.dynfile->size;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitialize everything
|
||||
*
|
||||
* @param data The data ptr from afl_custom_init
|
||||
*/
|
||||
void afl_custom_deinit(my_mutator_t *data) {
|
||||
|
||||
free(data->mutator_buf);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
387
custom_mutators/honggfuzz/honggfuzz.h
Normal file
387
custom_mutators/honggfuzz/honggfuzz.h
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
*
|
||||
* honggfuzz - core structures and macros
|
||||
* -----------------------------------------
|
||||
*
|
||||
* Author: Robert Swiecki <swiecki@google.com>
|
||||
*
|
||||
* Copyright 2010-2018 by Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HF_HONGGFUZZ_H_
|
||||
#define _HF_HONGGFUZZ_H_
|
||||
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "libhfcommon/util.h"
|
||||
|
||||
#define PROG_NAME "honggfuzz"
|
||||
#define PROG_VERSION "2.4"
|
||||
|
||||
/* Name of the template which will be replaced with the proper name of the file */
|
||||
#define _HF_FILE_PLACEHOLDER "___FILE___"
|
||||
|
||||
/* Default name of the report created with some architectures */
|
||||
#define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT"
|
||||
|
||||
/* Default stack-size of created threads. */
|
||||
#define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL) /* 2MB */
|
||||
|
||||
/* Name of envvar which indicates sequential number of fuzzer */
|
||||
#define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
|
||||
|
||||
/* Name of envvar which indicates that the netDriver should be used */
|
||||
#define _HF_THREAD_NETDRIVER_ENV "HFUZZ_USE_NETDRIVER"
|
||||
|
||||
/* Name of envvar which indicates honggfuzz's log level in use */
|
||||
#define _HF_LOG_LEVEL_ENV "HFUZZ_LOG_LEVEL"
|
||||
|
||||
/* Number of crash verifier iterations before tag crash as stable */
|
||||
#define _HF_VERIFIER_ITER 5
|
||||
|
||||
/* Size (in bytes) for report data to be stored in stack before written to file */
|
||||
#define _HF_REPORT_SIZE 32768
|
||||
|
||||
/* Perf bitmap size */
|
||||
#define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U)
|
||||
#define _HF_PERF_BITMAP_BITSZ_MASK 0x7FFFFFFULL
|
||||
/* Maximum number of PC guards (=trace-pc-guard) we support */
|
||||
#define _HF_PC_GUARD_MAX (1024ULL * 1024ULL * 64ULL)
|
||||
|
||||
/* Maximum size of the input file in bytes (1 MiB) */
|
||||
#define _HF_INPUT_MAX_SIZE (1024ULL * 1024ULL)
|
||||
|
||||
/* Default maximum size of produced inputs */
|
||||
#define _HF_INPUT_DEFAULT_SIZE (1024ULL * 8)
|
||||
|
||||
/* Per-thread bitmap */
|
||||
#define _HF_PERTHREAD_BITMAP_FD 1018
|
||||
/* FD used to report back used int/str constants from the fuzzed process */
|
||||
#define _HF_CMP_BITMAP_FD 1019
|
||||
/* FD used to log inside the child process */
|
||||
#define _HF_LOG_FD 1020
|
||||
/* FD used to represent the input file */
|
||||
#define _HF_INPUT_FD 1021
|
||||
/* FD used to pass coverage feedback from the fuzzed process */
|
||||
#define _HF_COV_BITMAP_FD 1022
|
||||
#define _HF_BITMAP_FD _HF_COV_BITMAP_FD /* Old name for _HF_COV_BITMAP_FD */
|
||||
/* FD used to pass data to a persistent process */
|
||||
#define _HF_PERSISTENT_FD 1023
|
||||
|
||||
/* Input file as a string */
|
||||
#define _HF_INPUT_FILE_PATH "/dev/fd/" HF_XSTR(_HF_INPUT_FD)
|
||||
|
||||
/* Maximum number of supported execve() args */
|
||||
#define _HF_ARGS_MAX 2048
|
||||
|
||||
/* Message indicating that the fuzzed process is ready for new data */
|
||||
static const uint8_t HFReadyTag = 'R';
|
||||
|
||||
/* Maximum number of active fuzzing threads */
|
||||
#define _HF_THREAD_MAX 1024U
|
||||
|
||||
/* Persistent-binary signature - if found within file, it means it's a persistent mode binary */
|
||||
#define _HF_PERSISTENT_SIG "\x01_LIBHFUZZ_PERSISTENT_BINARY_SIGNATURE_\x02\xFF"
|
||||
/* HF NetDriver signature - if found within file, it means it's a NetDriver-based binary */
|
||||
#define _HF_NETDRIVER_SIG "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF"
|
||||
|
||||
/* printf() nonmonetary separator. According to MacOSX's man it's supported there as well */
|
||||
#define _HF_NONMON_SEP "'"
|
||||
|
||||
typedef enum {
|
||||
_HF_DYNFILE_NONE = 0x0,
|
||||
_HF_DYNFILE_INSTR_COUNT = 0x1,
|
||||
_HF_DYNFILE_BRANCH_COUNT = 0x2,
|
||||
_HF_DYNFILE_BTS_EDGE = 0x10,
|
||||
_HF_DYNFILE_IPT_BLOCK = 0x20,
|
||||
_HF_DYNFILE_SOFT = 0x40,
|
||||
} dynFileMethod_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t cpuInstrCnt;
|
||||
uint64_t cpuBranchCnt;
|
||||
uint64_t bbCnt;
|
||||
uint64_t newBBCnt;
|
||||
uint64_t softCntPc;
|
||||
uint64_t softCntEdge;
|
||||
uint64_t softCntCmp;
|
||||
} hwcnt_t;
|
||||
|
||||
typedef enum {
|
||||
_HF_STATE_UNSET = 0,
|
||||
_HF_STATE_STATIC,
|
||||
_HF_STATE_DYNAMIC_DRY_RUN,
|
||||
_HF_STATE_DYNAMIC_MAIN,
|
||||
_HF_STATE_DYNAMIC_MINIMIZE,
|
||||
} fuzzState_t;
|
||||
|
||||
typedef enum {
|
||||
HF_MAYBE = -1,
|
||||
HF_NO = 0,
|
||||
HF_YES = 1,
|
||||
} tristate_t;
|
||||
|
||||
struct _dynfile_t {
|
||||
size_t size;
|
||||
uint64_t cov[4];
|
||||
size_t idx;
|
||||
int fd;
|
||||
uint64_t timeExecUSecs;
|
||||
char path[PATH_MAX];
|
||||
struct _dynfile_t* src;
|
||||
uint32_t refs;
|
||||
uint8_t* data;
|
||||
TAILQ_ENTRY(_dynfile_t) pointers;
|
||||
};
|
||||
|
||||
typedef struct _dynfile_t dynfile_t;
|
||||
|
||||
struct strings_t {
|
||||
size_t len;
|
||||
TAILQ_ENTRY(strings_t) pointers;
|
||||
char s[];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t pcGuardMap[_HF_PC_GUARD_MAX];
|
||||
uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
|
||||
uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
|
||||
uint64_t pidNewPC[_HF_THREAD_MAX];
|
||||
uint64_t pidNewEdge[_HF_THREAD_MAX];
|
||||
uint64_t pidNewCmp[_HF_THREAD_MAX];
|
||||
uint64_t guardNb;
|
||||
uint64_t pidTotalPC[_HF_THREAD_MAX];
|
||||
uint64_t pidTotalEdge[_HF_THREAD_MAX];
|
||||
uint64_t pidTotalCmp[_HF_THREAD_MAX];
|
||||
} feedback_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t cnt;
|
||||
struct {
|
||||
uint8_t val[32];
|
||||
uint32_t len;
|
||||
} valArr[1024 * 16];
|
||||
} cmpfeedback_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
size_t threadsMax;
|
||||
size_t threadsFinished;
|
||||
uint32_t threadsActiveCnt;
|
||||
pthread_t mainThread;
|
||||
pid_t mainPid;
|
||||
pthread_t threads[_HF_THREAD_MAX];
|
||||
} threads;
|
||||
struct {
|
||||
const char* inputDir;
|
||||
const char* outputDir;
|
||||
DIR* inputDirPtr;
|
||||
size_t fileCnt;
|
||||
size_t testedFileCnt;
|
||||
const char* fileExtn;
|
||||
size_t maxFileSz;
|
||||
size_t newUnitsAdded;
|
||||
char workDir[PATH_MAX];
|
||||
const char* crashDir;
|
||||
const char* covDirNew;
|
||||
bool saveUnique;
|
||||
bool saveSmaller;
|
||||
size_t dynfileqMaxSz;
|
||||
size_t dynfileqCnt;
|
||||
dynfile_t* dynfileqCurrent;
|
||||
dynfile_t* dynfileq2Current;
|
||||
TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq;
|
||||
bool exportFeedback;
|
||||
} io;
|
||||
struct {
|
||||
int argc;
|
||||
const char* const* cmdline;
|
||||
bool nullifyStdio;
|
||||
bool fuzzStdin;
|
||||
const char* externalCommand;
|
||||
const char* postExternalCommand;
|
||||
const char* feedbackMutateCommand;
|
||||
bool netDriver;
|
||||
bool persistent;
|
||||
uint64_t asLimit;
|
||||
uint64_t rssLimit;
|
||||
uint64_t dataLimit;
|
||||
uint64_t coreLimit;
|
||||
uint64_t stackLimit;
|
||||
bool clearEnv;
|
||||
char* env_ptrs[128];
|
||||
char env_vals[128][4096];
|
||||
sigset_t waitSigSet;
|
||||
} exe;
|
||||
struct {
|
||||
time_t timeStart;
|
||||
time_t runEndTime;
|
||||
time_t tmOut;
|
||||
time_t lastCovUpdate;
|
||||
int64_t timeOfLongestUnitUSecs;
|
||||
bool tmoutVTALRM;
|
||||
} timing;
|
||||
struct {
|
||||
struct {
|
||||
uint8_t val[512];
|
||||
size_t len;
|
||||
} dictionary[8192];
|
||||
size_t dictionaryCnt;
|
||||
const char* dictionaryFile;
|
||||
size_t mutationsMax;
|
||||
unsigned mutationsPerRun;
|
||||
size_t maxInputSz;
|
||||
} mutate;
|
||||
struct {
|
||||
bool useScreen;
|
||||
char cmdline_txt[65];
|
||||
int64_t lastDisplayUSecs;
|
||||
} display;
|
||||
struct {
|
||||
bool useVerifier;
|
||||
bool exitUponCrash;
|
||||
uint8_t exitCodeUponCrash;
|
||||
const char* reportFile;
|
||||
size_t dynFileIterExpire;
|
||||
bool only_printable;
|
||||
bool minimize;
|
||||
bool switchingToFDM;
|
||||
} cfg;
|
||||
struct {
|
||||
bool enable;
|
||||
bool del_report;
|
||||
} sanitizer;
|
||||
struct {
|
||||
fuzzState_t state;
|
||||
feedback_t* covFeedbackMap;
|
||||
int covFeedbackFd;
|
||||
cmpfeedback_t* cmpFeedbackMap;
|
||||
int cmpFeedbackFd;
|
||||
bool cmpFeedback;
|
||||
const char* blocklistFile;
|
||||
uint64_t* blocklist;
|
||||
size_t blocklistCnt;
|
||||
bool skipFeedbackOnTimeout;
|
||||
uint64_t maxCov[4];
|
||||
dynFileMethod_t dynFileMethod;
|
||||
hwcnt_t hwCnts;
|
||||
} feedback;
|
||||
struct {
|
||||
size_t mutationsCnt;
|
||||
size_t crashesCnt;
|
||||
size_t uniqueCrashesCnt;
|
||||
size_t verifiedCrashesCnt;
|
||||
size_t blCrashesCnt;
|
||||
size_t timeoutedCnt;
|
||||
} cnts;
|
||||
struct {
|
||||
bool enabled;
|
||||
int serverSocket;
|
||||
int clientSocket;
|
||||
} socketFuzzer;
|
||||
struct {
|
||||
pthread_rwlock_t dynfileq;
|
||||
pthread_mutex_t feedback;
|
||||
pthread_mutex_t report;
|
||||
pthread_mutex_t state;
|
||||
pthread_mutex_t input;
|
||||
pthread_mutex_t timing;
|
||||
} mutex;
|
||||
|
||||
/* For the Linux code */
|
||||
struct {
|
||||
int exeFd;
|
||||
uint64_t dynamicCutOffAddr;
|
||||
bool disableRandomization;
|
||||
void* ignoreAddr;
|
||||
const char* symsBlFile;
|
||||
char** symsBl;
|
||||
size_t symsBlCnt;
|
||||
const char* symsWlFile;
|
||||
char** symsWl;
|
||||
size_t symsWlCnt;
|
||||
uintptr_t cloneFlags;
|
||||
tristate_t useNetNs;
|
||||
bool kernelOnly;
|
||||
bool useClone;
|
||||
} arch_linux;
|
||||
/* For the NetBSD code */
|
||||
struct {
|
||||
void* ignoreAddr;
|
||||
const char* symsBlFile;
|
||||
char** symsBl;
|
||||
size_t symsBlCnt;
|
||||
const char* symsWlFile;
|
||||
char** symsWl;
|
||||
size_t symsWlCnt;
|
||||
} arch_netbsd;
|
||||
} honggfuzz_t;
|
||||
|
||||
typedef enum {
|
||||
_HF_RS_UNKNOWN = 0,
|
||||
_HF_RS_WAITING_FOR_INITIAL_READY = 1,
|
||||
_HF_RS_WAITING_FOR_READY = 2,
|
||||
_HF_RS_SEND_DATA = 3,
|
||||
} runState_t;
|
||||
|
||||
typedef struct {
|
||||
honggfuzz_t* global;
|
||||
pid_t pid;
|
||||
int64_t timeStartedUSecs;
|
||||
char crashFileName[PATH_MAX];
|
||||
uint64_t pc;
|
||||
uint64_t backtrace;
|
||||
uint64_t access;
|
||||
int exception;
|
||||
char report[_HF_REPORT_SIZE];
|
||||
bool mainWorker;
|
||||
unsigned mutationsPerRun;
|
||||
dynfile_t* dynfile;
|
||||
bool staticFileTryMore;
|
||||
uint32_t fuzzNo;
|
||||
int persistentSock;
|
||||
runState_t runState;
|
||||
bool tmOutSignaled;
|
||||
char* args[_HF_ARGS_MAX + 1];
|
||||
int perThreadCovFeedbackFd;
|
||||
unsigned triesLeft;
|
||||
dynfile_t* current;
|
||||
#if !defined(_HF_ARCH_DARWIN)
|
||||
timer_t timerId;
|
||||
#endif // !defined(_HF_ARCH_DARWIN)
|
||||
hwcnt_t hwCnts;
|
||||
|
||||
struct {
|
||||
/* For Linux code */
|
||||
uint8_t* perfMmapBuf;
|
||||
uint8_t* perfMmapAux;
|
||||
int cpuInstrFd;
|
||||
int cpuBranchFd;
|
||||
int cpuIptBtsFd;
|
||||
} arch_linux;
|
||||
} run_t;
|
||||
|
||||
#endif
|
106
custom_mutators/honggfuzz/input.h
Normal file
106
custom_mutators/honggfuzz/input.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef _HG_INPUT_
|
||||
#define _HG_INPUT_
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef __clang__
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "honggfuzz.h"
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
/*
|
||||
* Go-style defer scoped implementation
|
||||
*
|
||||
* If compiled with clang, use: -fblocks -lBlocksRuntime
|
||||
*
|
||||
* Example of use:
|
||||
*
|
||||
* {
|
||||
* int fd = open(fname, O_RDONLY);
|
||||
* if (fd == -1) {
|
||||
* error(....);
|
||||
* return;
|
||||
* }
|
||||
* defer { close(fd); };
|
||||
* ssize_t sz = read(fd, buf, sizeof(buf));
|
||||
* ...
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
#define __STRMERGE(a, b) a##b
|
||||
#define _STRMERGE(a, b) __STRMERGE(a, b)
|
||||
#ifdef __clang__
|
||||
#if __has_extension(blocks)
|
||||
static void __attribute__((unused)) __clang_cleanup_func(void (^*dfunc)(void)) {
|
||||
(*dfunc)();
|
||||
}
|
||||
|
||||
#define defer \
|
||||
void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \
|
||||
__attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^
|
||||
|
||||
#else /* __has_extension(blocks) */
|
||||
#define defer UNIMPLEMENTED - NO - SUPPORT - FOR - BLOCKS - IN - YOUR - CLANG - ENABLED
|
||||
#endif /* __has_extension(blocks) */
|
||||
#else /* !__clang__, e.g.: gcc */
|
||||
|
||||
#define __block
|
||||
#define _DEFER(a, count) \
|
||||
auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused))); \
|
||||
int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) \
|
||||
__attribute__((unused)); \
|
||||
void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
|
||||
#define defer _DEFER(a, __COUNTER__)
|
||||
#endif /* ifdef __clang__ */
|
||||
|
||||
#define HF_MIN(x, y) (x <= y ? x : y)
|
||||
#define HF_MAX(x, y) (x >= y ? x : y)
|
||||
#define ATOMIC_GET
|
||||
#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
|
||||
#define HF_ATTR_UNUSED __attribute__((unused))
|
||||
#define util_Malloc(x) malloc(x)
|
||||
|
||||
extern uint8_t * queue_input;
|
||||
extern size_t queue_input_size;
|
||||
extern afl_state_t * afl_struct;
|
||||
|
||||
inline void wmb() { }
|
||||
inline void LOG_F(const char *format, ...) { }
|
||||
static inline uint64_t util_rndGet(uint64_t min, uint64_t max) {
|
||||
return min + rand_below(afl_struct, max - min + 1);
|
||||
}
|
||||
static inline uint64_t util_rnd64() { return rand_below(afl_struct, 1 << 30); }
|
||||
|
||||
static inline const uint8_t* input_getRandomInputAsBuf(run_t* run, size_t* len) {
|
||||
*len = queue_input_size;
|
||||
run->dynfile->data = queue_input;
|
||||
run->dynfile->size = queue_input_size;
|
||||
return queue_input;
|
||||
}
|
||||
static inline void input_setSize(run_t* run, size_t sz) {
|
||||
run->dynfile->size = sz;
|
||||
}
|
||||
static inline void util_turnToPrintable(uint8_t* buf, size_t sz) {
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
buf[i] = buf[i] % 95 + 32;
|
||||
}
|
||||
static inline void util_rndBuf(uint8_t* buf, size_t sz) {
|
||||
if (sz == 0) return;
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
buf[i] = (uint8_t)rand_below(afl_struct, 256);
|
||||
}
|
||||
static inline uint8_t util_rndPrintable() {
|
||||
return 32 + rand_below(afl_struct, 127 - 32);
|
||||
}
|
||||
static inline void util_rndBufPrintable(uint8_t* buf, size_t sz) {
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
buf[i] = util_rndPrintable();
|
||||
}
|
||||
|
||||
#endif
|
3
custom_mutators/honggfuzz/libhfcommon/common.h
Normal file
3
custom_mutators/honggfuzz/libhfcommon/common.h
Normal file
@ -0,0 +1,3 @@
|
||||
#ifndef LOG_E
|
||||
#define LOG_E LOG_F
|
||||
#endif
|
1
custom_mutators/honggfuzz/libhfcommon/log.h
Symbolic link
1
custom_mutators/honggfuzz/libhfcommon/log.h
Symbolic link
@ -0,0 +1 @@
|
||||
common.h
|
1
custom_mutators/honggfuzz/libhfcommon/util.h
Symbolic link
1
custom_mutators/honggfuzz/libhfcommon/util.h
Symbolic link
@ -0,0 +1 @@
|
||||
common.h
|
907
custom_mutators/honggfuzz/mangle.c
Normal file
907
custom_mutators/honggfuzz/mangle.c
Normal file
@ -0,0 +1,907 @@
|
||||
/*
|
||||
*
|
||||
* honggfuzz - run->dynfile->datafer mangling routines
|
||||
* -----------------------------------------
|
||||
*
|
||||
* Author:
|
||||
* Robert Swiecki <swiecki@google.com>
|
||||
*
|
||||
* Copyright 2010-2018 by Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mangle.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "libhfcommon/common.h"
|
||||
#include "libhfcommon/log.h"
|
||||
#include "libhfcommon/util.h"
|
||||
|
||||
static inline size_t mangle_LenLeft(run_t* run, size_t off) {
|
||||
if (off >= run->dynfile->size) {
|
||||
LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
|
||||
}
|
||||
return (run->dynfile->size - off - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a random value <1:max>, but prefer smaller ones
|
||||
* Based on an idea by https://twitter.com/gamozolabs
|
||||
*/
|
||||
static inline size_t mangle_getLen(size_t max) {
|
||||
if (max > _HF_INPUT_MAX_SIZE) {
|
||||
LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE);
|
||||
}
|
||||
if (max == 0) {
|
||||
LOG_F("max == 0");
|
||||
}
|
||||
if (max == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Give 50% chance the the uniform distribution */
|
||||
if (util_rnd64() & 1) {
|
||||
return (size_t)util_rndGet(1, max);
|
||||
}
|
||||
|
||||
/* effectively exprand() */
|
||||
return (size_t)util_rndGet(1, util_rndGet(1, max));
|
||||
}
|
||||
|
||||
/* Prefer smaller values here, so use mangle_getLen() */
|
||||
static inline size_t mangle_getOffSet(run_t* run) {
|
||||
return mangle_getLen(run->dynfile->size) - 1;
|
||||
}
|
||||
|
||||
/* Offset which can be equal to the file size */
|
||||
static inline size_t mangle_getOffSetPlus1(run_t* run) {
|
||||
size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
|
||||
return mangle_getLen(reqlen) - 1;
|
||||
}
|
||||
|
||||
static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) {
|
||||
if (off_from >= run->dynfile->size) {
|
||||
return;
|
||||
}
|
||||
if (off_to >= run->dynfile->size) {
|
||||
return;
|
||||
}
|
||||
if (off_from == off_to) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len_from = run->dynfile->size - off_from;
|
||||
len = HF_MIN(len, len_from);
|
||||
|
||||
size_t len_to = run->dynfile->size - off_to;
|
||||
len = HF_MIN(len, len_to);
|
||||
|
||||
memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
|
||||
}
|
||||
|
||||
static inline void mangle_Overwrite(
|
||||
run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
size_t maxToCopy = run->dynfile->size - off;
|
||||
if (len > maxToCopy) {
|
||||
len = maxToCopy;
|
||||
}
|
||||
|
||||
memmove(&run->dynfile->data[off], src, len);
|
||||
if (printable) {
|
||||
util_turnToPrintable(&run->dynfile->data[off], len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) {
|
||||
if (run->dynfile->size >= run->global->mutate.maxInputSz) {
|
||||
return 0;
|
||||
}
|
||||
if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
|
||||
len = run->global->mutate.maxInputSz - run->dynfile->size;
|
||||
}
|
||||
|
||||
input_setSize(run, run->dynfile->size + len);
|
||||
mangle_Move(run, off, off + len, run->dynfile->size);
|
||||
if (printable) {
|
||||
memset(&run->dynfile->data[off], ' ', len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void mangle_Insert(
|
||||
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
|
||||
len = mangle_Inflate(run, off, len, printable);
|
||||
mangle_Overwrite(run, off, val, len, printable);
|
||||
}
|
||||
|
||||
static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) {
|
||||
if (util_rnd64() & 1) {
|
||||
mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
|
||||
} else {
|
||||
mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mangle_UseValueAt(
|
||||
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
|
||||
if (util_rnd64() & 1) {
|
||||
mangle_Overwrite(run, off, val, len, printable);
|
||||
} else {
|
||||
mangle_Insert(run, off, val, len, printable);
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) {
|
||||
/* No big deal if those two are overlapping */
|
||||
size_t off1 = mangle_getOffSet(run);
|
||||
size_t maxlen1 = run->dynfile->size - off1;
|
||||
size_t off2 = mangle_getOffSet(run);
|
||||
size_t maxlen2 = run->dynfile->size - off2;
|
||||
size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
|
||||
|
||||
if (off1 == off2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (len / 2); i++) {
|
||||
/*
|
||||
* First - from the head, next from the tail. Don't worry about layout of the overlapping
|
||||
* part - there's no good solution to that, and it can be left somewhat scrambled,
|
||||
* while still preserving the entropy
|
||||
*/
|
||||
const uint8_t tmp1 = run->dynfile->data[off2 + i];
|
||||
run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
|
||||
run->dynfile->data[off1 + i] = tmp1;
|
||||
const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
|
||||
run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i];
|
||||
run->dynfile->data[off1 + (len - 1) - i] = tmp2;
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||
|
||||
/* Use a temp buf, as Insert/Inflate can change source bytes */
|
||||
uint8_t* tmpbuf = (uint8_t*)util_Malloc(len);
|
||||
defer {
|
||||
free(tmpbuf);
|
||||
};
|
||||
memmove(tmpbuf, &run->dynfile->data[off], len);
|
||||
|
||||
mangle_UseValue(run, tmpbuf, len, printable);
|
||||
}
|
||||
|
||||
static void mangle_Bytes(run_t* run, bool printable) {
|
||||
uint16_t buf;
|
||||
if (printable) {
|
||||
util_rndBufPrintable((uint8_t*)&buf, sizeof(buf));
|
||||
} else {
|
||||
buf = util_rnd64();
|
||||
}
|
||||
|
||||
/* Overwrite with random 1-2-byte values */
|
||||
size_t toCopy = util_rndGet(1, 2);
|
||||
mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable);
|
||||
}
|
||||
|
||||
static void mangle_ByteRepeat(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t destOff = off + 1;
|
||||
size_t maxSz = run->dynfile->size - destOff;
|
||||
|
||||
/* No space to repeat */
|
||||
if (!maxSz) {
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = mangle_getLen(maxSz);
|
||||
if (util_rnd64() & 0x1) {
|
||||
len = mangle_Inflate(run, destOff, len, printable);
|
||||
}
|
||||
memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
|
||||
}
|
||||
|
||||
static void mangle_Bit(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
|
||||
if (printable) {
|
||||
util_turnToPrintable(&(run->dynfile->data[off]), 1);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const uint8_t val[8];
|
||||
const size_t size;
|
||||
} mangleMagicVals[] = {
|
||||
/* 1B - No endianness */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x02\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x03\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x04\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x05\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x06\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x07\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x08\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x09\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0A\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0B\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0C\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0D\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0E\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x0F\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x10\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x20\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x40\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x7E\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x7F\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\x81\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\xC0\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\xFE\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
{"\xFF\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||
/* 2B - NE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x01\x01\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x80\x80\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFF\xFF\x00\x00\x00\x00\x00\x00", 2},
|
||||
/* 2B - BE */
|
||||
{"\x00\x01\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x02\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x03\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x04\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x05\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x06\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x07\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x08\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x09\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0A\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0B\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0C\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0D\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0E\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x0F\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x10\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x20\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x40\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x7E\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x7F\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x80\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x81\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\xC0\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\xFE\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\xFF\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x7E\xFF\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x7F\xFF\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x80\x01\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFF\xFE\x00\x00\x00\x00\x00\x00", 2},
|
||||
/* 2B - LE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x01\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x02\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x03\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x04\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x05\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x06\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x07\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x08\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x09\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0A\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0B\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0C\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0D\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0E\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x0F\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x10\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x20\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x40\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x7E\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x7F\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x81\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xC0\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFE\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFF\x00\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFF\x7E\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFF\x7F\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x00\x80\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\x01\x80\x00\x00\x00\x00\x00\x00", 2},
|
||||
{"\xFE\xFF\x00\x00\x00\x00\x00\x00", 2},
|
||||
/* 4B - NE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x01\x01\x01\x01\x00\x00\x00\x00", 4},
|
||||
{"\x80\x80\x80\x80\x00\x00\x00\x00", 4},
|
||||
{"\xFF\xFF\xFF\xFF\x00\x00\x00\x00", 4},
|
||||
/* 4B - BE */
|
||||
{"\x00\x00\x00\x01\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x02\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x03\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x04\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x05\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x06\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x07\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x08\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x09\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0A\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0B\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0C\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0D\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0E\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x0F\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x10\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x20\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x40\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x7E\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x7F\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x80\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x81\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\xC0\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\xFE\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\xFF\x00\x00\x00\x00", 4},
|
||||
{"\x7E\xFF\xFF\xFF\x00\x00\x00\x00", 4},
|
||||
{"\x7F\xFF\xFF\xFF\x00\x00\x00\x00", 4},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x80\x00\x00\x01\x00\x00\x00\x00", 4},
|
||||
{"\xFF\xFF\xFF\xFE\x00\x00\x00\x00", 4},
|
||||
/* 4B - LE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x01\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x02\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x03\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x04\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x05\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x06\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x07\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x08\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x09\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0A\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0B\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0C\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0D\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0E\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x0F\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x10\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x20\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x40\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x7E\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x7F\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\x81\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\xC0\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\xFE\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\xFF\x00\x00\x00\x00\x00\x00\x00", 4},
|
||||
{"\xFF\xFF\xFF\x7E\x00\x00\x00\x00", 4},
|
||||
{"\xFF\xFF\xFF\x7F\x00\x00\x00\x00", 4},
|
||||
{"\x00\x00\x00\x80\x00\x00\x00\x00", 4},
|
||||
{"\x01\x00\x00\x80\x00\x00\x00\x00", 4},
|
||||
{"\xFE\xFF\xFF\xFF\x00\x00\x00\x00", 4},
|
||||
/* 8B - NE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x01\x01\x01\x01\x01\x01\x01\x01", 8},
|
||||
{"\x80\x80\x80\x80\x80\x80\x80\x80", 8},
|
||||
{"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
||||
/* 8B - BE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x01", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x02", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x03", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x04", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x05", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x06", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x07", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x08", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x09", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0A", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0B", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0C", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0D", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0E", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x0F", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x10", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x20", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x40", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x7E", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x7F", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x81", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\xC0", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\xFE", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\xFF", 8},
|
||||
{"\x7E\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
||||
{"\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x01", 8},
|
||||
{"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", 8},
|
||||
/* 8B - LE */
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x01\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x02\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x03\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x04\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x05\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x06\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x07\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x08\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x09\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0A\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0B\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0C\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0D\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0E\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x0F\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x10\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x20\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x40\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x7E\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x7F\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x80\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\x81\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\xC0\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\xFE\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\xFF\x00\x00\x00\x00\x00\x00\x00", 8},
|
||||
{"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7E", 8},
|
||||
{"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 8},
|
||||
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
|
||||
{"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
|
||||
{"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
||||
};
|
||||
|
||||
static void mangle_Magic(run_t* run, bool printable) {
|
||||
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
|
||||
mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable);
|
||||
}
|
||||
|
||||
static void mangle_StaticDict(run_t* run, bool printable) {
|
||||
if (run->global->mutate.dictionaryCnt == 0) {
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
|
||||
mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
|
||||
run->global->mutate.dictionary[choice].len, printable);
|
||||
}
|
||||
|
||||
static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) {
|
||||
if (!run->global->feedback.cmpFeedback) {
|
||||
return NULL;
|
||||
}
|
||||
cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap;
|
||||
uint32_t cnt = ATOMIC_GET(cmpf->cnt);
|
||||
if (cnt == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (cnt > ARRAYSIZE(cmpf->valArr)) {
|
||||
cnt = ARRAYSIZE(cmpf->valArr);
|
||||
}
|
||||
uint32_t choice = util_rndGet(0, cnt - 1);
|
||||
*len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
|
||||
if (*len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return cmpf->valArr[choice].val;
|
||||
}
|
||||
|
||||
static void mangle_ConstFeedbackDict(run_t* run, bool printable) {
|
||||
size_t len;
|
||||
const uint8_t* val = mangle_FeedbackDict(run, &len);
|
||||
if (val == NULL) {
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
mangle_UseValue(run, val, len, printable);
|
||||
}
|
||||
|
||||
static void mangle_MemSet(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||
int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
|
||||
|
||||
if (util_rnd64() & 1) {
|
||||
len = mangle_Inflate(run, off, len, printable);
|
||||
}
|
||||
|
||||
memset(&run->dynfile->data[off], val, len);
|
||||
}
|
||||
|
||||
static void mangle_MemClr(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||
int val = printable ? ' ' : 0;
|
||||
|
||||
if (util_rnd64() & 1) {
|
||||
len = mangle_Inflate(run, off, len, printable);
|
||||
}
|
||||
|
||||
memset(&run->dynfile->data[off], val, len);
|
||||
}
|
||||
|
||||
static void mangle_RandomBuf(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||
|
||||
if (util_rnd64() & 1) {
|
||||
len = mangle_Inflate(run, off, len, printable);
|
||||
}
|
||||
|
||||
if (printable) {
|
||||
util_rndBufPrintable(&run->dynfile->data[off], len);
|
||||
} else {
|
||||
util_rndBuf(&run->dynfile->data[off], len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mangle_AddSubWithRange(
|
||||
run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) {
|
||||
int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
|
||||
|
||||
switch (varLen) {
|
||||
case 1: {
|
||||
run->dynfile->data[off] += delta;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
int16_t val;
|
||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||
if (util_rnd64() & 0x1) {
|
||||
val += delta;
|
||||
} else {
|
||||
/* Foreign endianess */
|
||||
val = __builtin_bswap16(val);
|
||||
val += delta;
|
||||
val = __builtin_bswap16(val);
|
||||
}
|
||||
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int32_t val;
|
||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||
if (util_rnd64() & 0x1) {
|
||||
val += delta;
|
||||
} else {
|
||||
/* Foreign endianess */
|
||||
val = __builtin_bswap32(val);
|
||||
val += delta;
|
||||
val = __builtin_bswap32(val);
|
||||
}
|
||||
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
int64_t val;
|
||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||
if (util_rnd64() & 0x1) {
|
||||
val += delta;
|
||||
} else {
|
||||
/* Foreign endianess */
|
||||
val = __builtin_bswap64(val);
|
||||
val += delta;
|
||||
val = __builtin_bswap64(val);
|
||||
}
|
||||
mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_F("Unknown variable length size: %zu", varLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_AddSub(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
|
||||
/* 1,2,4,8 */
|
||||
size_t varLen = 1U << util_rndGet(0, 3);
|
||||
if ((run->dynfile->size - off) < varLen) {
|
||||
varLen = 1;
|
||||
}
|
||||
|
||||
uint64_t range;
|
||||
switch (varLen) {
|
||||
case 1:
|
||||
range = 16;
|
||||
break;
|
||||
case 2:
|
||||
range = 4096;
|
||||
break;
|
||||
case 4:
|
||||
range = 1048576;
|
||||
break;
|
||||
case 8:
|
||||
range = 268435456;
|
||||
break;
|
||||
default:
|
||||
LOG_F("Invalid operand size: %zu", varLen);
|
||||
}
|
||||
|
||||
mangle_AddSubWithRange(run, off, varLen, range, printable);
|
||||
}
|
||||
|
||||
static void mangle_IncByte(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
if (printable) {
|
||||
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
|
||||
} else {
|
||||
run->dynfile->data[off] += (uint8_t)1UL;
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_DecByte(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
if (printable) {
|
||||
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
|
||||
} else {
|
||||
run->dynfile->data[off] -= (uint8_t)1UL;
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_NegByte(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
if (printable) {
|
||||
run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
|
||||
} else {
|
||||
run->dynfile->data[off] = ~(run->dynfile->data[off]);
|
||||
}
|
||||
}
|
||||
|
||||
static void mangle_Expand(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
size_t len;
|
||||
if (util_rnd64() % 16) {
|
||||
len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
|
||||
} else {
|
||||
len = mangle_getLen(run->global->mutate.maxInputSz - off);
|
||||
}
|
||||
|
||||
mangle_Inflate(run, off, len, printable);
|
||||
}
|
||||
|
||||
static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) {
|
||||
if (run->dynfile->size <= 2U) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t off_start = mangle_getOffSet(run);
|
||||
size_t len = mangle_LenLeft(run, off_start);
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
if (util_rnd64() % 16) {
|
||||
len = mangle_getLen(HF_MIN(16, len));
|
||||
} else {
|
||||
len = mangle_getLen(len);
|
||||
}
|
||||
size_t off_end = off_start + len;
|
||||
size_t len_to_move = run->dynfile->size - off_end;
|
||||
|
||||
mangle_Move(run, off_end, off_start, len_to_move);
|
||||
input_setSize(run, run->dynfile->size - len);
|
||||
}
|
||||
static void mangle_ASCIINum(run_t* run, bool printable) {
|
||||
size_t len = util_rndGet(2, 8);
|
||||
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
|
||||
|
||||
mangle_UseValue(run, (const uint8_t*)buf, len, printable);
|
||||
}
|
||||
|
||||
static void mangle_ASCIINumChange(run_t* run, bool printable) {
|
||||
size_t off = mangle_getOffSet(run);
|
||||
|
||||
/* Find a digit */
|
||||
for (; off < run->dynfile->size; off++) {
|
||||
if (isdigit(run->dynfile->data[off])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t left = run->dynfile->size - off;
|
||||
if (left == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
uint64_t val = 0;
|
||||
/* 20 is maximum lenght of a string representing a 64-bit unsigned value */
|
||||
for (len = 0; (len < 20) && (len < left); len++) {
|
||||
char c = run->dynfile->data[off + len];
|
||||
if (!isdigit(c)) {
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
val += (c - '0');
|
||||
}
|
||||
|
||||
switch (util_rndGet(0, 7)) {
|
||||
case 0:
|
||||
val++;
|
||||
break;
|
||||
case 1:
|
||||
val--;
|
||||
break;
|
||||
case 2:
|
||||
val *= 2;
|
||||
break;
|
||||
case 3:
|
||||
val /= 2;
|
||||
break;
|
||||
case 4:
|
||||
val = util_rnd64();
|
||||
break;
|
||||
case 5:
|
||||
val += util_rndGet(1, 256);
|
||||
break;
|
||||
case 6:
|
||||
val -= util_rndGet(1, 256);
|
||||
break;
|
||||
case 7:
|
||||
val = ~(val);
|
||||
break;
|
||||
default:
|
||||
LOG_F("Invalid choice");
|
||||
};
|
||||
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
|
||||
|
||||
mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable);
|
||||
}
|
||||
|
||||
static void mangle_Splice(run_t* run, bool printable) {
|
||||
if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t sz = 0;
|
||||
const uint8_t* buf = input_getRandomInputAsBuf(run, &sz);
|
||||
if (!buf) {
|
||||
LOG_E("input_getRandomInputAsBuf() returned no input");
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
if (!sz) {
|
||||
mangle_Bytes(run, printable);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t remoteOff = mangle_getLen(sz) - 1;
|
||||
size_t len = mangle_getLen(sz - remoteOff);
|
||||
mangle_UseValue(run, &buf[remoteOff], len, printable);
|
||||
}
|
||||
|
||||
static void mangle_Resize(run_t* run, bool printable) {
|
||||
ssize_t oldsz = run->dynfile->size;
|
||||
ssize_t newsz = 0;
|
||||
|
||||
uint64_t choice = util_rndGet(0, 32);
|
||||
switch (choice) {
|
||||
case 0: /* Set new size arbitrarily */
|
||||
newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
|
||||
break;
|
||||
case 1 ... 4: /* Increase size by a small value */
|
||||
newsz = oldsz + (ssize_t)util_rndGet(0, 8);
|
||||
break;
|
||||
case 5: /* Increase size by a larger value */
|
||||
newsz = oldsz + (ssize_t)util_rndGet(9, 128);
|
||||
break;
|
||||
case 6 ... 9: /* Decrease size by a small value */
|
||||
newsz = oldsz - (ssize_t)util_rndGet(0, 8);
|
||||
break;
|
||||
case 10: /* Decrease size by a larger value */
|
||||
newsz = oldsz - (ssize_t)util_rndGet(9, 128);
|
||||
break;
|
||||
case 11 ... 32: /* Do nothing */
|
||||
newsz = oldsz;
|
||||
break;
|
||||
default:
|
||||
LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
|
||||
break;
|
||||
}
|
||||
if (newsz < 1) {
|
||||
newsz = 1;
|
||||
}
|
||||
if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
|
||||
newsz = run->global->mutate.maxInputSz;
|
||||
}
|
||||
|
||||
input_setSize(run, (size_t)newsz);
|
||||
if (newsz > oldsz) {
|
||||
if (printable) {
|
||||
memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mangle_mangleContent(run_t* run, int speed_factor) {
|
||||
static void (*const mangleFuncs[])(run_t * run, bool printable) = {
|
||||
mangle_Shrink,
|
||||
mangle_Expand,
|
||||
mangle_Bit,
|
||||
mangle_IncByte,
|
||||
mangle_DecByte,
|
||||
mangle_NegByte,
|
||||
mangle_AddSub,
|
||||
mangle_MemSet,
|
||||
mangle_MemClr,
|
||||
mangle_MemSwap,
|
||||
mangle_MemCopy,
|
||||
mangle_Bytes,
|
||||
mangle_ASCIINum,
|
||||
mangle_ASCIINumChange,
|
||||
mangle_ByteRepeat,
|
||||
mangle_Magic,
|
||||
mangle_StaticDict,
|
||||
mangle_ConstFeedbackDict,
|
||||
mangle_RandomBuf,
|
||||
mangle_Splice,
|
||||
};
|
||||
|
||||
if (run->mutationsPerRun == 0U) {
|
||||
return;
|
||||
}
|
||||
if (run->dynfile->size == 0U) {
|
||||
mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
|
||||
}
|
||||
|
||||
uint64_t changesCnt = run->global->mutate.mutationsPerRun;
|
||||
|
||||
if (speed_factor < 5) {
|
||||
changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
|
||||
} else if (speed_factor < 10) {
|
||||
changesCnt = run->global->mutate.mutationsPerRun;
|
||||
} else {
|
||||
changesCnt = HF_MIN(speed_factor, 10);
|
||||
changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
|
||||
}
|
||||
|
||||
/* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */
|
||||
if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
|
||||
if (util_rnd64() & 0x1) {
|
||||
mangle_Splice(run, run->global->cfg.only_printable);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint64_t x = 0; x < changesCnt; x++) {
|
||||
if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
|
||||
/*
|
||||
* mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary
|
||||
* exists. If so, give it 50% chance of being used among all mangling functions.
|
||||
*/
|
||||
mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable);
|
||||
} else {
|
||||
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
|
||||
mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
|
||||
}
|
||||
}
|
||||
|
||||
wmb();
|
||||
}
|
31
custom_mutators/honggfuzz/mangle.h
Normal file
31
custom_mutators/honggfuzz/mangle.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
*
|
||||
* honggfuzz - buffer mangling routines
|
||||
* -----------------------------------------
|
||||
*
|
||||
* Author: Robert Swiecki <swiecki@google.com>
|
||||
*
|
||||
* Copyright 2010-2018 by Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HF_MANGLE_H_
|
||||
#define _HF_MANGLE_H_
|
||||
|
||||
#include "honggfuzz.h"
|
||||
|
||||
extern void mangle_mangleContent(run_t* run, int speed_factor);
|
||||
|
||||
#endif
|
10
custom_mutators/libafl_base/.gitignore
vendored
Normal file
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
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
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
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
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);
|
35
custom_mutators/libfuzzer/FuzzerBuiltins.h
Normal file
35
custom_mutators/libfuzzer/FuzzerBuiltins.h
Normal file
@ -0,0 +1,35 @@
|
||||
//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Wrapper functions and macros around builtin functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_FUZZER_BUILTINS_H
|
||||
#define LLVM_FUZZER_BUILTINS_H
|
||||
|
||||
#include "FuzzerPlatform.h"
|
||||
|
||||
#if !LIBFUZZER_MSVC
|
||||
#include <cstdint>
|
||||
|
||||
#define GET_CALLER_PC() __builtin_return_address(0)
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
inline uint8_t Bswap(uint8_t x) { return x; }
|
||||
inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); }
|
||||
inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
|
||||
inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
|
||||
|
||||
inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); }
|
||||
inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); }
|
||||
inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); }
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
#endif // !LIBFUZZER_MSVC
|
||||
#endif // LLVM_FUZZER_BUILTINS_H
|
72
custom_mutators/libfuzzer/FuzzerBuiltinsMsvc.h
Normal file
72
custom_mutators/libfuzzer/FuzzerBuiltinsMsvc.h
Normal file
@ -0,0 +1,72 @@
|
||||
//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Wrapper functions and macros that use intrinsics instead of builtin functions
|
||||
// which cannot be compiled by MSVC.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_FUZZER_BUILTINS_MSVC_H
|
||||
#define LLVM_FUZZER_BUILTINS_MSVC_H
|
||||
|
||||
#include "FuzzerPlatform.h"
|
||||
|
||||
#if LIBFUZZER_MSVC
|
||||
#include <intrin.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent
|
||||
// from <intrin.h>
|
||||
#define GET_CALLER_PC() _ReturnAddress()
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
inline uint8_t Bswap(uint8_t x) { return x; }
|
||||
// Use alternatives to __builtin functions from <stdlib.h> and <intrin.h> on
|
||||
// Windows since the builtins are not supported by MSVC.
|
||||
inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); }
|
||||
inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); }
|
||||
inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); }
|
||||
|
||||
// The functions below were mostly copied from
|
||||
// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used
|
||||
// outside of Windows.
|
||||
inline uint32_t Clzll(uint64_t X) {
|
||||
unsigned long LeadZeroIdx = 0;
|
||||
|
||||
#if !defined(_M_ARM) && !defined(_M_X64)
|
||||
// Scan the high 32 bits.
|
||||
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X >> 32)))
|
||||
return static_cast<int>(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB.
|
||||
// Scan the low 32 bits.
|
||||
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X)))
|
||||
return static_cast<int>(63 - LeadZeroIdx);
|
||||
|
||||
#else
|
||||
if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
|
||||
#endif
|
||||
return 64;
|
||||
}
|
||||
|
||||
inline uint32_t Clz(uint32_t X) {
|
||||
unsigned long LeadZeroIdx = 0;
|
||||
if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx;
|
||||
return 32;
|
||||
}
|
||||
|
||||
inline int Popcountll(unsigned long long X) {
|
||||
#if !defined(_M_ARM) && !defined(_M_X64)
|
||||
return __popcnt(X) + __popcnt(X >> 32);
|
||||
#else
|
||||
return __popcnt64(X);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
#endif // LIBFUZER_MSVC
|
||||
#endif // LLVM_FUZZER_BUILTINS_MSVC_H
|
178
custom_mutators/libfuzzer/FuzzerCommand.h
Normal file
178
custom_mutators/libfuzzer/FuzzerCommand.h
Normal file
@ -0,0 +1,178 @@
|
||||
//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FuzzerCommand represents a command to run in a subprocess. It allows callers
|
||||
// to manage command line arguments and output and error streams.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_FUZZER_COMMAND_H
|
||||
#define LLVM_FUZZER_COMMAND_H
|
||||
|
||||
#include "FuzzerDefs.h"
|
||||
#include "FuzzerIO.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
class Command final {
|
||||
public:
|
||||
// This command line flag is used to indicate that the remaining command line
|
||||
// is immutable, meaning this flag effectively marks the end of the mutable
|
||||
// argument list.
|
||||
static inline const char *ignoreRemainingArgs() {
|
||||
return "-ignore_remaining_args=1";
|
||||
}
|
||||
|
||||
Command() : CombinedOutAndErr(false) {}
|
||||
|
||||
explicit Command(const Vector<std::string> &ArgsToAdd)
|
||||
: Args(ArgsToAdd), CombinedOutAndErr(false) {}
|
||||
|
||||
explicit Command(const Command &Other)
|
||||
: Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr),
|
||||
OutputFile(Other.OutputFile) {}
|
||||
|
||||
Command &operator=(const Command &Other) {
|
||||
Args = Other.Args;
|
||||
CombinedOutAndErr = Other.CombinedOutAndErr;
|
||||
OutputFile = Other.OutputFile;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Command() {}
|
||||
|
||||
// Returns true if the given Arg is present in Args. Only checks up to
|
||||
// "-ignore_remaining_args=1".
|
||||
bool hasArgument(const std::string &Arg) const {
|
||||
auto i = endMutableArgs();
|
||||
return std::find(Args.begin(), i, Arg) != i;
|
||||
}
|
||||
|
||||
// Gets all of the current command line arguments, **including** those after
|
||||
// "-ignore-remaining-args=1".
|
||||
const Vector<std::string> &getArguments() const { return Args; }
|
||||
|
||||
// Adds the given argument before "-ignore_remaining_args=1", or at the end
|
||||
// if that flag isn't present.
|
||||
void addArgument(const std::string &Arg) {
|
||||
Args.insert(endMutableArgs(), Arg);
|
||||
}
|
||||
|
||||
// Adds all given arguments before "-ignore_remaining_args=1", or at the end
|
||||
// if that flag isn't present.
|
||||
void addArguments(const Vector<std::string> &ArgsToAdd) {
|
||||
Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end());
|
||||
}
|
||||
|
||||
// Removes the given argument from the command argument list. Ignores any
|
||||
// occurrences after "-ignore_remaining_args=1", if present.
|
||||
void removeArgument(const std::string &Arg) {
|
||||
auto i = endMutableArgs();
|
||||
Args.erase(std::remove(Args.begin(), i, Arg), i);
|
||||
}
|
||||
|
||||
// Like hasArgument, but checks for "-[Flag]=...".
|
||||
bool hasFlag(const std::string &Flag) const {
|
||||
std::string Arg("-" + Flag + "=");
|
||||
auto IsMatch = [&](const std::string &Other) {
|
||||
return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
|
||||
};
|
||||
return std::any_of(Args.begin(), endMutableArgs(), IsMatch);
|
||||
}
|
||||
|
||||
// Returns the value of the first instance of a given flag, or an empty string
|
||||
// if the flag isn't present. Ignores any occurrences after
|
||||
// "-ignore_remaining_args=1", if present.
|
||||
std::string getFlagValue(const std::string &Flag) const {
|
||||
std::string Arg("-" + Flag + "=");
|
||||
auto IsMatch = [&](const std::string &Other) {
|
||||
return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
|
||||
};
|
||||
auto i = endMutableArgs();
|
||||
auto j = std::find_if(Args.begin(), i, IsMatch);
|
||||
std::string result;
|
||||
if (j != i) {
|
||||
result = j->substr(Arg.length());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Like AddArgument, but adds "-[Flag]=[Value]".
|
||||
void addFlag(const std::string &Flag, const std::string &Value) {
|
||||
addArgument("-" + Flag + "=" + Value);
|
||||
}
|
||||
|
||||
// Like RemoveArgument, but removes "-[Flag]=...".
|
||||
void removeFlag(const std::string &Flag) {
|
||||
std::string Arg("-" + Flag + "=");
|
||||
auto IsMatch = [&](const std::string &Other) {
|
||||
return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
|
||||
};
|
||||
auto i = endMutableArgs();
|
||||
Args.erase(std::remove_if(Args.begin(), i, IsMatch), i);
|
||||
}
|
||||
|
||||
// Returns whether the command's stdout is being written to an output file.
|
||||
bool hasOutputFile() const { return !OutputFile.empty(); }
|
||||
|
||||
// Returns the currently set output file.
|
||||
const std::string &getOutputFile() const { return OutputFile; }
|
||||
|
||||
// Configures the command to redirect its output to the name file.
|
||||
void setOutputFile(const std::string &FileName) { OutputFile = FileName; }
|
||||
|
||||
// Returns whether the command's stderr is redirected to stdout.
|
||||
bool isOutAndErrCombined() const { return CombinedOutAndErr; }
|
||||
|
||||
// Sets whether to redirect the command's stderr to its stdout.
|
||||
void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; }
|
||||
|
||||
// Returns a string representation of the command. On many systems this will
|
||||
// be the equivalent command line.
|
||||
std::string toString() const {
|
||||
std::stringstream SS;
|
||||
for (auto arg : getArguments())
|
||||
SS << arg << " ";
|
||||
if (hasOutputFile())
|
||||
SS << ">" << getOutputFile() << " ";
|
||||
if (isOutAndErrCombined())
|
||||
SS << "2>&1 ";
|
||||
std::string result = SS.str();
|
||||
if (!result.empty())
|
||||
result = result.substr(0, result.length() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
Command(Command &&Other) = delete;
|
||||
Command &operator=(Command &&Other) = delete;
|
||||
|
||||
Vector<std::string>::iterator endMutableArgs() {
|
||||
return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
|
||||
}
|
||||
|
||||
Vector<std::string>::const_iterator endMutableArgs() const {
|
||||
return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
|
||||
}
|
||||
|
||||
// The command arguments. Args[0] is the command name.
|
||||
Vector<std::string> Args;
|
||||
|
||||
// True indicates stderr is redirected to stdout.
|
||||
bool CombinedOutAndErr;
|
||||
|
||||
// If not empty, stdout is redirected to the named file.
|
||||
std::string OutputFile;
|
||||
};
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
#endif // LLVM_FUZZER_COMMAND_H
|
581
custom_mutators/libfuzzer/FuzzerCorpus.h
Normal file
581
custom_mutators/libfuzzer/FuzzerCorpus.h
Normal file
@ -0,0 +1,581 @@
|
||||
//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// fuzzer::InputCorpus
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_FUZZER_CORPUS
|
||||
#define LLVM_FUZZER_CORPUS
|
||||
|
||||
#include "FuzzerDataFlowTrace.h"
|
||||
#include "FuzzerDefs.h"
|
||||
#include "FuzzerIO.h"
|
||||
#include "FuzzerRandom.h"
|
||||
#include "FuzzerSHA1.h"
|
||||
#include "FuzzerTracePC.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace fuzzer {
|
||||
|
||||
struct InputInfo {
|
||||
Unit U; // The actual input data.
|
||||
std::chrono::microseconds TimeOfUnit;
|
||||
uint8_t Sha1[kSHA1NumBytes]; // Checksum.
|
||||
// Number of features that this input has and no smaller input has.
|
||||
size_t NumFeatures = 0;
|
||||
size_t Tmp = 0; // Used by ValidateFeatureSet.
|
||||
// Stats.
|
||||
size_t NumExecutedMutations = 0;
|
||||
size_t NumSuccessfullMutations = 0;
|
||||
bool NeverReduce = false;
|
||||
bool MayDeleteFile = false;
|
||||
bool Reduced = false;
|
||||
bool HasFocusFunction = false;
|
||||
Vector<uint32_t> UniqFeatureSet;
|
||||
Vector<uint8_t> DataFlowTraceForFocusFunction;
|
||||
// Power schedule.
|
||||
bool NeedsEnergyUpdate = false;
|
||||
double Energy = 0.0;
|
||||
size_t SumIncidence = 0;
|
||||
Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs;
|
||||
|
||||
// Delete feature Idx and its frequency from FeatureFreqs.
|
||||
bool DeleteFeatureFreq(uint32_t Idx) {
|
||||
if (FeatureFreqs.empty())
|
||||
return false;
|
||||
|
||||
// Binary search over local feature frequencies sorted by index.
|
||||
auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(),
|
||||
std::pair<uint32_t, uint16_t>(Idx, 0));
|
||||
|
||||
if (Lower != FeatureFreqs.end() && Lower->first == Idx) {
|
||||
FeatureFreqs.erase(Lower);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assign more energy to a high-entropy seed, i.e., that reveals more
|
||||
// information about the globally rare features in the neighborhood of the
|
||||
// seed. Since we do not know the entropy of a seed that has never been
|
||||
// executed we assign fresh seeds maximum entropy and let II->Energy approach
|
||||
// the true entropy from above. If ScalePerExecTime is true, the computed
|
||||
// entropy is scaled based on how fast this input executes compared to the
|
||||
// average execution time of inputs. The faster an input executes, the more
|
||||
// energy gets assigned to the input.
|
||||
void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime,
|
||||
std::chrono::microseconds AverageUnitExecutionTime) {
|
||||
Energy = 0.0;
|
||||
SumIncidence = 0;
|
||||
|
||||
// Apply add-one smoothing to locally discovered features.
|
||||
for (auto F : FeatureFreqs) {
|
||||
size_t LocalIncidence = F.second + 1;
|
||||
Energy -= LocalIncidence * logl(LocalIncidence);
|
||||
SumIncidence += LocalIncidence;
|
||||
}
|
||||
|
||||
// Apply add-one smoothing to locally undiscovered features.
|
||||
// PreciseEnergy -= 0; // since logl(1.0) == 0)
|
||||
SumIncidence += (GlobalNumberOfFeatures - FeatureFreqs.size());
|
||||
|
||||
// Add a single locally abundant feature apply add-one smoothing.
|
||||
size_t AbdIncidence = NumExecutedMutations + 1;
|
||||
Energy -= AbdIncidence * logl(AbdIncidence);
|
||||
SumIncidence += AbdIncidence;
|
||||
|
||||
// Normalize.
|
||||
if (SumIncidence != 0)
|
||||
Energy = (Energy / SumIncidence) + logl(SumIncidence);
|
||||
|
||||
if (ScalePerExecTime) {
|
||||
// Scaling to favor inputs with lower execution time.
|
||||
uint32_t PerfScore = 100;
|
||||
if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 10)
|
||||
PerfScore = 10;
|
||||
else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 4)
|
||||
PerfScore = 25;
|
||||
else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 2)
|
||||
PerfScore = 50;
|
||||
else if (TimeOfUnit.count() * 3 > AverageUnitExecutionTime.count() * 4)
|
||||
PerfScore = 75;
|
||||
else if (TimeOfUnit.count() * 4 < AverageUnitExecutionTime.count())
|
||||
PerfScore = 300;
|
||||
else if (TimeOfUnit.count() * 3 < AverageUnitExecutionTime.count())
|
||||
PerfScore = 200;
|
||||
else if (TimeOfUnit.count() * 2 < AverageUnitExecutionTime.count())
|
||||
PerfScore = 150;
|
||||
|
||||
Energy *= PerfScore;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the frequency of the feature Idx.
|
||||
void UpdateFeatureFrequency(uint32_t Idx) {
|
||||
NeedsEnergyUpdate = true;
|
||||
|
||||
// The local feature frequencies is an ordered vector of pairs.
|
||||
// If there are no local feature frequencies, push_back preserves order.
|
||||
// Set the feature frequency for feature Idx32 to 1.
|
||||
if (FeatureFreqs.empty()) {
|
||||
FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(Idx, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Binary search over local feature frequencies sorted by index.
|
||||
auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(),
|
||||
std::pair<uint32_t, uint16_t>(Idx, 0));
|
||||
|
||||
// If feature Idx32 already exists, increment its frequency.
|
||||
// Otherwise, insert a new pair right after the next lower index.
|
||||
if (Lower != FeatureFreqs.end() && Lower->first == Idx) {
|
||||
Lower->second++;
|
||||
} else {
|
||||
FeatureFreqs.insert(Lower, std::pair<uint32_t, uint16_t>(Idx, 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct EntropicOptions {
|
||||
bool Enabled;
|
||||
size_t NumberOfRarestFeatures;
|
||||
size_t FeatureFrequencyThreshold;
|
||||
bool ScalePerExecTime;
|
||||
};
|
||||
|
||||
class InputCorpus {
|
||||
static const uint32_t kFeatureSetSize = 1 << 21;
|
||||
static const uint8_t kMaxMutationFactor = 20;
|
||||
static const size_t kSparseEnergyUpdates = 100;
|
||||
|
||||
size_t NumExecutedMutations = 0;
|
||||
|
||||
EntropicOptions Entropic;
|
||||
|
||||
public:
|
||||
InputCorpus(const std::string &OutputCorpus, EntropicOptions Entropic)
|
||||
: Entropic(Entropic), OutputCorpus(OutputCorpus) {
|
||||
memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
|
||||
memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
|
||||
}
|
||||
~InputCorpus() {
|
||||
for (auto II : Inputs)
|
||||
delete II;
|
||||
}
|
||||
size_t size() const { return Inputs.size(); }
|
||||
size_t SizeInBytes() const {
|
||||
size_t Res = 0;
|
||||
for (auto II : Inputs)
|
||||
Res += II->U.size();
|
||||
return Res;
|
||||
}
|
||||
size_t NumActiveUnits() const {
|
||||
size_t Res = 0;
|
||||
for (auto II : Inputs)
|
||||
Res += !II->U.empty();
|
||||
return Res;
|
||||
}
|
||||
size_t MaxInputSize() const {
|
||||
size_t Res = 0;
|
||||
for (auto II : Inputs)
|
||||
Res = std::max(Res, II->U.size());
|
||||
return Res;
|
||||
}
|
||||
void IncrementNumExecutedMutations() { NumExecutedMutations++; }
|
||||
|
||||
size_t NumInputsThatTouchFocusFunction() {
|
||||
return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) {
|
||||
return II->HasFocusFunction;
|
||||
});
|
||||
}
|
||||
|
||||
size_t NumInputsWithDataFlowTrace() {
|
||||
return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) {
|
||||
return !II->DataFlowTraceForFocusFunction.empty();
|
||||
});
|
||||
}
|
||||
|
||||
bool empty() const { return Inputs.empty(); }
|
||||
const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; }
|
||||
InputInfo *AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile,
|
||||
bool HasFocusFunction, bool NeverReduce,
|
||||
std::chrono::microseconds TimeOfUnit,
|
||||
const Vector<uint32_t> &FeatureSet,
|
||||
const DataFlowTrace &DFT, const InputInfo *BaseII) {
|
||||
assert(!U.empty());
|
||||
if (FeatureDebug)
|
||||
Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
|
||||
Inputs.push_back(new InputInfo());
|
||||
InputInfo &II = *Inputs.back();
|
||||
II.U = U;
|
||||
II.NumFeatures = NumFeatures;
|
||||
II.NeverReduce = NeverReduce;
|
||||
II.TimeOfUnit = TimeOfUnit;
|
||||
II.MayDeleteFile = MayDeleteFile;
|
||||
II.UniqFeatureSet = FeatureSet;
|
||||
II.HasFocusFunction = HasFocusFunction;
|
||||
// Assign maximal energy to the new seed.
|
||||
II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size());
|
||||
II.SumIncidence = RareFeatures.size();
|
||||
II.NeedsEnergyUpdate = false;
|
||||
std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end());
|
||||
ComputeSHA1(U.data(), U.size(), II.Sha1);
|
||||
auto Sha1Str = Sha1ToString(II.Sha1);
|
||||
Hashes.insert(Sha1Str);
|
||||
if (HasFocusFunction)
|
||||
if (auto V = DFT.Get(Sha1Str))
|
||||
II.DataFlowTraceForFocusFunction = *V;
|
||||
// This is a gross heuristic.
|
||||
// Ideally, when we add an element to a corpus we need to know its DFT.
|
||||
// But if we don't, we'll use the DFT of its base input.
|
||||
if (II.DataFlowTraceForFocusFunction.empty() && BaseII)
|
||||
II.DataFlowTraceForFocusFunction = BaseII->DataFlowTraceForFocusFunction;
|
||||
DistributionNeedsUpdate = true;
|
||||
PrintCorpus();
|
||||
// ValidateFeatureSet();
|
||||
return &II;
|
||||
}
|
||||
|
||||
// Debug-only
|
||||
void PrintUnit(const Unit &U) {
|
||||
if (!FeatureDebug) return;
|
||||
for (uint8_t C : U) {
|
||||
if (C != 'F' && C != 'U' && C != 'Z')
|
||||
C = '.';
|
||||
Printf("%c", C);
|
||||
}
|
||||
}
|
||||
|
||||
// Debug-only
|
||||
void PrintFeatureSet(const Vector<uint32_t> &FeatureSet) {
|
||||
if (!FeatureDebug) return;
|
||||
Printf("{");
|
||||
for (uint32_t Feature: FeatureSet)
|
||||
Printf("%u,", Feature);
|
||||
Printf("}");
|
||||
}
|
||||
|
||||
// Debug-only
|
||||
void PrintCorpus() {
|
||||
if (!FeatureDebug) return;
|
||||
Printf("======= CORPUS:\n");
|
||||
int i = 0;
|
||||
for (auto II : Inputs) {
|
||||
if (std::find(II->U.begin(), II->U.end(), 'F') != II->U.end()) {
|
||||
Printf("[%2d] ", i);
|
||||
Printf("%s sz=%zd ", Sha1ToString(II->Sha1).c_str(), II->U.size());
|
||||
PrintUnit(II->U);
|
||||
Printf(" ");
|
||||
PrintFeatureSet(II->UniqFeatureSet);
|
||||
Printf("\n");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void Replace(InputInfo *II, const Unit &U) {
|
||||
assert(II->U.size() > U.size());
|
||||
Hashes.erase(Sha1ToString(II->Sha1));
|
||||
DeleteFile(*II);
|
||||
ComputeSHA1(U.data(), U.size(), II->Sha1);
|
||||
Hashes.insert(Sha1ToString(II->Sha1));
|
||||
II->U = U;
|
||||
II->Reduced = true;
|
||||
DistributionNeedsUpdate = true;
|
||||
}
|
||||
|
||||
bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
|
||||
bool HasUnit(const std::string &H) { return Hashes.count(H); }
|
||||
InputInfo &ChooseUnitToMutate(Random &Rand) {
|
||||
InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)];
|
||||
assert(!II.U.empty());
|
||||
return II;
|
||||
}
|
||||
|
||||
InputInfo &ChooseUnitToCrossOverWith(Random &Rand, bool UniformDist) {
|
||||
if (!UniformDist) {
|
||||
return ChooseUnitToMutate(Rand);
|
||||
}
|
||||
InputInfo &II = *Inputs[Rand(Inputs.size())];
|
||||
assert(!II.U.empty());
|
||||
return II;
|
||||
}
|
||||
|
||||
// Returns an index of random unit from the corpus to mutate.
|
||||
size_t ChooseUnitIdxToMutate(Random &Rand) {
|
||||
UpdateCorpusDistribution(Rand);
|
||||
size_t Idx = static_cast<size_t>(CorpusDistribution(Rand));
|
||||
assert(Idx < Inputs.size());
|
||||
return Idx;
|
||||
}
|
||||
|
||||
void PrintStats() {
|
||||
for (size_t i = 0; i < Inputs.size(); i++) {
|
||||
const auto &II = *Inputs[i];
|
||||
Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i,
|
||||
Sha1ToString(II.Sha1).c_str(), II.U.size(),
|
||||
II.NumExecutedMutations, II.NumSuccessfullMutations, II.HasFocusFunction);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintFeatureSet() {
|
||||
for (size_t i = 0; i < kFeatureSetSize; i++) {
|
||||
if(size_t Sz = GetFeature(i))
|
||||
Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz);
|
||||
}
|
||||
Printf("\n\t");
|
||||
for (size_t i = 0; i < Inputs.size(); i++)
|
||||
if (size_t N = Inputs[i]->NumFeatures)
|
||||
Printf(" %zd=>%zd ", i, N);
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
void DeleteFile(const InputInfo &II) {
|
||||
if (!OutputCorpus.empty() && II.MayDeleteFile)
|
||||
RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1)));
|
||||
}
|
||||
|
||||
void DeleteInput(size_t Idx) {
|
||||
InputInfo &II = *Inputs[Idx];
|
||||
DeleteFile(II);
|
||||
Unit().swap(II.U);
|
||||
II.Energy = 0.0;
|
||||
II.NeedsEnergyUpdate = false;
|
||||
DistributionNeedsUpdate = true;
|
||||
if (FeatureDebug)
|
||||
Printf("EVICTED %zd\n", Idx);
|
||||
}
|
||||
|
||||
void AddRareFeature(uint32_t Idx) {
|
||||
// Maintain *at least* TopXRarestFeatures many rare features
|
||||
// and all features with a frequency below ConsideredRare.
|
||||
// Remove all other features.
|
||||
while (RareFeatures.size() > Entropic.NumberOfRarestFeatures &&
|
||||
FreqOfMostAbundantRareFeature > Entropic.FeatureFrequencyThreshold) {
|
||||
|
||||
// Find most and second most abbundant feature.
|
||||
uint32_t MostAbundantRareFeatureIndices[2] = {RareFeatures[0],
|
||||
RareFeatures[0]};
|
||||
size_t Delete = 0;
|
||||
for (size_t i = 0; i < RareFeatures.size(); i++) {
|
||||
uint32_t Idx2 = RareFeatures[i];
|
||||
if (GlobalFeatureFreqs[Idx2] >=
|
||||
GlobalFeatureFreqs[MostAbundantRareFeatureIndices[0]]) {
|
||||
MostAbundantRareFeatureIndices[1] = MostAbundantRareFeatureIndices[0];
|
||||
MostAbundantRareFeatureIndices[0] = Idx2;
|
||||
Delete = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove most abundant rare feature.
|
||||
RareFeatures[Delete] = RareFeatures.back();
|
||||
RareFeatures.pop_back();
|
||||
|
||||
for (auto II : Inputs) {
|
||||
if (II->DeleteFeatureFreq(MostAbundantRareFeatureIndices[0]))
|
||||
II->NeedsEnergyUpdate = true;
|
||||
}
|
||||
|
||||
// Set 2nd most abundant as the new most abundant feature count.
|
||||
FreqOfMostAbundantRareFeature =
|
||||
GlobalFeatureFreqs[MostAbundantRareFeatureIndices[1]];
|
||||
}
|
||||
|
||||
// Add rare feature, handle collisions, and update energy.
|
||||
RareFeatures.push_back(Idx);
|
||||
GlobalFeatureFreqs[Idx] = 0;
|
||||
for (auto II : Inputs) {
|
||||
II->DeleteFeatureFreq(Idx);
|
||||
|
||||
// Apply add-one smoothing to this locally undiscovered feature.
|
||||
// Zero energy seeds will never be fuzzed and remain zero energy.
|
||||
if (II->Energy > 0.0) {
|
||||
II->SumIncidence += 1;
|
||||
II->Energy += logl(II->SumIncidence) / II->SumIncidence;
|
||||
}
|
||||
}
|
||||
|
||||
DistributionNeedsUpdate = true;
|
||||
}
|
||||
|
||||
bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) {
|
||||
assert(NewSize);
|
||||
Idx = Idx % kFeatureSetSize;
|
||||
uint32_t OldSize = GetFeature(Idx);
|
||||
if (OldSize == 0 || (Shrink && OldSize > NewSize)) {
|
||||
if (OldSize > 0) {
|
||||
size_t OldIdx = SmallestElementPerFeature[Idx];
|
||||
InputInfo &II = *Inputs[OldIdx];
|
||||
assert(II.NumFeatures > 0);
|
||||
II.NumFeatures--;
|
||||
if (II.NumFeatures == 0)
|
||||
DeleteInput(OldIdx);
|
||||
} else {
|
||||
NumAddedFeatures++;
|
||||
if (Entropic.Enabled)
|
||||
AddRareFeature((uint32_t)Idx);
|
||||
}
|
||||
NumUpdatedFeatures++;
|
||||
if (FeatureDebug)
|
||||
Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
|
||||
SmallestElementPerFeature[Idx] = Inputs.size();
|
||||
InputSizesPerFeature[Idx] = NewSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Increment frequency of feature Idx globally and locally.
|
||||
void UpdateFeatureFrequency(InputInfo *II, size_t Idx) {
|
||||
uint32_t Idx32 = Idx % kFeatureSetSize;
|
||||
|
||||
// Saturated increment.
|
||||
if (GlobalFeatureFreqs[Idx32] == 0xFFFF)
|
||||
return;
|
||||
uint16_t Freq = GlobalFeatureFreqs[Idx32]++;
|
||||
|
||||
// Skip if abundant.
|
||||
if (Freq > FreqOfMostAbundantRareFeature ||
|
||||
std::find(RareFeatures.begin(), RareFeatures.end(), Idx32) ==
|
||||
RareFeatures.end())
|
||||
return;
|
||||
|
||||
// Update global frequencies.
|
||||
if (Freq == FreqOfMostAbundantRareFeature)
|
||||
FreqOfMostAbundantRareFeature++;
|
||||
|
||||
// Update local frequencies.
|
||||
if (II)
|
||||
II->UpdateFeatureFrequency(Idx32);
|
||||
}
|
||||
|
||||
size_t NumFeatures() const { return NumAddedFeatures; }
|
||||
size_t NumFeatureUpdates() const { return NumUpdatedFeatures; }
|
||||
|
||||
private:
|
||||
|
||||
static const bool FeatureDebug = false;
|
||||
|
||||
size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
|
||||
|
||||
void ValidateFeatureSet() {
|
||||
if (FeatureDebug)
|
||||
PrintFeatureSet();
|
||||
for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++)
|
||||
if (GetFeature(Idx))
|
||||
Inputs[SmallestElementPerFeature[Idx]]->Tmp++;
|
||||
for (auto II: Inputs) {
|
||||
if (II->Tmp != II->NumFeatures)
|
||||
Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures);
|
||||
assert(II->Tmp == II->NumFeatures);
|
||||
II->Tmp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the probability distribution for the units in the corpus.
|
||||
// Must be called whenever the corpus or unit weights are changed.
|
||||
//
|
||||
// Hypothesis: inputs that maximize information about globally rare features
|
||||
// are interesting.
|
||||
void UpdateCorpusDistribution(Random &Rand) {
|
||||
// Skip update if no seeds or rare features were added/deleted.
|
||||
// Sparse updates for local change of feature frequencies,
|
||||
// i.e., randomly do not skip.
|
||||
if (!DistributionNeedsUpdate &&
|
||||
(!Entropic.Enabled || Rand(kSparseEnergyUpdates)))
|
||||
return;
|
||||
|
||||
DistributionNeedsUpdate = false;
|
||||
|
||||
size_t N = Inputs.size();
|
||||
assert(N);
|
||||
Intervals.resize(N + 1);
|
||||
Weights.resize(N);
|
||||
std::iota(Intervals.begin(), Intervals.end(), 0);
|
||||
|
||||
std::chrono::microseconds AverageUnitExecutionTime(0);
|
||||
for (auto II : Inputs) {
|
||||
AverageUnitExecutionTime += II->TimeOfUnit;
|
||||
}
|
||||
AverageUnitExecutionTime /= N;
|
||||
|
||||
bool VanillaSchedule = true;
|
||||
if (Entropic.Enabled) {
|
||||
for (auto II : Inputs) {
|
||||
if (II->NeedsEnergyUpdate && II->Energy != 0.0) {
|
||||
II->NeedsEnergyUpdate = false;
|
||||
II->UpdateEnergy(RareFeatures.size(), Entropic.ScalePerExecTime,
|
||||
AverageUnitExecutionTime);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
|
||||
if (Inputs[i]->NumFeatures == 0) {
|
||||
// If the seed doesn't represent any features, assign zero energy.
|
||||
Weights[i] = 0.;
|
||||
} else if (Inputs[i]->NumExecutedMutations / kMaxMutationFactor >
|
||||
NumExecutedMutations / Inputs.size()) {
|
||||
// If the seed was fuzzed a lot more than average, assign zero energy.
|
||||
Weights[i] = 0.;
|
||||
} else {
|
||||
// Otherwise, simply assign the computed energy.
|
||||
Weights[i] = Inputs[i]->Energy;
|
||||
}
|
||||
|
||||
// If energy for all seeds is zero, fall back to vanilla schedule.
|
||||
if (Weights[i] > 0.0)
|
||||
VanillaSchedule = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (VanillaSchedule) {
|
||||
for (size_t i = 0; i < N; i++)
|
||||
Weights[i] = Inputs[i]->NumFeatures
|
||||
? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 : 1)
|
||||
: 0.;
|
||||
}
|
||||
|
||||
if (FeatureDebug) {
|
||||
for (size_t i = 0; i < N; i++)
|
||||
Printf("%zd ", Inputs[i]->NumFeatures);
|
||||
Printf("SCORE\n");
|
||||
for (size_t i = 0; i < N; i++)
|
||||
Printf("%f ", Weights[i]);
|
||||
Printf("Weights\n");
|
||||
}
|
||||
CorpusDistribution = std::piecewise_constant_distribution<double>(
|
||||
Intervals.begin(), Intervals.end(), Weights.begin());
|
||||
}
|
||||
std::piecewise_constant_distribution<double> CorpusDistribution;
|
||||
|
||||
Vector<double> Intervals;
|
||||
Vector<double> Weights;
|
||||
|
||||
std::unordered_set<std::string> Hashes;
|
||||
Vector<InputInfo*> Inputs;
|
||||
|
||||
size_t NumAddedFeatures = 0;
|
||||
size_t NumUpdatedFeatures = 0;
|
||||
uint32_t InputSizesPerFeature[kFeatureSetSize];
|
||||
uint32_t SmallestElementPerFeature[kFeatureSetSize];
|
||||
|
||||
bool DistributionNeedsUpdate = true;
|
||||
uint16_t FreqOfMostAbundantRareFeature = 0;
|
||||
uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {};
|
||||
Vector<uint32_t> RareFeatures;
|
||||
|
||||
std::string OutputCorpus;
|
||||
};
|
||||
|
||||
} // namespace fuzzer
|
||||
|
||||
#endif // LLVM_FUZZER_CORPUS
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user