├── .clang-format ├── .custom-format.py ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── examples ├── .gitignore ├── Makefile ├── README.md ├── Runtime.c ├── afl-compiler-rt.o.c ├── forking-fuzzer.c ├── libaflfuzzer-harness-libpng.c ├── libaflfuzzer-harness-test.c ├── libaflfuzzer.c ├── llmp-main.c ├── prune_shm.sh └── target.c ├── include ├── afl-returns.h ├── aflpp.h ├── alloc-inl.h ├── android-ashmem.h ├── cmplog.h ├── common.h ├── config.h ├── debug.h ├── engine.h ├── feedback.h ├── fuzzone.h ├── input.h ├── llmp.h ├── mutator.h ├── observer.h ├── os.h ├── queue.h ├── rand.h ├── shmem.h ├── snapshot-inl.h ├── stage.h ├── types.h ├── xxh3.h └── xxhash.h ├── src ├── aflpp.c ├── common.c ├── engine.c ├── feedback.c ├── fuzzone.c ├── input.c ├── llmp.c ├── mutator.c ├── observer.c ├── os.c ├── queue.c ├── shmem.c └── stage.c ├── styleGuide.md └── test ├── Makefile ├── unit_llmp.c └── unit_test.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: true 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: true 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: false 15 | AllowShortIfStatementsOnASingleLine: true 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: Yes 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Attach 41 | BreakBeforeInheritanceComma: false 42 | BreakInheritanceList: BeforeColon 43 | BreakBeforeTernaryOperators: true 44 | BreakConstructorInitializersBeforeComma: false 45 | BreakConstructorInitializers: BeforeColon 46 | BreakAfterJavaFieldAnnotations: false 47 | BreakStringLiterals: true 48 | ColumnLimit: 120 49 | CommentPragmas: '^ IWYU pragma:' 50 | CompactNamespaces: false 51 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 52 | ConstructorInitializerIndentWidth: 4 53 | ContinuationIndentWidth: 4 54 | Cpp11BracedListStyle: true 55 | DerivePointerAlignment: false 56 | DisableFormat: false 57 | ExperimentalAutoDetectBinPacking: false 58 | FixNamespaceComments: true 59 | ForEachMacros: 60 | - foreach 61 | - Q_FOREACH 62 | - BOOST_FOREACH 63 | IncludeBlocks: Preserve 64 | IncludeCategories: 65 | - Regex: '^' 66 | Priority: 2 67 | - Regex: '^<.*\.h>' 68 | Priority: 1 69 | - Regex: '^<.*' 70 | Priority: 2 71 | - Regex: '.*' 72 | Priority: 3 73 | IncludeIsMainRegex: '([-_](test|unittest))?$' 74 | IndentCaseLabels: true 75 | IndentPPDirectives: BeforeHash 76 | IndentWidth: 2 77 | IndentWrappedFunctionNames: false 78 | JavaScriptQuotes: Leave 79 | JavaScriptWrapImports: true 80 | KeepEmptyLinesAtTheStartOfBlocks: false 81 | MacroBlockBegin: '' 82 | MacroBlockEnd: '' 83 | MaxEmptyLinesToKeep: 1 84 | NamespaceIndentation: None 85 | ObjCBinPackProtocolList: Never 86 | ObjCBlockIndentWidth: 2 87 | ObjCSpaceAfterProperty: false 88 | ObjCSpaceBeforeProtocolList: true 89 | PenaltyBreakAssignment: 2 90 | PenaltyBreakBeforeFirstCallParameter: 1 91 | PenaltyBreakComment: 300 92 | PenaltyBreakFirstLessLess: 120 93 | PenaltyBreakString: 1000 94 | PenaltyBreakTemplateDeclaration: 10 95 | PenaltyExcessCharacter: 1000000 96 | PenaltyReturnTypeOnItsOwnLine: 200 97 | PointerAlignment: Right 98 | RawStringFormats: 99 | - Language: Cpp 100 | Delimiters: 101 | - cc 102 | - CC 103 | - cpp 104 | - Cpp 105 | - CPP 106 | - 'c++' 107 | - 'C++' 108 | CanonicalDelimiter: '' 109 | BasedOnStyle: google 110 | - Language: TextProto 111 | Delimiters: 112 | - pb 113 | - PB 114 | - proto 115 | - PROTO 116 | EnclosingFunctions: 117 | - EqualsProto 118 | - EquivToProto 119 | - PARSE_PARTIAL_TEXT_PROTO 120 | - PARSE_TEST_PROTO 121 | - PARSE_TEXT_PROTO 122 | - ParseTextOrDie 123 | - ParseTextProtoOrDie 124 | CanonicalDelimiter: '' 125 | BasedOnStyle: google 126 | ReflowComments: true 127 | SortIncludes: false 128 | SortUsingDeclarations: true 129 | SpaceAfterCStyleCast: false 130 | SpaceAfterTemplateKeyword: true 131 | SpaceBeforeAssignmentOperators: true 132 | SpaceBeforeCpp11BracedList: false 133 | SpaceBeforeCtorInitializerColon: true 134 | SpaceBeforeInheritanceColon: true 135 | SpaceBeforeParens: ControlStatements 136 | SpaceBeforeRangeBasedForLoopColon: true 137 | SpaceInEmptyParentheses: false 138 | SpacesBeforeTrailingComments: 2 139 | SpacesInAngles: false 140 | SpacesInContainerLiterals: true 141 | SpacesInCStyleCastParentheses: false 142 | SpacesInParentheses: false 143 | SpacesInSquareBrackets: false 144 | Standard: Auto 145 | TabWidth: 8 146 | UseTab: Never 147 | ... 148 | 149 | -------------------------------------------------------------------------------- /.custom-format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # american fuzzy lop++ - custom code formatter 4 | # -------------------------------------------- 5 | # 6 | # Written and maintaned by Andrea Fioraldi 7 | # 8 | # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. 9 | # Copyright 2019-2020 AFLplusplus Project. All rights reserved. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at: 14 | # 15 | # http://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | 18 | import subprocess 19 | import sys 20 | import os 21 | import re 22 | 23 | # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use 24 | 25 | with open(".clang-format") as f: 26 | fmt = f.read() 27 | 28 | CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN") 29 | if CLANG_FORMAT_BIN is None: 30 | o = 0 31 | try: 32 | p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE) 33 | o, _ = p.communicate() 34 | o = str(o, "utf-8") 35 | o = re.sub(r".*ersion ", "", o) 36 | #o = o[len("clang-format version "):].strip() 37 | o = o[:o.find(".")] 38 | o = int(o) 39 | except: 40 | print ("clang-format-10 is needed. Aborted.") 41 | exit(1) 42 | #if o < 7: 43 | # if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0: 44 | # CLANG_FORMAT_BIN = 'clang-format-7' 45 | # elif subprocess.call(['which', 'clang-format-8'], stdout=subprocess.PIPE) == 0: 46 | # CLANG_FORMAT_BIN = 'clang-format-8' 47 | # elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0: 48 | # CLANG_FORMAT_BIN = 'clang-format-9' 49 | # elif subprocess.call(['which', 'clang-format-10'], stdout=subprocess.PIPE) == 0: 50 | # CLANG_FORMAT_BIN = 'clang-format-10' 51 | # else: 52 | # print ("clang-format 7 or above is needed. Aborted.") 53 | # exit(1) 54 | else: 55 | CLANG_FORMAT_BIN = 'clang-format-10' 56 | 57 | COLUMN_LIMIT = 80 58 | for line in fmt.split("\n"): 59 | line = line.split(":") 60 | if line[0].strip() == "ColumnLimit": 61 | COLUMN_LIMIT = int(line[1].strip()) 62 | 63 | 64 | def custom_format(filename): 65 | p = subprocess.Popen([CLANG_FORMAT_BIN, filename], stdout=subprocess.PIPE) 66 | src, _ = p.communicate() 67 | src = str(src, "utf-8") 68 | 69 | in_define = False 70 | last_line = None 71 | out = "" 72 | 73 | for line in src.split("\n"): 74 | if line.lstrip().startswith("#"): 75 | if line[line.find("#")+1:].lstrip().startswith("define"): 76 | in_define = True 77 | 78 | if "/*" in line and not line.strip().startswith("/*") and line.endswith("*/") and len(line) < (COLUMN_LIMIT-2): 79 | cmt_start = line.rfind("/*") 80 | line = line[:cmt_start] + " " * (COLUMN_LIMIT-2 - len(line)) + line[cmt_start:] 81 | 82 | define_padding = 0 83 | if last_line is not None and in_define and last_line.endswith("\\"): 84 | last_line = last_line[:-1] 85 | define_padding = max(0, len(last_line[last_line.rfind("\n")+1:])) 86 | 87 | if last_line is not None and last_line.strip().endswith("{") and line.strip() != "": 88 | line = (" " * define_padding + "\\" if in_define else "") + "\n" + line 89 | elif last_line is not None and last_line.strip().startswith("}") and line.strip() != "": 90 | line = (" " * define_padding + "\\" if in_define else "") + "\n" + line 91 | elif line.strip().startswith("}") and last_line is not None and last_line.strip() != "": 92 | line = (" " * define_padding + "\\" if in_define else "") + "\n" + line 93 | 94 | if not line.endswith("\\"): 95 | in_define = False 96 | 97 | out += line + "\n" 98 | last_line = line 99 | 100 | return (out) 101 | 102 | args = sys.argv[1:] 103 | if len(args) == 0: 104 | print ("Usage: ./format.py [-i] ") 105 | print () 106 | print (" The -i option, if specified, let the script to modify in-place") 107 | print (" the source files. By default the results are written to stdout.") 108 | print() 109 | exit(1) 110 | 111 | in_place = False 112 | if args[0] == "-i": 113 | in_place = True 114 | args = args[1:] 115 | 116 | for filename in args: 117 | code = custom_format(filename) 118 | if in_place: 119 | with open(filename, "w") as f: 120 | f.write(code) 121 | else: 122 | print(code) 123 | 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | *.dSym 29 | 30 | # Executables 31 | *.exe 32 | *.out 33 | *.app 34 | 35 | # IDE Stuff 36 | .vscode 37 | 38 | executor 39 | target 40 | 41 | examples/out-* 42 | 43 | examples/success 44 | llmp-main 45 | in-mem 46 | testcase 47 | test/unit_llmp 48 | test/unit_test 49 | 50 | testcases 51 | 52 | example-fuzzer 53 | examples/in-memory-fuzzer 54 | examples/forking-fuzzer 55 | examples/libaflfuzzer-libpng 56 | llvm.prof 57 | in 58 | out 59 | libaflfuzzer-test 60 | 61 | crash* 62 | timeout* 63 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "AFLplusplus"] 2 | path = AFLplusplus 3 | url = https://github.com/AFLplusplus/AFLplusplus.git 4 | [submodule "examples/AFLplusplus"] 5 | path = examples/AFLplusplus 6 | url = https://github.com/AFLplusplus/AFLplusplus.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGETS=libafl.so libafl.a libaflfuzzer.a examples/libaflfuzzer-test 2 | override CFLAGS += -g -fPIC -Iinclude -Wall -Wextra -Werror -Wshadow -fstack-protector-strong 3 | 4 | ifdef DEBUG 5 | AFL_DEBUG=1 # always enable logs for now 6 | override CFLAGS += -DDEBUG -ggdb -O0 -DAFL_DEBUG=1 7 | endif 8 | ifndef DEBUG 9 | override CFLAGS += -D_FORTIFY_SOURCE=2 -O3 10 | endif 11 | ifdef ASAN 12 | override CFLAGS += -fsanitize=address -fno-omit-frame-pointer 13 | override LDFLAGS += -fsanitize=address 14 | endif 15 | ifdef UBSAN 16 | override CFLAGS += -fsanitize=undefined -fno-omit-frame-pointer 17 | override LDFLAGS += -fsanitize=undefined 18 | endif 19 | ifdef MSAN 20 | CC := clang 21 | override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer 22 | override LDFLAGS += -fsanitize=memory 23 | endif 24 | 25 | all: $(TARGETS) examples 26 | 27 | clean: 28 | rm -f src/*.o examples/*.o 29 | rm -f $(TARGETS) example-fuzzer 30 | $(MAKE) -C examples clean 31 | 32 | deepclean: clean 33 | $(MAKE) -C examples deepclean 34 | 35 | # Compiling the common file 36 | src/common.o: src/common.c include/common.h 37 | $(CC) $(CFLAGS) src/common.c -c -o src/common.o 38 | 39 | # Compiling the input file 40 | src/input.o: src/input.c include/input.h include/common.h 41 | $(CC) $(CFLAGS) src/input.c -c -o src/input.o 42 | 43 | # Compiling the observation channel file 44 | src/observer.o: src/observer.c include/observer.h include/common.h 45 | $(CC) $(CFLAGS) src/observer.c -c -o src/observer.o 46 | 47 | # Compiling the queue file 48 | src/queue.o: src/queue.c include/queue.h src/input.o src/common.o 49 | $(CC) $(CFLAGS) src/queue.c -c -o src/queue.o 50 | 51 | # Compiling the mutator file 52 | src/mutator.o: src/mutator.c include/mutator.h src/common.o src/input.o 53 | $(CC) $(CFLAGS) src/mutator.c -c -o src/mutator.o 54 | 55 | # Compiling the feedback library 56 | src/feedback.o: src/feedback.c include/feedback.h src/common.o src/queue.o 57 | $(CC) $(CFLAGS) src/feedback.c -c -o src/feedback.o 58 | 59 | # Compiling the fuzzone library 60 | src/fuzzone.o: src/fuzzone.c include/fuzzone.h src/common.o 61 | $(CC) $(CFLAGS) src/fuzzone.c -c -o src/fuzzone.o 62 | 63 | src/shmem.o: src/shmem.c include/shmem.h 64 | $(CC) $(CFLAGS) src/shmem.c -c -o src/shmem.o 65 | 66 | # Compiling the Stage library 67 | src/stage.o: src/stage.c include/stage.h src/input.o 68 | $(CC) $(CFLAGS) src/stage.c -c -o src/stage.o 69 | 70 | # Compiling the engine library 71 | src/engine.o: src/engine.c include/engine.h src/feedback.o src/queue.o src/common.o include/aflpp.h 72 | $(CC) $(CFLAGS) src/engine.c -c -o src/engine.o 73 | 74 | # Compiling the OS helper for the library 75 | src/os.o: src/os.c include/os.h src/common.o src/input.o 76 | $(CC) $(CFLAGS) -Wno-error src/os.c -c -o src/os.o 77 | 78 | # Compiling the OS helper for the library 79 | src/llmp.o: src/llmp.c include/llmp.h 80 | $(CC) $(CFLAGS) src/llmp.c -c -o src/llmp.o 81 | 82 | # Compiling the final library 83 | src/afl.o: src/aflpp.c include/aflpp.h src/observer.o src/input.observation 84 | $(CC) $(CFLAGS) src/aflpp.c -c -o src/aflpp.o 85 | 86 | libafl.so: src/llmp.o src/aflpp.o src/engine.o src/stage.o src/fuzzone.o src/feedback.o src/mutator.o src/queue.o src/observer.o src/input.o src/common.o src/os.o src/shmem.o 87 | $(CC) $(CFLAGS) $(LDFLAGS) -shared $^ -o libafl.so 88 | 89 | libafl.a: src/llmp.o src/aflpp.o src/engine.o src/stage.o src/fuzzone.o src/feedback.o src/mutator.o src/queue.o src/observer.o src/input.o src/common.o src/os.o src/shmem.o 90 | @rm -f libafl.a 91 | ar -crs libafl.a $^ 92 | 93 | examples/afl-compiler-rt.o: examples/afl-compiler-rt.o.c 94 | clang -O3 -Iinclude -c -o examples/afl-compiler-rt.o examples/afl-compiler-rt.o.c 95 | 96 | libaflfuzzer.a: libafl.a examples/afl-compiler-rt.o examples/libaflfuzzer.c 97 | @rm -f libaflfuzzer.a 98 | clang $(CFLAGS) $(LDFLAGS) -c -o examples/libaflfuzzer.o examples/libaflfuzzer.c 99 | ar -crs libaflfuzzer.a src/*.o examples/afl-compiler-rt.o examples/libaflfuzzer.o 100 | 101 | examples/libaflfuzzer-test: libaflfuzzer.a examples/libaflfuzzer-harness-test.c 102 | clang -Iinclude -fsanitize-coverage=trace-pc-guard -o examples/libaflfuzzer-test examples/libaflfuzzer-harness-test.c libaflfuzzer.a -pthread -lrt $(CFLAGS) $(LDFLAGS) 103 | 104 | .PHONY: examples 105 | examples: 106 | $(MAKE) -C examples "CFLAGS=$(CFLAGS)" "LDFLAGS=$(LDFLAGS)" 107 | 108 | code-format: 109 | ./.custom-format.py -i src/*.c 110 | ./.custom-format.py -i include/*.h 111 | ./.custom-format.py -i examples/*.c 112 | ./.custom-format.py -i test/*.c 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibAFL 2 | 3 | **This repository is for the C version of LibAFL. It is superseeded by [LibAFL in Rust](https://github.com/AFLplusplus/LibAFL)!** 4 | 5 | LibAFL is a fuzzing library/framework developed for building efficient fuzzers. 6 | 7 | _Disaclaimer: LibAFL is still very WIP, likely the API will change a lot, do not use it now. However, feel free to contribute also with ideas or requests opening an issue._ 8 | 9 | LibAFL was initially developed as GSOC project by [rishi9101](https://github.com/rish9101) 10 | GSOC mentors: 11 | * [hexcoder](https://github.com/hexcoder-) 12 | * [domenukk](https://github.com/domenukk) 13 | 14 | ## Content 15 | 1. Introduction 16 | 2. Elements of Fuzzing 17 | 3. Features 18 | 4. Getting Started with LibAFL 19 | 20 | ## Introduction 21 | 22 | LibAFL is a framework to build fuzzers, with support for mutithreading. The main concept behind LibAFL is not to build the "best" fuzzer, but to give you the tools to craft the best fuzzer for your specific target with ease. 23 | 24 | We write this in C so you don't have to: eventually bindings for sane languages like rust will be added. 25 | 26 | LibAFL contains all the pieces to build fuzzers, think "LLVM of fuzzers". 27 | 28 | ## Elements of Fuzzing 29 | 30 | LibAFL defines the pieces of fuzzer as follows (based on work by [andreafioraldi](https://github.com/andreafioraldi)): 31 | 1. *Executor* - Structure to run the target and collecct observation (code coverage, exec time, ...). One example in `./examples` uses the AFL++ forkserver, the other one an in-mem-executor. 32 | 2. *Observation Channel* - Observation channel gives information about the last run of a target, depending on the context, e.g code-coverage metric and execution time. 33 | 3. *Feedback* - Feedback is the structure which infers valuable information from the run result stored in the observation channel. It scores the input being fuzzed based on the observation channels, and adds new entries to the queue, if necessary. 34 | 4. *Queue* - LibAFL supports two major types of queues. 35 | - *Feedback queue* - This type of queue is feedback specific i.e it is filled by entries which performed well based on a given feedback metric (say code-coverage). It also has a scheduling policy for itself which it can use to get next entries. 36 | - *Global queue* - This is the global queue for the fuzzer instance, it holds all the feedback queues, schedules one of the feedback queues for the next run. Also it has it's own queue which can also hold entries. 37 | 38 | 5. *Fuzz one* - This executes the actual fuzzing - it holds all stages of the fuzz instance (see below), handles the crashes/timeouts of the target, etc. 39 | 40 | 6. *Stage* - There can be many fuzzing stages in a fuzzer (e.g AFL has three stages, deterministic, havoc and splicing) and each stage can have it's own mutators. Thus a fuzzer can have multiple stages depending on if it's finding new finds in the current stage (or for how long the stage has been running). 41 | 42 | 7. *Mutators* - Mutators have been defined to be as generic as possible with function pointers which can cover almost all mutators, (and if they don't, you can always extend them :) ). There are functions for mutating, trimming, post-process of the data which are called at appropriate places by the lib. Also, mutators also can define functions which decide if fuzzing a queue entry is beneficial or not. These mutator structures are largely inspired by AFL++'s custom mutator API. 43 | 44 | 8. *Engine* - Finally, the engine is the central cog of the fuzzer. It binds all the other pieces(like executor, feedbacks, fuzzone) together. Every engine is also associated with a global queue, whose entries can be shared with other engine instances. 45 | 46 | ## Features 47 | 48 | As a fuzzing library, LibAFL packs with it large number of features which are very handy for fuzzing. 49 | 50 | 1. Multithreaded by nature - Imagine that you built 2 fuzzers but want to share their results,You can define these 2 fuzzers, run the first one in a thread and run, e.g., 3 instances of the second running on 3 threads. They may even share results between process boundaries with very low overhead. 51 | There are several multithreaded fuzzers, most notably honggfuzz, but LibAFL goes even further with different configurations running in different threads and processes, not simply mutlithreading the same fuzzer. This means we are able to fuzz the same target in multiple contexts at the same time with great efficiency! 52 | 53 | 2. Modular and pluggable - LibAFL is based on multiple "parts" that we think, consitutes a fuzzer. Did you ever write a fuzzer and want to use it's target executor? Just plug in the executor into the new fuzzer with LibAFL. 54 | 55 | ## Getting Started with LibAFL 56 | 57 | We have an example fuzzer ready at `examples/executor.c` so we can follow that. 58 | To try it out immediately: 59 | ```bash 60 | cd ./examples 61 | make test 62 | ``` 63 | Other examples are listed in [./examples/README.md](./examples/README.md). 64 | 65 | If you want to build your own fuzzer, this is how to do it: 66 | 67 | All the "Elements" (described above) in LibAFL can be extended by the user to suit their needs. to extend a strucuture, just include it in your custom struct as the first member 68 | 69 | ```C 70 | struct custom_executor { 71 | afl_executor_t base; // We include the base executor as the first member 72 | int some_extra_stuff; 73 | void * some_other_stuff; 74 | } 75 | ``` 76 | 77 | Each of this structure also has a set of function pointers assigned to them (sort of like a `vtable`) 78 | e.g 79 | 80 | ```C 81 | struct afl_executor_funcs { 82 | int (*run_target_cb)( 83 | afl_executor_t *); // The first argument of each function pointer is the executor itself. 84 | int (*place_input_cb)( 85 | afl_executor_t *, 86 | afl_raw_input_t *); 87 | } 88 | ``` 89 | So, in order to override them, you just have to take assign that function pointer to your own implementation :) (Thus, these can be easily extended) e.g 90 | 91 | ```C 92 | 93 | int custom_run_target(afl_executor_t * executor) { 94 | /* Some Custom stuff, like a forkserver for AFL */ 95 | } 96 | 97 | executor->funcs.run_target_cb = custom_run_target; 98 | // We override the basic definition for run_target 99 | ``` 100 | 101 | It is not recommended to change the function signatures for these methods, as many of these function pointers are called by the library internally during fuzzing. So, if you do need some extra information for any function, it's always better to put it in an extended struct :) 102 | 103 | The basic workflow for writing a fuzzer with LibAFL is as follows: 104 | 105 | 1. Let's decide on the input structure now. Now, this is not necessary, if raw_bytes and a length are all we need, no problem. But if your target takes a structured input (like a PNG, PDF etc), you can extend the `afl_raw_input_t` structure to include those 106 | 107 | 2. Build a simple executor, which runs the target, places the input for the target to read. A very simple example would be an executor which `forks` and `executes` the target as a child process, also placing the input correctly (in say, stdin or a file) for target to read. AFL's forkserver is another example of an executor. 108 | 109 | ```C 110 | // Let's build an executor. 111 | executor_t example_executor = afl_executor_new(); // This function allocates memory for a "base" executor AND initializes it. 112 | 113 | u8 place_input( afl_executor_t * executor, afl_raw_input_t * input ) { 114 | // We write to a file simply, this is totally user dependent 115 | int fd = open("some_file"); 116 | write(fd, input->bytes, input->len); 117 | } 118 | exit_type_t run_target_cb(afl_executor_t *executor) { 119 | pid_t child = fork(); 120 | 121 | if (!child) { 122 | exec("target"); // We execute the target 123 | } 124 | 125 | return 0; 126 | 127 | }; 128 | 129 | executor_t example_executor = afl_executor_new(); 130 | example_executor->funcs.place_input_cb = place_input 131 | example_executor->funcs.run_target_cb = run_target; 132 | 133 | ``` 134 | 135 | 3. If you're writing a greybox fuzzer, you probably want an observation channel which gains "insights" from the target's execution. An example would be the map based channel, which records the coverage (a simple map based channel is included in the library). Another observation channel could be the execution time of the target. 136 | 137 | ```C 138 | // Let's extend the base observation channel struct to make a timeout channel 139 | 140 | struct timeout_channel { 141 | afl_observer_t base; 142 | u64 last_run_time; 143 | u64 avg_exec_time; 144 | } 145 | 146 | // It is assumed that the observation channel is updated by the target itself (in case of coverage recording) or by the executor after running the target. 147 | 148 | // Since we extended the structure, We allocate memory for the structure ourselves; 149 | 150 | struct timeout_channel tmout_channel = malloc(sizeof(struct timeout_channel)); 151 | 152 | // Every structure, apart from the create function, has an init function too, which initializes the structure. You do have to initialize the rest of your extended structure yourself though. 153 | afl_observer_init(&tmout_channel->base, size_t unique_tag); 154 | 155 | // Let's add it to the executor now, it gets added to an array of channels 156 | executor->funcs.add_observer(executor, &tmout_base); 157 | 158 | ``` 159 | 160 | 4. You probably want to build a simple feedback for the observation channel, which reduces the observation channels input to a float (0.0 to 1.0) to decide the "score" of input in the context of that observation channel (e.g more code coverage, greater execution time means higher score). This feedback also decides if an input should be put in a feedback specific queue, global queue or both. 161 | 162 | ```C 163 | feedback_t * example feedback = afl_feedback_new(NULL, timeout_channel_id); // We can add the feedback queue instead of NULL here, but we'll add them later. 164 | 165 | float is_interesting(afl_feedback_t * feedback, afl_executor_t * executor) { 166 | 167 | afl_observer_t * obs_channel = feedback->channel; 168 | // Every feedback "should" store the correct idx of the observation channel in the array. 169 | 170 | //We can use the channel's unique tag to identify them. See example/executor.c for this. 171 | 172 | // Again completely user dependent 173 | if (first_condition) { 174 | return 0.0 175 | } else if (second_condition) { 176 | 177 | feedback->queue->funcs.add_to_queue(feedback->queue, executor->current_input) 178 | return 1.0; 179 | } 180 | 181 | return 0.5; 182 | } 183 | 184 | ``` 185 | 186 | 5. Now we create the queues for the fuzzer. If we have any feedback, and we want any feedback specific fuzzing, we can create a feedback queue and add it to the global queue. 187 | **But we need a global queue always.** 188 | 189 | In case of queues, we don't expect the user to extend or do much to the queue structure itself, but the scheduling, culling etc are totally on user's choice 190 | 191 | ```C 192 | // Let's create a global queue, one for each fuzzing "instance" we have. 193 | afl_queue_global_t *global_queue = afl_queue_global_new(NULL); // NULL is for the engine, if present pass a ptr to it. 194 | 195 | // Let's create a feedback queue, for the feedback we create above. 196 | afl_queue_feedback_t * feedback_queue = afl_queue_feedback_new(feedback, "Timeout feedback queue"); 197 | 198 | // Let's add it to the global queue 199 | global_queue->funcs.add_feedback_queue(feedback_queue); // Notice how we actually use funcs instead of funcs, this is because global_queue is extended from base_queue and required a few extra function pointers, thus this. 200 | 201 | ``` 202 | It's totally upto the user to redefine the queue's scheduling algorithms (both global and feedback queue's) according to their needs 203 | 204 | 205 | 206 | 6. Let's get a few mutators running now. Each mutator is part of a fuzzing stage (like AFL has three stages, deterministic, havoc and spilcing). So, every stage has it's own mutator. 207 | ```C 208 | afl_mutator_t * mutator = afl_mutator_new(NULL); 209 | // We'll add it to the stage later. 210 | 211 | void mutate(afl_mutator_t * mutator, afl_raw_input_t * input) { 212 | 213 | // Some mutation operator, bit-flip, byte flip etc. 214 | 215 | // We actually make a copy of the original input before sending it to mutate, so no need to worry about chaning the given input 216 | } 217 | 218 | void trim(afl_mutator_t * mutator, afl_raw_input_t * input) { 219 | // Trimming function for the mutator 220 | } 221 | 222 | mutator->funcs.mutate= mutate; 223 | mutator->funcs.trim = trim; 224 | 225 | fuzzing_stage_t * stage = afl_fuzzing_stage(NULL); 226 | // This is a fuzzing stage(mutations and stuff) so we use fuzzing_stage structure, there can be stages without mutation and mutators. 227 | 228 | stage->funcs.add_mutator_to_stage(stage, mutator); 229 | // We add the mutator 230 | ``` 231 | 232 | 7. Let's create a few cogs for the fuzzer, like engine and the fuzz_one. Engine is the central part of the fuzzer which holds everything else together. 233 | 234 | ```C 235 | afl_fuzz_one_t * fuzz_one = afl_fuzz_one_new(NULL); 236 | // Let's add the stage to the fuzzone 237 | 238 | fuzz_one->funcs.add_stage(fuzz_one, stage); 239 | 240 | afl_engine_t * engine = afl_engine_new(executor, fuzz_one, global_queue); 241 | 242 | ``` 243 | 244 | 8. We're done here. Now, we can just run the fuzzer :) 245 | 246 | ```C 247 | engine->funcs.load_testcases_from_dir(engine, dirpath); // Load the initial corpus 248 | 249 | engine->funcs.loop() // Fuzzing starts :) 250 | 251 | ``` 252 | 253 | Enjoy! 254 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | libpng-* 2 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | MAKEFILE_PATH := $(abspath .) 2 | LIBAFL_PATH := $(MAKEFILE_PATH)/.. 3 | CFLAGS += -g -Wall -Wextra -Wshadow -fstack-protector-strong 4 | override CFLAGS += -I../include 5 | override LDFLAGS += ../libafl.a -lpthread -lrt 6 | LIBPNG_URL = http://prdownloads.sourceforge.net/libpng/libpng-1.6.37.tar.gz?download 7 | 8 | ifdef DEBUG 9 | AFL_DEBUG=1 10 | override CFLAGS += -DDEBUG -ggdb -O0 -DAFL_DEBUG=1 11 | endif 12 | ifndef DEBUG 13 | override CFLAGS += -D_FORTIFY_SOURCE=2 -O3 14 | endif 15 | ifdef ASAN 16 | override CFLAGS += -fsanitize=address -fno-omit-frame-pointer 17 | override LDFLAGS += -fsanitize=address 18 | endif 19 | ifdef UBSAN 20 | override CFLAGS += -fsanitize=undefined -fno-omit-frame-pointer -lpthread 21 | override LDFLAGS += -fsanitize=undefined -lpthread 22 | endif 23 | ifdef MSAN 24 | CC := clang 25 | override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer 26 | override LDFLAGS += -fsanitize=memory 27 | endif 28 | 29 | all: target forking-fuzzer libaflfuzzer-libpng llmp-main 30 | 31 | afl-compiler-rt.o: afl-compiler-rt.o.c 32 | clang -O3 -I../include -c -o afl-compiler-rt.o afl-compiler-rt.o.c 33 | 34 | .PHONY: ../libafl.a 35 | ../libafl.a: 36 | $(MAKE) -C $(LIBAFL_PATH) "CFLAGS=$(CFLAGS)" "LDFLAGS=$(LDFLAGS)" "ASAN=$(ASAN)" "DEBUG=$(DEBUG)" libafl.a 37 | 38 | libpng-1.6.37.tar.gz: 39 | wget -c $(LIBPNG_URL) -O libpng-1.6.37.tar.gz 40 | 41 | libpng16.a: libpng-1.6.37.tar.gz 42 | tar -xvzf ./libpng-1.6.37.tar.gz || rm -f ./libpng-1.6.37.tar.gz 43 | cd libpng-1.6.37 && \ 44 | ./configure --disable-shared && \ 45 | $(MAKE) CC=clang CXX=clang++ CFLAGS="-D_DEFAULT_SOURCE -fsanitize-coverage=trace-pc-guard" CXXFLAGS="-D_DEFAULT_SOURCE -fsanitize-coverage=trace-pc-guard" LDFLAGS= 46 | cp libpng-1.6.37/.libs/libpng16.a ./ 47 | 48 | target: afl-compiler-rt.o target.c 49 | clang -fsanitize-coverage=trace-pc-guard -g target.c -o target 50 | 51 | forking-fuzzer: forking-fuzzer.c ../libafl.a 52 | $(CC) $(CFLAGS) forking-fuzzer.c -o forking-fuzzer $(LDFLAGS) 53 | 54 | llmp-main: llmp-main.c ../libafl.a 55 | $(CC) $(CFLAGS) llmp-main.c -o llmp-main $(LDFLAGS) 56 | 57 | libaflfuzzer-libpng: libpng16.a libaflfuzzer-harness-libpng.c ../libaflfuzzer.a 58 | clang -g -fsanitize-coverage=trace-pc-guard -Ilibpng-1.6.37 -o libaflfuzzer-libpng ../libaflfuzzer.a libaflfuzzer-harness-libpng.c ./libpng16.a -pthread -lrt -lz -lm $(LDFLAGS) 59 | 60 | test: clean forking-fuzzer target 61 | mkdir ./in || true 62 | echo "AAAAAA" > ./in/a 63 | echo "BBBBBB" > ./in/b 64 | LD_LIBRARY_PATH=.. ./forking-fuzzer ./in 2 ./target 65 | rm -rf ./in 66 | rm -rf ./out-* 67 | rm -rf ./crashes-* 2>/dev/null || trues 68 | 69 | clean: 70 | rm -rf out forking-fuzzer target success libaflfuzzer-libpng llmp-main 2>/dev/null || true 71 | rm -rf in 2>/dev/null || true 72 | rm -rf crashes-* 2>/dev/null || true 73 | rm -rf llmp-main || true 74 | rm -rf out-* || true 75 | 76 | deepclean: clean 77 | rm -rf libpng-1.6.37 libpng16.a 2>/dev/null || true 78 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # LibAFL Examples 2 | 3 | This folder contains all examples we curated so far. 4 | 5 | # `forking-fuzzer.c` 6 | To run the main one, a multi-threaded AFL++ clone, run `make test`. This will get aflpp (for its compilers), compile `target.c`, build the lib, then build and run `executor.c`, the actual fuzzer. 7 | 8 | # `in-memory-fuzzer.c` 9 | The build tis example, run make the lib (`make -C ..`) then `make-in-mem-fuzzer`. Then, run `LD_LIBRARY_PATH=.. ./in-mem`. 10 | This will run the (commited, we are sorry) `libpng.a` with an in-memory executor. 11 | 12 | # `llmp-main` 13 | Not really a fuzzer, but merely a test for fast, lock-free multiprocessing. 14 | Using `make llmp-main`, you can build a multiprocess example. Afterwards, you can run one broker with `LD_LIBRARY_PATH=.. ./llmp-main main [threadnum]` and spawn additinal out-of-process workers using `LD_LIBRARY_PATH=.. ./llmp-main worker`. -------------------------------------------------------------------------------- /examples/Runtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | 6 | #endif 7 | 8 | #define MAP_SIZE 65536 9 | 10 | extern uint8_t *__lafl_map; 11 | 12 | uint8_t __lafl_dummy_map[MAP_SIZE]; 13 | uint8_t *__lafl_map = __lafl_dummy_map; 14 | 15 | uint8_t *__lafl_edges_map = __lafl_dummy_map; 16 | uint8_t *__lafl_cmp_map = __lafl_dummy_map; 17 | 18 | uint32_t __lafl_max_edges_size = 0; 19 | 20 | void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { 21 | 22 | __lafl_edges_map[*guard]++; 23 | 24 | } 25 | 26 | void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { 27 | 28 | if (start == stop || *start) return; 29 | 30 | *(start++) = ++__lafl_max_edges_size; 31 | 32 | while (start < stop) { 33 | 34 | *start = ++__lafl_max_edges_size; 35 | start++; 36 | 37 | } 38 | 39 | } 40 | 41 | #define MAX(a, b) \ 42 | ({ \ 43 | \ 44 | __typeof__(a) _a = (a); \ 45 | __typeof__(b) _b = (b); \ 46 | _a > _b ? _a : _b; \ 47 | \ 48 | }) 49 | 50 | #if defined(__APPLE__) 51 | #pragma weak __sanitizer_cov_trace_const_cmp1 = __sanitizer_cov_trace_cmp1 52 | #pragma weak __sanitizer_cov_trace_const_cmp2 = __sanitizer_cov_trace_cmp2 53 | #pragma weak __sanitizer_cov_trace_const_cmp4 = __sanitizer_cov_trace_cmp4 54 | #pragma weak __sanitizer_cov_trace_const_cmp8 = __sanitizer_cov_trace_cmp8 55 | #else 56 | void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2) __attribute__((alias("__sanitizer_cov_trace_cmp1"))); 57 | void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2) 58 | __attribute__((alias("__sanitizer_cov_trace_cmp2"))); 59 | void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2) 60 | __attribute__((alias("__sanitizer_cov_trace_cmp4"))); 61 | void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) 62 | __attribute__((alias("__sanitizer_cov_trace_cmp8"))); 63 | #endif 64 | 65 | void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) { 66 | 67 | uintptr_t k = (uintptr_t)__builtin_return_address(0); 68 | k = (k >> 4) ^ (k << 8); 69 | k &= MAP_SIZE - 1; 70 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); 71 | 72 | } 73 | 74 | void __sanitizer_cov_trace_cmp2(uint16_t arg1, uint16_t arg2) { 75 | 76 | uintptr_t k = (uintptr_t)__builtin_return_address(0); 77 | k = (k >> 4) ^ (k << 8); 78 | k &= MAP_SIZE - 1; 79 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); 80 | 81 | } 82 | 83 | void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2) { 84 | 85 | uintptr_t k = (uintptr_t)__builtin_return_address(0); 86 | k = (k >> 4) ^ (k << 8); 87 | k &= MAP_SIZE - 1; 88 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); 89 | 90 | } 91 | 92 | void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2) { 93 | 94 | uintptr_t k = (uintptr_t)__builtin_return_address(0); 95 | k = (k >> 4) ^ (k << 8); 96 | k &= MAP_SIZE - 1; 97 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcountll(~(arg1 ^ arg2)))); 98 | 99 | } 100 | 101 | void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { 102 | 103 | uintptr_t rt = (uintptr_t)__builtin_return_address(0); 104 | if (cases[1] == 64) { 105 | 106 | for (uint64_t i = 0; i < cases[0]; i++) { 107 | 108 | uintptr_t k = rt + i; 109 | k = (k >> 4) ^ (k << 8); 110 | k &= MAP_SIZE - 1; 111 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcountll(~(val ^ cases[i + 2])))); 112 | 113 | } 114 | 115 | } else { 116 | 117 | for (uint64_t i = 0; i < cases[0]; i++) { 118 | 119 | uintptr_t k = rt + i; 120 | k = (k >> 4) ^ (k << 8); 121 | k &= MAP_SIZE - 1; 122 | __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(val ^ cases[i + 2])))); 123 | 124 | } 125 | 126 | } 127 | 128 | } 129 | 130 | #ifdef __cplusplus 131 | 132 | } 133 | 134 | #endif 135 | 136 | -------------------------------------------------------------------------------- /examples/libaflfuzzer-harness-libpng.c: -------------------------------------------------------------------------------- 1 | /* An in mmeory fuzzing example. Fuzzer for libpng library */ 2 | 3 | #include 4 | #include 5 | 6 | #include "png.h" 7 | 8 | /* The actual harness. Using PNG for our example. */ 9 | int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len) { 10 | 11 | png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 12 | 13 | png_set_user_limits(png_ptr, 65535, 65535); 14 | png_infop info_ptr = png_create_info_struct(png_ptr); 15 | png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); 16 | 17 | if (setjmp(png_jmpbuf(png_ptr))) return 0; 18 | 19 | png_set_progressive_read_fn(png_ptr, NULL, NULL, NULL, NULL); 20 | png_process_data(png_ptr, info_ptr, (uint8_t *)input, len); 21 | 22 | return 0; 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/libaflfuzzer-harness-test.c: -------------------------------------------------------------------------------- 1 | /* An in memeory fuzzing example. tests segfault, timeout and abort. */ 2 | 3 | #include 4 | #include 5 | #include "debug.h" 6 | 7 | static void force_segfault(void) { 8 | 9 | DBG("Crashing..."); 10 | /* If you don't segfault, what else will? */ 11 | printf("%d", ((int *)1337)[42]); 12 | 13 | } 14 | 15 | static void force_timeout(void) { 16 | 17 | DBG("Timeouting..."); 18 | static volatile int a = 1337; 19 | while (a) {} 20 | 21 | } 22 | 23 | /* The actual harness. Using PNG for our example. */ 24 | int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len) { 25 | 26 | if (len < 5) return 0; 27 | 28 | if (input[0] == 'a' && input[1] == 'a' && input[2] == 'a') { 29 | 30 | DBG("Crashing happy"); 31 | force_segfault(); 32 | 33 | } 34 | 35 | if (input[0] == 'b' && input[1] == 'b' && input[2] == 'b') { 36 | 37 | DBG("Timeouting happy"); 38 | force_timeout(); 39 | 40 | } 41 | 42 | if (input[0] == 'F') 43 | if (input[1] == 'A') 44 | if (input[2] == '$') 45 | if (input[3] == '$') 46 | if (input[4] == '$') abort(); 47 | 48 | return 0; 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /examples/llmp-main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Example main for llmp. 3 | */ 4 | 5 | #include 6 | 7 | #include "aflpp.h" 8 | #include "debug.h" 9 | #include "types.h" 10 | #include "llmp.h" 11 | #include "rand.h" 12 | 13 | /* Just a u32 in a msg, for testing purposes */ 14 | #define LLMP_TAG_RANDOM_U32_V1 (0x344D011) 15 | 16 | /* A client that randomly produces messages */ 17 | void llmp_clientloop_rand_u32(llmp_client_t *client, void *data) { 18 | 19 | (void)data; 20 | 21 | afl_rand_t rnd = {0}; 22 | 23 | AFL_TRY(afl_rand_init(&rnd), { FATAL("Error creating rnd! %s", afl_ret_stringify(err)); }); 24 | 25 | while (1) { 26 | 27 | llmp_message_t *msg = llmp_client_alloc_next(client, sizeof(u32)); 28 | msg->tag = LLMP_TAG_RANDOM_U32_V1; 29 | ((u32 *)msg->buf)[0] = afl_rand_below(&rnd, SIZE_MAX); 30 | 31 | OKF("%d Sending msg with id %d and payload %d.", client->id, msg->message_id, ((u32 *)msg->buf)[0]); 32 | 33 | llmp_client_send(client, msg); 34 | usleep(afl_rand_below(&rnd, 4000) * 1000); 35 | 36 | } 37 | 38 | } 39 | 40 | /* A client listening for new messages, then printing them */ 41 | void llmp_clientloop_print_u32(llmp_client_t *client_state, void *data) { 42 | 43 | (void)data; 44 | 45 | llmp_message_t *message; 46 | while (1) { 47 | 48 | MEM_BARRIER(); 49 | message = llmp_client_recv_blocking(client_state); 50 | 51 | if (message->tag == LLMP_TAG_RANDOM_U32_V1) { 52 | 53 | if (message->buf_len_padded < sizeof(u32)) { FATAL("BUG: incorrect buflen size for u32 message type"); } 54 | 55 | printf("Got a random int from the queue: %d\n", ((u32 *)message->buf)[0]); 56 | 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | /* Main entry point function */ 64 | int main(int argc, char **argv) { 65 | 66 | int thread_count = 1; 67 | int port = 0xAF1; 68 | 69 | bool is_main = true; 70 | 71 | if (argc < 2 || argc > 4) { FATAL("Usage ./llmp_test [main|worker] "); } 72 | 73 | if (!strcmp(argv[1], "worker")) { 74 | 75 | is_main = false; 76 | 77 | } else if (strcmp(argv[1], "main")) { 78 | 79 | FATAL( 80 | "Mode must either be main or worker!\n" 81 | "Usage ./llmp_test [main|worker] "); 82 | 83 | } 84 | 85 | if (argc > 2) { 86 | 87 | thread_count = atoi(argv[2]); 88 | if (thread_count < 0) { FATAL("Number of clients cannot be negative."); } 89 | OKF("Spawning %d clients", thread_count); 90 | 91 | } 92 | 93 | if (argc > 3) { 94 | 95 | port = atoi(argv[2]); 96 | if (port <= 0 || port >= 1 << 16) { FATAL("illegal port"); } 97 | 98 | } 99 | 100 | if (is_main) { 101 | 102 | /* The main node has a broker, a tcp server, and a few worker threads */ 103 | llmp_broker_t *broker = llmp_broker_new(); 104 | 105 | llmp_broker_register_local_server(broker, port); 106 | 107 | if (!llmp_broker_register_threaded_clientloop(broker, llmp_clientloop_print_u32, NULL)) { 108 | 109 | FATAL("error adding threaded client"); 110 | 111 | } 112 | 113 | int i; 114 | for (i = 0; i < thread_count; i++) { 115 | 116 | if (!llmp_broker_register_threaded_clientloop(broker, llmp_clientloop_rand_u32, NULL)) { 117 | 118 | FATAL("error adding threaded client"); 119 | 120 | } 121 | 122 | } 123 | 124 | OKF("Spawning main on port %d", port); 125 | llmp_broker_run(broker); 126 | 127 | } else { 128 | 129 | if (thread_count > 1) { WARNF("Multiple threads not supported for clients."); } 130 | 131 | OKF("Client will connect to port %d", port); 132 | // Worker only needs to spawn client threads. 133 | llmp_client_t *client_state = llmp_client_new(port); 134 | if (!client_state) { FATAL("Error connecting to broker at port %d", port); } 135 | llmp_clientloop_rand_u32(client_state, NULL); 136 | 137 | } 138 | 139 | FATAL("Unreachable"); 140 | 141 | } 142 | 143 | -------------------------------------------------------------------------------- /examples/prune_shm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ipcrm shm $(ipcs -m | tail -n +4 | cut -d ' ' -f2-3) 2>/dev/null || echo "No maps found" 4 | #on mac: ipcrm -m $(ipcs -m | tail -n +4 | cut -d ' ' -f2) 2>/dev/null || echo "No maps found" 5 | -------------------------------------------------------------------------------- /examples/target.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char file_name[20] = "./testcase"; 7 | 8 | int main() { 9 | 10 | char input[100] = {'\x00'}; 11 | 12 | int r = read(0, input, 4); 13 | if (!r) { puts("Error!\n"); } 14 | 15 | printf("In target\n"); 16 | 17 | if (input[2] == 'B' || input[2] == 'C') { 18 | 19 | puts("1st block hit"); 20 | 21 | if (input[2] == 'C') { 22 | 23 | puts("2nd block hit"); 24 | *(volatile int *)(NULL) = 0x0; // Crash 25 | 26 | } 27 | 28 | } 29 | 30 | exit(0); 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /include/afl-returns.h: -------------------------------------------------------------------------------- 1 | /* This file includes return codes for libafl. */ 2 | 3 | #ifndef AFL_RETURNS_H 4 | #define AFL_RETURNS_H 5 | 6 | #include 7 | #include 8 | 9 | #include "debug.h" 10 | 11 | /* Shorthand to check for RET_SUCCESS */ 12 | #define AFL_OK(expr) ((expr) == AFL_RET_SUCCESS) 13 | 14 | /* If expr != AFL_RET_SUCCESS, run block, error is in err. Return from here will return the parent func */ 15 | #define AFL_TRY(expr, block) \ 16 | do { \ 17 | \ 18 | afl_ret_t err = (expr); \ 19 | if (err != AFL_RET_SUCCESS) { \ 20 | \ 21 | DBG("AFL_TRY returning error: %s", afl_ret_stringify(err)); \ 22 | block \ 23 | \ 24 | } \ 25 | \ 26 | } while (0); 27 | 28 | /* Shorthand to check for RET_SUCCESS and assign to ret */ 29 | #define AFL_OK_RET(expr, ret) ((ret = (expr)) == AFL_RET_SUCCESS) 30 | 31 | typedef enum afl_ret { 32 | 33 | AFL_RET_SUCCESS = 0, 34 | AFL_RET_UNKNOWN_ERROR, 35 | AFL_RET_FILE_DUPLICATE, 36 | AFL_RET_ALLOC, 37 | AFL_RET_FILE_OPEN_ERROR, 38 | AFL_RET_FILE_SIZE, 39 | AFL_RET_SHORT_READ, 40 | AFL_RET_SHORT_WRITE, 41 | AFL_RET_ARRAY_END, 42 | AFL_RET_EXEC_ERROR, 43 | AFL_RET_BROKEN_TARGET, 44 | AFL_RET_NULL_PTR, 45 | AFL_RET_ERRNO, 46 | AFL_RET_NULL_QUEUE_ENTRY, 47 | AFL_RET_WRITE_TO_CRASH, 48 | AFL_RET_QUEUE_ENDS, 49 | AFL_RET_ERROR_INITIALIZE, 50 | AFL_RET_NO_FUZZ_WORKERS, 51 | AFL_RET_TRIM_FAIL, 52 | AFL_RET_ERROR_INPUT_COPY, 53 | AFL_RET_EMPTY, 54 | 55 | } afl_ret_t; 56 | 57 | /* Returns a string representation of afl_ret_t or of the errno if applicable */ 58 | static inline char *afl_ret_stringify(afl_ret_t afl_ret) { 59 | 60 | switch (afl_ret) { 61 | 62 | case AFL_RET_SUCCESS: 63 | return "Success"; 64 | case AFL_RET_ARRAY_END: 65 | return "No more elements in array"; 66 | case AFL_RET_EXEC_ERROR: 67 | return "Could not execute target"; 68 | case AFL_RET_BROKEN_TARGET: 69 | return "Target did not behave as expected"; 70 | case AFL_RET_ERROR_INPUT_COPY: 71 | return "Error creating input copy"; 72 | case AFL_RET_EMPTY: 73 | return "Empty data"; 74 | case AFL_RET_FILE_DUPLICATE: 75 | return "File exists"; 76 | case AFL_RET_ALLOC: 77 | if (!errno) { return "Allocation failed"; } 78 | /* fall-through */ 79 | case AFL_RET_FILE_OPEN_ERROR: 80 | if (!errno) { return "Error opening file"; } 81 | /* fall-through */ 82 | case AFL_RET_SHORT_READ: 83 | if (!errno) { return "Got less bytes than expected"; } 84 | /* fall-through */ 85 | case AFL_RET_ERRNO: 86 | return strerror(errno); 87 | default: 88 | return "Unknown error. Please report this bug!"; 89 | 90 | } 91 | 92 | } 93 | 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /include/aflpp.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #ifndef AFLPP_H 28 | #define AFLPP_H 29 | 30 | #include 31 | 32 | #include "common.h" 33 | #include "config.h" 34 | #include "observer.h" 35 | #include "input.h" 36 | #include "mutator.h" 37 | #include "queue.h" 38 | #include "engine.h" 39 | #include "fuzzone.h" 40 | #include "feedback.h" 41 | #include "stage.h" 42 | #include "os.h" 43 | #include "afl-returns.h" 44 | 45 | /* 46 | This is the generic forkserver interface that we have, in order to use the 47 | library to build something, agin "inherit" from this struct (yes, we'll be 48 | trying OO design principles here :D) and then extend adding your own fields to 49 | it. See the example forksever executor that we have in examples/ 50 | */ 51 | 52 | struct afl_executor_funcs { 53 | 54 | afl_ret_t (*init_cb)(afl_executor_t *); // can be NULL 55 | u8 (*destroy_cb)(afl_executor_t *); // can be NULL 56 | 57 | afl_exit_t (*run_target_cb)(afl_executor_t *); // Similar to afl_fsrv_run_target we have in afl 58 | u8 (*place_input_cb)(afl_executor_t *, afl_input_t *); // similar to the write_to_testcase function in afl. 59 | 60 | afl_ret_t (*observer_add)(afl_executor_t *, afl_observer_t *); // Add an observtion channel to the list 61 | 62 | afl_input_t *(*input_get)(afl_executor_t *); // Getter function for the current input 63 | 64 | void (*observers_reset)(afl_executor_t *); // Reset the observation channels 65 | 66 | }; 67 | 68 | // This is like the generic vtable for the executor. 69 | 70 | struct afl_executor { 71 | 72 | afl_observer_t **observors; // This will be swapped for the observation channel once its ready 73 | 74 | u32 observors_count; 75 | 76 | afl_input_t *current_input; // Holds current input for the executor 77 | 78 | struct afl_executor_funcs funcs; // afl executor_ops; 79 | 80 | }; 81 | 82 | afl_ret_t afl_executor_init(afl_executor_t *); 83 | void afl_executor_deinit(afl_executor_t *); 84 | afl_ret_t afl_executor_add_observer(afl_executor_t *, afl_observer_t *); 85 | afl_input_t *afl_executor_get_current_input(afl_executor_t *); 86 | void afl_observers_reset(afl_executor_t *); 87 | 88 | // Function used to create an executor, we alloc the memory ourselves and 89 | // initialize the executor 90 | 91 | AFL_NEW_AND_DELETE_FOR(afl_executor) 92 | 93 | /* Forkserver executor */ 94 | typedef struct afl_forkserver { 95 | 96 | afl_executor_t base; /* executer struct to inherit from */ 97 | 98 | u8 *trace_bits; /* SHM with instrumentation bitmap */ 99 | u8 use_stdin; /* use stdin for sending data */ 100 | 101 | s32 fsrv_pid, /* PID of the fork server */ 102 | child_pid, /* PID of the fuzzed program */ 103 | child_status, /* waitpid result for the child */ 104 | out_dir_fd, /* FD of the lock file */ 105 | dev_null_fd; 106 | 107 | s32 out_fd, /* Persistent fd for fsrv->out_file */ 108 | 109 | fsrv_ctl_fd, /* Fork server control pipe (write) */ 110 | fsrv_st_fd; /* Fork server status pipe (read) */ 111 | 112 | u32 exec_tmout; /* Configurable exec timeout (ms) */ 113 | u32 map_size; /* map size used by the target */ 114 | 115 | u64 total_execs; /* How often run_target was called */ 116 | 117 | char *out_file, /* File to fuzz, if any */ 118 | *target_path; /* Path of the target */ 119 | 120 | char **target_args; 121 | 122 | u32 last_run_timed_out; /* Traced process timed out? */ 123 | u32 last_run_time; /* Time this exec took to execute */ 124 | 125 | u8 last_kill_signal; /* Signal that killed the child */ 126 | 127 | } afl_forkserver_t; 128 | 129 | /* Functions related to the forkserver defined above */ 130 | afl_forkserver_t *fsrv_init(char *target_path, char **extra_target_args); 131 | afl_exit_t fsrv_run_target(afl_executor_t *fsrv_executor); 132 | u8 fsrv_place_input(afl_executor_t *fsrv_executor, afl_input_t *input); 133 | afl_ret_t fsrv_start(afl_executor_t *fsrv_executor); 134 | 135 | /* In-memory executor */ 136 | 137 | /* Function ptr for the harness */ 138 | typedef afl_exit_t (*harness_function_type)(afl_executor_t *executor, u8 *, size_t); 139 | 140 | typedef struct in_memory_executor { 141 | 142 | afl_executor_t base; 143 | harness_function_type harness; 144 | char ** argv; // These are to support the libfuzzer harnesses 145 | int argc; // To support libfuzzer harnesses 146 | afl_stage_t * stage; 147 | afl_queue_global_t * global_queue; 148 | 149 | } in_memory_executor_t; 150 | 151 | afl_exit_t in_memory_run_target(afl_executor_t *executor); 152 | u8 in_mem_executor_place_input(afl_executor_t *executor, afl_input_t *input); 153 | void in_memory_executor_init(in_memory_executor_t *in_memory_executor, harness_function_type harness); 154 | 155 | #endif 156 | 157 | -------------------------------------------------------------------------------- /include/android-ashmem.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - android shared memory compatibility layer 3 | ---------------------------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This header re-defines the shared memory routines used by AFL++ 22 | using the Andoid API. 23 | 24 | */ 25 | 26 | /* Thif file contains an android-specific shared mem wrapper */ 27 | 28 | #ifndef _ANDROID_ASHMEM_H 29 | #define _ANDROID_ASHMEM_H 30 | 31 | #ifdef __ANDROID__ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #if __ANDROID_API__ >= 26 40 | #define shmat bionic_shmat 41 | #define shmctl bionic_shmctl 42 | #define shmdt bionic_shmdt 43 | #define shmget bionic_shmget 44 | #endif 45 | 46 | #include 47 | #undef shmat 48 | #undef shmctl 49 | #undef shmdt 50 | #undef shmget 51 | #include 52 | 53 | #define ASHMEM_DEVICE "/dev/ashmem" 54 | 55 | static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { 56 | 57 | int ret = 0; 58 | if (__cmd == IPC_RMID) { 59 | 60 | int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); 61 | struct ashmem_pin pin = {0, (unsigned int)length}; 62 | ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); 63 | close(__shmid); 64 | 65 | } 66 | 67 | return ret; 68 | 69 | } 70 | 71 | static inline int shmget(key_t __key, size_t __size, int __shmflg) { 72 | 73 | (void)__shmflg; 74 | int fd, ret; 75 | char ourkey[11]; 76 | 77 | fd = open(ASHMEM_DEVICE, O_RDWR); 78 | if (fd < 0) return fd; 79 | 80 | sprintf(ourkey, "%d", __key); 81 | ret = ioctl(fd, ASHMEM_SET_NAME, ourkey); 82 | if (ret < 0) goto error; 83 | 84 | ret = ioctl(fd, ASHMEM_SET_SIZE, __size); 85 | if (ret < 0) goto error; 86 | 87 | return fd; 88 | 89 | error: 90 | close(fd); 91 | return ret; 92 | 93 | } 94 | 95 | static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { 96 | 97 | (void)__shmflg; 98 | int size; 99 | void *ptr; 100 | 101 | size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); 102 | if (size < 0) { return NULL; } 103 | 104 | ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0); 105 | if (ptr == MAP_FAILED) { return NULL; } 106 | 107 | return ptr; 108 | 109 | } 110 | 111 | #endif /* __ANDROID__ */ 112 | 113 | #endif 114 | 115 | -------------------------------------------------------------------------------- /include/cmplog.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - cmplog header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Forkserver design by Jann Horn 8 | 9 | Now maintained by Marc Heuse , 10 | Heiko Eißfeldt , 11 | Andrea Fioraldi , 12 | Dominik Maier 13 | 14 | Copyright 2016, 2017 Google Inc. All rights reserved. 15 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 16 | 17 | Licensed under the Apache License, Version 2.0 (the "License"); 18 | you may not use this file except in compliance with the License. 19 | You may obtain a copy of the License at: 20 | 21 | http://www.apache.org/licenses/LICENSE-2.0 22 | 23 | Shared code to handle the shared memory. This is used by the fuzzer 24 | as well the other components like afl-tmin, afl-showmap, etc... 25 | 26 | */ 27 | 28 | #ifndef _AFL_CMPLOG_H 29 | #define _AFL_CMPLOG_H 30 | 31 | #include "config.h" 32 | //#include "forkserver.h" 33 | 34 | #define CMP_MAP_W 65536 35 | #define CMP_MAP_H 256 36 | #define CMP_MAP_RTN_H (CMP_MAP_H / 4) 37 | 38 | #define SHAPE_BYTES(x) (x + 1) 39 | 40 | #define CMP_TYPE_INS 0 41 | #define CMP_TYPE_RTN 1 42 | 43 | struct cmp_header { 44 | 45 | unsigned hits : 20; 46 | 47 | unsigned cnt : 20; 48 | unsigned id : 16; 49 | 50 | unsigned shape : 5; // from 0 to 31 51 | unsigned type : 1; 52 | 53 | } __attribute__((packed)); 54 | 55 | struct cmp_operands { 56 | 57 | u64 v0; 58 | u64 v1; 59 | 60 | }; 61 | 62 | struct cmpfn_operands { 63 | 64 | u8 v0[32]; 65 | u8 v1[32]; 66 | 67 | }; 68 | 69 | typedef struct cmp_operands cmp_map_list[CMP_MAP_H]; 70 | 71 | struct cmp_map { 72 | 73 | struct cmp_header headers[CMP_MAP_W]; 74 | struct cmp_operands log[CMP_MAP_W][CMP_MAP_H]; 75 | 76 | }; 77 | 78 | /* Execs the child */ 79 | 80 | // void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv); 81 | 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | /* This file contains commonly used functionality for libafl */ 28 | 29 | #ifndef COMMON_H 30 | #define COMMON_H 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "types.h" 38 | #include "alloc-inl.h" 39 | #include "afl-returns.h" 40 | 41 | #define AFL_DEINITIALIZED (0xAF1DA10C) 42 | 43 | // We're declaring a few structs here which have an interdependency between them 44 | 45 | typedef struct afl_fuzz_one afl_fuzz_one_t; 46 | 47 | typedef struct afl_engine afl_engine_t; 48 | 49 | typedef struct afl_stage afl_stage_t; 50 | 51 | typedef struct afl_executor afl_executor_t; 52 | 53 | typedef struct afl_mutator afl_mutator_t; 54 | 55 | // Returns new buf containing the substring token 56 | void *afl_insert_substring(u8 *src_buf, u8 *dest_buf, size_t len, void *token, size_t token_len, size_t offset); 57 | // Erases remove_len number of bytes from offset 58 | size_t afl_erase_bytes(u8 *buf, size_t len, size_t offset, size_t remove_len); 59 | 60 | // Inserts a certain length of a byte value (byte) at offset in buf 61 | u8 *afl_insert_bytes(u8 *src_buf, u8 *dest_buf, size_t len, u8 byte, size_t insert_len, size_t offset); 62 | 63 | static inline char **afl_argv_cpy_dup(int argc, char **argv) { 64 | 65 | int i = 0; 66 | 67 | char **ret = calloc(1, (argc + 1) * sizeof(char *)); 68 | if (!ret) { return NULL; } 69 | 70 | for (i = 0; i < argc; i++) { 71 | 72 | ret[i] = strdup(argv[i]); 73 | if (!ret[i]) { 74 | 75 | int k; 76 | for (k = 0; k < i; k++) { 77 | 78 | free(ret[k]); 79 | 80 | } 81 | 82 | free(ret); 83 | return NULL; 84 | 85 | } 86 | 87 | } 88 | 89 | ret[i] = NULL; 90 | 91 | return ret; 92 | 93 | } 94 | 95 | /* Get unix time in microseconds */ 96 | u64 afl_get_cur_time_us(void); 97 | 98 | /* Get unix time in microseconds */ 99 | u64 afl_get_cur_time(void); 100 | 101 | /* Get unix time in seconds */ 102 | u64 afl_get_cur_time_s(void); 103 | 104 | /* returns true, if the given dir exists, else false */ 105 | bool afl_dir_exists(char *dirpath); 106 | 107 | /* This function uses select calls to wait on a child process for given 108 | * timeout_ms milliseconds and kills it if it doesn't terminate by that time */ 109 | static inline u32 afl_read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms) { 110 | 111 | fd_set readfds; 112 | FD_ZERO(&readfds); 113 | FD_SET(fd, &readfds); 114 | struct timeval timeout; 115 | int sret; 116 | ssize_t len_read; 117 | 118 | timeout.tv_sec = (timeout_ms / 1000); 119 | timeout.tv_usec = (timeout_ms % 1000) * 1000; 120 | #if !defined(__linux__) 121 | u64 read_start = afl_get_cur_time_us(); 122 | #endif 123 | 124 | /* set exceptfds as well to return when a child exited/closed the pipe. */ 125 | restart_select: 126 | sret = select(fd + 1, &readfds, NULL, NULL, &timeout); 127 | 128 | if (likely(sret > 0)) { 129 | 130 | restart_read: 131 | len_read = read(fd, (u8 *)buf, 4); 132 | 133 | if (likely(len_read == 4)) { // for speed we put this first 134 | 135 | #if defined(__linux__) 136 | u32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); 137 | #else 138 | u32 exec_ms = MIN(timeout_ms, afl_get_cur_time_us() - read_start); 139 | #endif 140 | 141 | // ensure to report 1 ms has passed (0 is an error) 142 | return exec_ms > 0 ? exec_ms : 1; 143 | 144 | } else if (unlikely(len_read == -1 && errno == EINTR)) { 145 | 146 | goto restart_read; 147 | 148 | } else if (unlikely(len_read < 4)) { 149 | 150 | return 0; 151 | 152 | } 153 | 154 | } else if (unlikely(!sret)) { 155 | 156 | *buf = -1; 157 | return timeout_ms + 1; 158 | 159 | } else if (unlikely(sret < 0)) { 160 | 161 | if (likely(errno == EINTR)) goto restart_select; 162 | 163 | *buf = -1; 164 | return 0; 165 | 166 | } 167 | 168 | return 0; // not reached 169 | 170 | } 171 | 172 | #endif 173 | 174 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - debug / error handling macros 3 | ---------------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | /* This file contains helpers for debugging and fancy printing */ 24 | 25 | #ifndef DEBUG_H 26 | #define DEBUG_H 27 | 28 | #include 29 | 30 | #include "types.h" 31 | #include "config.h" 32 | 33 | /* wrap __LINE__ (int) as string using preprocessor magic, see 34 | http://decompile.com/cpp/faq/file_and_line_error_string.htm 35 | */ 36 | #define _STR(x) #x 37 | #define TOSTRING(x) _STR(x) 38 | 39 | /******************* 40 | * Terminal colors * 41 | *******************/ 42 | #ifndef MESSAGES_TO_STDOUT 43 | #define MESSAGES_TO_STDOUT 44 | #endif 45 | 46 | #ifdef USE_COLOR 47 | 48 | #define cBLK "\x1b[0;30m" 49 | #define cRED "\x1b[0;31m" 50 | #define cGRN "\x1b[0;32m" 51 | #define cBRN "\x1b[0;33m" 52 | #define cBLU "\x1b[0;34m" 53 | #define cMGN "\x1b[0;35m" 54 | #define cCYA "\x1b[0;36m" 55 | #define cLGR "\x1b[0;37m" 56 | #define cGRA "\x1b[1;90m" 57 | #define cLRD "\x1b[1;91m" 58 | #define cLGN "\x1b[1;92m" 59 | #define cYEL "\x1b[1;93m" 60 | #define cLBL "\x1b[1;94m" 61 | #define cPIN "\x1b[1;95m" 62 | #define cLCY "\x1b[1;96m" 63 | #define cBRI "\x1b[1;97m" 64 | #define cRST "\x1b[0m" 65 | 66 | #define bgBLK "\x1b[40m" 67 | #define bgRED "\x1b[41m" 68 | #define bgGRN "\x1b[42m" 69 | #define bgBRN "\x1b[43m" 70 | #define bgBLU "\x1b[44m" 71 | #define bgMGN "\x1b[45m" 72 | #define bgCYA "\x1b[46m" 73 | #define bgLGR "\x1b[47m" 74 | #define bgGRA "\x1b[100m" 75 | #define bgLRD "\x1b[101m" 76 | #define bgLGN "\x1b[102m" 77 | #define bgYEL "\x1b[103m" 78 | #define bgLBL "\x1b[104m" 79 | #define bgPIN "\x1b[105m" 80 | #define bgLCY "\x1b[106m" 81 | #define bgBRI "\x1b[107m" 82 | 83 | #else 84 | 85 | #define cBLK "" 86 | #define cRED "" 87 | #define cGRN "" 88 | #define cBRN "" 89 | #define cBLU "" 90 | #define cMGN "" 91 | #define cCYA "" 92 | #define cLGR "" 93 | #define cGRA "" 94 | #define cLRD "" 95 | #define cLGN "" 96 | #define cYEL "" 97 | #define cLBL "" 98 | #define cPIN "" 99 | #define cLCY "" 100 | #define cBRI "" 101 | #define cRST "" 102 | 103 | #define bgBLK "" 104 | #define bgRED "" 105 | #define bgGRN "" 106 | #define bgBRN "" 107 | #define bgBLU "" 108 | #define bgMGN "" 109 | #define bgCYA "" 110 | #define bgLGR "" 111 | #define bgGRA "" 112 | #define bgLRD "" 113 | #define bgLGN "" 114 | #define bgYEL "" 115 | #define bgLBL "" 116 | #define bgPIN "" 117 | #define bgLCY "" 118 | #define bgBRI "" 119 | 120 | #endif /* ^USE_COLOR */ 121 | 122 | /************************* 123 | * Box drawing sequences * 124 | *************************/ 125 | 126 | #ifdef FANCY_BOXES 127 | 128 | #define SET_G1 "\x1b)0" /* Set G1 for box drawing */ 129 | #define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ 130 | #define bSTART "\x0e" /* Enter G1 drawing mode */ 131 | #define bSTOP "\x0f" /* Leave G1 drawing mode */ 132 | #define bH "q" /* Horizontal line */ 133 | #define bV "x" /* Vertical line */ 134 | #define bLT "l" /* Left top corner */ 135 | #define bRT "k" /* Right top corner */ 136 | #define bLB "m" /* Left bottom corner */ 137 | #define bRB "j" /* Right bottom corner */ 138 | #define bX "n" /* Cross */ 139 | #define bVR "t" /* Vertical, branch right */ 140 | #define bVL "u" /* Vertical, branch left */ 141 | #define bHT "v" /* Horizontal, branch top */ 142 | #define bHB "w" /* Horizontal, branch bottom */ 143 | 144 | #else 145 | 146 | #define SET_G1 "" 147 | #define RESET_G1 "" 148 | #define bSTART "" 149 | #define bSTOP "" 150 | #define bH "-" 151 | #define bV "|" 152 | #define bLT "+" 153 | #define bRT "+" 154 | #define bLB "+" 155 | #define bRB "+" 156 | #define bX "+" 157 | #define bVR "+" 158 | #define bVL "+" 159 | #define bHT "+" 160 | #define bHB "+" 161 | 162 | #endif /* ^FANCY_BOXES */ 163 | 164 | /*********************** 165 | * Misc terminal codes * 166 | ***********************/ 167 | 168 | #define TERM_HOME "\x1b[H" 169 | #define TERM_CLEAR TERM_HOME "\x1b[2J" 170 | #define cEOL "\x1b[0K" 171 | #define CURSOR_HIDE "\x1b[?25l" 172 | #define CURSOR_SHOW "\x1b[?25h" 173 | 174 | /************************ 175 | * Debug & error macros * 176 | ************************/ 177 | 178 | /* Just print stuff to the appropriate stream. */ 179 | 180 | #ifdef MESSAGES_TO_STDOUT 181 | #define SAYF(...) printf(__VA_ARGS__) 182 | #else 183 | #define SAYF(...) fprintf(stderr, __VA_ARGS__) 184 | #endif /* ^MESSAGES_TO_STDOUT */ 185 | 186 | /* Show a prefixed warning. */ 187 | 188 | #define WARNF(...) \ 189 | do { \ 190 | \ 191 | SAYF(cYEL "[!] " cBRI "WARNING: " cRST __VA_ARGS__); \ 192 | SAYF(cRST "\n"); \ 193 | \ 194 | } while (0) 195 | 196 | /* Show a prefixed "doing something" message. */ 197 | 198 | #define ACTF(...) \ 199 | do { \ 200 | \ 201 | SAYF(cLBL "[*] " cRST __VA_ARGS__); \ 202 | SAYF(cRST "\n"); \ 203 | \ 204 | } while (0) 205 | 206 | /* Show a prefixed "success" message. */ 207 | 208 | #define OKF(...) \ 209 | do { \ 210 | \ 211 | SAYF(cLGN "[+] " cRST __VA_ARGS__); \ 212 | SAYF(cRST "\n"); \ 213 | \ 214 | } while (0) 215 | 216 | /* Show a prefixed fatal error message (not used in afl). */ 217 | 218 | #define BADF(...) \ 219 | do { \ 220 | \ 221 | SAYF(cLRD "\n[-] " cRST __VA_ARGS__); \ 222 | SAYF(cRST "\n"); \ 223 | \ 224 | } while (0) 225 | 226 | #ifdef DEBUG 227 | #define DBG(...) \ 228 | do { \ 229 | \ 230 | SAYF(cMGN "[D]" cGRA " [" __FILE__ ":" TOSTRING(__LINE__) "] " cRST __VA_ARGS__); \ 231 | SAYF(cRST "\n"); \ 232 | fflush(stdout); \ 233 | \ 234 | } while (0) 235 | 236 | #else 237 | #define DBG(...) \ 238 | {} 239 | #endif 240 | 241 | /* Die with a verbose non-OS fatal error message. */ 242 | 243 | #define FATAL(...) \ 244 | do { \ 245 | \ 246 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " cRST __VA_ARGS__); \ 247 | SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, __FILE__, __LINE__); \ 248 | exit(1); \ 249 | \ 250 | } while (0) 251 | 252 | /* Die by calling abort() to provide a core dump. */ 253 | 254 | #define ABORT(...) \ 255 | do { \ 256 | \ 257 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " cRST __VA_ARGS__); \ 258 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __FUNCTION__, __FILE__, __LINE__); \ 259 | abort(); \ 260 | \ 261 | } while (0) 262 | 263 | /* Die while also including the output of perror(). */ 264 | 265 | #define PFATAL(...) \ 266 | do { \ 267 | \ 268 | fflush(stdout); \ 269 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " cRST __VA_ARGS__); \ 270 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __FUNCTION__, __FILE__, __LINE__); \ 271 | SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ 272 | exit(1); \ 273 | \ 274 | } while (0) 275 | 276 | /* Die with FATAL() or PFATAL() depending on the value of res (used to 277 | interpret different failure modes for read(), write(), etc). */ 278 | 279 | #define RPFATAL(res, ...) \ 280 | do { \ 281 | \ 282 | if (res < 0) \ 283 | PFATAL(__VA_ARGS__); \ 284 | else \ 285 | FATAL(__VA_ARGS__); \ 286 | \ 287 | } while (0) 288 | 289 | /* Error-checking versions of read() and write() that call RPFATAL() as 290 | appropriate. */ 291 | 292 | #endif /* ! _HAVE_DEBUG_H */ 293 | 294 | -------------------------------------------------------------------------------- /include/engine.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | The Engine is the main and central part of the fuzzer. It contains the 22 | queues, feedbacks, executor and the fuzz_one (which in turn has stages) 23 | 24 | */ 25 | 26 | #ifndef ENGINE_H 27 | #define ENGINE_H 28 | 29 | #include 30 | #include 31 | 32 | #include "common.h" 33 | #include "queue.h" 34 | #include "feedback.h" 35 | #include "afl-returns.h" 36 | #include "xxh3.h" 37 | #include "xxhash.h" 38 | #include "rand.h" 39 | #include "llmp.h" 40 | 41 | struct afl_engine_func { 42 | 43 | afl_queue_global_t *(*get_queue)(afl_engine_t *); 44 | afl_fuzz_one_t *(*get_fuzz_one)(afl_engine_t *); 45 | u64 (*get_execs)(afl_engine_t *); 46 | u64 (*get_start_time)(afl_engine_t *); 47 | 48 | void (*set_fuzz_one)(afl_engine_t *, afl_fuzz_one_t *); 49 | afl_ret_t (*add_feedback)(afl_engine_t *, afl_feedback_t *); 50 | void (*set_global_queue)(afl_engine_t *, afl_queue_global_t *); 51 | 52 | u8 (*execute)(afl_engine_t *, afl_input_t *); 53 | afl_ret_t (*handle_new_message)(afl_engine_t *, llmp_message_t *); 54 | afl_ret_t (*load_testcases_from_dir)(afl_engine_t *, char *); 55 | void (*load_zero_testcase)(size_t); 56 | 57 | afl_ret_t (*loop)(afl_engine_t *); 58 | 59 | }; 60 | 61 | struct afl_engine { 62 | 63 | afl_fuzz_one_t * fuzz_one; 64 | afl_queue_global_t * global_queue; 65 | afl_executor_t * executor; 66 | afl_queue_feedback_t *current_feedback_queue; 67 | afl_feedback_t ** feedbacks; // We're keeping a pointer of feedbacks here 68 | // to save memory, consideting the original 69 | // feedback would already be allocated 70 | u64 executions, start_time, last_update, crashes, feedbacks_count; 71 | u32 id; 72 | u8 verbose; 73 | s32 cpu_bound; // 1 if we want to bind to a cpu, 0 else 74 | char *in_dir; // Input corpus directory 75 | 76 | afl_rand_t rand; 77 | 78 | u8 * buf; // Reusable buf for realloc 79 | struct afl_engine_func funcs; 80 | llmp_client_t * llmp_client; // Our IPC for fuzzer communication 81 | 82 | }; 83 | 84 | /* TODO: Add default implementations for load_testcases and execute */ 85 | afl_queue_global_t *afl_engine_get_queue(afl_engine_t *); 86 | afl_fuzz_one_t * afl_engine_get_fuzz_one(afl_engine_t *); 87 | u64 afl_get_execs(afl_engine_t *); 88 | u64 afl_engine_get_start_time(afl_engine_t *); 89 | 90 | void afl_set_fuzz_one(afl_engine_t *, afl_fuzz_one_t *); 91 | afl_ret_t afl_engine_add_feedback(afl_engine_t *, afl_feedback_t *); 92 | void afl_set_global_queue(afl_engine_t *engine, afl_queue_global_t *global_queue); 93 | 94 | u8 afl_engine_execute(afl_engine_t *, afl_input_t *); 95 | afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *, char *); 96 | void afl_engine_load_zero_testcase(size_t); 97 | afl_ret_t afl_engine_handle_new_message(afl_engine_t *, llmp_message_t *); 98 | 99 | afl_ret_t afl_engine_loop(afl_engine_t *); // Not sure about this functions 100 | // use-case. Was in FFF though. 101 | 102 | afl_ret_t afl_engine_init(afl_engine_t *, afl_executor_t *, afl_fuzz_one_t *, afl_queue_global_t *); 103 | void afl_engine_deinit(afl_engine_t *); 104 | 105 | afl_ret_t afl_engine_check_configuration(afl_engine_t *engine); 106 | 107 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_engine, 108 | AFL_DECL_PARAMS(afl_executor_t *executor, afl_fuzz_one_t *fuzz_one, 109 | afl_queue_global_t *global_queue), 110 | AFL_CALL_PARAMS(executor, fuzz_one, global_queue)) 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /include/feedback.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #ifndef LIBFEEDBACK_H 28 | #define LIBFEEDBACK_H 29 | 30 | #include "queue.h" 31 | #include "observer.h" 32 | 33 | #define AFL_FEEDBACK_TAG_BASE (0xFEEDB43E) 34 | #define AFL_FEEDBACK_TAG_COV (0xFEEDC0F8) 35 | 36 | typedef struct afl_queue_feedback afl_queue_feedback_t; 37 | typedef struct afl_feedback afl_feedback_t; 38 | 39 | struct afl_feedback_funcs { 40 | 41 | float (*is_interesting)(afl_feedback_t *, afl_executor_t *); 42 | void (*set_feedback_queue)(afl_feedback_t *, afl_queue_feedback_t *); 43 | afl_queue_feedback_t *(*get_feedback_queue)(afl_feedback_t *); 44 | 45 | }; 46 | 47 | struct afl_feedback { 48 | 49 | afl_queue_feedback_t *queue; 50 | 51 | struct afl_feedback_funcs funcs; 52 | u32 tag; 53 | 54 | }; 55 | 56 | // Default implementation of the functions 57 | 58 | void afl_feedback_set_queue(afl_feedback_t *, afl_queue_feedback_t *); 59 | afl_queue_feedback_t *afl_feedback_get_queue(afl_feedback_t *); 60 | 61 | // "Constructors" and "destructors" for the feedback 62 | void afl_feedback_deinit(afl_feedback_t *); 63 | afl_ret_t afl_feedback_init(afl_feedback_t *, afl_queue_feedback_t *queue); 64 | 65 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_feedback, AFL_DECL_PARAMS(afl_queue_feedback_t *queue), AFL_CALL_PARAMS(queue)) 66 | 67 | /* Simple MaximizeMapFeedback implementation */ 68 | 69 | /* Coverage Feedback */ 70 | typedef struct afl_feedback_cov { 71 | 72 | afl_feedback_t base; 73 | 74 | /* This array holds the coveragemap observation channels the feedback is looking at */ 75 | afl_observer_covmap_t *observer_cov; 76 | 77 | u8 * virgin_bits; 78 | size_t size; 79 | 80 | } afl_feedback_cov_t; 81 | 82 | afl_ret_t afl_feedback_cov_init(afl_feedback_cov_t *feedback, afl_queue_feedback_t *queue, 83 | afl_observer_covmap_t *map_observer); 84 | void afl_feedback_cov_deinit(); 85 | 86 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_feedback_cov, 87 | AFL_DECL_PARAMS(afl_queue_feedback_t *queue, afl_observer_covmap_t *map_observer), 88 | AFL_CALL_PARAMS(queue, map_observer)) 89 | 90 | /* Set virgin bits according to the map passed into the func */ 91 | afl_ret_t afl_feedback_cov_set_virgin_bits(afl_feedback_cov_t *feedback, u8 *virgin_bits_copy_from, size_t size); 92 | 93 | /* Returns the "interestingness" of the current feedback */ 94 | float afl_feedback_cov_is_interesting(afl_feedback_t *feedback, afl_executor_t *fsrv); 95 | 96 | #endif 97 | 98 | -------------------------------------------------------------------------------- /include/fuzzone.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | 22 | 23 | */ 24 | 25 | #ifndef LIBFUZZONE_H 26 | #define LIBFUZZONE_H 27 | 28 | #include "types.h" 29 | #include "common.h" 30 | 31 | struct afl_fuzz_one_funcs { 32 | 33 | afl_ret_t (*perform)(afl_fuzz_one_t *); 34 | afl_ret_t (*add_stage)(afl_fuzz_one_t *, afl_stage_t *); 35 | afl_ret_t (*set_engine)(afl_fuzz_one_t *, afl_engine_t *); 36 | 37 | }; 38 | 39 | struct afl_fuzz_one { 40 | 41 | afl_engine_t *engine; 42 | afl_stage_t **stages; 43 | size_t stages_count; 44 | 45 | struct afl_fuzz_one_funcs funcs; 46 | 47 | }; 48 | 49 | afl_ret_t afl_fuzz_one_perform(afl_fuzz_one_t *); 50 | afl_ret_t afl_fuzz_one_add_stage(afl_fuzz_one_t *, afl_stage_t *); 51 | afl_ret_t afl_fuzz_one_set_engine(afl_fuzz_one_t *, afl_engine_t *); 52 | 53 | afl_ret_t afl_fuzz_one_init(afl_fuzz_one_t *, afl_engine_t *); 54 | void afl_fuzz_one_deinit(afl_fuzz_one_t *); 55 | 56 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_fuzz_one, AFL_DECL_PARAMS(afl_engine_t *engine), AFL_CALL_PARAMS(engine)) 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /include/input.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #ifndef LIBINPUT_H 28 | #define LIBINPUT_H 29 | 30 | #include "common.h" 31 | #include "afl-returns.h" 32 | 33 | typedef struct afl_input afl_input_t; 34 | 35 | struct afl_input_funcs { 36 | 37 | void (*deserialize)(afl_input_t *this_input, u8 *bytes, size_t len); 38 | u8 *(*serialize)(afl_input_t *this_input); 39 | afl_input_t *(*copy)(afl_input_t *this_input); 40 | void (*restore)(afl_input_t *this_input, afl_input_t *input); 41 | afl_ret_t (*load_from_file)(afl_input_t *this_input, char *fname); 42 | afl_ret_t (*save_to_file)(afl_input_t *this_input, char *fname); 43 | void (*clear)(afl_input_t *this_input); 44 | u8 *(*get_bytes)(afl_input_t *this_input); 45 | 46 | void (*delete)(afl_input_t *this_input); 47 | 48 | }; 49 | 50 | struct afl_input { 51 | 52 | u8 * bytes; // Raw input bytes 53 | size_t len; // Length of the input 54 | 55 | u8 *copy_buf; 56 | 57 | struct afl_input_funcs funcs; 58 | 59 | }; 60 | 61 | afl_ret_t afl_input_init(afl_input_t *input); 62 | void afl_input_deinit(afl_input_t *input); 63 | 64 | // Default implementations of the functions for raw input vtable 65 | 66 | void afl_input_deserialize(afl_input_t *this_input, u8 *bytes, size_t len); 67 | u8 * afl_input_serialize(afl_input_t *this_input); 68 | afl_input_t *afl_input_copy(afl_input_t *this_input); 69 | void afl_input_restore(afl_input_t *this_input, afl_input_t *input); 70 | afl_ret_t afl_input_load_from_file(afl_input_t *this_inputinput, char *fname); 71 | afl_ret_t afl_input_write_to_file(afl_input_t *this_input, char *fname); 72 | void afl_input_clear(afl_input_t *this_input); 73 | u8 * afl_input_get_bytes(afl_input_t *this_input); 74 | 75 | /* Write the contents of the input to a file at the given loc */ 76 | afl_ret_t afl_input_write_to_file(afl_input_t *data, char *filename); 77 | 78 | /* Write the contents of the input to a timeoutfile */ 79 | afl_ret_t afl_input_dump_to_timeoutfile(afl_input_t *data, char *); 80 | 81 | /* Write the contents of the input which causes a crash in the target to a crashfile */ 82 | afl_ret_t afl_input_dump_to_crashfile(afl_input_t *, char *); 83 | 84 | /* Function to create and destroy a new input, allocates memory and initializes 85 | it. In destroy, it first deinitializes the struct and then frees it. */ 86 | 87 | AFL_NEW_AND_DELETE_FOR(afl_input); 88 | 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /include/mutator.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | 22 | */ 23 | 24 | #ifndef LIBMUTATOR_H 25 | #define LIBMUTATOR_H 26 | 27 | #include "input.h" 28 | #include "queue.h" 29 | #include "engine.h" 30 | 31 | // Mutator struct will have many internal functions like mutate, trimming etc. 32 | // This is based on both the FFF prototype and the custom mutators that we have 33 | // in AFL++ without the AFL++ specific parts 34 | 35 | struct afl_mutator_funcs { 36 | 37 | void (*init)(afl_mutator_t *); 38 | 39 | // The params here are in_buf and out_buf. 40 | size_t (*trim)(afl_mutator_t *, afl_input_t *); 41 | 42 | // Mutate function 43 | size_t (*mutate)(afl_mutator_t *, afl_input_t *); 44 | 45 | // Checks if the queue entry is to be fuzzed or not 46 | afl_ret_t (*custom_queue_get)(afl_mutator_t *, afl_input_t *); 47 | void (*custom_queue_new_entry)(afl_mutator_t *, afl_entry_t *); 48 | // Post process API AFL++ 49 | void (*post_process)(afl_mutator_t *, afl_input_t *); 50 | 51 | afl_stage_t *(*get_stage)(afl_mutator_t *); 52 | 53 | }; 54 | 55 | struct afl_mutator { 56 | 57 | afl_engine_t *engine; 58 | u8 * mutate_buf; // Extra buf for mutators to work with for afl_realloc 59 | 60 | struct afl_mutator_funcs funcs; 61 | 62 | }; 63 | 64 | size_t afl_mutator_trim(afl_mutator_t *, u8 *, u8 *); 65 | afl_stage_t *afl_mutator_get_stage(afl_mutator_t *); 66 | 67 | afl_ret_t afl_mutator_init(afl_mutator_t *, afl_engine_t *); 68 | void afl_mutator_deinit(afl_mutator_t *); 69 | 70 | // A simple scheduled mutator based on the above mutator. Will act something 71 | // similar to the havoc stage 72 | 73 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_mutator, AFL_DECL_PARAMS(afl_engine_t *engine), AFL_CALL_PARAMS(engine)) 74 | 75 | typedef struct afl_mutator_scheduled afl_mutator_scheduled_t; 76 | typedef void (*afl_mutator_func)(afl_mutator_t *, afl_input_t *); 77 | 78 | struct afl_mutator_scheduled_funcs { 79 | 80 | size_t (*schedule)(afl_mutator_scheduled_t *); 81 | afl_ret_t (*add_func)(afl_mutator_scheduled_t *, afl_mutator_func); 82 | afl_ret_t (*add_default_funcs)(afl_mutator_scheduled_t *); 83 | size_t (*get_iters)(afl_mutator_scheduled_t *); 84 | 85 | }; 86 | 87 | struct afl_mutator_scheduled { 88 | 89 | afl_mutator_t base; 90 | afl_mutator_func *mutations; // A ptr to an array of mutation operator 91 | // functions 92 | size_t mutators_count; 93 | struct afl_mutator_scheduled_funcs funcs; 94 | size_t max_iterations; 95 | 96 | }; 97 | 98 | /* TODO add implementation for the _schedule_ and _iterations_ functions, need a 99 | * random list element pop type implementation for this */ 100 | size_t afl_iterations(afl_mutator_scheduled_t *); 101 | /* Add a mutator func to this mutators */ 102 | afl_ret_t afl_mutator_add_func(afl_mutator_scheduled_t *, afl_mutator_func); 103 | /* Add all default mutator funcs */ 104 | afl_ret_t afl_mutator_scheduled_add_havoc_funcs(afl_mutator_scheduled_t *mutator); 105 | size_t afl_schedule(afl_mutator_scheduled_t *); 106 | size_t afl_mutate_scheduled_mutator(afl_mutator_t *, afl_input_t *); 107 | 108 | afl_ret_t afl_mutator_scheduled_init(afl_mutator_scheduled_t *sched_mut, afl_engine_t *engine, size_t max_iterations); 109 | void afl_mutator_scheduled_deinit(afl_mutator_scheduled_t *); 110 | 111 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_mutator_scheduled, AFL_DECL_PARAMS(afl_engine_t *engine, size_t max_iterations), 112 | AFL_CALL_PARAMS(engine, max_iterations)) 113 | 114 | void afl_mutfunc_flip_bit(afl_mutator_t *mutator, afl_input_t *input); 115 | void afl_mutfunc_flip_2_bits(afl_mutator_t *mutator, afl_input_t *input); 116 | void afl_mutfunc_flip_4_bits(afl_mutator_t *mutator, afl_input_t *input); 117 | void afl_mutfunc_flip_byte(afl_mutator_t *mutator, afl_input_t *input); 118 | void afl_mutfunc_flip_2_bytes(afl_mutator_t *mutator, afl_input_t *input); 119 | void afl_mutfunc_flip_4_bytes(afl_mutator_t *mutator, afl_input_t *input); 120 | void afl_mutfunc_random_byte_add_sub(afl_mutator_t *mutator, afl_input_t *input); 121 | void afl_mutfunc_random_byte(afl_mutator_t *mutator, afl_input_t *input); 122 | void afl_mutfunc_delete_bytes(afl_mutator_t *mutator, afl_input_t *input); 123 | void afl_mutfunc_clone_bytes(afl_mutator_t *mutator, afl_input_t *input); 124 | void afl_mutfunc_splice(afl_mutator_t *mutator, afl_input_t *input); 125 | 126 | #endif 127 | 128 | -------------------------------------------------------------------------------- /include/observer.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #ifndef LIBOBSERVATIONCHANNEL_H 28 | #define LIBOBSERVATIONCHANNEL_H 29 | 30 | #include "common.h" 31 | #include "shmem.h" 32 | #include "afl-returns.h" 33 | 34 | #define AFL_OBSERVER_TAG_BASE (0x0B5EB45E) 35 | #define AFL_OBSERVER_TAG_COVMAP (0x0B5EC0FE) 36 | 37 | typedef struct afl_observer afl_observer_t; 38 | 39 | // vtable for the observation channel 40 | 41 | struct afl_observer_funcs { 42 | 43 | void (*flush)(afl_observer_t *); 44 | void (*reset)(afl_observer_t *); 45 | void (*post_exec)(afl_observer_t *, afl_engine_t *); 46 | 47 | }; 48 | 49 | struct afl_observer { 50 | 51 | u32 tag; 52 | struct afl_observer_funcs funcs; 53 | 54 | }; 55 | 56 | /* They're void now, but I think post_exec should have some return type? Since, 57 | * they'll mostly be implemented by user */ 58 | void afl_observer_flush(afl_observer_t *); 59 | void afl_observer_reset(afl_observer_t *); 60 | void afl_observer_post_exec(afl_observer_t *); 61 | // Functions to initialize and deinitialize the generic observation channel. P.S 62 | // You probably will need to extend it the way we've done below. 63 | 64 | afl_ret_t afl_observer_init(afl_observer_t *channel); 65 | void afl_observer_deinit(afl_observer_t *); 66 | 67 | /* Function to create and destroy a new observation channel, allocates memory 68 | and initializes it. In destroy, it first deinitializes the struct and then 69 | frees it. */ 70 | 71 | AFL_NEW_AND_DELETE_FOR(afl_observer) 72 | 73 | typedef struct afl_observer_covmap afl_observer_covmap_t; 74 | 75 | struct afl_observer_covmap_funcs { 76 | 77 | u8 *(*get_trace_bits)(afl_observer_covmap_t *); 78 | size_t (*get_map_size)(afl_observer_covmap_t *); 79 | 80 | }; 81 | 82 | struct afl_observer_covmap { 83 | 84 | afl_observer_t base; // Base observation channel "class" 85 | 86 | afl_shmem_t shared_map; 87 | 88 | struct afl_observer_covmap_funcs funcs; 89 | 90 | }; 91 | 92 | u8 * afl_observer_covmap_get_trace_bits(afl_observer_covmap_t *obs_channel); 93 | size_t afl_observer_covmap_get_map_size(afl_observer_covmap_t *obs_channel); 94 | 95 | // Functions to initialize and delete a map based observation channel 96 | 97 | afl_ret_t afl_observer_covmap_init(afl_observer_covmap_t *, size_t map_size); 98 | void afl_observer_covmap_deinit(afl_observer_covmap_t *); 99 | void afl_observer_covmap_reset(afl_observer_t *); 100 | 101 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_observer_covmap, AFL_DECL_PARAMS(size_t map_size), AFL_CALL_PARAMS(map_size)) 102 | 103 | #endif 104 | 105 | -------------------------------------------------------------------------------- /include/os.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBOS_H 2 | #define LIBOS_H 3 | 4 | #include "common.h" 5 | #include "input.h" 6 | 7 | #include 8 | #include 9 | 10 | // This has a few parts, the first deals with crash handling. 11 | 12 | /* afl_exit_t is for the fuzzed target, as opposed to afl_ret_t 13 | which is for internal functions. */ 14 | typedef enum afl_exit { 15 | 16 | AFL_EXIT_OK, 17 | AFL_EXIT_STOP, 18 | AFL_EXIT_CRASH, 19 | AFL_EXIT_SEGV, 20 | AFL_EXIT_BUS, 21 | AFL_EXIT_ABRT, 22 | AFL_EXIT_ILL, 23 | AFL_EXIT_FPE, 24 | AFL_EXIT_TIMEOUT, 25 | AFL_EXIT_OOM, 26 | 27 | } afl_exit_t; 28 | 29 | /* TODO: Add implementations for installing crash handlers */ 30 | typedef void (*afl_crash_handler_func)(afl_exit_t type, void *data); 31 | 32 | void install_crash_handler(afl_crash_handler_func callback); 33 | 34 | typedef enum afl_fork_result { FORK_FAILED, CHILD, PARENT } afl_fork_result_t; 35 | 36 | typedef struct afl_os { 37 | 38 | struct afl_os *(*current)(struct afl_os *); 39 | afl_fork_result_t (*fork)(struct afl_os *); 40 | void (*suspend)(struct afl_os *); 41 | void (*resume)(struct afl_os *); 42 | afl_exit_t (*wait)(struct afl_os *, bool untraced); 43 | 44 | pid_t handler_process; // Something similar to the child process 45 | 46 | } afl_os_t; 47 | 48 | void _afl_process_init_internal(afl_os_t *); 49 | 50 | static inline afl_os_t *afl_process_init(afl_os_t *process, pid_t handler_pid) { 51 | 52 | afl_os_t *new_process; 53 | 54 | if (process) { 55 | 56 | _afl_process_init_internal(process); 57 | process->handler_process = handler_pid; 58 | return process; 59 | 60 | } 61 | 62 | else { 63 | 64 | new_process = calloc(1, sizeof(afl_os_t)); 65 | if (!new_process) { return NULL; } 66 | _afl_process_init_internal(new_process); 67 | new_process->handler_process = (handler_pid); 68 | 69 | } 70 | 71 | return new_process; 72 | 73 | } 74 | 75 | afl_fork_result_t afl_proc_fork(afl_os_t *); 76 | void afl_proc_suspend(afl_os_t *); 77 | void afl_proc_resume(afl_os_t *); 78 | afl_exit_t afl_proc_wait(afl_os_t *, bool); 79 | 80 | afl_ret_t bind_to_cpu(); 81 | /* Run `handle_file` for each file in the dirpath, recursively. 82 | void *data will be passed to handle_file as 2nd param. 83 | if handle_file returns false, further execution stops. */ 84 | afl_ret_t afl_for_each_file(char *dirpath, bool (*handle_file)(char *filename, void *data), void *data); 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /include/queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #ifndef LIBQUEUE_H 28 | #define LIBQUEUE_H 29 | 30 | #include 31 | #include 32 | 33 | #include "input.h" 34 | #include "shmem.h" 35 | #include "feedback.h" 36 | 37 | /* 38 | This is the generic interface implementation for the queue and queue entries. 39 | We've tried to keep it generic and yet including, but if you want to extend the 40 | queue/entry, simply "inherit" this struct by including it in your custom struct 41 | and keeping it as the first member of your struct. 42 | */ 43 | 44 | typedef struct afl_queue afl_queue_t; 45 | typedef struct afl_entry afl_entry_t; 46 | typedef struct afl_feedback afl_feedback_t; 47 | 48 | struct afl_entry_funcs { 49 | 50 | afl_input_t *(*get_input)(afl_entry_t *); 51 | bool (*is_on_disk)(afl_entry_t *); 52 | afl_entry_t *(*get_next)(afl_entry_t *); 53 | afl_entry_t *(*get_prev)(afl_entry_t *); 54 | afl_entry_t *(*get_parent)(afl_entry_t *); 55 | afl_entry_t *(*get_child)(afl_entry_t *, size_t); /*TODO: Still need to add a base implementation for this.*/ 56 | 57 | }; 58 | 59 | typedef struct __attribute__((__packed__)) afl_entry_info { 60 | 61 | u64 hash, exec_us; 62 | u32 bytes_set, bits_set; 63 | u8 trimmed, has_new_coverage, variable, skip_entry; 64 | 65 | } afl_entry_info_t; 66 | 67 | struct afl_entry { 68 | 69 | afl_entry_info_t *info; 70 | afl_input_t * input; 71 | u8 * map; 72 | bool on_disk, info_calloc; 73 | char filename[FILENAME_LEN_MAX]; 74 | struct afl_queue *queue; 75 | struct afl_entry *next; 76 | struct afl_entry *prev; 77 | struct afl_entry *parent; 78 | 79 | struct afl_entry_funcs funcs; 80 | 81 | }; 82 | 83 | afl_ret_t afl_entry_init(afl_entry_t *, afl_input_t *, afl_entry_info_t *); 84 | void afl_entry_deinit(afl_entry_t *); 85 | 86 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_entry, AFL_DECL_PARAMS(afl_input_t *input, afl_entry_info_t *info), 87 | AFL_CALL_PARAMS(input, info)) 88 | // AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_queue_feedback, AFL_DECL_PARAMS(afl_feedback_t *feedback, char *name), 89 | // AFL_CALL_PARAMS(feedback, name)); 90 | 91 | // Default implementations for the functions for queue_entry vtable 92 | afl_input_t *afl_entry_get_input(afl_entry_t *entry); 93 | afl_entry_t *afl_entry_get_next(afl_entry_t *entry); 94 | afl_entry_t *afl_entry_get_prev(afl_entry_t *entry); 95 | afl_entry_t *afl_entry_get_parent(afl_entry_t *entry); 96 | 97 | typedef struct afl_queue afl_queue_t; 98 | 99 | struct afl_queue_funcs { 100 | 101 | afl_ret_t (*insert)(afl_queue_t *, afl_entry_t *); 102 | void (*remove_from_queue)(afl_queue_t *); 103 | 104 | afl_entry_t *(*get)(afl_queue_t *); 105 | afl_entry_t *(*get_next_in_queue)(afl_queue_t *, int); 106 | afl_entry_t *(*get_queue_entry)(afl_queue_t *, u32); 107 | afl_entry_t *(*get_queue_base)(afl_queue_t *); 108 | size_t (*get_size)(afl_queue_t *); 109 | char *(*get_dirpath)(afl_queue_t *); 110 | size_t (*get_names_id)(afl_queue_t *); 111 | bool (*get_save_to_files)(afl_queue_t *); 112 | 113 | void (*set_dirpath)(afl_queue_t *, char *); 114 | void (*set_engine)(afl_queue_t *, afl_engine_t *); 115 | 116 | }; 117 | 118 | struct afl_queue { 119 | 120 | afl_entry_t ** entries; 121 | size_t entries_count; 122 | afl_entry_t * base; 123 | u64 current; 124 | int engine_id; 125 | afl_engine_t * engine; 126 | afl_entry_t * end; 127 | char dirpath[PATH_MAX]; 128 | size_t names_id; 129 | bool save_to_files; 130 | bool fuzz_started; 131 | struct afl_queue_funcs funcs; 132 | 133 | }; 134 | 135 | /* TODO: Add the base */ 136 | 137 | afl_ret_t afl_queue_init(afl_queue_t *); 138 | void afl_queue_deinit(afl_queue_t *); 139 | 140 | afl_ret_t afl_queue_insert(afl_queue_t *, afl_entry_t *); 141 | size_t afl_queue_get_size(afl_queue_t *); 142 | char * afl_queue_get_dirpath(afl_queue_t *); 143 | size_t afl_queue_get_names_id(afl_queue_t *); 144 | bool afl_queue_should_save_to_file(afl_queue_t *); 145 | void afl_queue_set_dirpath(afl_queue_t *, char *); 146 | void afl_queue_set_engine(afl_queue_t *queue, afl_engine_t *engine); 147 | void afl_queue_global_set_engine(afl_queue_t *, afl_engine_t *); 148 | afl_entry_t *afl_queue_next_base_queue(afl_queue_t *queue, int engine_id); 149 | afl_entry_t *afl_queue_get_entry(afl_queue_t *queue, u32 entry); 150 | 151 | AFL_NEW_AND_DELETE_FOR(afl_queue) 152 | 153 | typedef struct afl_queue_feedback { 154 | 155 | afl_queue_t base; // Inheritence from base queue 156 | 157 | afl_feedback_t *feedback; 158 | char * name; 159 | 160 | } afl_queue_feedback_t; 161 | 162 | afl_ret_t afl_queue_feedback_init(afl_queue_feedback_t *, afl_feedback_t *, 163 | char *); // "constructor" for the above feedback queue 164 | 165 | void afl_queue_feedback_deinit(afl_queue_feedback_t *); 166 | 167 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_queue_feedback, AFL_DECL_PARAMS(afl_feedback_t *feedback, char *name), 168 | AFL_CALL_PARAMS(feedback, name)); 169 | 170 | typedef struct afl_queue_global afl_queue_global_t; 171 | 172 | struct afl_queue_global_funcs { 173 | 174 | int (*schedule)(afl_queue_global_t *); 175 | afl_ret_t (*add_feedback_queue)(afl_queue_global_t *, afl_queue_feedback_t *); 176 | 177 | }; 178 | 179 | struct afl_queue_global { 180 | 181 | afl_queue_t base; 182 | afl_queue_feedback_t **feedback_queues; // One global queue can have 183 | // multiple feedback queues 184 | 185 | size_t feedback_queues_count; 186 | 187 | struct afl_queue_global_funcs funcs; 188 | /*TODO: Add a map of Engine:feedback_queue 189 | UPDATE: Engine will have a ptr to current feedback queue rather than this*/ 190 | 191 | }; 192 | 193 | // Default implementations of global queue vtable functions 194 | afl_ret_t afl_queue_global_add_feedback_queue(afl_queue_global_t *, afl_queue_feedback_t *); 195 | int afl_queue_global_schedule(afl_queue_global_t *); 196 | void afl_queue_global_set_engine(afl_queue_t *, afl_engine_t *); 197 | 198 | // Function to get next entry from queue, we override the base_queue 199 | // implementation 200 | afl_entry_t *afl_queue_next_global_queue(afl_queue_t *queue, int engine_id); 201 | 202 | /* Register this as global queue for the engine. 203 | TODO: Make this a method of engine instead */ 204 | void afl_queue_global_set_engine(afl_queue_t *global_queue_base, afl_engine_t *engine); 205 | 206 | /* TODO: ADD defualt implementation for the schedule function based on random. 207 | */ 208 | 209 | afl_ret_t afl_queue_global_init(afl_queue_global_t *); 210 | void afl_queue_global_deinit(afl_queue_global_t *); 211 | 212 | AFL_NEW_AND_DELETE_FOR(afl_queue_global) 213 | 214 | #endif 215 | 216 | -------------------------------------------------------------------------------- /include/rand.h: -------------------------------------------------------------------------------- 1 | #ifndef AFL_RAND_H 2 | #define AFL_RAND_H 3 | 4 | #include 5 | #include "types.h" 6 | #include "common.h" 7 | #include "xxh3.h" 8 | 9 | typedef struct afl_rand { 10 | 11 | u32 rand_cnt; /* Random number counter*/ 12 | u64 rand_seed[4]; 13 | s32 dev_urandom_fd; 14 | s64 init_seed; 15 | bool fixed_seed; 16 | 17 | } afl_rand_t; 18 | 19 | static inline u64 afl_rand_rotl(const u64 x, int k) { 20 | 21 | return (x << k) | (x >> (64 - k)); 22 | 23 | } 24 | 25 | static inline void afl_rand_seed(afl_rand_t *rnd, s64 init_seed) { 26 | 27 | rnd->init_seed = init_seed; 28 | rnd->fixed_seed = true; 29 | rnd->rand_seed[0] = XXH64((u8 *)&rnd->init_seed, sizeof(rnd->init_seed), HASH_CONST); 30 | rnd->rand_seed[1] = rnd->rand_seed[0] ^ 0x1234567890abcdef; 31 | rnd->rand_seed[2] = rnd->rand_seed[0] & 0x0123456789abcdef; 32 | rnd->rand_seed[3] = rnd->rand_seed[0] | 0x01abcde43f567908; 33 | 34 | } 35 | 36 | /* get the next random number */ 37 | static inline u64 afl_rand_next(afl_rand_t *rnd) { 38 | 39 | const uint64_t result = afl_rand_rotl(rnd->rand_seed[0] + rnd->rand_seed[3], 23) + rnd->rand_seed[0]; 40 | 41 | const uint64_t t = rnd->rand_seed[1] << 17; 42 | 43 | rnd->rand_seed[2] ^= rnd->rand_seed[0]; 44 | rnd->rand_seed[3] ^= rnd->rand_seed[1]; 45 | rnd->rand_seed[1] ^= rnd->rand_seed[2]; 46 | rnd->rand_seed[0] ^= rnd->rand_seed[3]; 47 | 48 | rnd->rand_seed[2] ^= t; 49 | 50 | rnd->rand_seed[3] = afl_rand_rotl(rnd->rand_seed[3], 45); 51 | 52 | return result; 53 | 54 | } 55 | 56 | /* get a random int below the given int (exclusive) */ 57 | static inline u64 afl_rand_below(afl_rand_t *rnd, u64 limit) { 58 | 59 | if (limit <= 1) { return 0; } 60 | 61 | /* The boundary not being necessarily a power of 2, 62 | we need to ensure the result uniformity. */ 63 | if (unlikely(!rnd->rand_cnt--) && likely(!rnd->fixed_seed)) { 64 | 65 | int read_len = read(rnd->dev_urandom_fd, &rnd->rand_seed, sizeof(rnd->rand_seed)); 66 | (void)read_len; 67 | rnd->rand_cnt = (RESEED_RNG / 2) + (rnd->rand_seed[1] % RESEED_RNG); 68 | 69 | } 70 | 71 | /* Modulo is biased - we don't want our fuzzing to be biased so let's do it 72 | right. See 73 | https://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator 74 | */ 75 | 76 | u64 unbiased_rnd; 77 | do { 78 | 79 | unbiased_rnd = afl_rand_next(rnd); 80 | 81 | } while (unlikely(unbiased_rnd >= (UINT64_MAX - (UINT64_MAX % limit)))); 82 | 83 | return unbiased_rnd % limit; 84 | 85 | } 86 | 87 | /* A random number between min and max, both inclusive */ 88 | static inline u64 afl_rand_between(afl_rand_t *rand, u64 min, u64 max) { 89 | 90 | return min + afl_rand_below(rand, max - min + 1); 91 | 92 | } 93 | 94 | /* initialize with a fixed seed (for reproducability) */ 95 | static inline afl_ret_t afl_rand_init_fixed_seed(afl_rand_t *rnd, s64 init_seed) { 96 | 97 | memset(rnd, 0, sizeof(afl_rand_t)); 98 | afl_rand_seed(rnd, init_seed); 99 | return AFL_RET_SUCCESS; 100 | 101 | } 102 | 103 | /* initialize feeded by urandom */ 104 | static inline afl_ret_t afl_rand_init(afl_rand_t *rnd) { 105 | 106 | memset(rnd, 0, sizeof(afl_rand_t)); 107 | rnd->dev_urandom_fd = open("/dev/urandom", O_RDONLY); 108 | if (!rnd->dev_urandom_fd) { return AFL_RET_FILE_OPEN_ERROR; } 109 | rnd->fixed_seed = false; 110 | /* do one call to rand_below to seed the rng */ 111 | afl_rand_below(rnd, 1); 112 | return AFL_RET_SUCCESS; 113 | 114 | } 115 | 116 | static inline void afl_rand_deinit(afl_rand_t *rnd) { 117 | 118 | if (rnd->dev_urandom_fd) { close(rnd->dev_urandom_fd); } 119 | 120 | } 121 | 122 | AFL_NEW_AND_DELETE_FOR(afl_rand); 123 | 124 | #endif /* AFL_RAND_H */ 125 | 126 | -------------------------------------------------------------------------------- /include/shmem.h: -------------------------------------------------------------------------------- 1 | #ifndef AFL_SHMEM_H 2 | #define AFL_SHMEM_H 3 | 4 | #include "types.h" 5 | 6 | #define AFL_SHMEM_STRLEN_MAX (20) 7 | 8 | // A generic sharememory region to be used by any functions (queues or feedbacks 9 | // too.) 10 | 11 | typedef struct afl_shmem { 12 | 13 | /* Serialized map id */ 14 | char shm_str[AFL_SHMEM_STRLEN_MAX]; 15 | #ifdef USEMMAP 16 | int g_shm_fd; 17 | #else 18 | int shm_id; 19 | #endif 20 | 21 | u8 * map; 22 | size_t map_size; 23 | 24 | } afl_shmem_t; 25 | 26 | // Functions to create Shared memory region, for observation channels and 27 | // opening inputs and stuff. 28 | u8 * afl_shmem_init(afl_shmem_t *sharedmem, size_t map_size); 29 | u8 * afl_shmem_by_str(afl_shmem_t *shm, char *shm_str, size_t map_size); 30 | void afl_shmem_deinit(afl_shmem_t *sharedmem); 31 | 32 | /* Write sharedmap as env var */ 33 | afl_ret_t afl_shmem_to_env_var(afl_shmem_t *shmem, char *env_name); 34 | 35 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_shmem, AFL_DECL_PARAMS(size_t map_size), AFL_CALL_PARAMS(map_size)) 36 | 37 | #endif /* AFL_SHMEM_H */ 38 | 39 | -------------------------------------------------------------------------------- /include/snapshot-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - snapshot helpers routines 3 | ------------------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Forkserver design by Jann Horn 8 | 9 | Now maintained by Marc Heuse , 10 | Heiko Eißfeldt , 11 | Andrea Fioraldi , 12 | Dominik Maier 13 | 14 | Copyright 2016, 2017 Google Inc. All rights reserved. 15 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 16 | 17 | Licensed under the Apache License, Version 2.0 (the "License"); 18 | you may not use this file except in compliance with the License. 19 | You may obtain a copy of the License at: 20 | 21 | http://www.apache.org/licenses/LICENSE-2.0 22 | 23 | */ 24 | 25 | // From AFL-Snapshot-LKM/include/afl_snapshot.h (must be kept synced) 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #define AFL_SNAPSHOT_FILE_NAME "/dev/afl_snapshot" 32 | 33 | #define AFL_SNAPSHOT_IOCTL_MAGIC 44313 34 | 35 | #define AFL_SNAPSHOT_IOCTL_DO _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 1) 36 | #define AFL_SNAPSHOT_IOCTL_CLEAN _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 2) 37 | #define AFL_SNAPSHOT_EXCLUDE_VMRANGE _IOR(AFL_SNAPSHOT_IOCTL_MAGIC, 3, struct afl_snapshot_vmrange_args *) 38 | #define AFL_SNAPSHOT_INCLUDE_VMRANGE _IOR(AFL_SNAPSHOT_IOCTL_MAGIC, 4, struct afl_snapshot_vmrange_args *) 39 | #define AFL_SNAPSHOT_IOCTL_TAKE _IOR(AFL_SNAPSHOT_IOCTL_MAGIC, 5, int) 40 | #define AFL_SNAPSHOT_IOCTL_RESTORE _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 6) 41 | 42 | // Trace new mmaped ares and unmap them on restore. 43 | #define AFL_SNAPSHOT_MMAP 1 44 | // Do not snapshot any page (by default all writeable not-shared pages 45 | // are shanpshotted. 46 | #define AFL_SNAPSHOT_BLOCK 2 47 | // Snapshot file descriptor state, close newly opened descriptors 48 | #define AFL_SNAPSHOT_FDS 4 49 | // Snapshot registers state 50 | #define AFL_SNAPSHOT_REGS 8 51 | // Perform a restore when exit_group is invoked 52 | #define AFL_SNAPSHOT_EXIT 16 53 | // TODO(andrea) allow not COW snapshots (high perf on small processes) 54 | // Disable COW, restore all the snapshotted pages 55 | #define AFL_SNAPSHOT_NOCOW 32 56 | // Do not snapshot Stack pages 57 | #define AFL_SNAPSHOT_NOSTACK 64 58 | 59 | struct afl_snapshot_vmrange_args { 60 | 61 | unsigned long start, end; 62 | 63 | }; 64 | 65 | static int afl_snapshot_dev_fd; 66 | 67 | static int afl_snapshot_init(void) { 68 | 69 | afl_snapshot_dev_fd = open(AFL_SNAPSHOT_FILE_NAME, 0); 70 | return afl_snapshot_dev_fd; 71 | 72 | } 73 | 74 | static void afl_snapshot_exclude_vmrange(void *start, void *end) { 75 | 76 | struct afl_snapshot_vmrange_args args = {(unsigned long)start, (unsigned long)end}; 77 | ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_EXCLUDE_VMRANGE, &args); 78 | 79 | } 80 | 81 | static void afl_snapshot_include_vmrange(void *start, void *end) { 82 | 83 | struct afl_snapshot_vmrange_args args = {(unsigned long)start, (unsigned long)end}; 84 | ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_INCLUDE_VMRANGE, &args); 85 | 86 | } 87 | 88 | static int afl_snapshot_take(int config) { 89 | 90 | return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_TAKE, config); 91 | 92 | } 93 | 94 | static int afl_snapshot_do(void) { 95 | 96 | return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_DO); 97 | 98 | } 99 | 100 | static void afl_snapshot_restore(void) { 101 | 102 | ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_RESTORE); 103 | 104 | } 105 | 106 | static void afl_snapshot_clean(void) { 107 | 108 | ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_CLEAN); 109 | 110 | } 111 | 112 | -------------------------------------------------------------------------------- /include/stage.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | #ifndef LIBSTAGE_H 24 | #define LIBSTAGE_H 25 | 26 | #include "input.h" 27 | 28 | struct afl_stage_funcs { 29 | 30 | afl_ret_t (*perform)(afl_stage_t *, afl_input_t *input); 31 | size_t (*get_iters)(afl_stage_t *); // A function which tells how many mutated 32 | // inputs to generate out of a given input 33 | /* Change the void pointer to a mutator * once it is ready */ 34 | afl_ret_t (*add_mutator_to_stage)(afl_stage_t *, afl_mutator_t *); 35 | 36 | }; 37 | 38 | struct afl_stage { 39 | 40 | afl_engine_t * engine; 41 | struct afl_stage_funcs funcs; 42 | /* The list of mutator operators that this stage has */ 43 | afl_mutator_t **mutators; 44 | 45 | size_t mutators_count; 46 | 47 | }; 48 | 49 | afl_ret_t afl_stage_run(afl_stage_t *, afl_input_t *, bool); 50 | float afl_stage_is_interesting(afl_stage_t *); 51 | afl_ret_t afl_stage_perform(afl_stage_t *, afl_input_t *); 52 | size_t afl_stage_get_iters(afl_stage_t *); 53 | afl_ret_t afl_stage_init(afl_stage_t *, afl_engine_t *); 54 | void afl_stage_deinit(afl_stage_t *); 55 | afl_ret_t afl_stage_add_mutator(afl_stage_t *, afl_mutator_t *); 56 | 57 | AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(afl_stage, AFL_DECL_PARAMS(afl_engine_t *engine), AFL_CALL_PARAMS(engine)) 58 | 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - type definitions and minor macros 3 | -------------------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | #ifndef TYPES_H 24 | #define TYPES_H 25 | 26 | #include 27 | #include 28 | 29 | #include "afl-returns.h" 30 | 31 | typedef uint8_t u8; 32 | typedef uint16_t u16; 33 | typedef uint32_t u32; 34 | 35 | /* Extended forkserver option values */ 36 | 37 | /* Reporting errors */ 38 | #define FS_OPT_ERROR 0xf800008f 39 | #define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8) 40 | #define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8) 41 | #define FS_ERROR_MAP_SIZE 1 42 | #define FS_ERROR_MAP_ADDR 2 43 | #define FS_ERROR_SHM_OPEN 4 44 | #define FS_ERROR_SHMAT 8 45 | #define FS_ERROR_MMAP 16 46 | 47 | /* Reporting options */ 48 | #define FS_OPT_ENABLED 0x80000001 49 | #define FS_OPT_MAPSIZE 0x40000000 50 | #define FS_OPT_SNAPSHOT 0x20000000 51 | #define FS_OPT_AUTODICT 0x10000000 52 | #define FS_OPT_SHDMEM_FUZZ 0x01000000 53 | #define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 54 | // FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 55 | #define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1) 56 | #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) 57 | #define FS_OPT_SET_MAPSIZE(x) (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) 58 | 59 | typedef unsigned long long u64; 60 | 61 | typedef int8_t s8; 62 | typedef int16_t s16; 63 | typedef int32_t s32; 64 | typedef int64_t s64; 65 | 66 | #ifndef MIN 67 | #define MIN(a, b) \ 68 | ({ \ 69 | \ 70 | __typeof__(a) _a = (a); \ 71 | __typeof__(b) _b = (b); \ 72 | _a < _b ? _a : _b; \ 73 | \ 74 | }) 75 | 76 | #define MAX(a, b) \ 77 | ({ \ 78 | \ 79 | __typeof__(a) _a = (a); \ 80 | __typeof__(b) _b = (b); \ 81 | _a > _b ? _a : _b; \ 82 | \ 83 | }) 84 | 85 | #endif /* !MIN */ 86 | 87 | #define SWAP16(_x) \ 88 | ({ \ 89 | \ 90 | u16 _ret = (_x); \ 91 | (u16)((_ret << 8) | (_ret >> 8)); \ 92 | \ 93 | }) 94 | 95 | #define SWAP32(_x) \ 96 | ({ \ 97 | \ 98 | u32 _ret = (_x); \ 99 | (u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | ((_ret >> 8) & 0x0000FF00)); \ 100 | \ 101 | }) 102 | 103 | #define SWAP64(_x) \ 104 | ({ \ 105 | \ 106 | u64 _ret = (_x); \ 107 | _ret = (_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \ 108 | _ret = (_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \ 109 | _ret = (_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8; \ 110 | _ret; \ 111 | \ 112 | }) 113 | 114 | #ifdef AFL_LLVM_PASS 115 | #if defined(__linux__) || !defined(__ANDROID__) 116 | #define AFL_SR(s) (srandom(s)) 117 | #define AFL_R(x) (random() % (x)) 118 | #else 119 | #define AFL_SR(s) ((void)s) 120 | #define AFL_R(x) (arc4random_uniform(x)) 121 | #endif 122 | #else 123 | #if defined(__linux__) || !defined(__ANDROID__) 124 | #define SR(s) (srandom(s)) 125 | #define R(x) (random() % (x)) 126 | #else 127 | #define SR(s) ((void)s) 128 | #define R(x) (arc4random_uniform(x)) 129 | #endif 130 | #endif /* ^AFL_LLVM_PASS */ 131 | 132 | #define STRINGIFY_INTERNAL(x) #x 133 | #define STRINGIFY(x) STRINGIFY_INTERNAL(x) 134 | 135 | #define MEM_BARRIER() __asm__ volatile("" ::: "memory") 136 | 137 | #if __GNUC__ < 6 138 | #ifndef likely 139 | #define likely(_x) (_x) 140 | #endif 141 | #ifndef unlikely 142 | #define unlikely(_x) (_x) 143 | #endif 144 | #else 145 | #ifndef likely 146 | #define likely(_x) __builtin_expect(!!(_x), 1) 147 | #endif 148 | #ifndef unlikely 149 | #define unlikely(_x) __builtin_expect(!!(_x), 0) 150 | #endif 151 | #endif 152 | 153 | #define AFL_NEW_AND_DELETE_FOR(init_type) AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(init_type, AFL_DECL_PARAMS(void), ret) 154 | 155 | /* 156 | This makro wraps all our afl_ ... _init and _deinit calls with _new and _delete wrappers. 157 | The _new wrapper allocates memory, and return NULL or the pointer, depending on result. 158 | The _delete wrapper calls _denit and deallocates the pointer, as created by _new. 159 | For decl and call, use AFL_DECL/CALL_PARAMS 160 | */ 161 | #define AFL_NEW_AND_DELETE_FOR_WITH_PARAMS(init_type, decl_params, call_params) \ 162 | static inline init_type##_t *init_type##_new(decl_params) { \ 163 | \ 164 | /*printf("Allocating " #init_type " with decl_params " #decl_params */ \ 165 | /*" and call params " #call_params " and size %ld\n", sizeof(init_type##_t) );*/ \ 166 | init_type##_t *ret = calloc(1, sizeof(init_type##_t)); \ 167 | if (!ret) { return NULL; } \ 168 | if (init_type##_init(call_params) != AFL_RET_SUCCESS) { \ 169 | \ 170 | free(ret); \ 171 | return NULL; \ 172 | \ 173 | } \ 174 | return ret; \ 175 | \ 176 | } \ 177 | \ 178 | static inline void init_type##_delete(init_type##_t *init_type) { \ 179 | \ 180 | init_type##_deinit(init_type); \ 181 | free(init_type); \ 182 | \ 183 | } 184 | 185 | #define AFL_DECL_PARAMS(...) __VA_ARGS__ 186 | #define AFL_CALL_PARAMS(...) ret, __VA_ARGS__ 187 | 188 | #endif /* ! _HAVE_TYPES_H */ 189 | 190 | -------------------------------------------------------------------------------- /src/aflpp.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - queue relates routines 3 | --------------------------------------------- 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt and 9 | Andrea Fioraldi 10 | 11 | Copyright 2016, 2017 Google Inc. All rights reserved. 12 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 13 | Licensed under the Apache License, Version 2.0 (the "License"); 14 | you may not use this file except in compliance with the License. 15 | You may obtain a copy of the License at: 16 | 17 | http://www.apache.org/licenses/LICENSE-2.0 18 | 19 | This is the actual code for the library framework. 20 | 21 | */ 22 | #include 23 | #include 24 | #include 25 | 26 | #include "aflpp.h" 27 | #include "stdbool.h" 28 | #include "afl-returns.h" 29 | 30 | afl_ret_t afl_executor_init(afl_executor_t *executor) { 31 | 32 | memset(executor, 0, sizeof(afl_executor_t)); 33 | executor->current_input = NULL; 34 | executor->observors = NULL; 35 | executor->observors_count = 0; 36 | 37 | // Default implementations of the functions 38 | executor->funcs.init_cb = NULL; 39 | executor->funcs.destroy_cb = NULL; 40 | executor->funcs.place_input_cb = NULL; 41 | executor->funcs.run_target_cb = NULL; 42 | executor->funcs.observer_add = afl_executor_add_observer; 43 | executor->funcs.observers_reset = afl_observers_reset; 44 | 45 | return AFL_RET_SUCCESS; 46 | 47 | } 48 | 49 | // Default implementations for executor vtable 50 | void afl_executor_deinit(afl_executor_t *executor) { 51 | 52 | size_t i; 53 | executor->current_input = NULL; 54 | 55 | for (i = 0; i < executor->observors_count; i++) { 56 | 57 | afl_observer_deinit(executor->observors[i]); 58 | 59 | } 60 | 61 | afl_free(executor->observors); 62 | executor->observors = NULL; 63 | 64 | executor->observors_count = 0; 65 | 66 | } 67 | 68 | afl_ret_t afl_executor_add_observer(afl_executor_t *executor, afl_observer_t *obs_channel) { 69 | 70 | executor->observors_count++; 71 | 72 | executor->observors = afl_realloc(executor->observors, executor->observors_count * sizeof(afl_observer_t *)); 73 | if (!executor->observors) { return AFL_RET_ALLOC; } 74 | executor->observors[executor->observors_count - 1] = obs_channel; 75 | 76 | return AFL_RET_SUCCESS; 77 | 78 | } 79 | 80 | afl_input_t *afl_executor_get_current_input(afl_executor_t *executor) { 81 | 82 | return executor->current_input; 83 | 84 | } 85 | 86 | void afl_observers_reset(afl_executor_t *executor) { 87 | 88 | size_t i; 89 | for (i = 0; i < executor->observors_count; ++i) { 90 | 91 | afl_observer_t *obs_channel = executor->observors[i]; 92 | if (obs_channel->funcs.reset) { obs_channel->funcs.reset(obs_channel); } 93 | 94 | } 95 | 96 | } 97 | 98 | /* Function to simple initialize the forkserver */ 99 | afl_forkserver_t *fsrv_init(char *target_path, char **target_args) { 100 | 101 | afl_forkserver_t *fsrv = calloc(1, sizeof(afl_forkserver_t)); 102 | if (!fsrv) { return NULL; } 103 | 104 | if (afl_executor_init(&(fsrv->base))) { 105 | 106 | free(fsrv); 107 | return NULL; 108 | 109 | } 110 | 111 | /* defining standard functions for the forkserver vtable */ 112 | fsrv->base.funcs.init_cb = fsrv_start; 113 | fsrv->base.funcs.place_input_cb = fsrv_place_input; 114 | fsrv->base.funcs.run_target_cb = fsrv_run_target; 115 | fsrv->use_stdin = 1; 116 | 117 | fsrv->target_path = target_path; 118 | fsrv->target_args = target_args; 119 | fsrv->out_file = calloc(1, 50); 120 | snprintf(fsrv->out_file, 50, "out-%d", rand()); 121 | 122 | char **target_args_copy = target_args; 123 | while (*target_args_copy != NULL) { 124 | 125 | if (!strcmp(*target_args_copy, "@@")) { 126 | 127 | fsrv->use_stdin = 0; 128 | *target_args_copy = fsrv->out_file; // Replace @@ with the output file name 129 | break; 130 | 131 | } 132 | 133 | target_args_copy++; 134 | 135 | } 136 | 137 | /* FD for the stdin of the child process */ 138 | if (fsrv->use_stdin) { 139 | 140 | if (!fsrv->out_file) { 141 | 142 | fsrv->out_fd = -1; 143 | 144 | } else { 145 | 146 | fsrv->out_fd = open((char *)fsrv->out_file, O_WRONLY | O_CREAT, 0600); 147 | if (!fsrv->out_fd) { 148 | 149 | afl_executor_deinit(&fsrv->base); 150 | free(fsrv); 151 | return NULL; 152 | 153 | } 154 | 155 | } 156 | 157 | } 158 | 159 | fsrv->out_dir_fd = -1; 160 | 161 | fsrv->dev_null_fd = open("/dev/null", O_WRONLY); 162 | if (!fsrv->dev_null_fd) { 163 | 164 | close(fsrv->out_fd); 165 | afl_executor_deinit(&fsrv->base); 166 | free(fsrv); 167 | return NULL; 168 | 169 | } 170 | 171 | /* exec related stuff */ 172 | fsrv->child_pid = -1; 173 | fsrv->exec_tmout = 0; /* Default exec time in ms */ 174 | 175 | return fsrv; 176 | 177 | } 178 | 179 | /* This function starts up the forkserver for further process requests */ 180 | afl_ret_t fsrv_start(afl_executor_t *fsrv_executor) { 181 | 182 | afl_forkserver_t *fsrv = (afl_forkserver_t *)fsrv_executor; 183 | 184 | int st_pipe[2], ctl_pipe[2]; 185 | s32 status; 186 | s32 rlen; 187 | 188 | ACTF("Spinning up the fork server..."); 189 | 190 | if (pipe(st_pipe) || pipe(ctl_pipe)) { return AFL_RET_ERRNO; } 191 | 192 | fsrv->last_run_timed_out = 0; 193 | fsrv->fsrv_pid = fork(); 194 | 195 | if (fsrv->fsrv_pid < 0) { return AFL_RET_ERRNO; } 196 | 197 | if (!fsrv->fsrv_pid) { 198 | 199 | /* CHILD PROCESS */ 200 | 201 | setsid(); 202 | 203 | if (fsrv->use_stdin) { 204 | 205 | fsrv->out_fd = open((char *)fsrv->out_file, O_RDONLY | O_CREAT, 0600); 206 | if (!fsrv->out_fd) { PFATAL("Could not open outfile in child"); } 207 | 208 | dup2(fsrv->out_fd, 0); 209 | close(fsrv->out_fd); 210 | 211 | } 212 | 213 | dup2(fsrv->dev_null_fd, 1); 214 | dup2(fsrv->dev_null_fd, 2); 215 | 216 | /* Set up control and status pipes, close the unneeded original fds. */ 217 | 218 | if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) { PFATAL("dup2() failed"); } 219 | if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) { PFATAL("dup2() failed"); } 220 | 221 | close(ctl_pipe[0]); 222 | close(ctl_pipe[1]); 223 | close(st_pipe[0]); 224 | close(st_pipe[1]); 225 | 226 | execv(fsrv->target_path, fsrv->target_args); 227 | 228 | /* Use a distinctive bitmap signature to tell the parent about execv() 229 | falling through. */ 230 | 231 | fsrv->trace_bits = (u8 *)0xdeadbeef; 232 | fprintf(stderr, "Error: execv to target failed\n"); 233 | exit(0); 234 | 235 | } 236 | 237 | /* PARENT PROCESS */ 238 | 239 | char pid_buf[16]; 240 | sprintf(pid_buf, "%d", fsrv->fsrv_pid); 241 | /* Close the unneeded endpoints. */ 242 | 243 | close(ctl_pipe[0]); 244 | close(st_pipe[1]); 245 | 246 | fsrv->fsrv_ctl_fd = ctl_pipe[1]; 247 | fsrv->fsrv_st_fd = st_pipe[0]; 248 | 249 | /* Wait for the fork server to come up, but don't wait too long. */ 250 | 251 | rlen = 0; 252 | if (fsrv->exec_tmout) { 253 | 254 | u32 time_ms = afl_read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->exec_tmout * FORK_WAIT_MULT); 255 | 256 | if (!time_ms) { 257 | 258 | kill(fsrv->fsrv_pid, SIGKILL); 259 | 260 | } else if (time_ms > fsrv->exec_tmout * FORK_WAIT_MULT) { 261 | 262 | fsrv->last_run_timed_out = 1; 263 | kill(fsrv->fsrv_pid, SIGKILL); 264 | 265 | } else { 266 | 267 | rlen = 4; 268 | 269 | } 270 | 271 | } else { 272 | 273 | rlen = read(fsrv->fsrv_st_fd, &status, 4); 274 | 275 | } 276 | 277 | /* If we have a four-byte "hello" message from the server, we're all set. 278 | Otherwise, try to figure out what went wrong. */ 279 | 280 | if (rlen == 4) { 281 | 282 | OKF("All right - fork server is up."); 283 | return AFL_RET_SUCCESS; 284 | 285 | } 286 | 287 | if (fsrv->trace_bits == (u8 *)0xdeadbeef) { 288 | 289 | WARNF("Unable to execute target application ('%s')", fsrv->target_args[0]); 290 | return AFL_RET_EXEC_ERROR; 291 | 292 | } 293 | 294 | WARNF("Fork server handshake failed"); 295 | return AFL_RET_BROKEN_TARGET; 296 | 297 | } 298 | 299 | /* Places input in the executor for the target */ 300 | u8 fsrv_place_input(afl_executor_t *fsrv_executor, afl_input_t *input) { 301 | 302 | afl_forkserver_t *fsrv = (afl_forkserver_t *)fsrv_executor; 303 | 304 | if (!fsrv->use_stdin) { fsrv->out_fd = open(fsrv->out_file, O_RDWR | O_CREAT | O_EXCL, 00600); } 305 | 306 | ssize_t write_len = write(fsrv->out_fd, input->bytes, input->len); 307 | 308 | if (write_len < 0 || (size_t)write_len != input->len) { FATAL("Short Write"); } 309 | 310 | fsrv->base.current_input = input; 311 | 312 | if (!fsrv->use_stdin) { close(fsrv->out_fd); } 313 | 314 | return write_len; 315 | 316 | } 317 | 318 | /* Execute target application. Return status 319 | information.*/ 320 | afl_exit_t fsrv_run_target(afl_executor_t *fsrv_executor) { 321 | 322 | afl_forkserver_t *fsrv = (afl_forkserver_t *)fsrv_executor; 323 | 324 | s32 res; 325 | u32 exec_ms; 326 | u32 write_value = fsrv->last_run_timed_out; 327 | 328 | /* After this memset, fsrv->trace_bits[] are effectively volatile, so we 329 | must prevent any earlier operations from venturing into that 330 | territory. */ 331 | 332 | // memset(fsrv->trace_bits, 0, fsrv->map_size); 333 | 334 | MEM_BARRIER(); 335 | 336 | /* we have the fork server (or faux server) up and running 337 | First, tell it if the previous run timed out. */ 338 | 339 | if ((res = write(fsrv->fsrv_ctl_fd, &write_value, 4)) != 4) { 340 | 341 | RPFATAL(res, "Unable to request new process from fork server (OOM?)"); 342 | 343 | } 344 | 345 | fsrv->last_run_timed_out = 0; 346 | 347 | if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { 348 | 349 | RPFATAL(res, "Unable to request new process from fork server (OOM?)"); 350 | 351 | } 352 | 353 | if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); } 354 | 355 | exec_ms = afl_read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, fsrv->exec_tmout); 356 | 357 | if (exec_ms > fsrv->exec_tmout) { 358 | 359 | /* If there was no response from forkserver after timeout seconds, 360 | we kill the child. The forkserver should inform us afterwards */ 361 | 362 | kill(fsrv->child_pid, SIGKILL); 363 | fsrv->last_run_timed_out = 1; 364 | if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } 365 | 366 | } 367 | 368 | if (!exec_ms) {} 369 | 370 | if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; } 371 | 372 | fsrv->total_execs++; 373 | if (!fsrv->use_stdin) { unlink(fsrv->out_file); } 374 | 375 | /* Any subsequent operations on fsrv->trace_bits must not be moved by the 376 | compiler below this point. Past this location, fsrv->trace_bits[] 377 | behave very normally and do not have to be treated as volatile. */ 378 | 379 | MEM_BARRIER(); 380 | 381 | /* Report outcome to caller. */ 382 | 383 | if (WIFSIGNALED(fsrv->child_status)) { 384 | 385 | fsrv->last_kill_signal = WTERMSIG(fsrv->child_status); 386 | 387 | if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) { return AFL_EXIT_TIMEOUT; } 388 | 389 | return AFL_EXIT_CRASH; 390 | 391 | } 392 | 393 | return AFL_EXIT_OK; 394 | 395 | } 396 | 397 | /* An in-mem executor we have */ 398 | 399 | void in_memory_executor_init(in_memory_executor_t *in_memory_executor, harness_function_type harness) { 400 | 401 | afl_executor_init(&in_memory_executor->base); 402 | in_memory_executor->harness = harness; 403 | in_memory_executor->argv = NULL; 404 | in_memory_executor->argc = 0; 405 | 406 | in_memory_executor->base.funcs.run_target_cb = in_memory_run_target; 407 | in_memory_executor->base.funcs.place_input_cb = in_mem_executor_place_input; 408 | 409 | } 410 | 411 | void in_memory_executor_deinit(in_memory_executor_t *in_memory_executor) { 412 | 413 | afl_executor_deinit(&in_memory_executor->base); 414 | in_memory_executor->harness = NULL; 415 | in_memory_executor->argv = NULL; 416 | in_memory_executor->argc = 0; 417 | 418 | in_memory_executor->base.funcs.run_target_cb = in_memory_run_target; 419 | in_memory_executor->base.funcs.place_input_cb = in_mem_executor_place_input; 420 | 421 | } 422 | 423 | u8 in_mem_executor_place_input(afl_executor_t *executor, afl_input_t *input) { 424 | 425 | executor->current_input = input; 426 | return 0; 427 | 428 | } 429 | 430 | afl_exit_t in_memory_run_target(afl_executor_t *executor) { 431 | 432 | in_memory_executor_t *in_memory_executor = (in_memory_executor_t *)executor; 433 | 434 | afl_input_t *input = in_memory_executor->base.current_input; 435 | 436 | u8 *data = (input->funcs.serialize) ? (input->funcs.serialize(input)) : input->bytes; 437 | 438 | afl_exit_t run_result = in_memory_executor->harness(&in_memory_executor->base, data, input->len); 439 | 440 | return run_result; 441 | 442 | } 443 | 444 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #include 28 | 29 | #include "common.h" 30 | 31 | /* Get unix time in microseconds */ 32 | inline u64 afl_get_cur_time_us(void) { 33 | 34 | struct timeval tv; 35 | struct timezone tz; 36 | 37 | gettimeofday(&tv, &tz); 38 | 39 | return (tv.tv_sec * 1000000ULL) + tv.tv_usec; 40 | 41 | } 42 | 43 | bool afl_dir_exists(char *dirpath) { 44 | 45 | DIR *dir_in = NULL; 46 | 47 | size_t dir_name_size = strlen(dirpath); 48 | 49 | if (dirpath[dir_name_size - 1] == '/') { dirpath[dir_name_size - 1] = '\0'; } 50 | 51 | if (!(dir_in = opendir(dirpath))) { return false; } 52 | closedir(dir_in); 53 | return true; 54 | 55 | } 56 | 57 | /* Get unix time in seconds */ 58 | inline u64 afl_get_cur_time(void) { 59 | 60 | return afl_get_cur_time_us() / 1000; 61 | 62 | } 63 | 64 | /* Get unix time in microseconds */ 65 | inline u64 afl_get_cur_time_s(void) { 66 | 67 | struct timeval tv; 68 | struct timezone tz; 69 | 70 | gettimeofday(&tv, &tz); 71 | 72 | return tv.tv_sec; 73 | 74 | } 75 | 76 | /* Few helper functions */ 77 | 78 | void *afl_insert_substring(u8 *src_buf, u8 *dest_buf, size_t len, void *token, size_t token_len, size_t offset) { 79 | 80 | // void *new_buf = calloc(len + token_len + 1, 1); 81 | memmove(dest_buf, src_buf, offset); 82 | 83 | memmove(dest_buf + offset, token, token_len); 84 | 85 | memmove(dest_buf + offset + token_len, src_buf + offset, len - offset); 86 | 87 | return dest_buf; 88 | 89 | } 90 | 91 | /* This function inserts given number of bytes at a certain offset in a string 92 | and returns a ptr to the newly allocated memory. NOTE: You have to free the 93 | original memory(if malloced) yourself*/ 94 | u8 *afl_insert_bytes(u8 *src_buf, u8 *dest_buf, size_t len, u8 byte, size_t insert_len, size_t offset) { 95 | 96 | memmove(dest_buf, src_buf, offset); 97 | 98 | memset(dest_buf + offset, byte, insert_len); 99 | 100 | memmove(dest_buf + offset + insert_len, src_buf + offset, len - offset); 101 | 102 | return dest_buf; 103 | 104 | } 105 | 106 | size_t afl_erase_bytes(u8 *buf, size_t len, size_t offset, size_t remove_len) { 107 | 108 | memmove(buf + offset, buf + offset + remove_len, len - offset - remove_len); 109 | memset(buf + len - remove_len, 0x0, remove_len); 110 | 111 | size_t new_size = len - remove_len; 112 | 113 | return new_size; 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/engine.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "engine.h" 33 | #include "aflpp.h" 34 | #include "afl-returns.h" 35 | #include "fuzzone.h" 36 | #include "os.h" 37 | #include "queue.h" 38 | #include "input.h" 39 | 40 | afl_ret_t afl_engine_init(afl_engine_t *engine, afl_executor_t *executor, afl_fuzz_one_t *fuzz_one, 41 | afl_queue_global_t *global_queue) { 42 | 43 | engine->executor = executor; 44 | engine->fuzz_one = fuzz_one; 45 | engine->global_queue = global_queue; 46 | engine->feedbacks = NULL; 47 | engine->feedbacks_count = 0; 48 | engine->executions = 0; 49 | engine->cpu_bound = -1; // Initialize bound cpu to -1 (0xffffffff) bit mask for non affinity 50 | 51 | if (global_queue) { global_queue->base.funcs.set_engine(&global_queue->base, engine); } 52 | 53 | engine->funcs.get_queue = afl_engine_get_queue; 54 | engine->funcs.get_execs = afl_get_execs; 55 | engine->funcs.get_fuzz_one = afl_engine_get_fuzz_one; 56 | engine->funcs.get_start_time = afl_engine_get_start_time; 57 | 58 | engine->funcs.set_fuzz_one = afl_set_fuzz_one; 59 | engine->funcs.add_feedback = afl_engine_add_feedback; 60 | engine->funcs.set_global_queue = afl_set_global_queue; 61 | 62 | engine->funcs.execute = afl_engine_execute; 63 | engine->funcs.load_testcases_from_dir = afl_engine_load_testcases_from_dir; 64 | engine->funcs.loop = afl_engine_loop; 65 | engine->funcs.handle_new_message = afl_engine_handle_new_message; 66 | afl_ret_t ret = afl_rand_init(&engine->rand); 67 | 68 | engine->buf = NULL; 69 | 70 | if (ret != AFL_RET_SUCCESS) { return ret; } 71 | 72 | engine->id = afl_rand_next(&engine->rand); 73 | 74 | return AFL_RET_SUCCESS; 75 | 76 | } 77 | 78 | void afl_engine_deinit(afl_engine_t *engine) { 79 | 80 | size_t i; 81 | /* Let's free everything associated with the engine here, except the queues, 82 | * should we leave anything else? */ 83 | 84 | afl_rand_deinit(&engine->rand); 85 | 86 | engine->fuzz_one = NULL; 87 | engine->executor = NULL; 88 | engine->global_queue = NULL; 89 | 90 | for (i = 0; i < engine->feedbacks_count; ++i) { 91 | 92 | engine->feedbacks[i] = NULL; 93 | 94 | } 95 | 96 | afl_free(engine->feedbacks); 97 | engine->feedbacks = NULL; 98 | 99 | engine->start_time = 0; 100 | engine->current_feedback_queue = NULL; 101 | engine->feedbacks_count = 0; 102 | engine->executions = 0; 103 | 104 | } 105 | 106 | afl_queue_global_t *afl_engine_get_queue(afl_engine_t *engine) { 107 | 108 | return engine->global_queue; 109 | 110 | } 111 | 112 | afl_fuzz_one_t *afl_engine_get_fuzz_one(afl_engine_t *engine) { 113 | 114 | return engine->fuzz_one; 115 | 116 | } 117 | 118 | u64 afl_get_execs(afl_engine_t *engine) { 119 | 120 | return engine->executions; 121 | 122 | } 123 | 124 | u64 afl_engine_get_start_time(afl_engine_t *engine) { 125 | 126 | return engine->start_time; 127 | 128 | } 129 | 130 | void afl_set_fuzz_one(afl_engine_t *engine, afl_fuzz_one_t *fuzz_one) { 131 | 132 | engine->fuzz_one = fuzz_one; 133 | 134 | if (fuzz_one) { fuzz_one->funcs.set_engine(engine->fuzz_one, engine); } 135 | 136 | } 137 | 138 | void afl_set_global_queue(afl_engine_t *engine, afl_queue_global_t *global_queue) { 139 | 140 | engine->global_queue = global_queue; 141 | 142 | if (global_queue) { global_queue->base.funcs.set_engine(&global_queue->base, engine); } 143 | 144 | } 145 | 146 | afl_ret_t afl_engine_add_feedback(afl_engine_t *engine, afl_feedback_t *feedback) { 147 | 148 | engine->feedbacks_count++; 149 | engine->feedbacks = afl_realloc(engine->feedbacks, engine->feedbacks_count * sizeof(afl_feedback_t *)); 150 | if (!engine->feedbacks) { return AFL_RET_ALLOC; } 151 | 152 | engine->feedbacks[engine->feedbacks_count - 1] = feedback; 153 | 154 | return AFL_RET_SUCCESS; 155 | 156 | } 157 | 158 | static bool afl_engine_handle_single_testcase_load(char *infile, void *data) { 159 | 160 | afl_engine_t *engine = (afl_engine_t *)data; 161 | 162 | afl_input_t *input = afl_input_new(); 163 | 164 | if (!input) { 165 | 166 | DBG("Error allocating input %s", infile); 167 | return false; 168 | 169 | } 170 | 171 | AFL_TRY(input->funcs.load_from_file(input, infile), { 172 | 173 | WARNF("Error loading seed %s: %s", infile, afl_ret_stringify(err)); 174 | free(input); 175 | return false; 176 | 177 | }); 178 | 179 | /* 180 | afl_ret_t run_result = engine->funcs.execute(engine, input); 181 | 182 | if (run_result == AFL_RET_SUCCESS) { 183 | 184 | if (engine->verbose) OKF("Loaded seed %s", infile); 185 | 186 | } else { 187 | 188 | WARNF("Error loading seed %s", infile); 189 | // free(input); // should we? 190 | return false; 191 | 192 | } 193 | 194 | // We add the corpus to the queue initially for all the feedback queues 195 | 196 | size_t i; 197 | for (i = 0; i < engine->feedbacks_count; ++i) { 198 | 199 | afl_entry_t *entry = afl_entry_new(input); 200 | if (!entry) { 201 | 202 | DBG("Error allocating entry."); 203 | return false; 204 | 205 | } 206 | 207 | engine->feedbacks[i]->queue->base.funcs.insert(&engine->feedbacks[i]->queue->base, entry); 208 | 209 | } 210 | 211 | //if (run_result == AFL_RET_WRITE_TO_CRASH) { if (engine->verbose) WARNF("Crashing input found in initial corpus, 212 | this is usually not a good idea.\n"); } 213 | */ 214 | /* We add the corpus to the global queue */ 215 | afl_entry_t *entry = afl_entry_new(input, NULL); 216 | if (!entry) { 217 | 218 | DBG("Error allocating entry."); 219 | return false; 220 | 221 | } 222 | 223 | engine->global_queue->base.funcs.insert(&engine->global_queue->base, entry); 224 | if (engine->verbose) OKF("Loaded seed %s", infile); 225 | 226 | return true; 227 | 228 | } 229 | 230 | afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *engine, char *dirpath) { 231 | 232 | return afl_for_each_file(dirpath, afl_engine_handle_single_testcase_load, (void *)engine); 233 | 234 | } 235 | 236 | afl_ret_t afl_engine_handle_new_message(afl_engine_t *engine, llmp_message_t *msg) { 237 | 238 | /* Default implementation, handles only new queue entry messages. Users have 239 | * liberty with this function */ 240 | 241 | if (msg->tag == LLMP_TAG_NEW_QUEUE_ENTRY_V1) { 242 | 243 | afl_input_t *input = afl_input_new(); 244 | if (!input) { return AFL_RET_ALLOC; } 245 | 246 | /* the msg will stick around forever, so this is safe. */ 247 | input->bytes = msg->buf; 248 | input->len = msg->buf_len; 249 | 250 | afl_entry_info_t *info_ptr = (afl_entry_info_t *)((u8 *)(msg->buf + msg->buf_len)); 251 | 252 | afl_entry_t *new_entry = afl_entry_new(input, info_ptr); 253 | 254 | /* Users can experiment here, adding entries to different queues based on 255 | * the message tag. Right now, let's just add it to all queues*/ 256 | size_t i = 0; 257 | engine->global_queue->base.funcs.insert(&engine->global_queue->base, new_entry); 258 | afl_queue_feedback_t **feedback_queues = engine->global_queue->feedback_queues; 259 | for (i = 0; i < engine->global_queue->feedback_queues_count; ++i) { 260 | 261 | feedback_queues[i]->base.funcs.insert(&feedback_queues[i]->base, new_entry); 262 | 263 | } 264 | 265 | } 266 | 267 | return AFL_RET_SUCCESS; 268 | 269 | } 270 | 271 | u8 afl_engine_execute(afl_engine_t *engine, afl_input_t *input) { 272 | 273 | size_t i; 274 | afl_executor_t *executor = engine->executor; 275 | 276 | executor->funcs.observers_reset(executor); 277 | 278 | executor->funcs.place_input_cb(executor, input); 279 | 280 | if (engine->start_time == 0) { engine->start_time = time(NULL); } 281 | 282 | afl_exit_t run_result = executor->funcs.run_target_cb(executor); 283 | 284 | engine->executions++; 285 | 286 | /* We've run the target with the executor, we can now simply postExec call the 287 | * observation channels*/ 288 | 289 | for (i = 0; i < executor->observors_count; ++i) { 290 | 291 | afl_observer_t *obs_channel = executor->observors[i]; 292 | if (obs_channel->funcs.post_exec) { obs_channel->funcs.post_exec(executor->observors[i], engine); } 293 | 294 | } 295 | 296 | // Now based on the return of executor's run target, we basically return an 297 | // afl_ret_t type to the callee 298 | 299 | switch (run_result) { 300 | 301 | case AFL_EXIT_OK: 302 | case AFL_EXIT_TIMEOUT: 303 | return AFL_RET_SUCCESS; 304 | default: { 305 | 306 | afl_queue_global_t *global_queue = afl_engine_get_queue(engine); 307 | if (afl_input_dump_to_crashfile(executor->current_input, global_queue->base.dirpath) == AFL_RET_SUCCESS) 308 | engine->crashes++; 309 | return AFL_RET_WRITE_TO_CRASH; 310 | 311 | } 312 | 313 | } 314 | 315 | } 316 | 317 | afl_ret_t afl_engine_loop(afl_engine_t *engine) { 318 | 319 | while (true) { 320 | 321 | afl_ret_t fuzz_one_ret = engine->fuzz_one->funcs.perform(engine->fuzz_one); 322 | 323 | /* let's call this engine's message handler */ 324 | 325 | if (engine->funcs.handle_new_message) { 326 | 327 | /* Let's read the broadcasted messages now */ 328 | llmp_message_t *msg = NULL; 329 | 330 | while ((msg = llmp_client_recv(engine->llmp_client))) { 331 | 332 | AFL_TRY(engine->funcs.handle_new_message(engine, msg), { return err; }); 333 | 334 | } 335 | 336 | } 337 | 338 | switch (fuzz_one_ret) { 339 | 340 | // case AFL_RET_WRITE_TO_CRASH: 341 | 342 | // // crash_write_return = 343 | // // afl_input_dump_to_crashfile(engine->executor->current_input); 344 | 345 | // return AFL_RET_WRITE_TO_CRASH; 346 | 347 | // break; 348 | 349 | case AFL_RET_NULL_QUEUE_ENTRY: 350 | SAYF("NULL QUEUE\n"); 351 | return fuzz_one_ret; 352 | case AFL_RET_ERROR_INPUT_COPY: 353 | return fuzz_one_ret; 354 | default: 355 | continue; 356 | 357 | } 358 | 359 | } 360 | 361 | } 362 | 363 | /* A function which can be run just before starting the fuzzing process. This checks if the engine(and all it's 364 | * components) is initialized or not */ 365 | 366 | afl_ret_t afl_engine_check_configuration(afl_engine_t *engine) { 367 | 368 | bool has_warning = false; 369 | 370 | #define AFL_WARN_ENGINE(str) \ 371 | do { \ 372 | \ 373 | WARNF("No " str " present in engine-%u", engine->id); \ 374 | has_warning = true; \ 375 | \ 376 | } while (0); 377 | 378 | if (!engine) { 379 | 380 | WARNF("Engine is null"); 381 | return AFL_RET_NULL_PTR; 382 | 383 | } 384 | 385 | /* Let's start by checking the essential parts of engine, executor, feedback(if available) */ 386 | 387 | if (!engine->executor) { 388 | 389 | // WARNF("No executor present in engine-%u", engine->id); 390 | // goto error; 391 | AFL_WARN_ENGINE("executor"); 392 | 393 | } 394 | 395 | afl_executor_t *executor = engine->executor; 396 | 397 | if (!engine->global_queue) { AFL_WARN_ENGINE("global_queue") } 398 | afl_queue_global_t *global_queue = engine->global_queue; 399 | 400 | if (!engine->fuzz_one) { AFL_WARN_ENGINE("fuzzone") } 401 | afl_fuzz_one_t *fuzz_one = engine->fuzz_one; 402 | 403 | for (size_t i = 0; i < engine->feedbacks_count; ++i) { 404 | 405 | if (!engine->feedbacks[i]) { 406 | 407 | WARNF("Feedback is NULL at %zu idx but feedback count is greater (%llu).", i, engine->feedbacks_count); 408 | has_warning = true; 409 | break; 410 | 411 | } 412 | 413 | } 414 | 415 | if (!engine->llmp_client) { AFL_WARN_ENGINE("llmp client") } 416 | 417 | if (executor) { 418 | 419 | for (size_t i = 0; i < executor->observors_count; ++i) { 420 | 421 | if (!executor->observors[i]) { AFL_WARN_ENGINE("observation channel") } 422 | 423 | } 424 | 425 | } 426 | 427 | if (global_queue) { 428 | 429 | for (size_t i = 0; i < global_queue->feedback_queues_count; ++i) { 430 | 431 | if (!global_queue->feedback_queues[i]) { AFL_WARN_ENGINE("Feedback queue") } 432 | 433 | } 434 | 435 | } 436 | 437 | if (fuzz_one) { 438 | 439 | for (size_t i = 0; i < fuzz_one->stages_count; ++i) { 440 | 441 | if (!fuzz_one->stages[i]) { AFL_WARN_ENGINE("Stage") } 442 | /* Stage needs to be checked properly */ 443 | 444 | } 445 | 446 | } 447 | 448 | if (has_warning) { return AFL_RET_ERROR_INITIALIZE; } 449 | 450 | return AFL_RET_SUCCESS; 451 | 452 | #undef AFL_WARN_ENGINE 453 | 454 | } 455 | 456 | -------------------------------------------------------------------------------- /src/feedback.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #include "feedback.h" 28 | #include "observer.h" 29 | #include "aflpp.h" 30 | 31 | afl_ret_t afl_feedback_init(afl_feedback_t *feedback, afl_queue_feedback_t *queue) { 32 | 33 | feedback->queue = queue; 34 | 35 | feedback->funcs.set_feedback_queue = afl_feedback_set_queue; 36 | feedback->funcs.get_feedback_queue = afl_feedback_get_queue; 37 | feedback->funcs.is_interesting = NULL; 38 | 39 | feedback->tag = AFL_FEEDBACK_TAG_BASE; 40 | 41 | return AFL_RET_SUCCESS; 42 | 43 | } 44 | 45 | void afl_feedback_deinit(afl_feedback_t *feedback) { 46 | 47 | feedback->tag = AFL_DEINITIALIZED; 48 | 49 | /* Since feedback is deinitialized, we remove it's ptr from the feedback_queue 50 | */ 51 | feedback->queue = NULL; 52 | 53 | } 54 | 55 | void afl_feedback_set_queue(afl_feedback_t *feedback, afl_queue_feedback_t *queue) { 56 | 57 | feedback->queue = queue; 58 | 59 | if (queue) { queue->feedback = feedback; } 60 | 61 | } 62 | 63 | afl_queue_feedback_t *afl_feedback_get_queue(afl_feedback_t *feedback) { 64 | 65 | return feedback->queue; 66 | 67 | } 68 | 69 | /* Map feedback. Can be easily used with a tracebits map similar to AFL++ */ 70 | 71 | afl_ret_t afl_feedback_cov_init(afl_feedback_cov_t *feedback, afl_queue_feedback_t *queue, 72 | afl_observer_covmap_t *observer_cov) { 73 | 74 | size_t size = observer_cov->shared_map.map_size; 75 | 76 | feedback->observer_cov = observer_cov; 77 | 78 | feedback->virgin_bits = calloc(1, size); 79 | if (!feedback->virgin_bits) { return AFL_RET_ALLOC; } 80 | memset(feedback->virgin_bits, 0xff, size); 81 | 82 | AFL_TRY(afl_feedback_init(&feedback->base, queue), { 83 | 84 | free(feedback->virgin_bits); 85 | return err; 86 | 87 | }); 88 | 89 | feedback->size = size; 90 | feedback->base.funcs.is_interesting = afl_feedback_cov_is_interesting; 91 | 92 | feedback->base.tag = AFL_FEEDBACK_TAG_COV; 93 | 94 | return AFL_RET_SUCCESS; 95 | 96 | } 97 | 98 | /* Set virgin bits according to the map passed into the func */ 99 | afl_ret_t afl_feedback_cov_set_virgin_bits(afl_feedback_cov_t *feedback, u8 *virgin_bits_copy_from, size_t size) { 100 | 101 | if (size != feedback->observer_cov->shared_map.map_size) { 102 | 103 | FATAL("Virgin bitmap size may never differs from observer_covmap size"); 104 | 105 | } 106 | 107 | feedback->virgin_bits = realloc(feedback->virgin_bits, size); 108 | if (!feedback->virgin_bits) { 109 | 110 | DBG("Failed to alloc %ld bytes for virgin_bitmap", size); 111 | feedback->size = 0; 112 | return AFL_RET_ALLOC; 113 | 114 | } 115 | 116 | memcpy(feedback->virgin_bits, virgin_bits_copy_from, size); 117 | feedback->size = size; 118 | return AFL_RET_SUCCESS; 119 | 120 | } 121 | 122 | void afl_feedback_cov_deinit(afl_feedback_cov_t *feedback) { 123 | 124 | free(feedback->virgin_bits); 125 | feedback->virgin_bits = NULL; 126 | feedback->size = 0; 127 | afl_feedback_deinit(&feedback->base); 128 | 129 | } 130 | 131 | float __attribute__((hot)) afl_feedback_cov_is_interesting(afl_feedback_t *feedback, afl_executor_t *fsrv) { 132 | 133 | (void)fsrv; 134 | 135 | #ifdef AFL_DEBUG 136 | if (feedback->tag != AFL_FEEDBACK_TAG_COV) { FATAL("Called cov_is_interesting with non-cov feeback"); } 137 | #endif 138 | 139 | afl_feedback_cov_t * map_feedback = (afl_feedback_cov_t *)feedback; 140 | afl_observer_covmap_t *obs_channel = map_feedback->observer_cov; 141 | 142 | #ifdef WORD_SIZE_64 143 | 144 | u64 *current = (u64 *)obs_channel->shared_map.map; 145 | u64 *virgin = (u64 *)map_feedback->virgin_bits; 146 | 147 | u32 i = (obs_channel->shared_map.map_size >> 3); 148 | 149 | #else 150 | 151 | u32 *current = (u32 *)obs_channel->shared_map.map; 152 | u32 *virgin = (u32 *)map_feedback->virgin_bits; 153 | 154 | u32 i = (obs_channel->shared_map.map_size >> 2); 155 | 156 | #endif /* ^WORD_SIZE_64 */ 157 | // the map size must be a minimum of 8 bytes. 158 | // for variable/dynamic map sizes this is ensured in the forkserver 159 | 160 | float ret = 0.0; 161 | 162 | while (i--) { 163 | 164 | /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap 165 | that have not been already cleared from the virgin map - since this will 166 | almost always be the case. */ 167 | 168 | // the (*current) is unnecessary but speeds up the overall comparison 169 | if (unlikely(*current) && unlikely(*current & *virgin)) { 170 | 171 | if (likely(ret < 2)) { 172 | 173 | u8 *cur = (u8 *)current; 174 | u8 *vir = (u8 *)virgin; 175 | 176 | /* Looks like we have not found any new bytes yet; see if any non-zero 177 | bytes in current[] are pristine in virgin[]. */ 178 | 179 | #ifdef WORD_SIZE_64 180 | 181 | if (*virgin == 0xffffffffffffffff || (cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || 182 | (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) || 183 | (cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) { 184 | 185 | ret = 1.0; 186 | 187 | } else { 188 | 189 | ret = 0.5; 190 | 191 | } 192 | 193 | #else 194 | 195 | if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || 196 | (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) 197 | ret = 1.0; 198 | else 199 | ret = 0.5; 200 | 201 | #endif /* ^WORD_SIZE_64 */ 202 | 203 | } 204 | 205 | *virgin &= ~*current; 206 | 207 | } 208 | 209 | ++current; 210 | ++virgin; 211 | 212 | } 213 | 214 | #ifdef DEBUG 215 | DBG("MAP: %p %lu", obs_channel->shared_map.map, obs_channel->shared_map.map_size); 216 | for (u32 j = 0; j < obs_channel->shared_map.map_size; j++) { 217 | 218 | if (obs_channel->shared_map.map[j]) { printf(" %04x=%02x", j, obs_channel->shared_map.map[j]); } 219 | 220 | } 221 | 222 | printf(" ret=%f\n", ret); 223 | #endif 224 | 225 | return ret; 226 | 227 | } 228 | 229 | -------------------------------------------------------------------------------- /src/fuzzone.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | #include "queue.h" 24 | #include "fuzzone.h" 25 | #include "engine.h" 26 | #include "stage.h" 27 | 28 | afl_ret_t afl_fuzz_one_init(afl_fuzz_one_t *fuzz_one, afl_engine_t *engine) { 29 | 30 | fuzz_one->engine = engine; 31 | 32 | if (engine) { engine->fuzz_one = fuzz_one; } 33 | 34 | fuzz_one->funcs.add_stage = afl_fuzz_one_add_stage; 35 | fuzz_one->funcs.perform = afl_fuzz_one_perform; 36 | fuzz_one->funcs.set_engine = afl_fuzz_one_set_engine; 37 | 38 | return AFL_RET_SUCCESS; 39 | 40 | } 41 | 42 | void afl_fuzz_one_deinit(afl_fuzz_one_t *fuzz_one) { 43 | 44 | size_t i; 45 | /* Also remove the fuzz one from engine */ 46 | fuzz_one->engine = NULL; 47 | 48 | /* TODO: Should we deinitialize the stages or just remove the reference of 49 | * fuzzone from them? */ 50 | for (i = 0; i < fuzz_one->stages_count; ++i) { 51 | 52 | fuzz_one->stages[i] = NULL; 53 | 54 | } 55 | 56 | afl_free(fuzz_one->stages); 57 | fuzz_one->stages = NULL; 58 | fuzz_one->stages_count = 0; 59 | 60 | } 61 | 62 | afl_ret_t afl_fuzz_one_perform(afl_fuzz_one_t *fuzz_one) { 63 | 64 | // Fuzzone grabs the current queue entry from the global queue and 65 | // sends it to stage. 66 | size_t i; 67 | 68 | afl_queue_global_t *global_queue = fuzz_one->engine->global_queue; 69 | 70 | afl_entry_t *queue_entry = 71 | global_queue->base.funcs.get_next_in_queue((afl_queue_t *)global_queue, fuzz_one->engine->id); 72 | 73 | if (!queue_entry) { return AFL_RET_NULL_QUEUE_ENTRY; } 74 | 75 | /* Fuzz the entry with every stage */ 76 | for (i = 0; i < fuzz_one->stages_count; ++i) { 77 | 78 | afl_stage_t *current_stage = fuzz_one->stages[i]; 79 | afl_ret_t stage_ret = current_stage->funcs.perform(current_stage, queue_entry->input); 80 | 81 | switch (stage_ret) { 82 | 83 | case AFL_RET_SUCCESS: 84 | continue; 85 | default: 86 | return stage_ret; 87 | 88 | } 89 | 90 | } 91 | 92 | return AFL_RET_SUCCESS; 93 | 94 | } 95 | 96 | afl_ret_t afl_fuzz_one_add_stage(afl_fuzz_one_t *fuzz_one, afl_stage_t *stage) { 97 | 98 | if (!stage || !fuzz_one) { return AFL_RET_NULL_PTR; } 99 | 100 | fuzz_one->stages_count++; 101 | fuzz_one->stages = afl_realloc(fuzz_one->stages, fuzz_one->stages_count * sizeof(afl_stage_t *)); 102 | if (!fuzz_one->stages) { return AFL_RET_ALLOC; } 103 | 104 | fuzz_one->stages[fuzz_one->stages_count - 1] = stage; 105 | 106 | stage->engine = fuzz_one->engine; 107 | 108 | return AFL_RET_SUCCESS; 109 | 110 | } 111 | 112 | afl_ret_t afl_fuzz_one_set_engine(afl_fuzz_one_t *fuzz_one, afl_engine_t *engine) { 113 | 114 | size_t i; 115 | fuzz_one->engine = engine; 116 | 117 | if (engine) { engine->fuzz_one = fuzz_one; } 118 | 119 | for (i = 0; i < fuzz_one->stages_count; ++i) { 120 | 121 | fuzz_one->stages[i]->engine = engine; 122 | 123 | } 124 | 125 | return AFL_RET_SUCCESS; 126 | 127 | } 128 | 129 | -------------------------------------------------------------------------------- /src/input.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "input.h" 33 | #include "afl-returns.h" 34 | #include "xxh3.h" 35 | #include "xxhash.h" 36 | #include "alloc-inl.h" 37 | 38 | afl_ret_t afl_input_init(afl_input_t *input) { 39 | 40 | input->funcs.clear = afl_input_clear; 41 | input->funcs.copy = afl_input_copy; 42 | input->funcs.deserialize = afl_input_deserialize; 43 | input->funcs.get_bytes = afl_input_get_bytes; 44 | input->funcs.load_from_file = afl_input_load_from_file; 45 | input->funcs.restore = afl_input_restore; 46 | input->funcs.save_to_file = afl_input_write_to_file; 47 | input->funcs.serialize = afl_input_serialize; 48 | input->funcs.delete = afl_input_delete; 49 | 50 | input->copy_buf = NULL; 51 | 52 | input->bytes = NULL; 53 | input->len = 0; 54 | 55 | return AFL_RET_SUCCESS; 56 | 57 | } 58 | 59 | void afl_input_deinit(afl_input_t *input) { 60 | 61 | /* Deiniting requires a little hack. We free the byte ONLY if copy buf is not NULL. Because then we can assume that 62 | * the input is in the queue*/ 63 | if (input->bytes && input->copy_buf) { 64 | 65 | free(input->bytes); 66 | afl_free(input->copy_buf); 67 | 68 | } 69 | 70 | input->bytes = NULL; 71 | input->len = 0; 72 | 73 | return; 74 | 75 | } 76 | 77 | // default implemenatations for the vtable functions for the raw_input type 78 | 79 | void afl_input_clear(afl_input_t *input) { 80 | 81 | memset(input->bytes, 0x0, input->len); 82 | input->len = 0; 83 | 84 | return; 85 | 86 | } 87 | 88 | afl_input_t *afl_input_copy(afl_input_t *orig_inp) { 89 | 90 | afl_input_t *copy_inp = afl_input_new(); 91 | if (!copy_inp) { return NULL; } 92 | copy_inp->bytes = afl_realloc(orig_inp->copy_buf, (orig_inp->len) * sizeof(u8)); 93 | orig_inp->copy_buf = copy_inp->bytes; 94 | if (!copy_inp->bytes) { 95 | 96 | afl_input_delete(copy_inp); 97 | return NULL; 98 | 99 | } 100 | 101 | memcpy(copy_inp->bytes, orig_inp->bytes, orig_inp->len); 102 | copy_inp->len = orig_inp->len; 103 | return copy_inp; 104 | 105 | } 106 | 107 | void afl_input_deserialize(afl_input_t *input, u8 *bytes, size_t len) { 108 | 109 | if (input->bytes) free(input->bytes); 110 | input->bytes = bytes; 111 | input->len = len; 112 | 113 | return; 114 | 115 | } 116 | 117 | u8 *afl_input_get_bytes(afl_input_t *input) { 118 | 119 | return input->bytes; 120 | 121 | } 122 | 123 | afl_ret_t afl_input_load_from_file(afl_input_t *input, char *fname) { 124 | 125 | struct stat st; 126 | s32 fd = open(fname, O_RDONLY); 127 | 128 | if (fd < 0) { return AFL_RET_FILE_OPEN_ERROR; } 129 | 130 | if (fstat(fd, &st) || !st.st_size) { 131 | 132 | close(fd); 133 | return AFL_RET_FILE_SIZE; 134 | 135 | } 136 | 137 | input->len = st.st_size; 138 | input->bytes = calloc(input->len + 1, 1); 139 | if (!input->bytes) { 140 | 141 | close(fd); 142 | return AFL_RET_ALLOC; 143 | 144 | } 145 | 146 | ssize_t ret = read(fd, input->bytes, input->len); 147 | close(fd); 148 | 149 | if (ret < 0 || (size_t)ret != input->len) { 150 | 151 | free(input->bytes); 152 | input->bytes = NULL; 153 | return AFL_RET_SHORT_READ; 154 | 155 | } 156 | 157 | return AFL_RET_SUCCESS; 158 | 159 | } 160 | 161 | afl_ret_t afl_input_write_to_file(afl_input_t *input, char *fname) { 162 | 163 | // if it already exists we will not overwrite it 164 | if (access(fname, W_OK) == 0) return AFL_RET_FILE_DUPLICATE; 165 | 166 | s32 fd = open(fname, O_RDWR | O_CREAT | O_EXCL, 0600); 167 | 168 | if (fd < 0) { return AFL_RET_FILE_OPEN_ERROR; } 169 | 170 | ssize_t write_len = write(fd, input->bytes, input->len); 171 | close(fd); 172 | 173 | if (write_len < (ssize_t)input->len) { return AFL_RET_SHORT_WRITE; } 174 | 175 | return AFL_RET_SUCCESS; 176 | 177 | } 178 | 179 | void afl_input_restore(afl_input_t *input, afl_input_t *new_inp) { 180 | 181 | input->bytes = new_inp->bytes; 182 | 183 | return; 184 | 185 | } 186 | 187 | u8 *afl_input_serialize(afl_input_t *input) { 188 | 189 | // Very stripped down implementation, actually depends on user alot. 190 | return input->bytes; 191 | 192 | } 193 | 194 | afl_ret_t afl_input_dump_to_file(char *filetag, afl_input_t *data, char *directory) { 195 | 196 | char filename[PATH_MAX]; 197 | 198 | /* TODO: This filename should be replaced by "crashes-SHA_OF_BYTES" later */ 199 | 200 | u64 input_data_checksum = XXH64(data->bytes, data->len, HASH_CONST); 201 | if (directory) { 202 | 203 | snprintf(filename, sizeof(filename), "%s/%s-%016llx", directory, filetag, input_data_checksum); 204 | 205 | } else { 206 | 207 | snprintf(filename, sizeof(filename), "%s-%016llx", filetag, input_data_checksum); 208 | 209 | } 210 | 211 | return afl_input_write_to_file(data, filename); 212 | 213 | } 214 | 215 | // Timeout related functions 216 | afl_ret_t afl_input_dump_to_timeoutfile(afl_input_t *data, char *directory) { 217 | 218 | return afl_input_dump_to_file("timeout", data, directory); 219 | 220 | } 221 | 222 | // Crash related functions 223 | afl_ret_t afl_input_dump_to_crashfile(afl_input_t *data, char *directory) { 224 | 225 | return afl_input_dump_to_file("crash", data, directory); 226 | 227 | } 228 | 229 | -------------------------------------------------------------------------------- /src/observer.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #include "observer.h" 28 | #include "afl-returns.h" 29 | #include "common.h" 30 | 31 | afl_ret_t afl_observer_init(afl_observer_t *channel) { 32 | 33 | (void)channel; 34 | 35 | channel->tag = AFL_OBSERVER_TAG_BASE; 36 | return AFL_RET_SUCCESS; 37 | 38 | } 39 | 40 | void afl_observer_deinit(afl_observer_t *channel) { 41 | 42 | channel->tag = AFL_DEINITIALIZED; 43 | (void)channel; 44 | 45 | } 46 | 47 | void afl_observer_flush(afl_observer_t *channel) { 48 | 49 | (void)channel; 50 | 51 | /* TODO: Implementation */ 52 | return; 53 | 54 | } 55 | 56 | void afl_observer_reset(afl_observer_t *channel) { 57 | 58 | (void)channel; 59 | 60 | /* TODO: Implementation */ 61 | return; 62 | 63 | } 64 | 65 | void afl_observer_post_exec(afl_observer_t *channel) { 66 | 67 | (void)channel; 68 | 69 | /* TODO: Implementation */ 70 | return; 71 | 72 | } 73 | 74 | afl_ret_t afl_observer_covmap_init(afl_observer_covmap_t *map_channel, size_t map_size) { 75 | 76 | afl_observer_init(&map_channel->base); 77 | map_channel->base.tag = AFL_OBSERVER_TAG_COVMAP; 78 | 79 | if (!afl_shmem_init(&map_channel->shared_map, map_size)) { return AFL_RET_ERROR_INITIALIZE; } 80 | 81 | map_channel->base.funcs.reset = afl_observer_covmap_reset; 82 | 83 | map_channel->funcs.get_map_size = afl_observer_covmap_get_map_size; 84 | map_channel->funcs.get_trace_bits = afl_observer_covmap_get_trace_bits; 85 | 86 | return AFL_RET_SUCCESS; 87 | 88 | } 89 | 90 | void afl_observer_covmap_deinit(afl_observer_covmap_t *map_channel) { 91 | 92 | afl_shmem_deinit(&map_channel->shared_map); 93 | 94 | afl_observer_deinit(&map_channel->base); 95 | 96 | } 97 | 98 | void afl_observer_covmap_reset(afl_observer_t *channel) { 99 | 100 | afl_observer_covmap_t *map_channel = (afl_observer_covmap_t *)channel; 101 | 102 | memset(map_channel->shared_map.map, 0, map_channel->shared_map.map_size); 103 | 104 | } 105 | 106 | u8 *afl_observer_covmap_get_trace_bits(afl_observer_covmap_t *obs_channel) { 107 | 108 | return obs_channel->shared_map.map; 109 | 110 | } 111 | 112 | size_t afl_observer_covmap_get_map_size(afl_observer_covmap_t *obs_channel) { 113 | 114 | return obs_channel->shared_map.map_size; 115 | 116 | } 117 | 118 | -------------------------------------------------------------------------------- /src/queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | This is the Library based on AFL++ which can be used to build 22 | customized fuzzers for a specific target while taking advantage of 23 | a lot of features that AFL++ already provides. 24 | 25 | */ 26 | 27 | #include 28 | 29 | #include "queue.h" 30 | #include "feedback.h" 31 | #include "engine.h" 32 | #include "fuzzone.h" 33 | #include "stage.h" 34 | #include "mutator.h" 35 | #include "config.h" 36 | 37 | // We start with the implementation of queue_entry functions here. 38 | afl_ret_t afl_entry_init(afl_entry_t *entry, afl_input_t *input, afl_entry_info_t *info) { 39 | 40 | entry->input = input; 41 | if (!info) { 42 | 43 | entry->info = calloc(1, sizeof(afl_entry_info_t)); 44 | if (!entry->info) { return AFL_RET_ALLOC; } 45 | entry->info_calloc = 1; 46 | 47 | } else { 48 | 49 | entry->info = info; 50 | 51 | } 52 | 53 | entry->funcs.get_input = afl_entry_get_input; 54 | entry->funcs.get_next = afl_entry_get_next; 55 | entry->funcs.get_prev = afl_entry_get_prev; 56 | entry->funcs.get_parent = afl_entry_get_parent; 57 | 58 | return AFL_RET_SUCCESS; 59 | 60 | } 61 | 62 | void afl_entry_deinit(afl_entry_t *entry) { 63 | 64 | /* We remove the element from the linked-list */ 65 | 66 | if (entry->next) { entry->next->prev = entry->prev; } 67 | 68 | if (entry->prev) { entry->prev->next = entry->next; } 69 | 70 | /* we also delete the input associated with it */ 71 | entry->input->funcs.delete(entry->input); 72 | 73 | /* and the info structure */ 74 | if (entry->info_calloc) { free(entry->info); } 75 | 76 | /* 77 | // Unneeded as the structure is free'd via the macro 78 | entry->next = NULL; 79 | entry->prev = NULL; 80 | entry->queue = NULL; 81 | entry->parent = NULL; 82 | entry->info = NULL; 83 | entry->input = NULL; 84 | */ 85 | 86 | } 87 | 88 | // Default implementations for the queue entry vtable functions 89 | afl_input_t *afl_entry_get_input(afl_entry_t *entry) { 90 | 91 | return entry->input; 92 | 93 | } 94 | 95 | afl_entry_t *afl_entry_get_next(afl_entry_t *entry) { 96 | 97 | return entry->next; 98 | 99 | } 100 | 101 | afl_entry_t *afl_entry_get_prev(afl_entry_t *entry) { 102 | 103 | return entry->prev; 104 | 105 | } 106 | 107 | afl_entry_t *afl_entry_get_parent(afl_entry_t *entry) { 108 | 109 | return entry->parent; 110 | 111 | } 112 | 113 | // We implement the queue based functions now. 114 | 115 | afl_ret_t afl_queue_init(afl_queue_t *queue) { 116 | 117 | queue->entries = NULL; 118 | queue->save_to_files = false; 119 | queue->fuzz_started = false; 120 | queue->entries_count = 0; 121 | queue->base = NULL; 122 | queue->current = 0; 123 | memset(queue->dirpath, 0, PATH_MAX); 124 | 125 | queue->funcs.insert = afl_queue_insert; 126 | queue->funcs.get_size = afl_queue_get_size; 127 | queue->funcs.get_dirpath = afl_queue_get_dirpath; 128 | queue->funcs.get_names_id = afl_queue_get_names_id; 129 | queue->funcs.get_save_to_files = afl_queue_should_save_to_file; 130 | queue->funcs.set_dirpath = afl_queue_set_dirpath; 131 | queue->funcs.set_engine = afl_queue_set_engine; 132 | queue->funcs.get_next_in_queue = afl_queue_next_base_queue; 133 | queue->funcs.get_queue_entry = afl_queue_get_entry; 134 | 135 | return AFL_RET_SUCCESS; 136 | 137 | } 138 | 139 | void afl_queue_deinit(afl_queue_t *queue) { 140 | 141 | /*TODO: Clear the queue entries too here*/ 142 | 143 | afl_entry_t *entry = queue->base; 144 | 145 | while (entry) { 146 | 147 | /* Grab the next entry of queue */ 148 | afl_entry_t *next_entry = entry->next; 149 | 150 | /* We destroy the queue, since none of the entries have references anywhere 151 | * else anyways */ 152 | afl_entry_delete(entry); 153 | 154 | entry = next_entry; 155 | 156 | } 157 | 158 | afl_free(queue->entries); 159 | 160 | queue->base = NULL; 161 | queue->current = 0; 162 | queue->entries_count = 0; 163 | queue->fuzz_started = false; 164 | 165 | } 166 | 167 | /* *** Possible error cases here? *** */ 168 | afl_ret_t afl_queue_insert(afl_queue_t *queue, afl_entry_t *entry) { 169 | 170 | if (!entry->input) { 171 | 172 | // Never add an entry with NULL input, something's wrong! 173 | WARNF("Queue entry with NULL input"); 174 | return AFL_RET_NULL_PTR; 175 | 176 | } 177 | 178 | // Before we add the entry to the queue, we call the custom mutators 179 | // get_next_in_queue function, so that it can gain some extra info from the 180 | // fuzzed queue(especially helpful in case of grammar mutator, e.g see hogfuzz 181 | // mutator AFL++) 182 | 183 | afl_fuzz_one_t *fuzz_one = queue->engine->fuzz_one; 184 | 185 | if (fuzz_one) { 186 | 187 | size_t i; 188 | for (i = 0; i < fuzz_one->stages_count; ++i) { 189 | 190 | afl_stage_t *stage = fuzz_one->stages[i]; 191 | size_t j; 192 | for (j = 0; j < stage->mutators_count; ++j) { 193 | 194 | if (stage->mutators[j]->funcs.custom_queue_new_entry) { 195 | 196 | stage->mutators[j]->funcs.custom_queue_new_entry(stage->mutators[j], entry); 197 | 198 | } 199 | 200 | } 201 | 202 | } 203 | 204 | } 205 | 206 | queue->entries_count++; 207 | queue->entries = afl_realloc(queue->entries, queue->entries_count * sizeof(afl_entry_t *)); 208 | if (!queue->entries) { return AFL_RET_ALLOC; } 209 | 210 | queue->entries[queue->entries_count - 1] = entry; 211 | 212 | /* Let's save the entry to disk */ 213 | if (queue->save_to_files && queue->dirpath[0] && !entry->on_disk) { 214 | 215 | u64 input_data_checksum = XXH64(entry->input->bytes, entry->input->len, HASH_CONST); 216 | 217 | snprintf(entry->filename, FILENAME_LEN_MAX - 1, "%s/queue-%016llx", queue->dirpath, input_data_checksum); 218 | 219 | entry->input->funcs.save_to_file(entry->input, entry->filename); 220 | 221 | entry->on_disk = true; 222 | 223 | } 224 | 225 | return AFL_RET_SUCCESS; 226 | 227 | } 228 | 229 | size_t afl_queue_get_size(afl_queue_t *queue) { 230 | 231 | return queue->entries_count; 232 | 233 | } 234 | 235 | char *afl_queue_get_dirpath(afl_queue_t *queue) { 236 | 237 | return queue->dirpath; 238 | 239 | } 240 | 241 | size_t afl_queue_get_names_id(afl_queue_t *queue) { 242 | 243 | return queue->names_id; 244 | 245 | } 246 | 247 | bool afl_queue_should_save_to_file(afl_queue_t *queue) { 248 | 249 | return queue->save_to_files; 250 | 251 | } 252 | 253 | void afl_queue_set_dirpath(afl_queue_t *queue, char *new_dirpath) { 254 | 255 | if (new_dirpath) { 256 | 257 | strcpy(queue->dirpath, new_dirpath); 258 | 259 | /* Let's create the directory if it's not already created */ 260 | struct stat dir; 261 | 262 | if (!((stat(queue->dirpath, &dir) == 0) && (S_ISDIR(dir.st_mode)))) { 263 | 264 | if (mkdir(queue->dirpath, 0777) != 0) { WARNF("Error creating queue directory"); }; 265 | 266 | } 267 | 268 | } else { 269 | 270 | memset(queue->dirpath, 0, PATH_MAX); // We are unsetting the directory path 271 | 272 | } 273 | 274 | queue->save_to_files = true; 275 | // If the dirpath is empty, we make the save_to_files bool as false 276 | if (!queue->dirpath[0]) { queue->save_to_files = false; } 277 | 278 | } 279 | 280 | void afl_queue_set_engine(afl_queue_t *queue, afl_engine_t *engine) { 281 | 282 | queue->engine = engine; 283 | if (engine) { queue->engine_id = engine->id; } 284 | 285 | } 286 | 287 | afl_entry_t *afl_queue_get_entry(afl_queue_t *queue, u32 entry) { 288 | 289 | if (queue->entries_count <= entry) { return NULL; } 290 | return queue->entries[entry]; 291 | 292 | } 293 | 294 | afl_entry_t *afl_queue_next_base_queue(afl_queue_t *queue, int engine_id) { 295 | 296 | if (queue->entries_count) { 297 | 298 | afl_entry_t *current = queue->entries[queue->current]; 299 | 300 | if (engine_id != queue->engine_id && current->info->skip_entry) { return current; } 301 | 302 | // If some other engine grabs from the queue, don't update the queue's 303 | // current entry 304 | // If we reach the end of queue, start from beginning 305 | queue->current = (queue->current + 1) % queue->entries_count; 306 | 307 | return current; 308 | 309 | } else { 310 | 311 | DBG("Empty queue at %p", queue); 312 | // Queue empty :( 313 | return NULL; 314 | 315 | } 316 | 317 | } 318 | 319 | afl_ret_t afl_queue_feedback_init(afl_queue_feedback_t *feedback_queue, afl_feedback_t *feedback, char *name) { 320 | 321 | afl_queue_init(&(feedback_queue->base)); 322 | feedback_queue->feedback = feedback; 323 | 324 | if (feedback) { feedback->queue = feedback_queue; } 325 | 326 | if (!name) { name = (char *)""; } 327 | 328 | feedback_queue->name = name; 329 | 330 | return AFL_RET_SUCCESS; 331 | 332 | } 333 | 334 | void afl_queue_feedback_deinit(afl_queue_feedback_t *feedback_queue) { 335 | 336 | feedback_queue->feedback = NULL; 337 | 338 | afl_queue_deinit(&feedback_queue->base); 339 | feedback_queue->name = NULL; 340 | 341 | } 342 | 343 | afl_ret_t afl_queue_global_init(afl_queue_global_t *global_queue) { 344 | 345 | afl_queue_init(&(global_queue->base)); 346 | 347 | global_queue->feedback_queues_count = 0; 348 | global_queue->feedback_queues = NULL; 349 | 350 | global_queue->base.funcs.set_engine = afl_queue_global_set_engine; 351 | 352 | global_queue->funcs.add_feedback_queue = afl_queue_global_add_feedback_queue; 353 | global_queue->funcs.schedule = afl_queue_global_schedule; 354 | global_queue->base.funcs.get_next_in_queue = afl_queue_next_global_queue; 355 | global_queue->base.funcs.set_engine = afl_queue_global_set_engine; 356 | 357 | return AFL_RET_SUCCESS; 358 | 359 | } 360 | 361 | void afl_queue_global_deinit(afl_queue_global_t *global_queue) { 362 | 363 | /* Should we also deinit the feedback queues?? */ 364 | size_t i; 365 | 366 | afl_queue_deinit(&global_queue->base); 367 | 368 | for (i = 0; i < global_queue->feedback_queues_count; ++i) { 369 | 370 | global_queue->feedback_queues[i] = NULL; 371 | 372 | } 373 | 374 | afl_free(global_queue->feedback_queues); 375 | global_queue->feedback_queues = NULL; 376 | global_queue->feedback_queues_count = 0; 377 | 378 | } 379 | 380 | afl_ret_t afl_queue_global_add_feedback_queue(afl_queue_global_t *global_queue, afl_queue_feedback_t *feedback_queue) { 381 | 382 | global_queue->feedback_queues_count++; 383 | global_queue->feedback_queues = 384 | afl_realloc(global_queue->feedback_queues, global_queue->feedback_queues_count * sizeof(afl_queue_feedback_t *)); 385 | if (!global_queue->feedback_queues) { 386 | 387 | global_queue->feedback_queues_count = 0; 388 | return AFL_RET_ALLOC; 389 | 390 | } 391 | 392 | global_queue->feedback_queues[global_queue->feedback_queues_count - 1] = feedback_queue; 393 | afl_engine_t *engine = global_queue->base.engine; 394 | feedback_queue->base.funcs.set_engine(&feedback_queue->base, engine); 395 | return AFL_RET_SUCCESS; 396 | 397 | } 398 | 399 | afl_entry_t *afl_queue_next_global_queue(afl_queue_t *queue, int engine_id) { 400 | 401 | // This is to stop from compiler complaining about the incompatible pointer 402 | // type for the function ptrs. We need a better solution for this to pass the 403 | // scheduled_mutator rather than the mutator as an argument. 404 | afl_queue_global_t *global_queue = (afl_queue_global_t *)queue; 405 | 406 | int fbck_idx = global_queue->funcs.schedule(global_queue); 407 | 408 | if (fbck_idx != -1) { 409 | 410 | afl_queue_feedback_t *feedback_queue = global_queue->feedback_queues[fbck_idx]; 411 | afl_entry_t * next_entry = feedback_queue->base.funcs.get_next_in_queue(&(feedback_queue->base), engine_id); 412 | 413 | if (next_entry) { 414 | 415 | return next_entry; 416 | 417 | } else { 418 | 419 | return afl_queue_next_base_queue(queue, engine_id); 420 | 421 | } 422 | 423 | } else { 424 | 425 | // We don't have any more entries feedback queue, so base queue it is. 426 | return afl_queue_next_base_queue(queue, engine_id); 427 | 428 | } 429 | 430 | } 431 | 432 | int afl_queue_global_schedule(afl_queue_global_t *queue) { 433 | 434 | return afl_rand_below(&queue->base.engine->rand, queue->feedback_queues_count); 435 | 436 | } 437 | 438 | /* TODO: make this a method for engine instead */ 439 | void afl_queue_global_set_engine(afl_queue_t *global_queue_base, afl_engine_t *engine) { 440 | 441 | size_t i; 442 | afl_queue_global_t *global_queue = (afl_queue_global_t *)global_queue_base; 443 | 444 | // First add engine to the global queue itself 445 | 446 | afl_queue_set_engine(&global_queue->base, engine); 447 | // Set engine's queue to the global queue 448 | 449 | if (engine) { engine->global_queue = global_queue; } 450 | 451 | for (i = 0; i < global_queue->feedback_queues_count; ++i) { 452 | 453 | // Set this engine to every feedback queue in global queue 454 | global_queue->feedback_queues[i]->base.funcs.set_engine(&(global_queue->feedback_queues[i]->base), engine); 455 | 456 | } 457 | 458 | } 459 | 460 | -------------------------------------------------------------------------------- /src/shmem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifdef USEMMAP 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #else 11 | #include 12 | #include 13 | #endif 14 | 15 | #ifdef __ANDROID__ 16 | #include "android-ashmem.h" 17 | #endif 18 | 19 | #include "types.h" 20 | #include "shmem.h" 21 | 22 | void afl_shmem_deinit(afl_shmem_t *shm) { 23 | 24 | if (!shm || !shm->map) { 25 | 26 | // Not set or not initialized; 27 | return; 28 | 29 | } 30 | 31 | shm->shm_str[0] = '\0'; 32 | 33 | #ifdef USEMMAP 34 | if (shm->map != NULL) { 35 | 36 | munmap(shm->map, shm->map_size); 37 | shm->map = NULL; 38 | 39 | } 40 | 41 | if (shm->g_shm_fd != -1) { 42 | 43 | close(shm->g_shm_fd); 44 | shm->g_shm_fd = -1; 45 | 46 | } 47 | 48 | #else 49 | shmctl(shm->shm_id, IPC_RMID, NULL); 50 | #endif 51 | 52 | shm->map = NULL; 53 | 54 | } 55 | 56 | u8 *afl_shmem_init(afl_shmem_t *shm, size_t map_size) { 57 | 58 | shm->map_size = map_size; 59 | 60 | shm->map = NULL; 61 | 62 | #ifdef USEMMAP 63 | 64 | shm->g_shm_fd = -1; 65 | 66 | /* ====== 67 | generate random file name for multi instance 68 | 69 | thanks to f*cking glibc we can not use tmpnam securely, it generates a 70 | security warning that cannot be suppressed 71 | so we do this worse workaround */ 72 | snprintf(shm->shm_str, 20, "/afl_%d_%ld", getpid(), random()); 73 | 74 | /* create the shared memory segment as if it was a file */ 75 | shm->g_shm_fd = shm_open(shm->shm_str, O_CREAT | O_RDWR | O_EXCL, 0600); 76 | if (shm->g_shm_fd == -1) { 77 | 78 | shm->shm_str[0] = '\0'; 79 | return NULL; 80 | 81 | } 82 | 83 | /* configure the size of the shared memory segment */ 84 | if (ftruncate(shm->g_shm_fd, map_size)) { 85 | 86 | close(shm->g_shm_fd); 87 | shm_unlink(shm->shm_str); 88 | shm->shm_str[0] = '\0'; 89 | return NULL; 90 | 91 | } 92 | 93 | /* map the shared memory segment to the address space of the process */ 94 | shm->map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->g_shm_fd, 0); 95 | if (shm->map == MAP_FAILED || shm->map == ((void *)-1) || !shm->map) { 96 | 97 | close(shm->g_shm_fd); 98 | shm_unlink(shm->shm_str); 99 | shm->g_shm_fd = -1; 100 | shm->shm_str[0] = '\0'; 101 | return NULL; 102 | 103 | } 104 | 105 | #else 106 | 107 | shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600); 108 | 109 | if (shm->shm_id < 0) { 110 | 111 | shm->shm_str[0] = '\0'; 112 | return NULL; 113 | 114 | } 115 | 116 | snprintf(shm->shm_str, sizeof(shm->shm_str), "%d", shm->shm_id); 117 | shm->shm_str[sizeof(shm->shm_str) - 1] = '\0'; 118 | 119 | shm->map = shmat(shm->shm_id, NULL, 0); 120 | 121 | if (shm->map == (void *)-1 || !shm->map) { 122 | 123 | shmctl(shm->shm_id, IPC_RMID, NULL); 124 | shm->shm_id = -1; 125 | shm->shm_str[0] = '\0'; 126 | return NULL; 127 | 128 | } 129 | 130 | #endif 131 | 132 | return shm->map; 133 | 134 | } 135 | 136 | u8 *afl_shmem_by_str(afl_shmem_t *shm, char *shm_str, size_t map_size) { 137 | 138 | if (!shm || !shm_str || !shm_str[0] || !map_size) { return NULL; } 139 | shm->map = NULL; 140 | 141 | shm->map_size = map_size; 142 | strncpy(shm->shm_str, shm_str, sizeof(shm->shm_str) - 1); 143 | 144 | #ifdef USEMMAP 145 | const char * shm_file_path = shm_str; 146 | unsigned char *shm_base = NULL; 147 | 148 | /* create the shared memory segment as if it was a file */ 149 | shm->g_shm_fd = shm_open(shm_file_path, O_RDWR, 0600); 150 | if (shm->g_shm_fd == -1) { 151 | 152 | shm->shm_str[0] = '\0'; 153 | return NULL; 154 | 155 | } 156 | 157 | /* map the shared memory segment to the address space of the process */ 158 | shm_base = mmap(0, shm->map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->g_shm_fd, 0); 159 | if (shm_base == MAP_FAILED) { 160 | 161 | close(shm->g_shm_fd); 162 | shm->g_shm_fd = -1; 163 | shm->map_size = 0; 164 | shm->shm_str[0] = '\0'; 165 | 166 | return NULL; 167 | 168 | } 169 | 170 | shm->map = shm_base; 171 | #else 172 | shm->shm_id = atoi(shm_str); 173 | 174 | shm->map = shmat(shm->shm_id, NULL, 0); 175 | 176 | if (shm->map == (void *)-1) { 177 | 178 | shm->map = NULL; 179 | shm->map_size = 0; 180 | shm->shm_str[0] = '\0'; 181 | return NULL; 182 | 183 | } 184 | 185 | #endif 186 | 187 | return shm->map; 188 | 189 | } 190 | 191 | /* Write sharedmap as env var and the size as name#_SIZE */ 192 | afl_ret_t afl_shmem_to_env_var(afl_shmem_t *shmem, char *env_name) { 193 | 194 | if (!env_name || !shmem || !env_name[0] || !shmem->shm_str[0] || strlen(env_name) > 200) { return AFL_RET_NULL_PTR; } 195 | 196 | char shm_str[256]; 197 | snprintf(shm_str, sizeof(shm_str), "%d", shmem->shm_id); 198 | if (setenv(env_name, (char *)shm_str, 1) < 0) { return AFL_RET_ERRNO; } 199 | 200 | /* Write the size to env, too */ 201 | char size_env_name[256]; 202 | snprintf(size_env_name, sizeof(size_env_name), "%s_SIZE", env_name); 203 | snprintf(shm_str, sizeof(shm_str), "%d", shmem->shm_id); 204 | if (setenv(size_env_name, (char *)shm_str, 1) < 0) { return AFL_RET_ERRNO; } 205 | 206 | return AFL_RET_SUCCESS; 207 | 208 | } 209 | 210 | -------------------------------------------------------------------------------- /src/stage.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop++ - fuzzer header 3 | ------------------------------------ 4 | 5 | Originally written by Michal Zalewski 6 | 7 | Now maintained by Marc Heuse , 8 | Heiko Eißfeldt , 9 | Andrea Fioraldi , 10 | Dominik Maier 11 | 12 | Copyright 2016, 2017 Google Inc. All rights reserved. 13 | Copyright 2019-2020 AFLplusplus Project. All rights reserved. 14 | 15 | Licensed under the Apache License, Version 2.0 (the "License"); 16 | you may not use this file except in compliance with the License. 17 | You may obtain a copy of the License at: 18 | 19 | http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | */ 22 | 23 | #include "stage.h" 24 | #include "engine.h" 25 | #include "fuzzone.h" 26 | #include "mutator.h" 27 | 28 | afl_ret_t afl_stage_init(afl_stage_t *stage, afl_engine_t *engine) { 29 | 30 | stage->engine = engine; 31 | 32 | // We also add this stage to the engine's fuzzone 33 | if (engine) { engine->fuzz_one->funcs.add_stage(engine->fuzz_one, stage); } 34 | 35 | stage->funcs.get_iters = afl_stage_get_iters; 36 | stage->funcs.perform = afl_stage_perform; 37 | stage->funcs.add_mutator_to_stage = afl_stage_add_mutator; 38 | 39 | return AFL_RET_SUCCESS; 40 | 41 | } 42 | 43 | void afl_stage_deinit(afl_stage_t *stage) { 44 | 45 | stage->engine = NULL; 46 | 47 | for (size_t i = 0; i < stage->mutators_count; ++i) { 48 | 49 | afl_mutator_deinit(stage->mutators[i]); 50 | 51 | } 52 | 53 | afl_free(stage->mutators); 54 | stage->mutators = NULL; 55 | 56 | } 57 | 58 | afl_ret_t afl_stage_add_mutator(afl_stage_t *stage, afl_mutator_t *mutator) { 59 | 60 | if (!stage || !mutator) { return AFL_RET_NULL_PTR; } 61 | 62 | stage->mutators_count++; 63 | stage->mutators = afl_realloc(stage->mutators, stage->mutators_count * sizeof(afl_mutator_t *)); 64 | if (!stage->mutators) { return AFL_RET_ALLOC; } 65 | 66 | stage->mutators[stage->mutators_count - 1] = mutator; 67 | 68 | return AFL_RET_SUCCESS; 69 | 70 | } 71 | 72 | size_t afl_stage_get_iters(afl_stage_t *stage) { 73 | 74 | return (1 + afl_rand_below(&stage->engine->rand, 128)); 75 | 76 | } 77 | 78 | afl_ret_t afl_stage_run(afl_stage_t *stage, afl_input_t *input, bool overwrite) { 79 | 80 | afl_input_t *copy; 81 | if (!overwrite) 82 | copy = input->funcs.copy(input); 83 | else 84 | copy = input; 85 | 86 | /* Let's post process the mutated data now. */ 87 | size_t j; 88 | for (j = 0; j < stage->mutators_count; ++j) { 89 | 90 | afl_mutator_t *mutator = stage->mutators[j]; 91 | 92 | if (mutator->funcs.post_process) { mutator->funcs.post_process(mutator, copy); } 93 | 94 | } 95 | 96 | afl_ret_t ret = stage->engine->funcs.execute(stage->engine, copy); 97 | 98 | if (!overwrite) afl_input_delete(copy); 99 | 100 | return ret; 101 | 102 | } 103 | 104 | float afl_stage_is_interesting(afl_stage_t *stage) { 105 | 106 | float interestingness = 0.0f; 107 | 108 | afl_feedback_t **feedbacks = stage->engine->feedbacks; 109 | size_t j; 110 | for (j = 0; j < stage->engine->feedbacks_count; ++j) { 111 | 112 | interestingness += feedbacks[j]->funcs.is_interesting(feedbacks[j], stage->engine->executor); 113 | 114 | } 115 | 116 | return interestingness; 117 | 118 | } 119 | 120 | /* Perform default for fuzzing stage */ 121 | afl_ret_t afl_stage_perform(afl_stage_t *stage, afl_input_t *input) { 122 | 123 | // size_t i; 124 | // This is to stop from compiler complaining about the incompatible pointer 125 | // type for the function ptrs. We need a better solution for this to pass the 126 | // scheduled_mutator rather than the mutator as an argument. 127 | 128 | size_t num = stage->funcs.get_iters(stage); 129 | 130 | for (size_t i = 0; i < num; ++i) { 131 | 132 | afl_input_t *copy = input->funcs.copy(input); 133 | if (!copy) { return AFL_RET_ERROR_INPUT_COPY; } 134 | 135 | size_t j; 136 | for (j = 0; j < stage->mutators_count; ++j) { 137 | 138 | afl_mutator_t *mutator = stage->mutators[j]; 139 | // If the mutator decides not to fuzz this input, don't fuzz it. This is to support the custom mutator API of 140 | // AFL++ 141 | if (mutator->funcs.custom_queue_get) { 142 | 143 | mutator->funcs.custom_queue_get(mutator, copy); 144 | continue; 145 | 146 | } 147 | 148 | if (mutator->funcs.trim) { 149 | 150 | size_t orig_len = copy->len; 151 | size_t trim_len = mutator->funcs.trim(mutator, copy); 152 | 153 | if (trim_len > orig_len) { return AFL_RET_TRIM_FAIL; } 154 | 155 | } 156 | 157 | mutator->funcs.mutate(mutator, copy); 158 | 159 | } 160 | 161 | afl_ret_t ret = afl_stage_run(stage, copy, true); 162 | 163 | /* Let's collect some feedback on the input now */ 164 | float interestingness = afl_stage_is_interesting(stage); 165 | 166 | if (interestingness >= 0.5) { 167 | 168 | /* TODO: Use queue abstraction instead */ 169 | llmp_message_t *msg = llmp_client_alloc_next(stage->engine->llmp_client, copy->len + sizeof(afl_entry_info_t)); 170 | if (!msg) { 171 | 172 | DBG("Error allocating llmp message"); 173 | return AFL_RET_ALLOC; 174 | 175 | } 176 | 177 | memcpy(msg->buf, copy->bytes, copy->len); 178 | 179 | /* TODO FIXME - here we fill in the entry info structure on the queue */ 180 | // afl_entry_info_t *info_ptr = (afl_entry_info_t*)((u8*)(msg->buf + copy->len)); 181 | // e.g. fill map hash 182 | 183 | msg->tag = LLMP_TAG_NEW_QUEUE_ENTRY_V1; 184 | if (!llmp_client_send(stage->engine->llmp_client, msg)) { 185 | 186 | DBG("An error occurred sending our previously allocated msg"); 187 | return AFL_RET_UNKNOWN_ERROR; 188 | 189 | } 190 | 191 | /* we don't add it to the queue but wait for it to come back from the broker for now. 192 | TODO: Tidy this up. */ 193 | interestingness = 0.0f; 194 | 195 | } 196 | 197 | /* If the input is interesting and there is a global queue add the input to 198 | * the queue */ 199 | /* TODO: 0.5 is a random value. How do we want to chose interesting input? */ 200 | /* This block of code is never reached in the above case where we wait for it to return from the broker*/ 201 | if (interestingness >= 0.5 && stage->engine->global_queue) { 202 | 203 | afl_input_t *input_copy = copy->funcs.copy(copy); 204 | 205 | if (!input_copy) { return AFL_RET_ERROR_INPUT_COPY; } 206 | 207 | afl_entry_t *entry = afl_entry_new(input_copy, NULL); 208 | 209 | if (!entry) { return AFL_RET_ALLOC; } 210 | 211 | afl_queue_global_t *queue = stage->engine->global_queue; 212 | 213 | queue->base.funcs.insert((afl_queue_t *)queue, entry); 214 | 215 | } 216 | 217 | afl_input_delete(copy); 218 | 219 | switch (ret) { 220 | 221 | case AFL_RET_SUCCESS: 222 | continue; 223 | // We'll add more cases here based on the type of exit_ret value given by 224 | // the executor.Those will be handled in the engine itself. 225 | default: 226 | return ret; 227 | 228 | } 229 | 230 | } 231 | 232 | return AFL_RET_SUCCESS; 233 | 234 | } 235 | 236 | -------------------------------------------------------------------------------- /styleGuide.md: -------------------------------------------------------------------------------- 1 | 2 | # Here is the code format style that is followed in this codebase 3 | 4 | ## Function and struct member Names 5 | 6 | 1. Most of the structs here follow a simple way of naming. Although it may differ sometimes, the structs exposed for the user are `type defined (using the keyword typedef)` as *struct_name_**t***. A simple example is 7 | 8 | ```C 9 | typedef struct afl_raw_input { 10 | 11 | u8 * bytes; 12 | size_t len; 13 | 14 | struct raw_input_functions *functions; 15 | 16 | } afl_raw_input_t; 17 | ``` 18 | 19 | The structs which aren't `type defined` are meant mostly for the internal use by the library. And the user need not play with it themself. 20 | 21 | 2. Most of the structs implemented here have a `vtable struct` and the name of this `vtable struct` is *name_of_orig_struct_**functions***, e.g for `struct queue_entry` the vtable is `struct queue_entry_functions` 22 | 23 | 3. For the vtable, many of the functions have a default implementation that is provided for each function (if we see it fit). The name of these functions start and end with an `_` e.g `_get_queue_size_`, so users can know this is the default behaviour of the function pointer. 24 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | MAKEFILE_PATH := $(abspath .) 2 | #AFL_DIR:=$(realpath $(MAKEFILE_PATH)/../examples/AFLplusplus) 3 | override CFLAGS+=-g -L$(MAKEFILE_PATH)/.. -I$(MAKEFILE_PATH)/../include ../libafl.a -lm -Wall -Wextra -Wshadow -Werror -Og -fstack-protector-strong 4 | 5 | ifdef DEBU 6 | AFL_DEBUG=1 7 | override CFLAGS += -DAFL_DEBUG 8 | endif 9 | ifdef ASAN 10 | override CFLAGS += -fsanitize=address -fno-omit-frame-pointer 11 | override LDFLAGS += -fsanitize=address 12 | endif 13 | ifdef UBSAN 14 | override CFLAGS += -fsanitize=undefined -fno-omit-frame-pointer 15 | override LDFLAGS += -fsanitize=undefined 16 | endif 17 | ifdef MSAN 18 | CC := clang 19 | override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer 20 | override LDFLAGS += -fsanitize=memory 21 | endif 22 | 23 | all: test 24 | 25 | ../libafl.a: 26 | make DEBUG=1 ASAN=1 -C .. libafl.a 27 | 28 | unit_test: ./unit_test.c ../libafl.a 29 | $(CC) ./unit_test.c -o ./unit_test -Wl,--wrap=exit -lcmocka $(CFLAGS) -lrt -lpthread 30 | 31 | unit_llmp: ./unit_llmp.c ../libafl.a 32 | $(CC) ./unit_llmp.c -o ./unit_llmp -Wl,--wrap=exit -lcmocka $(CFLAGS) -lrt -lpthread #-Wl,--wrap=printf 33 | 34 | test: unit_test unit_llmp 35 | rm -rf ./testcases || true 36 | LD_LIBRARY_PATH=.. ./unit_test 37 | LD_LIBRARY_PATH=.. ./unit_llmp 38 | 39 | clean: 40 | rm -rf ./testcases || true 41 | rm unit_test || true 42 | rm unit_llmp || true 43 | -------------------------------------------------------------------------------- /test/unit_llmp.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | /* cmocka < 1.0 didn't support these features we need */ 10 | #ifndef assert_ptr_equal 11 | #define assert_ptr_equal(a, b) \ 12 | _assert_int_equal(cast_ptr_to_largest_integral_type(a), cast_ptr_to_largest_integral_type(b), __FILE__, __LINE__) 13 | #define CMUnitTest UnitTest 14 | #define cmocka_unit_test unit_test 15 | #define cmocka_run_group_tests(t, setup, teardown) run_tests(t) 16 | #endif 17 | 18 | extern void mock_assert(const int result, const char *const expression, const char *const file, const int line); 19 | #undef assert 20 | #define assert(expression) mock_assert((int)(expression), #expression, __FILE__, __LINE__); 21 | 22 | /* remap exit -> assert, then use cmocka's mock_assert 23 | (compile with `--wrap=exit`) */ 24 | extern void exit(int status); 25 | extern void __real_exit(int status); 26 | void __wrap_exit(int status); 27 | void __wrap_exit(int status) { 28 | 29 | (void)status; 30 | assert(0); 31 | 32 | } 33 | 34 | /* ignore all printfs */ 35 | #undef printf 36 | extern int printf(const char *format, ...); 37 | extern int __real_printf(const char *format, ...); 38 | int __wrap_printf(const char *format, ...); 39 | int __wrap_printf(const char *format, ...) { 40 | 41 | (void)format; 42 | return 1; 43 | 44 | } 45 | 46 | #include "llmp.h" 47 | 48 | static inline void test_llmp_client(void **state) { 49 | 50 | (void)state; 51 | 52 | llmp_client_t *client = llmp_client_new_unconnected(); 53 | /* Make sure we can allocate something that's too big for our current map */ 54 | assert_non_null(llmp_client_alloc_next(client, LLMP_INITIAL_MAP_SIZE + 10)); 55 | 56 | // Make sure larger allocations work and create a new map :) 57 | assert_int_equal(client->out_map_count, 2); 58 | llmp_client_delete(client); 59 | 60 | } 61 | 62 | #define CORRECT_DATA_TAG (0xC088EC7) 63 | static void eop_hook(llmp_client_t *state, llmp_page_t *page, void *data) { 64 | 65 | OKF("Hook triggered! :)\n"); 66 | 67 | /* make sure we get the latest page in the stage */ 68 | assert_ptr_equal((u8 *)page, state->out_maps[state->out_map_count - 1].map); 69 | 70 | /* make sure data contains what we put in */ 71 | assert_int_equal(((u32 *)data)[0], CORRECT_DATA_TAG); 72 | ((u32 *)data)[1]++; 73 | 74 | } 75 | 76 | static void test_client_eop(void **state) { 77 | 78 | (void)state; 79 | 80 | llmp_client_t *client = llmp_client_new_unconnected(); 81 | 82 | /* loc 1 = tag, loc2 = eop count */ 83 | u32 infos[2]; 84 | infos[0] = CORRECT_DATA_TAG; 85 | infos[1] = 0; 86 | 87 | llmp_client_add_new_out_page_hook(client, eop_hook, (void *)&infos); 88 | 89 | assert_int_equal(client->new_out_page_hook_count, 1); 90 | 91 | u32 i; 92 | for (i = 0; i < 15000; i++) { 93 | 94 | llmp_message_t *last_msg = llmp_client_alloc_next(client, i * 10); 95 | assert(last_msg && "Last_msg was null :("); 96 | last_msg->tag = 0x7357; 97 | assert_int_equal(last_msg->buf_len, i * 10); 98 | assert_true(last_msg->buf_len_padded >= last_msg->buf_len && "BUG! buf_len supposedly larger than buf_len_padded!"); 99 | llmp_client_send(client, last_msg); 100 | 101 | } 102 | 103 | llmp_client_delete(client); 104 | 105 | assert_int_not_equal(infos[1], 0); 106 | assert_int_not_equal(infos[1], 1); 107 | 108 | } 109 | 110 | static inline void test_llmp_client_message_cancel(void **state) { 111 | 112 | (void)state; 113 | 114 | llmp_client_t * client = llmp_client_new_unconnected(); 115 | llmp_message_t *old_msg = llmp_client_alloc_next(client, 10); 116 | 117 | llmp_client_cancel(client, old_msg); 118 | llmp_message_t *new_msg = llmp_client_alloc_next(client, 100); 119 | 120 | assert_ptr_equal(old_msg, new_msg); 121 | assert_true(llmp_client_send(client, new_msg)); 122 | 123 | llmp_message_t *old_msg2 = llmp_client_alloc_next(client, 10); 124 | 125 | llmp_client_cancel(client, old_msg2); 126 | llmp_message_t *new_msg2 = llmp_client_alloc_next(client, 100); 127 | 128 | assert_ptr_not_equal(old_msg, old_msg2); 129 | assert_ptr_not_equal(new_msg, new_msg2); 130 | 131 | assert_ptr_equal(old_msg2, new_msg2); 132 | 133 | assert_true(llmp_client_send(client, new_msg2)); 134 | 135 | llmp_client_delete(client); 136 | 137 | } 138 | 139 | int main(int argc, char **argv) { 140 | 141 | (void)argc; 142 | (void)argv; 143 | const struct CMUnitTest tests[] = { 144 | 145 | cmocka_unit_test(test_llmp_client), 146 | cmocka_unit_test(test_client_eop), 147 | cmocka_unit_test(test_llmp_client_message_cancel), 148 | 149 | }; 150 | 151 | // return cmocka_run_group_tests (tests, setup, teardown); 152 | __real_exit(cmocka_run_group_tests(tests, NULL, NULL)); 153 | 154 | // fake return for dumb compilers 155 | return 0; 156 | 157 | } 158 | 159 | --------------------------------------------------------------------------------