├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CONTRIBUTING.md ├── ChangeLog ├── LICENSE ├── README.md ├── afl-analyze.c ├── afl-fuzz.c ├── afl-showmap.c ├── afl-staticinstr.c ├── afl-staticinstr.h ├── afl-tmin.c ├── afl_docs ├── COPYING ├── ChangeLog ├── INSTALL ├── QuickStartGuide.txt ├── README ├── env_variables.txt ├── historical_notes.txt ├── notes_for_asan.txt ├── parallel_fuzzing.txt ├── perf_tips.txt ├── sister_projects.txt ├── status_screen.txt ├── technical_details.txt ├── visualization │ └── afl_gzip.png └── vuln_samples │ ├── bash-cmd-exec.var │ ├── bash-uninit-mem.var │ ├── ffmpeg-h264-bad-ptr-800m.mp4 │ ├── ffmpeg-h264-bad-read.mp4 │ ├── ffmpeg-h264-call-stack-overflow.mp4 │ ├── firefox-bmp-leak.bmp │ ├── firefox-chrome-leak.jpg │ ├── firefox-gif-leak.gif │ ├── firefox-gif-leak2.gif │ ├── jxrlib-crash.jxr │ ├── jxrlib-crash2.jxr │ ├── jxrlib-crash3.jxr │ ├── jxrlib-crash4.jxr │ ├── lesspipe-cpio-bad-write.cpio │ ├── libjpeg-sos-leak.jpg │ ├── libjpeg-turbo-dht-leak.jpg │ ├── libtiff-bad-write.tif │ ├── libtiff-uninit-mem.tif │ ├── libtiff-uninit-mem2.tif │ ├── libtiff-uninit-mem3.tif │ ├── libtiff-uninit-mem4.tif │ ├── libxml2-bad-read.xml │ ├── msie-dht-leak.jpg │ ├── msie-jxr-mem-leak.jxr │ ├── msie-png-mem-leak.png │ ├── msie-tiff-mem-leak.tif │ ├── msie-zlib-dos.png │ ├── openssl-null-ptr.der │ ├── openssl-null-ptr2.der │ ├── photoshop-mem-leak.jpg │ ├── sqlite-bad-free.sql │ ├── sqlite-bad-ptr.sql │ ├── sqlite-bad-ptr2.sql │ ├── sqlite-bad-ptr3.sql │ ├── sqlite-heap-overflow.sql │ ├── sqlite-heap-overwrite.sql │ ├── sqlite-negative-memset.sql │ ├── sqlite-null-ptr1.sql │ ├── sqlite-null-ptr10.sql │ ├── sqlite-null-ptr11.sql │ ├── sqlite-null-ptr12.sql │ ├── sqlite-null-ptr13.sql │ ├── sqlite-null-ptr14.sql │ ├── sqlite-null-ptr15.sql │ ├── sqlite-null-ptr2.sql │ ├── sqlite-null-ptr3.sql │ ├── sqlite-null-ptr4.sql │ ├── sqlite-null-ptr5.sql │ ├── sqlite-null-ptr6.sql │ ├── sqlite-null-ptr7.sql │ ├── sqlite-null-ptr8.sql │ ├── sqlite-null-ptr9.sql │ ├── sqlite-oob-read.sql │ ├── sqlite-oob-write.sql │ ├── sqlite-stack-buf-overflow.sql │ ├── sqlite-stack-exhaustion.sql │ ├── sqlite-unint-mem.sql │ ├── sqlite-use-after-free.sql │ ├── strings-stack-overflow │ ├── tcpdump-arp-crash.pcap │ ├── tcpdump-ppp-crash.pcap │ ├── unrtf-arbitrary-read.rtf │ └── unzip-t-mem-corruption.zip ├── afl_post_library ├── CMakeLists.txt └── post_library.c ├── alloc-inl.h ├── config.h ├── custom_net_fuzzer.c ├── custom_net_fuzzer.def ├── custom_winafl_server.c ├── custom_winafl_server.def ├── custom_winafl_server.h ├── debug.h ├── gdiplus.cpp ├── hash.h ├── ipttool.c ├── ipttool.h ├── modules.c ├── modules.h ├── ptdecode.c ├── ptdecode.h ├── readme_dr.md ├── readme_pt.md ├── readme_syzygy.md ├── readme_tinyinst.md ├── screenshots ├── afl-fuzz.gif ├── afl-instr.png └── winafl-cmin.py.png ├── test.cpp ├── test_netmode.cpp ├── test_simple_winsock_client.cpp ├── test_static.cpp ├── testcases ├── README.testcases ├── _extras │ ├── gif.dict │ ├── html_tags.dict │ ├── jpeg.dict │ ├── js.dict │ ├── pdf.dict │ ├── png.dict │ ├── sql.dict │ ├── tiff.dict │ ├── webp.dict │ └── xml.dict ├── archives │ ├── common │ │ ├── ar │ │ │ └── small_archive.a │ │ ├── bzip2 │ │ │ └── small_archive.bz2 │ │ ├── cab │ │ │ └── small_archive.cab │ │ ├── compress │ │ │ └── small_archive.Z │ │ ├── cpio │ │ │ └── small_archive.cpio │ │ ├── gzip │ │ │ └── small_archive.gz │ │ ├── lzo │ │ │ └── small_archive.lzo │ │ ├── rar │ │ │ └── small_archive.rar │ │ ├── tar │ │ │ └── small_archive.tar │ │ ├── xz │ │ │ └── small_archive.xz │ │ └── zip │ │ │ └── small_archive.zip │ └── exotic │ │ ├── arj │ │ └── small_archive.arj │ │ ├── lha │ │ └── small_archive.lha │ │ ├── lrzip │ │ └── small_archive.lrz │ │ ├── lzip │ │ └── small_archive.lz │ │ ├── lzma │ │ └── small_archive.lzma │ │ ├── rzip │ │ └── small_archive.rz │ │ └── zoo │ │ └── small_archive.zoo ├── images │ ├── bmp │ │ └── not_kitty.bmp │ ├── gif │ │ └── not_kitty.gif │ ├── ico │ │ └── not_kitty.ico │ ├── jp2 │ │ └── not_kitty.jp2 │ ├── jpeg │ │ └── not_kitty.jpg │ ├── jxr │ │ └── not_kitty.jxr │ ├── png │ │ ├── not_kitty.png │ │ ├── not_kitty_alpha.png │ │ ├── not_kitty_gamma.png │ │ └── not_kitty_icc.png │ ├── tiff │ │ └── not_kitty.tiff │ └── webp │ │ └── not_kitty.webp ├── multimedia │ └── h264 │ │ └── small_movie.mp4 ├── others │ ├── js │ │ └── small_script.js │ ├── pcap │ │ └── small_capture.pcap │ ├── pdf │ │ └── small.pdf │ ├── rtf │ │ └── small_document.rtf │ ├── sql │ │ └── simple_queries.sql │ ├── text │ │ └── hello_world.txt │ └── xml │ │ └── small_document.xml └── tests │ ├── big.txt │ ├── bigalloc.txt │ ├── crash.txt │ ├── crash_gs.txt │ ├── exception.txt │ ├── hang.txt │ ├── normal.txt │ └── small.txt ├── tinyinst_afl.cpp ├── tinyinst_afl.h ├── tinyinst_covmap.cpp ├── tinyinst_covmap.h ├── types.h ├── utils.h ├── winafl-cmin.py ├── winafl-plot.py ├── winafl-whatsup.py ├── winafl.c ├── winaflpt-debug.c ├── winaflpt.c └── winaflpt.h /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | jobs: 4 | build_winafl: 5 | runs-on: windows-2019 6 | strategy: 7 | matrix: 8 | platform: [Win32, x64] 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Add submodules 12 | run: git submodule update --init --recursive 13 | - name: Create build dir 14 | run: mkdir build_${{ matrix.platform }} 15 | - name: Download DynamoRIO 16 | working-directory: build_${{ matrix.platform }} 17 | run: | 18 | pip install requests 19 | python -c "import requests; response = requests.get('https://api.github.com/repos/DynamoRIO/dynamorio/releases/latest').json(); url = [asset['browser_download_url'] for asset in response['assets'] if 'Windows' in asset['browser_download_url']][0]; print ('Downloading DynamoRIO from ' + url); fh = open('DynamoRio.zip', 'wb'); fh.write(requests.get(url).content)" 20 | 7z x DynamoRio.zip 21 | mv DynamoRIO-Windows-* DynamoRio-Windows 22 | - name: Run cmake 23 | working-directory: build_${{ matrix.platform }} 24 | run: cmake -G"Visual Studio 16 2019" -A ${{ matrix.platform }} -DDynamoRIO_DIR="build_${{ matrix.platform }}\DynamoRIO-Windows\cmake" -DINTELPT=1 .. 25 | - name: Build 26 | run: cmake --build build_${{ matrix.platform }} --config Release 27 | - name: Add Python scripts to build artifacts dir 28 | run: cp *.py build_${{ matrix.platform }}\bin\Release\ 29 | - name: Upload Build Artifacts 30 | uses: actions/upload-artifact@v2 31 | with: 32 | name: build_${{ matrix.platform }} 33 | path: build_${{ matrix.platform }}\bin\Release 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build32 2 | build64 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/winipt"] 2 | path = third_party/winipt 3 | url = https://github.com/ionescu007/winipt 4 | [submodule "third_party/processor-trace"] 5 | path = third_party/processor-trace 6 | url = https://github.com/01org/processor-trace 7 | [submodule "third_party/TinyInst"] 8 | path = third_party/TinyInst 9 | url = https://github.com/googleprojectzero/TinyInst.git 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | if (${USE_COLOR}) 4 | add_definitions(-DUSE_COLOR) 5 | endif() 6 | 7 | if (${USE_DRSYMS}) 8 | add_definitions(-DUSE_DRSYMS) 9 | endif() 10 | 11 | if (${INTELPT}) 12 | add_definitions(-DINTELPT) 13 | endif() 14 | 15 | if (${INTELPT}) 16 | add_subdirectory(third_party/processor-trace) 17 | endif() 18 | 19 | if (${TINYINST}) 20 | add_definitions(-DTINYINST) 21 | endif() 22 | 23 | if (${TINYINST}) 24 | add_subdirectory(third_party/TinyInst) 25 | endif() 26 | 27 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 28 | 29 | project(test) 30 | 31 | add_executable(test 32 | test.cpp 33 | ) 34 | 35 | project(test_netmode) 36 | 37 | add_executable(test_netmode test_netmode.cpp) 38 | 39 | add_executable(test_servermode test_simple_winsock_client.cpp) 40 | 41 | if(NOT ("${CMAKE_GENERATOR}" MATCHES "(Win64)" OR "${CMAKE_GENERATOR_PLATFORM}" MATCHES "(64)")) 42 | 43 | project(test_static) 44 | 45 | add_executable(test_static 46 | test_static.cpp 47 | afl-staticinstr.c 48 | ) 49 | 50 | target_link_libraries(test_static "psapi.lib") 51 | 52 | set_target_properties(test_static PROPERTIES COMPILE_FLAGS "/EHsc") 53 | set_target_properties(test_static PROPERTIES LINK_FLAGS "/PROFILE") 54 | 55 | endif() 56 | 57 | project(test_gdiplus) 58 | 59 | add_executable(test_gdiplus 60 | gdiplus.cpp 61 | ) 62 | 63 | target_link_libraries(test_gdiplus gdiplus) 64 | 65 | project(afl-analyze) 66 | add_executable(afl-analyze 67 | afl-analyze.c 68 | ) 69 | 70 | project(afl-showmap) 71 | 72 | add_executable(afl-showmap 73 | afl-showmap.c 74 | ) 75 | 76 | project(afl-tmin) 77 | 78 | add_executable(afl-tmin 79 | afl-tmin.c 80 | ) 81 | 82 | add_library(custom_winafl_server SHARED custom_winafl_server.c custom_winafl_server.def) 83 | 84 | add_library(custom_net_fuzzer SHARED custom_net_fuzzer.c custom_net_fuzzer.def) 85 | 86 | if (${INTELPT}) 87 | 88 | project(winipt) 89 | 90 | include_directories(third_party/winipt/inc) 91 | 92 | ADD_LIBRARY(winipt STATIC 93 | ipttool.c 94 | third_party/winipt/libipt/win32.c 95 | ) 96 | 97 | target_compile_definitions(winipt PRIVATE UNICODE _UNICODE) 98 | 99 | project(winaflpt-debug) 100 | 101 | include_directories(third_party/winipt/inc) 102 | include_directories(third_party/processor-trace/libipt/internal/include) 103 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/processor-trace/libipt/include) 104 | 105 | SET(PT_ADDITIONAL_SOURCES 106 | winaflpt.c 107 | ptdecode.c 108 | third_party/processor-trace/libipt/src/pt_cpu.c 109 | third_party/processor-trace/libipt/src/windows/pt_cpuid.c 110 | ) 111 | 112 | ADD_EXECUTABLE(winaflpt-debug 113 | winaflpt-debug.c 114 | ${PT_ADDITIONAL_SOURCES} 115 | ) 116 | 117 | target_link_libraries(winaflpt-debug winipt) 118 | target_link_libraries(winaflpt-debug libipt) 119 | 120 | target_link_libraries(winaflpt-debug "psapi.lib") 121 | target_link_libraries(winaflpt-debug "Dbghelp.lib") 122 | 123 | endif() 124 | 125 | if (${TINYINST}) 126 | ADD_LIBRARY(winafl_tinyinst STATIC 127 | tinyinst_covmap.h 128 | tinyinst_covmap.cpp 129 | tinyinst_afl.h 130 | tinyinst_afl.cpp 131 | ) 132 | 133 | target_link_libraries(winafl_tinyinst tinyinst) 134 | target_link_libraries(winafl_tinyinst "onecore.lib") 135 | 136 | endif() 137 | 138 | 139 | project(afl-fuzz) 140 | 141 | SET(AFL_FUZZ_SOURCES afl-fuzz.c) 142 | 143 | if (${INTELPT}) 144 | 145 | include_directories(third_party/winipt/inc) 146 | include_directories(third_party/processor-trace/libipt/internal/include) 147 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/processor-trace/libipt/include) 148 | 149 | SET(AFL_FUZZ_SOURCES ${AFL_FUZZ_SOURCES} ${PT_ADDITIONAL_SOURCES}) 150 | 151 | endif() 152 | 153 | add_executable(afl-fuzz 154 | ${AFL_FUZZ_SOURCES} 155 | ) 156 | 157 | if (${INTELPT}) 158 | 159 | target_link_libraries(afl-fuzz winipt) 160 | target_link_libraries(afl-fuzz libipt) 161 | 162 | target_link_libraries(afl-fuzz "psapi.lib") 163 | target_link_libraries(afl-fuzz "Dbghelp.lib") 164 | 165 | endif() 166 | 167 | if (${TINYINST}) 168 | target_link_libraries(afl-fuzz winafl_tinyinst) 169 | endif() 170 | 171 | if (NOT "${DynamoRIO_DIR}" STREQUAL "") 172 | 173 | project(WinAFL) 174 | 175 | set(DynamoRIO_LOG_COMPATIBILITY on) 176 | 177 | find_package(DynamoRIO) 178 | if (NOT DynamoRIO_FOUND) 179 | message(FATAL_ERROR "DynamoRIO package required to build") 180 | endif(NOT DynamoRIO_FOUND) 181 | 182 | if (STATIC_LIBRARY) 183 | set(libtype STATIC) 184 | else() 185 | set(libtype SHARED) 186 | endif () 187 | 188 | add_library(winafl ${libtype} 189 | winafl.c 190 | modules.c 191 | ) 192 | configure_DynamoRIO_client(winafl) 193 | use_DynamoRIO_extension(winafl drmgr) 194 | use_DynamoRIO_extension(winafl drx) 195 | use_DynamoRIO_extension(winafl drcontainers) 196 | use_DynamoRIO_extension(winafl drreg) 197 | use_DynamoRIO_extension(winafl drwrap) 198 | if (${USE_DRSYMS}) 199 | use_DynamoRIO_extension(winafl drsyms) 200 | endif() 201 | 202 | # VS2015 Fix 203 | if (NOT (MSVC_VERSION LESS 1900)) 204 | target_link_libraries(winafl "libucrt.lib") 205 | target_link_libraries(winafl "libvcruntime.lib") 206 | endif() 207 | 208 | endif() 209 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to any Google project must be accompanied by a Contributor License 9 | Agreement. This is necessary because you own the copyright to your changes, even 10 | after your contribution becomes part of this project. So this agreement simply 11 | gives us permission to use and redistribute your contributions as part of the 12 | project. Head over to to see your current 13 | agreements on file or to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult [GitHub Help] for more 23 | information on using pull requests. 24 | 25 | [GitHub Help]: https://help.github.com/articles/about-pull-requests/ 26 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | ========= 2 | ChangeLog 3 | ========= 4 | 5 | ----------------------------------- 6 | Version 1.16b (based on afl 2.43b): 7 | ----------------------------------- 8 | 9 | - Fixed an issue with Intel PT mode where target processes were not 10 | terminated properly. 11 | Reported by Jason Shirk 12 | 13 | - Added a port of afl-analyze 14 | Contributed by L4ys 15 | 16 | - DynamoRIO version update - started building prebuilt binaries with 17 | DynamoRIO 7.1 18 | 19 | ---------------------------------- 20 | Version 1.16 (based on afl 2.43b): 21 | ---------------------------------- 22 | 23 | - Intel PT support. 24 | 25 | - Fix target_path in afl-showmap in drioless mode 26 | Contributed by L4ys 27 | 28 | ---------------------------------- 29 | Version 1.15 (based on afl 2.43b): 30 | ---------------------------------- 31 | 32 | - Added -p flag which persists DynamoRIO cache across process restarts. 33 | This might have a slight positive impact on performance in some scenarios, 34 | such as where WinAFL persistece can't be used effectively, or 35 | with very complex targets. 36 | 37 | - Fix custom_net_fuzzer to avoid consuming system resources by 38 | unclosed sockets. 39 | Contributed by MostafaSoliman 40 | 41 | ---------------------------------- 42 | Version 1.14 (based on afl 2.43b): 43 | ---------------------------------- 44 | 45 | - Added support for third-party DLLs for custom test cases processing 46 | This currently comes with (experimental) network fuzzing implementation 47 | (both server- and client- side) 48 | Contributed by Maksim Shudrak 49 | 50 | - New "In App Persistence" mode that relaxes target_method restrictions 51 | if the target process can be made to loop on its own 52 | Contributed by Guy Inbar 53 | 54 | - Implemented setup_post on Windows 55 | Contributed by Quang Nguyễn 56 | 57 | - Added separate timeout for process initialization and the first run 58 | Contributed by Netanel Ben Simon 59 | 60 | - Added color support to afl-showmap & afl-tmin 61 | Contributed by Yoav Alon 62 | 63 | - added winafl-plot.py a winafl replacement for afl-plot 64 | Contributed by Yoav Alon 65 | 66 | - added winafl-whatsup.py a winafl replacement for afl-whatsup 67 | Contributed by Yoav Alon 68 | 69 | - Fixed compilation issue on newer versions of DynamoRIO 70 | Contributed by Yoav Alon 71 | 72 | - Other minor fixes and improvements 73 | Contributed by L4ys, Yoav Alon, Netanel Ben Simon and others 74 | 75 | ---------------------------------- 76 | Version 1.13 (based on afl 2.43b): 77 | ---------------------------------- 78 | 79 | - Added support for catching failfast-type issues 80 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 81 | 82 | - Added support for catching Application Verifier errors 83 | Contributed by yoava333 84 | 85 | - Added support for processor affinity for afl-fuzz and target process 86 | Contributed by yoava333 87 | 88 | - Added support for ansi terminal on windows 10 89 | Contributed by yoava333 90 | 91 | - Make sure names of the output files generated by inafl-cmin.py are unique 92 | Contributed by x9090 93 | 94 | - Fixed a crash on zero sized input files 95 | Contributed by yoava333 96 | 97 | - Fixed a bug in load_extra that could cause errors or incorrect behavior when reading extras directory 98 | 99 | - Fixed a race condition where afl-fuzz could attempt to fuzz the target process while it was getting killed 100 | 101 | - fuzzer_pid now gets reported correctly in the fuzzer_stats file 102 | 103 | ---------------------------------- 104 | Version 1.12 (based on afl 2.43b): 105 | ---------------------------------- 106 | 107 | - Windows port of afl-tmin 108 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 109 | 110 | ---------------------------------- 111 | Version 1.11 (based on afl 2.43b): 112 | ---------------------------------- 113 | 114 | - Add support for setting a memory limit (-m flag) 115 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 116 | 117 | ---------------------------------- 118 | Version 1.10 (based on afl 2.43b): 119 | ---------------------------------- 120 | 121 | - Add static instrumentation mode 122 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 123 | 124 | ----------------------------------- 125 | Version 1.09b (based on afl 2.43b): 126 | ----------------------------------- 127 | 128 | - Fixed slave mode (broken by 1.09 update) 129 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 130 | 131 | - Fixed missing last_crash_time (broken by 1.09 update) 132 | Contributed by x9090 133 | 134 | ---------------------------------- 135 | Version 1.09 (based on afl 2.43b): 136 | ---------------------------------- 137 | 138 | - Bringing WinAFL up to speed with AFL 2.43b 139 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 140 | 141 | - Fixed a memory leak in fuzz_one 142 | Contributed by juanvazquez 143 | 144 | ---------------------------------- 145 | Version 1.08 (based on afl 1.96b): 146 | ---------------------------------- 147 | 148 | - It is now possible to collect coverage only from a thread that executed 149 | target function using -thread_coverage flag 150 | 151 | - When -target_method flag is used, symbols are now looked up from pdb files 152 | in addition to exported symbols 153 | 154 | - Added a missing call to classify_counts() from run_target() 155 | 156 | ---------------------------------- 157 | Version 1.07 (based on afl 1.96b): 158 | ---------------------------------- 159 | 160 | - Previous_offset is now stored in TLS. 161 | Edge coverage for multithreaded targets should now be more usable. 162 | 163 | ---------------------------------- 164 | Version 1.06 (based on afl 1.96b): 165 | ---------------------------------- 166 | 167 | - Windows port of afl-cmin 168 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 169 | - Use exe_name instead of the preferred name 170 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 171 | - Add option to choose the calling convention 172 | Contributed by shawndenbow 173 | - Fix for building on VS2015 174 | Contributed by b1ack0wl 175 | 176 | ---------------------------------- 177 | Version 1.05 (based on afl 1.96b): 178 | ---------------------------------- 179 | 180 | - Windows port of afl-showmap 181 | Contributed by Axel "0vercl0k" Souchet of MSRC Vulnerabilities and Mitigations Team 182 | - Expaded README a bit. 183 | 184 | ---------------------------------- 185 | Version 1.04 (based on afl 1.96b): 186 | ---------------------------------- 187 | 188 | Various fixes / improvements contributed by Axel "0vercl0k" Souchet: 189 | - Mute stdout/stderr unless AFL_NO_SINKHOLE env variable is set. 190 | - Allow several slaveless instances to be run on the same machine. 191 | - Fix getopt to properly handle options without parameters. 192 | - Automatically remove the child pid file. 193 | - Case insensitive module name comparison. 194 | - More debugging messages. 195 | 196 | ---------------------------------- 197 | Version 1.03 (based on afl 1.96b): 198 | ---------------------------------- 199 | 200 | - Fixed dictionary loading. 201 | Reported by Hugo Meier. 202 | 203 | ---------------------------------- 204 | Version 1.02 (based on afl 1.96b): 205 | ---------------------------------- 206 | 207 | - Fixed incorrect quoting of target command line arguments. 208 | 209 | - Debug mode now reports encountered exceptions. 210 | 211 | ---------------------------------- 212 | Version 1.01 (based on afl 1.96b): 213 | ---------------------------------- 214 | 215 | - Fixed a bug where previous offset wasn't updated in the edge coverage 216 | instrumentation mode. This effectively caused edge coverage to behave 217 | the same as basic block coverage. 218 | Reported by Rodrigo Axel Monroy. 219 | 220 | - Changed the default coverage mode to basic block in order for the default 221 | configuration to work better with muti-threaded apps. 222 | 223 | - Added -no_follow_children to DR runtime flags. This can fix problems if the 224 | target process creates a child process. 225 | 226 | - More data in now written to the debug log 227 | 228 | ---------------------------------- 229 | Version 1.00 (based on afl 1.96b): 230 | ---------------------------------- 231 | 232 | - Initial release. 233 | -------------------------------------------------------------------------------- /afl-staticinstr.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL persistent loop implementation for statically instrumented target 3 | ----------------------------------------------------------------------- 4 | 5 | Written by Axel "0vercl0k" Souchet <0vercl0k@tuxfamily.org> 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at: 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | This header is the glue you need to make afl-fuzz and your statically 14 | instrumented target play nice together. 15 | 16 | The entry-point __afl_persistent_loop is meant to be called at the start of the harness, 17 | in a loop like below. The function will set up everything needed to communicate 18 | and synchronize with afl-fuzz - if it is present (named pipe, shm, etc). 19 | 20 | while(__afl_persistent_loop()) { 21 | // init state 22 | // exercise target 23 | // clear state 24 | } 25 | 26 | If afl-fuzz isn't detected, then the function will simply return TRUE the first 27 | time so that the body gets executed once. 28 | */ 29 | #pragma once 30 | #include 31 | #include 32 | #include 33 | 34 | #if defined(_M_X64) || defined(__amd64__) 35 | #error Static instrumentation is only available for 32 bit binaries 36 | #endif 37 | 38 | // 39 | // Enable the variable behavior debugging mode. 40 | // 41 | 42 | // #define AFL_STATIC_VARIABLE_BEHAVIOR_DEBUG 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | 48 | BOOL __afl_persistent_loop(); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /afl_docs/INSTALL: -------------------------------------------------------------------------------- 1 | ========================= 2 | Installation instructions 3 | ========================= 4 | 5 | This document provides basic installation instructions and discusses known 6 | issues for a variety of platforms. See README for the general instruction 7 | manual. 8 | 9 | 1) Linux on x86 10 | --------------- 11 | 12 | This platform is expected to work well. Compile the program with: 13 | 14 | $ make 15 | 16 | You can start using the fuzzer without installation, but it is also possible to 17 | install it with: 18 | 19 | # make install 20 | 21 | There are no special dependencies to speak of; you will need GNU make and a 22 | working compiler (gcc or clang). Some of the optional scripts bundled with the 23 | program may depend on bash, gdb, and similar basic tools. 24 | 25 | If you are using clang, please review llvm_mode/README.llvm; the LLVM 26 | integration mode can offer substantial performance gains compared to the 27 | traditional approach. 28 | 29 | You may have to change several settings to get optimal results (most notably, 30 | disable crash reporting utilities and switch to a different CPU governor), but 31 | afl-fuzz will guide you through that if necessary. 32 | 33 | 2) OpenBSD, FreeBSD, NetBSD on x86 34 | ---------------------------------- 35 | 36 | Similarly to Linux, these platforms are expected to work well and are 37 | regularly tested. Compile everything with GNU make: 38 | 39 | $ gmake 40 | 41 | Note that BSD make will *not* work; if you do not have gmake on your system, 42 | please install it first. As on Linux, you can use the fuzzer itself without 43 | installation, or install it with: 44 | 45 | # gmake install 46 | 47 | Keep in mind that if you are using csh as your shell, the syntax of some of the 48 | shell commands given in the README and other docs will be different. 49 | 50 | The llvm_mode requires a dynamically linked, fully-operational installation of 51 | clang. At least on FreeBSD, the clang binaries are static and do not include 52 | some of the essential tools, so if you want to make it work, you may need to 53 | follow the instructions in llvm_mode/README.llvm. 54 | 55 | Beyond that, everything should work as advertised. 56 | 57 | The QEMU mode is currently supported only on Linux. I think it's just a QEMU 58 | problem, I couldn't get a vanilla copy of user-mode emulation support working 59 | correctly on BSD at all. 60 | 61 | 3) MacOS X on x86 62 | ----------------- 63 | 64 | MacOS X should work, but there are some gotchas due to the idiosyncrasies of 65 | the platform. On top of this, I have limited release testing capabilities 66 | and depend mostly on user feedback. 67 | 68 | To build AFL, install Xcode and follow the general instructions for Linux. 69 | 70 | The Xcode 'gcc' tool is just a wrapper for clang, so be sure to use afl-clang 71 | to compile any instrumented binaries; afl-gcc will fail unless you have GCC 72 | installed from another source (in which case, please specify AFL_CC and 73 | AFL_CXX to point to the "real" GCC binaries). 74 | 75 | Only 64-bit compilation will work on the platform; porting the 32-bit 76 | instrumentation would require a fair amount of work due to the way OS X 77 | handles relocations, and today, virtually all MacOS X boxes are 64-bit. 78 | 79 | The crash reporting daemon that comes by default with MacOS X will cause 80 | problems with fuzzing. You need to turn it off by following the instructions 81 | provided here: http://goo.gl/CCcd5u 82 | 83 | The fork() semantics on OS X are a bit unusual compared to other unix systems 84 | and definitely don't look POSIX-compliant. This means two things: 85 | 86 | - Fuzzing will be probably slower than on Linux. In fact, some folks report 87 | considerable performance gains by running the jobs inside a Linux VM on 88 | MacOS X. 89 | 90 | - Some non-portable, platform-specific code may be incompatible with the 91 | AFL forkserver. If you run into any problems, set AFL_NO_FORKSRV=1 in the 92 | environment before starting afl-fuzz. 93 | 94 | User emulation mode of QEMU does not appear to be supported on MacOS X, so 95 | black-box instrumentation mode (-Q) will not work. 96 | 97 | The llvm_mode requires a fully-operational installation of clang. The one that 98 | comes with Xcode is missing some of the essential headers and helper tools. 99 | See llvm_mode/README.llvm for advice on how to build the compiler from scratch. 100 | 101 | 4) Linux or *BSD on non-x86 systems 102 | ----------------------------------- 103 | 104 | Standard build will fail on non-x86 systems, but you should be able to 105 | leverage two other options: 106 | 107 | - The LLVM mode (see llvm_mode/README.llvm), which does not rely on 108 | x86-specific assembly shims, 109 | 110 | - The QEMU mode (see qemu_mode/README.qemu), which can be also used for 111 | fuzzing cross-platform binaries. 112 | 113 | In both cases, you will need to set AFL_NOX86=1 before running make or gmake. 114 | 115 | 5) Solaris on x86 116 | ----------------- 117 | 118 | The fuzzer reportedly works on Solaris, but I have not tested this first-hand, 119 | and the user base is fairly small, so I don't have a lot of feedback. 120 | 121 | To get the ball rolling, you will need to use GNU make and GCC or clang. I'm 122 | being told that the stock version of GCC that comes with the platform does not 123 | work properly due to its reliance on a hardcoded location for 'as' (completely 124 | ignoring the -B parameter or $PATH). 125 | 126 | To fix this, you may want to build stock GCC from the source, like so: 127 | 128 | $ ./configure --prefix=$HOME/gcc --with-gnu-as --with-gnu-ld \ 129 | --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr 130 | $ make 131 | $ sudo make install 132 | 133 | Do *not* specify --with-as=/usr/gnu/bin/as - this will produce a GCC binary that 134 | ignores the -B flag and you will be back to square one. 135 | 136 | If you have system-wide crash reporting enabled, you may run into problems 137 | similar to the gotchas for Linux and MacOS X, but I have not verified this. 138 | More information about AppCrash can be found here: 139 | 140 | http://www.oracle.com/technetwork/server-storage/solaris10/app-crash-142906.html 141 | 142 | User emulation mode of QEMU is not available on Solaris, so black-box 143 | instrumentation mode (-Q) will not work. 144 | 145 | 6) Everything else 146 | ------------------ 147 | 148 | You're on your own. On POSIX-compliant systems, you may be able to compile and 149 | run the fuzzer; and the LLVM mode may offer a way to instrument non-x86 code. 150 | 151 | The fuzzer will not run on Windows. It will also not work under Cygwin. It 152 | could be ported to the latter platform fairly easily, but it's a pretty bad 153 | idea, because Cygwin is extremely slow. It makes much more sense to use 154 | VirtualBox or so to run a hardware-accelerated Linux VM; it will run around 155 | 20x faster or so. If you have a *really* compelling use case for Cygwin, let 156 | me know. 157 | 158 | Although Android on x86 should theoretically work, the stock kernel has SHM 159 | support compiled out, so you will need to address this issue first. It's 160 | possible that all you need is this: 161 | 162 | https://github.com/pelya/android-shmem 163 | -------------------------------------------------------------------------------- /afl_docs/QuickStartGuide.txt: -------------------------------------------------------------------------------- 1 | ===================== 2 | AFL quick start guide 3 | ===================== 4 | 5 | You should read docs/README. It's pretty short. If you really can't, here's 6 | how to hit the ground running: 7 | 8 | 1) Compile AFL with 'make'. If build fails, see docs/INSTALL for tips. 9 | 10 | 2) Find or write a reasonably fast and simple program that takes data from 11 | a file or stdin, processes it in a test-worthy way, then exits cleanly. 12 | If testing a network service, modify it to run in the foreground and read 13 | from stdin. When fuzzing a format that uses checksums, comment out the 14 | checksum verification code, too. 15 | 16 | The program must crash properly when a fault is encountered. Watch out for 17 | custom SIGSEGV or SIGABRT handlers and background processes. 18 | 19 | 3) Compile the program / library to be fuzzed using afl-gcc. A common way to 20 | do this would be: 21 | 22 | CC=/path/to/afl-gcc CXX=/path/to/afl-g++ ./configure --disable-shared 23 | make clean all 24 | 25 | If program build fails, ping . 26 | 27 | 4) Get a small but valid input file that makes sense to the program. When 28 | fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in 29 | testcases/README.testcases, too. 30 | 31 | 5) If the program reads from stdin, run 'afl-fuzz' like so: 32 | 33 | ./afl-fuzz -i testcase_dir -o findings_dir -- \ 34 | /path/to/tested/program [...program's cmdline...] 35 | 36 | If the program takes input from a file, you can put @@ in the program's 37 | command line; AFL will put an auto-generated file name in there for you. 38 | 39 | 6) Investigate anything shown in red in the fuzzer UI by promptly consulting 40 | docs/status_screen.txt. 41 | 42 | That's it. Sit back, relax, and - time permitting - try to skim through the 43 | following files: 44 | 45 | - docs/README - A general introduction to AFL, 46 | - docs/perf_tips.txt - Simple tips on how to fuzz more quickly, 47 | - docs/status_screen.txt - An explanation of the tidbits shown in the UI, 48 | - docs/parallel_fuzzing.txt - Advice on running AFL on multiple cores. 49 | -------------------------------------------------------------------------------- /afl_docs/historical_notes.txt: -------------------------------------------------------------------------------- 1 | ================ 2 | Historical notes 3 | ================ 4 | 5 | This doc talks about the rationale of some of the high-level design decisions 6 | for American Fuzzy Lop. It's adopted from a discussion with Rob Graham. 7 | See README for the general instruction manual, and technical_details.txt for 8 | additional implementation-level insights. 9 | 10 | 1) Influences 11 | ------------- 12 | 13 | In short, afl-fuzz is inspired chiefly by the work done by Tavis Ormandy back 14 | in 2007. Tavis did some very persuasive experiments using gcov block coverage 15 | to select optimal test cases out of a large corpus of data, and then using 16 | them as a starting point for traditional fuzzing workflows. 17 | 18 | (By "persuasive", I mean: netting a significant number of interesting 19 | vulnerabilities.) 20 | 21 | In parallel to this, both Tavis and I were interested in evolutionary fuzzing. 22 | Tavis had his experiments, and I was working on a tool called bunny-the-fuzzer, 23 | released somewhere in 2007. 24 | 25 | Bunny used a generational algorithm not much different from afl-fuzz, but 26 | also tried to reason about the relationship between various input bits and 27 | the internal state of the program, with hopes of deriving some additional value 28 | from that. The reasoning / correlation part was probably in part inspired by 29 | other projects done around the same time by Will Drewry and Chris Evans. 30 | 31 | The state correlation approach sounded very sexy on paper, but ultimately, made 32 | the fuzzer complicated, brittle, and cumbersome to use; every other target 33 | program would require a tweak or two. Because Bunny didn't fare a whole lot 34 | better than less sophisticated brute-force tools, I eventually decided to write 35 | it off. You can still find its original documentation at: 36 | 37 | https://code.google.com/p/bunny-the-fuzzer/wiki/BunnyDoc 38 | 39 | There has been a fair amount of independent work, too. Most notably, a few 40 | weeks earlier that year, Jared DeMott had a Defcon presentation about a 41 | coverage-driven fuzzer that relied on coverage as a fitness function. 42 | 43 | Jared's approach was by no means identical to what afl-fuzz does, but it was in 44 | the same ballpark. His fuzzer tried to explicitly solve for the maximum coverage 45 | with a single input file; in comparison, afl simply selects for cases that do 46 | something new (which yields better results - see technical_details.txt). 47 | 48 | A few years later, Gabriel Campana released fuzzgrind, a tool that relied purely 49 | on Valgrind and a constraint solver to maximize coverage without any brute-force 50 | bits; and Microsoft Research folks talked extensively about their still 51 | non-public, solver-based SAGE framework. 52 | 53 | In the past six years or so, I've also seen a fair number of academic papers 54 | that dealt with smart fuzzing (focusing chiefly on symbolic execution) and a 55 | couple papers that discussed proof-of-concept applications of genetic 56 | algorithms with the same goals in mind. I'm unconvinced how practical most of 57 | these experiments were; I suspect that many of them suffer from the 58 | bunny-the-fuzzer's curse of being cool on paper and in carefully designed 59 | experiments, but failing the ultimate test of being able to find new, 60 | worthwhile security bugs in otherwise well-fuzzed, real-world software. 61 | 62 | In some ways, the baseline that the "cool" solutions have to compete against is 63 | a lot more impressive than it may seem, making it difficult for competitors to 64 | stand out. For a singular example, check out the work by Gynvael and Mateusz 65 | Jurczyk, applying "dumb" fuzzing to ffmpeg, a prominent and security-critical 66 | component of modern browsers and media players: 67 | 68 | http://googleonlinesecurity.blogspot.com/2014/01/ffmpeg-and-thousand-fixes.html 69 | 70 | Effortlessly getting comparable results with state-of-the-art symbolic execution 71 | in equally complex software still seems fairly unlikely, and hasn't been 72 | demonstrated in practice so far. 73 | 74 | But I digress; ultimately, attribution is hard, and glorying the fundamental 75 | concepts behind AFL is probably a waste of time. The devil is very much in the 76 | often-overlooked details, which brings us to... 77 | 78 | 2) Design goals for afl-fuzz 79 | ---------------------------- 80 | 81 | In short, I believe that the current implementation of afl-fuzz takes care of 82 | several itches that seemed impossible to scratch with other tools: 83 | 84 | 1) Speed. It's genuinely hard to compete with brute force when your "smart" 85 | approach is resource-intensive. If your instrumentation makes it 10x more 86 | likely to find a bug, but runs 100x slower, your users are getting a bad 87 | deal. 88 | 89 | To avoid starting with a handicap, afl-fuzz is meant to let you fuzz most of 90 | the intended targets at roughly their native speed - so even if it doesn't 91 | add value, you do not lose much. 92 | 93 | On top of this, the tool leverages instrumentation to actually reduce the 94 | amount of work in a couple of ways: for example, by carefully trimming the 95 | corpus or skipping non-functional but non-trimmable regions in the input 96 | files. 97 | 98 | 2) Rock-solid reliability. It's hard to compete with brute force if your 99 | approach is brittle and fails unexpectedly. Automated testing is attractive 100 | because it's simple to use and scalable; anything that goes against these 101 | principles is an unwelcome trade-off and means that your tool will be used 102 | less often and with less consistent results. 103 | 104 | Most of the approaches based on symbolic execution, taint tracking, or 105 | complex syntax-aware instrumentation are currently fairly unreliable with 106 | real-world targets. Perhaps more importantly, their failure modes can render 107 | them strictly worse than "dumb" tools, and such degradation can be difficult 108 | for less experienced users to notice and correct. 109 | 110 | In contrast, afl-fuzz is designed to be rock solid, chiefly by keeping it 111 | simple. In fact, at its core, it's designed to be just a very good 112 | traditional fuzzer with a wide range of interesting, well-researched 113 | strategies to go by. The fancy parts just help it focus the effort in 114 | places where it matters the most. 115 | 116 | 3) Simplicity. The author of a testing framework is probably the only person 117 | who truly understands the impact of all the settings offered by the tool - 118 | and who can dial them in just right. Yet, even the most rudimentary fuzzer 119 | frameworks often come with countless knobs and fuzzing ratios that need to 120 | be guessed by the operator ahead of the time. This can do more harm than 121 | good. 122 | 123 | AFL is designed to avoid this as much as possible. The three knobs you 124 | can play with are the output file, the memory limit, and the ability to 125 | override the default, auto-calibrated timeout. The rest is just supposed to 126 | work. When it doesn't, user-friendly error messages outline the probable 127 | causes and workarounds, and get you back on track right away. 128 | 129 | 4) Chainability. Most general-purpose fuzzers can't be easily employed 130 | against resource-hungry or interaction-heavy tools, necessitating the 131 | creation of custom in-process fuzzers or the investment of massive CPU 132 | power (most of which is wasted on tasks not directly related to the code 133 | we actually want to test). 134 | 135 | AFL tries to scratch this itch by allowing users to use more lightweight 136 | targets (e.g., standalone image parsing libraries) to create small 137 | corpora of interesting test cases that can be fed into a manual testing 138 | process or a UI harness later on. 139 | 140 | As mentioned in technical_details.txt, AFL does all this not by systematically 141 | applying a single overarching CS concept, but by experimenting with a variety 142 | of small, complementary methods that were shown to reliably yields results 143 | better than chance. The use of instrumentation is a part of that toolkit, but is 144 | far from being the most important one. 145 | 146 | Ultimately, what matters is that afl-fuzz is designed to find cool bugs - and 147 | has a pretty robust track record of doing just that. 148 | -------------------------------------------------------------------------------- /afl_docs/notes_for_asan.txt: -------------------------------------------------------------------------------- 1 | ================================== 2 | Notes for using ASAN with afl-fuzz 3 | ================================== 4 | 5 | This file discusses some of the caveats for fuzzing under ASAN, and suggests 6 | a handful of alternatives. See README for the general instruction manual. 7 | 8 | 1) Short version 9 | ---------------- 10 | 11 | ASAN on 64-bit systems requests a lot of memory in a way that can't be easily 12 | distinguished from a misbehaving program bent on crashing your system. 13 | 14 | Because of this, fuzzing with ASAN is recommended only in four scenarios: 15 | 16 | - On 32-bit systems, where we can always enforce a reasonable memory limit 17 | (-m 800 or so is a good starting point), 18 | 19 | - On 64-bit systems only if you can do one of the following: 20 | 21 | - Compile the binary in 32-bit mode (gcc -m32), 22 | 23 | - Precisely gauge memory needs using http://jwilk.net/software/recidivm . 24 | 25 | - Limit the memory available to process using cgroups on Linux (see 26 | experimental/asan_cgroups). 27 | 28 | To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The 29 | afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags. 30 | Note that ASAN is incompatible with -static, so be mindful of that. 31 | 32 | (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) 33 | 34 | There is also the option of generating a corpus using a non-ASAN binary, and 35 | then feeding it to an ASAN-instrumented one to check for bugs. This is faster, 36 | and can give you somewhat comparable results. 37 | 38 | 2) Long version 39 | --------------- 40 | 41 | ASAN allocates a huge region of virtual address space for bookkeeping purposes. 42 | Most of this is never actually accessed, so the OS never has to allocate any 43 | real pages of memory for the process, and the VM grabbed by ASAN is essentially 44 | "free" - but the mapping counts against the standard OS-enforced limit 45 | (RLIMIT_AS, aka ulimit -v). 46 | 47 | On our end, afl-fuzz tries to protect you from processes that go off-rails 48 | and start consuming all the available memory in a vain attempt to parse a 49 | malformed input file. This happens surprisingly often, so enforcing such a limit 50 | is important for almost any fuzzer: the alternative is for the kernel OOM 51 | handler to step in and start killing random processes to free up resources. 52 | Needless to say, that's not a very nice prospect to live with. 53 | 54 | Unfortunately, un*x systems offer no portable way to limit the amount of 55 | pages actually given to a process in a way that distinguishes between that 56 | and the harmless "land grab" done by ASAN. In principle, there are three standard 57 | ways to limit the size of the heap: 58 | 59 | - The RLIMIT_AS mechanism (ulimit -v) caps the size of the virtual space - 60 | but as noted, this pays no attention to the number of pages actually 61 | in use by the process, and doesn't help us here. 62 | 63 | - The RLIMIT_DATA mechanism (ulimit -d) seems like a good fit, but it applies 64 | only to the traditional sbrk() / brk() methods of requesting heap space; 65 | modern allocators, including the one in glibc, routinely rely on mmap() 66 | instead, and circumvent this limit completely. 67 | 68 | - Finally, the RLIMIT_RSS limit (ulimit -m) sounds like what we need, but 69 | doesn't work on Linux - mostly because nobody felt like implementing it. 70 | 71 | There are also cgroups, but they are Linux-specific, not universally available 72 | even on Linux systems, and they require root permissions to set up; I'm a bit 73 | hesitant to make afl-fuzz require root permissions just for that. That said, 74 | if you are on Linux and want to use cgroups, check out the contributed script 75 | that ships in experimental/asan_cgroups/. 76 | 77 | In settings where cgroups aren't available, we have no nice, portable way to 78 | avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for 79 | binaries compiled in 32-bit mode (-m32), this is not a big deal: ASAN needs 80 | around 600-800 MB or so, depending on the compiler - so all you need to do is 81 | to specify -m that is a bit higher than that. 82 | 83 | On 64-bit systems, the situation is more murky, because the ASAN allocation 84 | is completely outlandish - around 17.5 TB in older versions, and closer to 85 | 20 TB with newest ones. The actual amount of memory on your system is 86 | (probably!) just a tiny fraction of that - so unless you dial the limit 87 | with surgical precision, you will get no protection from OOM bugs. 88 | 89 | On my system, the amount of memory grabbed by ASAN with a slightly older 90 | version of gcc is around 17,825,850 MB; for newest clang, it's 20,971,600. 91 | But there is no guarantee that these numbers are stable, and if you get them 92 | wrong by "just" a couple gigs or so, you will be at risk. 93 | 94 | To get the precise number, you can use the recidivm tool developed by Jakub 95 | Wilk (http://jwilk.net/software/recidivm). In absence of this, ASAN is *not* 96 | recommended when fuzzing 64-bit binaries, unless you are confident that they 97 | are robust and enforce reasonable memory limits (in which case, you can 98 | specify '-m none' when calling afl-fuzz). 99 | 100 | Using recidivm or running with no limits aside, there are two other decent 101 | alternatives: build a corpus of test cases using a non-ASAN binary, and then 102 | examine them with ASAN, Valgrind, or other heavy-duty tools in a more 103 | controlled setting; or compile the target program with -m32 (32-bit mode) 104 | if your system supports that. 105 | 106 | 3) Interactions with the QEMU mode 107 | ---------------------------------- 108 | 109 | ASAN, MSAN, and other sanitizers appear to be incompatible with QEMU user 110 | emulation, so please do not try to use them with the -Q option; QEMU doesn't 111 | seem to appreciate the shadow VM trick used by these tools, and will likely 112 | just allocate all your physical memory, then crash. 113 | 114 | 4) What about UBSAN? 115 | -------------------- 116 | 117 | Some folks expressed interest in fuzzing with UBSAN. This isn't officially 118 | supported, because many installations of UBSAN don't offer a consistent way 119 | to abort() on fault conditions or to terminate with a distinctive exit code. 120 | 121 | That said, some versions of the library can be binary-patched to address this 122 | issue, while newer releases support explicit compile-time flags - see this 123 | mailing list thread for tips: 124 | 125 | https://groups.google.com/forum/#!topic/afl-users/GyeSBJt4M38 126 | -------------------------------------------------------------------------------- /afl_docs/perf_tips.txt: -------------------------------------------------------------------------------- 1 | ================================= 2 | Tips for performance optimization 3 | ================================= 4 | 5 | This file provides tips for troubleshooting slow or wasteful fuzzing jobs. 6 | See README for the general instruction manual. 7 | 8 | 1) Keep your test cases small 9 | ----------------------------- 10 | 11 | This is probably the single most important step to take! Large test cases do 12 | not merely take more time and memory to be parsed by the tested binary, but 13 | also make the fuzzing process dramatically less efficient in several other 14 | ways. 15 | 16 | To illustrate, let's say that you're randomly flipping bits in a file, one bit 17 | at a time. Let's assume that if you flip bit #47, you will hit a security bug; 18 | flipping any other bit just results in an invalid document. 19 | 20 | Now, if your starting test case is 100 bytes long, you will have a 71% chance of 21 | triggering the bug within the first 1,000 execs - not bad! But if the test case 22 | is 1 kB long, the probability that we will randomly hit the right pattern in 23 | the same timeframe goes down to 11%. And if it has 10 kB of non-essential 24 | cruft, the odds plunge to 1%. 25 | 26 | On top of that, with larger inputs, the binary may be now running 5-10x times 27 | slower than before - so the overall drop in fuzzing efficiency may be easily 28 | as high as 500x or so. 29 | 30 | In practice, this means that you shouldn't fuzz image parsers with your 31 | vacation photos. Generate a tiny 16x16 picture instead, and run it through 32 | jpegtran or pngcrunch for good measure. The same goes for most other types 33 | of documents. 34 | 35 | There's plenty of small starting test cases in ../testcases/* - try them out 36 | or submit new ones! 37 | 38 | If you want to start with a larger, third-party corpus, run afl-cmin with an 39 | aggressive timeout on that data set first. 40 | 41 | 2) Use a simpler target 42 | ----------------------- 43 | 44 | Consider using a simpler target binary in your fuzzing work. For example, for 45 | image formats, bundled utilities such as djpeg, readpng, or gifhisto are 46 | considerably (10-20x) faster than the convert tool from ImageMagick - all while 47 | exercising roughly the same library-level image parsing code. 48 | 49 | Even if you don't have a lightweight harness for a particular target, remember 50 | that you can always use another, related library to generate a corpus that will 51 | be then manually fed to a more resource-hungry program later on. 52 | 53 | 3) Use LLVM instrumentation 54 | --------------------------- 55 | 56 | When fuzzing slow targets, you can gain 2x performance improvement by using 57 | the LLVM-based instrumentation mode described in llvm_mode/README.llvm. Note 58 | that this mode requires the use of clang and will not work with GCC. 59 | 60 | The LLVM mode also offers a "persistent", in-process fuzzing mode that can 61 | work well for certain types of self-contained libraries, and for fast targets, 62 | can offer performance gains up to 5-10x; and a "deferred fork server" mode 63 | that can offer huge benefits for programs with high startup overhead. Both 64 | modes require you to edit the source code of the fuzzed program, but the 65 | changes often amount to just strategically placing a single line or two. 66 | 67 | 4) Profile and optimize the binary 68 | ---------------------------------- 69 | 70 | Check for any parameters or settings that obviously improve performance. For 71 | example, the djpeg utility that comes with IJG jpeg and libjpeg-turbo can be 72 | called with: 73 | 74 | -dct fast -nosmooth -onepass -dither none -scale 1/4 75 | 76 | ...and that will speed things up. There is a corresponding drop in the quality 77 | of decoded images, but it's probably not something you care about. 78 | 79 | In some programs, it is possible to disable output altogether, or at least use 80 | an output format that is computationally inexpensive. For example, with image 81 | transcoding tools, converting to a BMP file will be a lot faster than to PNG. 82 | 83 | With some laid-back parsers, enabling "strict" mode (i.e., bailing out after 84 | first error) may result in smaller files and improved run time without 85 | sacrificing coverage; for example, for sqlite, you may want to specify -bail. 86 | 87 | If the program is still too slow, you can use strace -tt or an equivalent 88 | profiling tool to see if the targeted binary is doing anything silly. 89 | Sometimes, you can speed things up simply by specifying /dev/null as the 90 | config file, or disabling some compile-time features that aren't really needed 91 | for the job (try ./configure --help). One of the notoriously resource-consuming 92 | things would be calling other utilities via exec*(), popen(), system(), or 93 | equivalent calls; for example, tar can invoke external decompression tools 94 | when it decides that the input file is a compressed archive. 95 | 96 | Some programs may also intentionally call sleep(), usleep(), or nanosleep(); 97 | vim is a good example of that. 98 | 99 | In programs that are slow due to unavoidable initialization overhead, you may 100 | want to try the LLVM deferred forkserver mode (see llvm_mode/README.llvm), 101 | which can give you speed gains up to 10x, as mentioned above. 102 | 103 | Last but not least, if you are using ASAN and the performance is unacceptable, 104 | consider turning it off for now, and manually examining the generated corpus 105 | with an ASAN-enabled binary later on. 106 | 107 | 5) Instrument just what you need 108 | -------------------------------- 109 | 110 | Instrument just the libraries you actually want to stress-test right now, one 111 | at a time. Let the program use system-wide, non-instrumented libraries for 112 | any functionality you don't actually want to fuzz. For example, in most 113 | cases, it doesn't make to instrument libgmp just because you're testing a 114 | crypto app that relies on it for bignum math. 115 | 116 | Beware of programs that come with oddball third-party libraries bundled with 117 | their source code (Spidermonkey is a good example of this). Check ./configure 118 | options to use non-instrumented system-wide copies instead. 119 | 120 | 6) Parallelize your fuzzers 121 | --------------------------- 122 | 123 | The fuzzer is designed to need ~1 core per job. This means that on a, say, 124 | 4-core system, you can easily run four parallel fuzzing jobs with relatively 125 | little performance hit. For tips on how to do that, see parallel_fuzzing.txt. 126 | 127 | The afl-gotcpu utility can help you understand if you still have idle CPU 128 | capacity on your system. (It won't tell you about memory bandwidth, cache 129 | misses, or similar factors, but they are less likely to be a concern.) 130 | 131 | 7) Keep memory use and timeouts in check 132 | ---------------------------------------- 133 | 134 | If you have increased the -m or -t limits more than truly necessary, consider 135 | dialing them back down. 136 | 137 | For programs that are nominally very fast, but get sluggish for some inputs, 138 | you can also try setting -t values that are more punishing than what afl-fuzz 139 | dares to use on its own. On fast and idle machines, going down to -t 5 may be 140 | a viable plan. 141 | 142 | The -m parameter is worth looking at, too. Some programs can end up spending 143 | a fair amount of time allocating and initializing megabytes of memory when 144 | presented with pathological inputs. Low -m values can make them give up sooner 145 | and not waste CPU time. 146 | 147 | 8) Check OS configuration 148 | ------------------------- 149 | 150 | There are several OS-level factors that may affect fuzzing speed: 151 | 152 | - High system load. Use idle machines where possible. Kill any non-essential 153 | CPU hogs (idle browser windows, media players, complex screensavers, etc). 154 | 155 | - Network filesystems, either used for fuzzer input / output, or accessed by 156 | the fuzzed binary to read configuration files (pay special attention to the 157 | home directory - many programs search it for dot-files). 158 | 159 | - On-demand CPU scaling. The Linux 'ondemand' governor performs its analysis 160 | on a particular schedule and is known to underestimate the needs of 161 | short-lived processes spawned by afl-fuzz (or any other fuzzer). On Linux, 162 | this can be fixed with: 163 | 164 | cd /sys/devices/system/cpu 165 | echo performance | tee cpu*/cpufreq/scaling_governor 166 | 167 | On other systems, the impact of CPU scaling will be different; when fuzzing, 168 | use OS-specific tools to find out if all cores are running at full speed. 169 | 170 | - Suboptimal scheduling strategies. The significance of this will vary from 171 | one target to another, but on Linux, you may want to make sure that the 172 | following options are set: 173 | 174 | echo 1 >/proc/sys/kernel/sched_child_runs_first 175 | echo 1 >/proc/sys/kernel/sched_autogroup_enabled 176 | 177 | Setting a different scheduling policy for the fuzzer process - say 178 | SCHED_RR - can usually speed things up, too, but needs to be done with 179 | care. 180 | 181 | 9) If all other options fail, use -d 182 | ------------------------------------ 183 | 184 | For programs that are genuinely slow, in cases where you really can't escape 185 | using huge input files, or when you simply want to get quick and dirty results 186 | early on, you can always resort to the -d mode. 187 | 188 | The mode causes afl-fuzz to skip all the deterministic fuzzing steps, which 189 | makes output a lot less neat and makes the testing a bit less in-depth, but 190 | it will give you an experience more familiar from other fuzzing tools. 191 | -------------------------------------------------------------------------------- /afl_docs/sister_projects.txt: -------------------------------------------------------------------------------- 1 | =============== 2 | Sister projects 3 | =============== 4 | 5 | This doc lists some of the projects that are inspired by, derived from, 6 | designed for, or meant to integrate with AFL. See README for the general 7 | instruction manual. 8 | 9 | ---------------------------- 10 | Support for other languages: 11 | ---------------------------- 12 | 13 | Python AFL (Jakub Wilk) 14 | ----------------------- 15 | 16 | Allows fuzz-testing of Python programs. Uses custom instrumentation and its 17 | own forkserver. 18 | 19 | http://jwilk.net/software/python-afl 20 | 21 | Go-fuzz (Dmitry Vyukov) 22 | ----------------------- 23 | 24 | AFL-inspired guided fuzzing approach for Go targets: 25 | 26 | https://github.com/dvyukov/go-fuzz 27 | 28 | afl.rs (Keegan McAllister) 29 | -------------------------- 30 | 31 | Allows Rust features to be easily fuzzed with AFL (using the LLVM mode). 32 | 33 | https://github.com/kmcallister/afl.rs 34 | 35 | AFL for GCJ Java and other GCC frontends (-) 36 | -------------------------------------------- 37 | 38 | GCC Java programs are actually supported out of the box - simply rename 39 | afl-gcc to afl-gcj. Unfortunately, by default, unhandled exceptions in GCJ do 40 | not result in abort() being called, so you will need to manually add a 41 | top-level exception handler that exits with SIGABRT or something equivalent. 42 | 43 | Other GCC-supported languages should be fairly easy to get working, but may 44 | face similar problems. See https://gcc.gnu.org/frontends.html for a list of 45 | options. 46 | 47 | AFL-style in-process fuzzer for LLVM (Kostya Serebryany) 48 | -------------------------------------------------------- 49 | 50 | Provides an evolutionary instrumentation-guided fuzzing harness that allows 51 | some programs to be fuzzed without the fork / execve overhead. (Similar 52 | functionality is now available as the "persistent" feature described in 53 | ../llvm_mode/README.llvm.) 54 | 55 | http://llvm.org/docs/LibFuzzer.html 56 | 57 | AFL fixup shim (Ben Nagy) 58 | ------------------------- 59 | 60 | Allows AFL_POST_LIBRARY postprocessors to be written in arbitrary languages 61 | that don't have C / .so bindings. Includes examples in Go. 62 | 63 | https://github.com/bnagy/aflfix 64 | 65 | ---------------- 66 | Network fuzzing: 67 | ---------------- 68 | 69 | Preeny (Yan Shoshitaishvili) 70 | ---------------------------- 71 | 72 | Provides a fairly simple way to convince dynamically linked network-centric 73 | programs to read from a file or not fork. Not AFL-specific, but described as 74 | useful by many users. Some assembly required. 75 | 76 | https://github.com/zardus/preeny 77 | 78 | ------------------------------------------- 79 | Distributed fuzzing and related automation: 80 | ------------------------------------------- 81 | 82 | roving (Richo Healey) 83 | --------------------- 84 | 85 | A client-server architecture for effortlessly orchestrating AFL runs across 86 | a fleet of machines. You don't want to use this on systems that face the 87 | Internet or live in other untrusted environments. 88 | 89 | https://github.com/richo/roving 90 | 91 | Distfuzz-AFL (Martijn Bogaard) 92 | ------------------------------ 93 | 94 | Simplifies the management of afl-fuzz instances on remote machines. The 95 | author notes that the current implementation isn't secure and should not 96 | be exposed on the Internet. 97 | 98 | https://github.com/MartijnB/disfuzz-afl 99 | 100 | afl-launch (Ben Nagy) 101 | --------------------- 102 | 103 | Batch AFL launcher utility with a simple CLI. 104 | 105 | https://github.com/bnagy/afl-launch 106 | 107 | AFL Utils (rc0r) 108 | ---------------- 109 | 110 | Simplifies the triage of discovered crashes, start parallel instances, etc. 111 | 112 | https://github.com/rc0r/afl-utils 113 | 114 | afl-fuzzing-scripts (Tobias Ospelt) 115 | ----------------------------------- 116 | 117 | Simplifies starting up multiple parallel AFL jobs. 118 | 119 | https://github.com/floyd-fuh/afl-fuzzing-scripts/ 120 | 121 | afl-sid (Jacek Wielemborek) 122 | --------------------------- 123 | 124 | Allows users to more conveniently build and deploy AFL via Docker. 125 | 126 | https://github.com/d33tah/afl-sid 127 | 128 | ------------------------------------- 129 | Crash triage, coverage analysis, etc: 130 | ------------------------------------- 131 | 132 | afl-crash-analyzer (Tobias Ospelt) 133 | ---------------------------------- 134 | 135 | Makes it easier to navigate and annotate crashing test cases. 136 | 137 | https://github.com/floyd-fuh/afl-crash-analyzer/ 138 | 139 | Crashwalk (Ben Nagy) 140 | -------------------- 141 | 142 | AFL-aware tool to annotate and sort through crashing test cases. 143 | 144 | https://github.com/bnagy/crashwalk 145 | 146 | afl-cov (Michael Rash) 147 | ---------------------- 148 | 149 | Produces human-readable coverage data based on the output queue of afl-fuzz. 150 | 151 | https://github.com/mrash/afl-cov 152 | 153 | RecidiVM (Jakub Wilk) 154 | --------------------- 155 | 156 | Makes it easy to estimate memory usage limits when fuzzing with ASAN or MSAN. 157 | 158 | http://jwilk.net/software/recidivm 159 | 160 | ------------------------------- 161 | Narrow-purpose or experimental: 162 | ------------------------------- 163 | 164 | Pause and resume scripts (Ben Nagy) 165 | ----------------------------------- 166 | 167 | Simple automation to suspend and resume groups of fuzzing jobs. 168 | 169 | https://gist.github.com/bnagy/8f0eb29eb125653f73fd 170 | 171 | Static binary-only instrumentation (Aleksandar Nikolich) 172 | -------------------------------------------------------- 173 | 174 | Allows black-box binaries to be instrumented statically (i.e., by modifying 175 | the binary ahead of the time, rather than translating it on the run). Author 176 | reports better performance compared to QEMU, but occasional translation 177 | errors with stripped binaries. 178 | 179 | https://github.com/vrtadmin/moflow/tree/master/afl-dyninst 180 | 181 | AFL PIN (Parker Thompson) 182 | ------------------------- 183 | 184 | Early-stage Intel PIN instrumentation support (from before we settled on 185 | faster-running QEMU). 186 | 187 | https://github.com/mothran/aflpin 188 | 189 | AFL-style instrumentation in llvm (Kostya Serebryany) 190 | ----------------------------------------------------- 191 | 192 | Allows AFL-equivalent instrumentation to be injected at compiler level. 193 | This is currently not supported by AFL as-is, but may be useful in other 194 | projects. 195 | 196 | https://code.google.com/p/address-sanitizer/wiki/AsanCoverage#Coverage_counters 197 | 198 | AFL JS (Han Choongwoo) 199 | ---------------------- 200 | 201 | One-off optimizations to speed up the fuzzing of JavaScriptCore (now likely 202 | superseded by LLVM deferred forkserver init - see llvm_mode/README.llvm). 203 | 204 | https://github.com/tunz/afl-fuzz-js 205 | 206 | AFL harness for fwknop (Michael Rash) 207 | ------------------------------------- 208 | 209 | An example of a fairly involved integration with AFL. 210 | 211 | https://github.com/mrash/fwknop/tree/master/test/afl 212 | 213 | Building harnesses for DNS servers (Jonathan Foote, Ron Bowes) 214 | -------------------------------------------------------------- 215 | 216 | Two articles outlining the general principles and showing some example code. 217 | 218 | https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop 219 | https://goo.gl/j9EgFf 220 | 221 | Fuzzer shell for SQLite (Richard Hipp) 222 | -------------------------------------- 223 | 224 | A simple SQL shell designed specifically for fuzzing the underlying library. 225 | 226 | http://www.sqlite.org/src/artifact/9e7e273da2030371 227 | 228 | -------------------------------------------------------------------------------- /afl_docs/visualization/afl_gzip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/visualization/afl_gzip.png -------------------------------------------------------------------------------- /afl_docs/vuln_samples/bash-cmd-exec.var: -------------------------------------------------------------------------------- 1 | () { _; } >_[$($())] { id; } -------------------------------------------------------------------------------- /afl_docs/vuln_samples/bash-uninit-mem.var: -------------------------------------------------------------------------------- 1 | () { x() { _; }; x() { _; } <O));insert into t0 2 | select randomblob(0)-trim(0); 3 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-bad-ptr.sql: -------------------------------------------------------------------------------- 1 | SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE""""""""; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-bad-ptr2.sql: -------------------------------------------------------------------------------- 1 | PRAGMA foreign_keys=1;CREATE TABLE t1("""0"PRIMARY KEy REFERENCES t1 ON DELETE SET NULL);REPLACE INTO t1 SELECT(0); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-bad-ptr3.sql: -------------------------------------------------------------------------------- 1 | create table t(l);PRAGMA writable_schema=ON; 2 | UPDATE sqlite_master SET sql='0 0000000000000000000000000000000000000000000000000000000000000000000000000000000[%S';PRAGMA t;SAVEPOINT x;ROLLBACK;VACUUM; 3 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-heap-overflow.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS t;CREATE VIRTUAL TABLE t0 USING fts4();insert into t0 select zeroblob(0);SAVEPOINT O;insert into t0 2 | select(0);SAVEPOINT E;insert into t0 SELECT 0 UNION SELECT 0'x'ORDER BY x; 3 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-heap-overwrite.sql: -------------------------------------------------------------------------------- 1 | ATTACH "file:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA?mode=memory&cache=shared" AS x; -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-negative-memset.sql: -------------------------------------------------------------------------------- 1 | SELECT*from(select"",zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(150000000),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)),(select"",zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),(0),zeroblob(150000000),(0),zeroblob(0),(0)EXCEPT select zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr1.sql: -------------------------------------------------------------------------------- 1 | create table t0(t);insert into t0 2 | select strftime(); 3 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr10.sql: -------------------------------------------------------------------------------- 1 | SELECT fts3_tokenizer(@0()); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr11.sql: -------------------------------------------------------------------------------- 1 | select''like''like''like#0; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr12.sql: -------------------------------------------------------------------------------- 1 | PRAGMA e;select lower(0);select lower(0)"a",""GROUP BY a ORDER BY a; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr13.sql: -------------------------------------------------------------------------------- 1 | WITH x AS(SELECT*FROM t)SELECT""EXCEPT SELECT 0 ORDER BY 0 COLLATE""; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr14.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE x USING fts4();VALUES(0,0),(0,0),(0,0),(0,0);PRAGMA writable_schema=ON;UPDATE sqlite_master SET sql=''WHERE name='';UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';SAVEPOINT K;SAVEPOINT T;SAVEPOINT T;ANALYZE;ROLLBACK;SAVEPOINT E;DROP TABLE IF EXISTS t; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr15.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t4 USING fts4(0,b,c,notindexed=0);INSERT INTO t4 VALUES('','','0');BEGIN;INSERT INTO t4 VALUES('','','0');INSERT INTO t4(t4)VALUES('integrity-check'); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr2.sql: -------------------------------------------------------------------------------- 1 | DETACH(select group_concat(q)); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr3.sql: -------------------------------------------------------------------------------- 1 | select(select strftime()); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr4.sql: -------------------------------------------------------------------------------- 1 | select n()AND+#00; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr5.sql: -------------------------------------------------------------------------------- 1 | select e.*,0 from(s,(L))e; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr6.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/sqlite-null-ptr6.sql -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr7.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t USING fts4(tokenize=); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr8.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE p(a UNIQUE,PRIMARY KEY('a'))WITHOUT rowid; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-null-ptr9.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE t0(z);WITH d(x)AS(SELECT*UNION SELECT 0)INSERT INTO t0 SELECT 0 FROM d; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-oob-read.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/sqlite-oob-read.sql -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-oob-write.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t0 USING fts4(x,order=DESC); 2 | INSERT INTO t0(docid,x)VALUES(-1E0,'0(o'); 3 | INSERT INTO t0 VALUES(''); 4 | INSERT INTO t0 VALUES(''); 5 | INSeRT INTO t0 VALUES('o'); 6 | SELECT docid FROM t0 WHERE t0 MATCH'"0*o"'; 7 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-stack-buf-overflow.sql: -------------------------------------------------------------------------------- 1 | SELECT printf('%*.*f',90000||006000000&6600000000,00000000000000000909000000000000.0000000000000000)""WHERE"">""; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-stack-exhaustion.sql: -------------------------------------------------------------------------------- 1 | CREATE VIRTUAL TABLE t0 USING fts4(content=t0); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-unint-mem.sql: -------------------------------------------------------------------------------- 1 | REATE VIRTUAL TABLE t0 USING fts4(prefix=0);INSERT INTO t0 VALUES(0); 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/sqlite-use-after-free.sql: -------------------------------------------------------------------------------- 1 | create table t(s);PRAGMA writable_schema=ON;UPDATE sqlite_master SET sql='ANALYZE;CREATE VIRTUAL TABLE t USING fts3;DROP TABLE t;DROP TABLE EXISTS t';PRAGMA r;SAVEPOINT T;ANALYZE;ROLLBACK;SAVEPOINT E;DROP TABLE IF EXISTS t; 2 | -------------------------------------------------------------------------------- /afl_docs/vuln_samples/strings-stack-overflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/strings-stack-overflow -------------------------------------------------------------------------------- /afl_docs/vuln_samples/tcpdump-arp-crash.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/tcpdump-arp-crash.pcap -------------------------------------------------------------------------------- /afl_docs/vuln_samples/tcpdump-ppp-crash.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/tcpdump-ppp-crash.pcap -------------------------------------------------------------------------------- /afl_docs/vuln_samples/unrtf-arbitrary-read.rtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/unrtf-arbitrary-read.rtf -------------------------------------------------------------------------------- /afl_docs/vuln_samples/unzip-t-mem-corruption.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/afl_docs/vuln_samples/unzip-t-mem-corruption.zip -------------------------------------------------------------------------------- /afl_post_library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | project(post_library) 4 | 5 | set(CMAKE_CXX_FLAGS_RELEASE "/MT") 6 | set(CMAKE_CXX_FLAGS_DEBUG "/MTd") 7 | 8 | set(CMAKE_C_FLAGS_RELEASE "/MT") 9 | set(CMAKE_C_FLAGS_DEBUG "/MTd") 10 | 11 | add_library(post_library SHARED 12 | post_library.c 13 | ) 14 | 15 | 16 | -------------------------------------------------------------------------------- /afl_post_library/post_library.c: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - postprocessor library example 3 | -------------------------------------------------- 4 | Written and maintained by Michal Zalewski 5 | Copyright 2015 Google Inc. All rights reserved. 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at: 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | Postprocessor libraries can be passed to afl-fuzz to perform final cleanup 11 | of any mutated test cases - for example, to fix up checksums in PNG files. 12 | Please heed the following warnings: 13 | 1) In almost all cases, it is more productive to comment out checksum logic 14 | in the targeted binary (as shown in ../libpng_no_checksum/). One possible 15 | exception is the process of fuzzing binary-only software in QEMU mode. 16 | 2) The use of postprocessors for anything other than checksums is questionable 17 | and may cause more harm than good. AFL is normally pretty good about 18 | dealing with length fields, magic values, etc. 19 | 3) Postprocessors that do anything non-trivial must be extremely robust to 20 | gracefully handle malformed data and other error conditions - otherwise, 21 | they will crash and take afl-fuzz down with them. Be wary of reading past 22 | *len and of integer overflows when calculating file offsets. 23 | In other words, THIS IS PROBABLY NOT WHAT YOU WANT - unless you really, 24 | honestly know what you're doing =) 25 | With that out of the way: the postprocessor library is passed to afl-fuzz 26 | via AFL_POST_LIBRARY. The library must be compiled with: 27 | gcc -shared -Wall -O3 post_library.so.c -o post_library.so 28 | AFL will call the afl_postprocess() function for every mutated output buffer. 29 | From there, you have three choices: 30 | 1) If you don't want to modify the test case, simply return the original 31 | buffer pointer ('in_buf'). 32 | 2) If you want to skip this test case altogether and have AFL generate a 33 | new one, return NULL. Use this sparingly - it's faster than running 34 | the target program with patently useless inputs, but still wastes CPU 35 | time. 36 | 3) If you want to modify the test case, allocate an appropriately-sized 37 | buffer, move the data into that buffer, make the necessary changes, and 38 | then return the new pointer. You can update *len if necessary, too. 39 | Note that the buffer will *not* be freed for you. To avoid memory leaks, 40 | you need to free it or reuse it on subsequent calls (as shown below). 41 | *** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. *** 42 | Aight. The example below shows a simple postprocessor that tries to make 43 | sure that all input files start with "GIF89a". 44 | PS. If you don't like C, you can try out the unix-based wrapper from 45 | Ben Nagy instead: https://github.com/bnagy/aflfix 46 | */ 47 | 48 | #include 49 | #include 50 | #include 51 | 52 | /* Header that must be present at the beginning of every test case: */ 53 | 54 | #define HEADER "GIF89a" 55 | 56 | /* The actual postprocessor routine called by afl-fuzz: */ 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | #ifdef _MSC_VER 61 | __declspec(dllexport) 62 | #endif 63 | const unsigned char* afl_postprocess(const unsigned char* in_buf, 64 | unsigned int* len) { 65 | 66 | static unsigned char* saved_buf; 67 | unsigned char* new_buf; 68 | 69 | /* Skip execution altogether for buffers shorter than 6 bytes (just to 70 | show how it's done). We can trust *len to be sane. */ 71 | 72 | if (*len < strlen(HEADER)) return NULL; 73 | 74 | /* Do nothing for buffers that already start with the expected header. */ 75 | 76 | if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf; 77 | 78 | /* Allocate memory for new buffer, reusing previous allocation if 79 | possible. */ 80 | 81 | new_buf = realloc(saved_buf, *len); 82 | 83 | /* If we're out of memory, the most graceful thing to do is to return the 84 | original buffer and give up on modifying it. Let AFL handle OOM on its 85 | own later on. */ 86 | 87 | if (!new_buf) return in_buf; 88 | saved_buf = new_buf; 89 | 90 | /* Copy the original data to the new location. */ 91 | 92 | memcpy(new_buf, in_buf, *len); 93 | 94 | /* Insert the new header. */ 95 | 96 | memcpy(new_buf, HEADER, strlen(HEADER)); 97 | 98 | /* Return modified buffer. No need to update *len in this particular case, 99 | as we're not changing it. */ 100 | 101 | return new_buf; 102 | 103 | } 104 | #ifdef __cplusplus 105 | } 106 | #endif -------------------------------------------------------------------------------- /custom_net_fuzzer.c: -------------------------------------------------------------------------------- 1 | /* 2 | custom_net_fuzzer - a shared DLL to enable network fuzzing in winAFL 3 | ------------------------------------------------------------- 4 | 5 | Written and maintained by Maksim Shudrak 6 | 7 | Copyright 2018 Salesforce Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #include "custom_winafl_server.h" 24 | 25 | static u8 enable_socket_fuzzing = 0; /* Enable network fuzzing */ 26 | static u8 is_TCP = 1; /* TCP or UDP */ 27 | static u32 target_port = 0x0; /* Target port to send test cases */ 28 | static u32 socket_init_delay = SOCKET_INIT_DELAY; /* Socket init delay */ 29 | static u8 *target_ip_address = NULL; /* Target IP to send test cases */ 30 | 31 | 32 | static SOCKET ListenSocket = INVALID_SOCKET; 33 | static SOCKET ClientSocket = INVALID_SOCKET; 34 | 35 | static void send_data_tcp(const char *buf, const int buf_len, int first_time) { 36 | static struct sockaddr_in si_other; 37 | static int slen = sizeof(si_other); 38 | static WSADATA wsa; 39 | int s; 40 | 41 | if (first_time == 0x0) { 42 | /* wait while the target process open the socket */ 43 | Sleep(socket_init_delay); 44 | 45 | if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) 46 | FATAL("WSAStartup failed. Error Code : %d", WSAGetLastError()); 47 | 48 | // setup address structure 49 | memset((char *)&si_other, 0, sizeof(si_other)); 50 | si_other.sin_family = AF_INET; 51 | si_other.sin_port = htons(target_port); 52 | si_other.sin_addr.S_un.S_addr = inet_addr((char *)target_ip_address); 53 | } 54 | 55 | /* In case of TCP we need to open a socket each time we want to establish 56 | * connection. In theory we can keep connections always open but it might 57 | * cause our target behave differently (probably there are a bunch of 58 | * applications where we should apply such scheme to trigger interesting 59 | * behavior). 60 | */ 61 | if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == SOCKET_ERROR) 62 | FATAL("socket() failed with error code : %d", WSAGetLastError()); 63 | 64 | // Connect to server. 65 | if (connect(s, (SOCKADDR *)& si_other, slen) == SOCKET_ERROR) 66 | FATAL("connect() failed with error code : %d", WSAGetLastError()); 67 | 68 | // Send our buffer 69 | if (send(s, buf, buf_len, 0) == SOCKET_ERROR) 70 | FATAL("send() failed with error code : %d", WSAGetLastError()); 71 | 72 | // shutdown the connection since no more data will be sent 73 | if (shutdown(s, 0x1/*SD_SEND*/) == SOCKET_ERROR) 74 | FATAL("shutdown failed with error: %d\n", WSAGetLastError()); 75 | // close the socket to avoid consuming much resources 76 | if (closesocket(s) == SOCKET_ERROR) 77 | FATAL("closesocket failed with error: %d\n", WSAGetLastError()); 78 | } 79 | 80 | static void send_data_udp(const char *buf, const int buf_len, int first_time) { 81 | static struct sockaddr_in si_other; 82 | static int s, slen = sizeof(si_other); 83 | static WSADATA wsa; 84 | 85 | if (first_time == 0x0) { 86 | /* wait while the target process open the socket */ 87 | Sleep(socket_init_delay); 88 | 89 | if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) 90 | FATAL("WSAStartup failed. Error Code : %d", WSAGetLastError()); 91 | 92 | if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) 93 | FATAL("socket() failed with error code : %d", WSAGetLastError()); 94 | 95 | // setup address structure 96 | memset((char *)&si_other, 0, sizeof(si_other)); 97 | si_other.sin_family = AF_INET; 98 | si_other.sin_port = htons(target_port); 99 | si_other.sin_addr.S_un.S_addr = inet_addr((char *)target_ip_address); 100 | } 101 | 102 | // send the data 103 | if (sendto(s, buf, buf_len, 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR) 104 | FATAL("sendto() failed with error code : %d", WSAGetLastError()); 105 | } 106 | 107 | #define DEFAULT_BUFLEN 4096 108 | 109 | CUSTOM_SERVER_API int APIENTRY dll_run(char *data, long size, int fuzz_iterations) { 110 | if (is_TCP) 111 | send_data_tcp(data, size, fuzz_iterations); 112 | else 113 | send_data_udp(data, size, fuzz_iterations); 114 | return 1; 115 | } 116 | 117 | static int optind; 118 | static u8 *optarg; 119 | 120 | int getopt(int argc, char **argv, char *optstring) { 121 | char *c; 122 | optarg = NULL; 123 | int i = 0; 124 | 125 | while (1) { 126 | if (optind == argc) return -1; 127 | 128 | if (argv[optind][0] != '-') { 129 | optind++; 130 | continue; 131 | } 132 | if (!argv[optind][1]) { 133 | optind++; 134 | continue; 135 | } 136 | 137 | c = strchr(optstring, argv[optind][1]); 138 | if (!c) { 139 | optind++; 140 | continue; 141 | } 142 | 143 | optind++; 144 | if (c[1] == ':') { 145 | if (optind == argc) return -1; 146 | optarg = argv[optind]; 147 | optind++; 148 | } 149 | 150 | return (int)(c[0]); 151 | } 152 | } 153 | 154 | void usage() { 155 | printf("Network fuzzing options:\n\n"\ 156 | " -a - IP address to send data in\n"\ 157 | " -U - Use UDP (default TCP)\n"\ 158 | " -p - Port to send data in\n"\ 159 | " -w - Delay in milliseconds before start sending data\n"); 160 | exit(1); 161 | } 162 | static int optind; 163 | static u8 *optarg; 164 | 165 | #define MAX_ARGS 28 166 | 167 | char **convert_to_array(char *args, int *argc) { 168 | int element_id = 0; 169 | int last_element_offset = 0; 170 | char *c = NULL; 171 | 172 | int length = strlen(args); 173 | char **argv = malloc(MAX_ARGS * sizeof (char *)); 174 | 175 | while (args) { 176 | c = strchr(args, ' '); 177 | if (!c) 178 | break; 179 | 180 | int len = c - args; 181 | if (len <= 0) 182 | break; 183 | 184 | char *element = malloc(len); 185 | memcpy(element, args, len); 186 | element[len] = '\0'; 187 | 188 | argv[element_id] = element; 189 | 190 | element_id++; 191 | if (element_id >= MAX_ARGS) { 192 | usage(); 193 | break; 194 | } 195 | 196 | args = c + 1; 197 | } 198 | argv[element_id] = strdup(args); 199 | 200 | *argc = element_id + 1; 201 | return argv; 202 | } 203 | 204 | CUSTOM_SERVER_API int APIENTRY dll_init() { 205 | s32 opt; 206 | static int iSendResult; 207 | static int first_time = 0x1; 208 | int argc; 209 | 210 | if (!first_time) 211 | return 1; 212 | 213 | char *args = getenv("AFL_CUSTOM_DLL_ARGS"); 214 | 215 | char **argv = convert_to_array(args, &argc); 216 | 217 | if (args == NULL) 218 | usage(); 219 | 220 | while ((opt = getopt(argc, argv, "Ua:p:w:")) > 0) { 221 | switch (opt) { 222 | case 'a': 223 | target_ip_address = ck_strdup(optarg); 224 | 225 | break; 226 | 227 | case 'U': 228 | is_TCP = 0; 229 | 230 | break; 231 | 232 | case 'p': 233 | if (sscanf(optarg, "%u", &target_port) < 1 || 234 | optarg[0] == '-') FATAL("Bad syntax used for -p"); 235 | 236 | break; 237 | 238 | case 'w': 239 | if (sscanf(optarg, "%u", &socket_init_delay) < 1 || 240 | optarg[0] == '-') FATAL("Bad syntax used for -w"); 241 | 242 | break; 243 | default: 244 | break; 245 | } 246 | } 247 | 248 | if (target_ip_address == NULL || target_port == 0) 249 | usage(); 250 | 251 | printf("Ready to begin fuzzing. Target IP= %s, target port = %d\n", 252 | target_ip_address, target_port); 253 | first_time = 0x0; 254 | return 1; 255 | } 256 | -------------------------------------------------------------------------------- /custom_net_fuzzer.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | dll_init 3 | dll_run 4 | -------------------------------------------------------------------------------- /custom_winafl_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | custom_winafl_server - a shared DLL to enable server-mode fuzzing in winAFL: 3 | ------------------------------------------------------------- 4 | 5 | Written and maintained by Maksim Shudrak 6 | 7 | Copyright 2018 Salesforce Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #include "custom_winafl_server.h" 24 | 25 | static SOCKET ListenSocket = INVALID_SOCKET; 26 | static SOCKET ClientSocket = INVALID_SOCKET; 27 | 28 | #define DEFAULT_BUFLEN 4096 29 | 30 | //#define DEBUG_SERVER 1 31 | 32 | /* open data and send it back into TCP/UDP socket (winAFL is a server) */ 33 | static int send_response(char *buf, long fsize, SOCKET ClientSocket) { 34 | /* send our test case */ 35 | #ifdef DEBUG_SERVER 36 | printf("Sending %s\n", buf); 37 | #endif 38 | int iSendResult = send(ClientSocket, buf, fsize, 0); 39 | if (iSendResult == SOCKET_ERROR) { 40 | printf("send failed with error: %d\n", WSAGetLastError()); 41 | closesocket(ClientSocket); 42 | WSACleanup(); 43 | ExitProcess(-1); 44 | return 0; 45 | } 46 | #ifdef DEBUG_SERVER 47 | printf("Bytes sent: %d\n", iSendResult); 48 | #endif 49 | 50 | return 1; 51 | } 52 | 53 | static int recv_loop(SOCKET ClientSocket) { 54 | int iResult; 55 | char recvbuf[DEFAULT_BUFLEN]; 56 | int recvbuflen = DEFAULT_BUFLEN; 57 | 58 | do { 59 | iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); 60 | if (iResult > 0) { 61 | #ifdef DEBUG_SERVER 62 | printf("Bytes received: %d\n", iResult); 63 | #endif 64 | } 65 | else if (iResult == 0) { 66 | #ifdef DEBUG_SERVER 67 | printf("Connection closing...\n"); 68 | #endif 69 | } 70 | else { 71 | printf("recv failed with error: %d\n", WSAGetLastError()); 72 | closesocket(ClientSocket); 73 | WSACleanup(); 74 | ExitProcess(-1); 75 | return 0; 76 | } 77 | } while (iResult > 0); 78 | return 1; 79 | } 80 | 81 | #define DEFAULT_BUFLEN 4096 82 | 83 | typedef struct _test_case_struct { 84 | long size; 85 | char *data; 86 | } test_case_struct; 87 | 88 | /* server-mode routings */ 89 | DWORD WINAPI handle_incoming_connection(LPVOID lpParam) { 90 | static int iResult; 91 | test_case_struct *test_case = (test_case_struct *)lpParam; 92 | 93 | #ifdef DEBUG_SERVER 94 | printf("Handling incoming connections\n"); 95 | #endif 96 | 97 | // Accept a client socket 98 | ClientSocket = accept(ListenSocket, NULL, NULL); 99 | if (ClientSocket == INVALID_SOCKET) { 100 | printf("accept failed with error: %d\n", WSAGetLastError()); 101 | closesocket(ListenSocket); 102 | WSACleanup(); 103 | ExitProcess(-1); 104 | return 0; 105 | } 106 | 107 | recv_loop(ClientSocket); 108 | 109 | /* answer with test case to our client */ 110 | int res = send_response(test_case->data, test_case->size, ClientSocket); 111 | 112 | if (!res) { 113 | printf("Failed to send response"); 114 | ExitProcess(-1); 115 | return 0; 116 | } 117 | 118 | // shutdown the connection since we're done 119 | iResult = shutdown(ClientSocket, SD_SEND); 120 | if (iResult == SOCKET_ERROR) { 121 | printf("shutdown failed with error: %d\n", WSAGetLastError()); 122 | closesocket(ClientSocket); 123 | WSACleanup(); 124 | ExitProcess(-1); 125 | return 0; 126 | } 127 | free(test_case->data); 128 | free(test_case); 129 | return 1; 130 | } 131 | 132 | HANDLE hr = NULL; 133 | 134 | CUSTOM_SERVER_API int APIENTRY dll_run(char *data, long size, int fuzz_iterations) { 135 | DWORD dwThreadId; 136 | test_case_struct *test_case = (test_case_struct *)malloc(sizeof(test_case_struct)); 137 | test_case->data = (char *)malloc(size); 138 | 139 | memcpy(test_case->data, data, size); 140 | test_case->size = size; 141 | 142 | /* we have to create a second thread to avoid blocking winAFL in recv */ 143 | if (hr != NULL) 144 | WaitForSingleObject(hr, INFINITE); /* we have to wait our previous thread to finish exec */ 145 | hr = CreateThread(NULL, 0, handle_incoming_connection, (LPVOID)test_case, 0, &dwThreadId); 146 | if (hr == NULL) 147 | return 0; 148 | 149 | return 1; 150 | } 151 | 152 | void usage() { 153 | printf("Please setup AFL_CUSTOM_DLL_ARGS=\n"); 154 | exit(1); 155 | } 156 | 157 | /* winAFL is a TCP server now (TODO: implement UDP server) */ 158 | CUSTOM_SERVER_API int APIENTRY dll_init() { 159 | static WSADATA wsaData; 160 | static int iResult; 161 | s32 opt; 162 | static struct addrinfo *result = NULL; 163 | static struct addrinfo hints; 164 | static int iSendResult; 165 | 166 | static int first_time = 0x1; 167 | unsigned char *server_bind_port = NULL; 168 | 169 | if (!first_time) 170 | return 1; 171 | 172 | server_bind_port = getenv("AFL_CUSTOM_DLL_ARGS"); 173 | if (server_bind_port == NULL) 174 | usage(); 175 | 176 | printf("Initializing custom winAFL server\n"); 177 | 178 | // Initialize Winsock 179 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 180 | if (iResult != 0) { 181 | printf("WSAStartup failed with error: %d\n", iResult); 182 | return 0; 183 | } 184 | 185 | ZeroMemory(&hints, sizeof(hints)); 186 | hints.ai_family = AF_INET; 187 | hints.ai_socktype = SOCK_STREAM; 188 | hints.ai_protocol = IPPROTO_TCP; 189 | hints.ai_flags = AI_PASSIVE; 190 | 191 | // Resolve the server address and port 192 | iResult = getaddrinfo(NULL, server_bind_port, &hints, &result); 193 | if (iResult != 0) { 194 | printf("getaddrinfo failed with error: %d\n", iResult); 195 | WSACleanup(); 196 | return 0; 197 | } 198 | 199 | // Create a SOCKET for connecting to server 200 | ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 201 | if (ListenSocket == INVALID_SOCKET) { 202 | printf("socket failed with error: %ld\n", WSAGetLastError()); 203 | freeaddrinfo(result); 204 | WSACleanup(); 205 | return 0; 206 | } 207 | 208 | // Setup the TCP listening socket 209 | iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 210 | if (iResult == SOCKET_ERROR) { 211 | printf("bind failed with error: %d\n", WSAGetLastError()); 212 | freeaddrinfo(result); 213 | closesocket(ListenSocket); 214 | WSACleanup(); 215 | return 0; 216 | } 217 | 218 | freeaddrinfo(result); 219 | 220 | iResult = listen(ListenSocket, SOMAXCONN); 221 | if (iResult == SOCKET_ERROR) { 222 | printf("listen failed with error: %d\n", WSAGetLastError()); 223 | closesocket(ListenSocket); 224 | WSACleanup(); 225 | ExitProcess(-1); 226 | return 0; 227 | } 228 | 229 | printf("WinAFL server is listening on port %s\n", server_bind_port); 230 | first_time = 0x0; 231 | 232 | return 1; 233 | } -------------------------------------------------------------------------------- /custom_winafl_server.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | dll_init 3 | dll_run 4 | -------------------------------------------------------------------------------- /custom_winafl_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | custom_winafl_server - a shared DLL to enable server-mode fuzzing in winAFL: 3 | ------------------------------------------------------------- 4 | 5 | Written and maintained by Maksim Shudrak 6 | 7 | Copyright 2018 Salesforce Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | */ 21 | 22 | #pragma once 23 | 24 | #define WIN32_LEAN_AND_MEAN /* prevent winsock.h to be included in windows.h */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | 38 | #pragma comment(lib,"ws2_32.lib") //Winsock Library 39 | #pragma comment( lib, "wininet") 40 | 41 | #include "alloc-inl.h" 42 | 43 | #define CUSTOM_SERVER_API __declspec(dllexport) 44 | 45 | CUSTOM_SERVER_API int APIENTRY dll_init(); 46 | CUSTOM_SERVER_API int APIENTRY dll_run(char *data, long size, int fuzz_iterations); 47 | 48 | /* Default delay in milliseconds to let the target open a socket and start listen for 49 | * incoming packages. 50 | */ 51 | #define SOCKET_INIT_DELAY 30000 -------------------------------------------------------------------------------- /debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - debug / error handling macros 3 | -------------------------------------------------- 4 | 5 | Original AFL code written by Michal Zalewski 6 | 7 | Windows fork written and maintained by Ivan Fratric 8 | 9 | Copyright 2016 Google Inc. 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 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, 19 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | See the License for the specific language governing permissions and 21 | limitations under the License. 22 | 23 | */ 24 | 25 | #ifndef _HAVE_DEBUG_H 26 | #define _HAVE_DEBUG_H 27 | 28 | #include 29 | 30 | #include "types.h" 31 | #include "config.h" 32 | 33 | #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING 34 | #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 35 | #endif 36 | 37 | /******************* 38 | * Terminal colors * 39 | *******************/ 40 | 41 | #ifdef USE_COLOR 42 | 43 | # define cBLK "\x1b[0;30m" 44 | # define cRED "\x1b[0;31m" 45 | # define cGRN "\x1b[0;32m" 46 | # define cBRN "\x1b[0;33m" 47 | # define cBLU "\x1b[0;34m" 48 | # define cMGN "\x1b[0;35m" 49 | # define cCYA "\x1b[0;36m" 50 | # define cLGR "\x1b[0;37m" 51 | # define cGRA "\x1b[1;30m" 52 | # define cLRD "\x1b[1;31m" 53 | # define cLGN "\x1b[1;32m" 54 | # define cYEL "\x1b[1;33m" 55 | # define cLBL "\x1b[1;34m" 56 | # define cPIN "\x1b[1;35m" 57 | # define cLCY "\x1b[1;36m" 58 | # define cBRI "\x1b[1;37m" 59 | # define cRST "\x1b[0m" 60 | 61 | # define bgBLK "\x1b[40m" 62 | # define bgRED "\x1b[41m" 63 | # define bgGRN "\x1b[42m" 64 | # define bgBRN "\x1b[43m" 65 | # define bgBLU "\x1b[44m" 66 | # define bgMGN "\x1b[45m" 67 | # define bgCYA "\x1b[46m" 68 | # define bgLGR "\x1b[47m" 69 | # define bgGRA "\x1b[100m" 70 | # define bgLRD "\x1b[101m" 71 | # define bgLGN "\x1b[102m" 72 | # define bgYEL "\x1b[103m" 73 | # define bgLBL "\x1b[104m" 74 | # define bgPIN "\x1b[105m" 75 | # define bgLCY "\x1b[106m" 76 | # define bgBRI "\x1b[107m" 77 | 78 | #else 79 | 80 | # define cBLK "" 81 | # define cRED "" 82 | # define cGRN "" 83 | # define cBRN "" 84 | # define cBLU "" 85 | # define cMGN "" 86 | # define cCYA "" 87 | # define cLGR "" 88 | # define cGRA "" 89 | # define cLRD "" 90 | # define cLGN "" 91 | # define cYEL "" 92 | # define cLBL "" 93 | # define cPIN "" 94 | # define cLCY "" 95 | # define cBRI "" 96 | # define cRST "" 97 | 98 | # define bgBLK "" 99 | # define bgRED "" 100 | # define bgGRN "" 101 | # define bgBRN "" 102 | # define bgBLU "" 103 | # define bgMGN "" 104 | # define bgCYA "" 105 | # define bgLGR "" 106 | # define bgGRA "" 107 | # define bgLRD "" 108 | # define bgLGN "" 109 | # define bgYEL "" 110 | # define bgLBL "" 111 | # define bgPIN "" 112 | # define bgLCY "" 113 | # define bgBRI "" 114 | 115 | #endif /* ^USE_COLOR */ 116 | 117 | /************************* 118 | * Box drawing sequences * 119 | *************************/ 120 | 121 | #ifdef FANCY_BOXES 122 | 123 | # define SET_G1 "\x1b)0" /* Set G1 for box drawing */ 124 | # define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ 125 | # define bSTART "\x0e" /* Enter G1 drawing mode */ 126 | # define bSTOP "\x0f" /* Leave G1 drawing mode */ 127 | # define bH "q" /* Horizontal line */ 128 | # define bV "x" /* Vertical line */ 129 | # define bLT "l" /* Left top corner */ 130 | # define bRT "k" /* Right top corner */ 131 | # define bLB "m" /* Left bottom corner */ 132 | # define bRB "j" /* Right bottom corner */ 133 | # define bX "n" /* Cross */ 134 | # define bVR "t" /* Vertical, branch right */ 135 | # define bVL "u" /* Vertical, branch left */ 136 | # define bHT "v" /* Horizontal, branch top */ 137 | # define bHB "w" /* Horizontal, branch bottom */ 138 | 139 | #else 140 | 141 | # define SET_G1 "" 142 | # define RESET_G1 "" 143 | # define bSTART "" 144 | # define bSTOP "" 145 | # define bH "-" 146 | # define bV "|" 147 | # define bLT "+" 148 | # define bRT "+" 149 | # define bLB "+" 150 | # define bRB "+" 151 | # define bX "+" 152 | # define bVR "+" 153 | # define bVL "+" 154 | # define bHT "+" 155 | # define bHB "+" 156 | 157 | #endif /* ^FANCY_BOXES */ 158 | 159 | /*********************** 160 | * Misc terminal codes * 161 | ***********************/ 162 | 163 | #ifdef USE_COLOR 164 | 165 | #define TERM_HOME "\x1b[H" 166 | #define TERM_CLEAR TERM_HOME "\x1b[2J" 167 | #define cEOL "\x1b[0K" 168 | #define CURSOR_HIDE "\x1b[?25l" 169 | #define CURSOR_SHOW "\x1b[?25h" 170 | 171 | #else 172 | 173 | #define TERM_HOME "" 174 | #define TERM_CLEAR "" 175 | #define cEOL "" 176 | #define CURSOR_HIDE "" 177 | #define CURSOR_SHOW "" 178 | 179 | #endif /* ^USE_COLORS */ 180 | 181 | /************************ 182 | * Debug & error macros * 183 | ************************/ 184 | 185 | /* Just print stuff to the appropriate stream. */ 186 | 187 | #ifdef MESSAGES_TO_STDOUT 188 | # define SAYF(...) printf(__VA_ARGS__) 189 | #else 190 | # define SAYF(...) fprintf(stderr, __VA_ARGS__) 191 | #endif /* ^MESSAGES_TO_STDOUT */ 192 | 193 | /* Show a prefixed warning. */ 194 | 195 | #define WARNF(...) do { \ 196 | SAYF(cYEL "[!] " cBRI "WARNING: " cRST __VA_ARGS__); \ 197 | SAYF(cRST "\n"); \ 198 | } while (0) 199 | 200 | /* Show a prefixed "doing something" message. */ 201 | 202 | #define ACTF(...) do { \ 203 | SAYF(cLBL "[*] " cRST __VA_ARGS__); \ 204 | SAYF(cRST "\n"); \ 205 | } while (0) 206 | 207 | /* Show a prefixed "success" message. */ 208 | 209 | #define OKF(...) do { \ 210 | SAYF(cLGN "[+] " cRST __VA_ARGS__); \ 211 | SAYF(cRST "\n"); \ 212 | } while (0) 213 | 214 | /* Show a prefixed fatal error message (not used in afl). */ 215 | 216 | #define BADF(...) do { \ 217 | SAYF(cLRD "\n[-] " cRST __VA_ARGS__); \ 218 | SAYF(cRST "\n"); \ 219 | } while (0) 220 | 221 | /* Die with a verbose non-OS fatal error message. */ 222 | 223 | #define FATAL(...) do { \ 224 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] PROGRAM ABORT : " cBRI __VA_ARGS__); \ 225 | SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ 226 | __FUNCTION__, __FILE__, __LINE__); \ 227 | exit(1); \ 228 | } while (0) 229 | 230 | /* Die by calling abort() to provide a core dump. */ 231 | 232 | #define ABORT(...) do { \ 233 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] PROGRAM ABORT : " cBRI __VA_ARGS__); \ 234 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ 235 | __FUNCTION__, __FILE__, __LINE__); \ 236 | abort(); \ 237 | } while (0) 238 | 239 | /* Die while also including the output of perror(). */ 240 | 241 | #define PFATAL(...) do { \ 242 | fflush(stdout); \ 243 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] SYSTEM ERROR : " cBRI __VA_ARGS__); \ 244 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ 245 | __FUNCTION__, __FILE__, __LINE__); \ 246 | SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ 247 | exit(1); \ 248 | } while (0) 249 | 250 | /* Die with FAULT() or PFAULT() depending on the value of res (used to 251 | interpret different failure modes for read(), write(), etc). */ 252 | 253 | #define RPFATAL(res, ...) do { \ 254 | if (res < 0) PFATAL(__VA_ARGS__); else FATAL(__VA_ARGS__); \ 255 | } while (0) 256 | 257 | /* Error-checking versions of read() and write() that call RPFATAL() as 258 | appropriate. */ 259 | 260 | #define ck_write(fd, buf, len, fn) do { \ 261 | u32 _len = (len); \ 262 | s32 _res = _write(fd, buf, _len); \ 263 | if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ 264 | } while (0) 265 | 266 | #define ck_read(fd, buf, len, fn) do { \ 267 | u32 _len = (len); \ 268 | s32 _res = _read(fd, buf, _len); \ 269 | if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ 270 | } while (0) 271 | 272 | 273 | static void enable_ansi_console(void) { 274 | // Set output mode to handle virtual terminal sequences 275 | DWORD mode = 0; 276 | HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); 277 | if (console_handle == INVALID_HANDLE_VALUE) { 278 | return; 279 | } 280 | 281 | if (!GetConsoleMode(console_handle, &mode)) { 282 | return; 283 | } 284 | 285 | mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; 286 | // Ignore errors 287 | SetConsoleMode(console_handle, mode); 288 | } 289 | 290 | 291 | #endif /* ! _HAVE_DEBUG_H */ 292 | -------------------------------------------------------------------------------- /gdiplus.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL - GDI+ test binary (image parsing) 3 | ----------------------------------------- 4 | 5 | Written and maintained by Ivan Fratric 6 | 7 | Copyright 2016 Google Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace Gdiplus; 28 | 29 | wchar_t* charToWChar(const char* text) 30 | { 31 | size_t size = strlen(text) + 1; 32 | wchar_t* wa = new wchar_t[size]; 33 | mbstowcs(wa,text,size); 34 | return wa; 35 | } 36 | 37 | int main(int argc, char** argv) 38 | { 39 | if(argc < 2) { 40 | printf("Usage: %s \n", argv[0]); 41 | return 0; 42 | } 43 | 44 | GdiplusStartupInput gdiplusStartupInput; 45 | ULONG_PTR gdiplusToken; 46 | GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 47 | 48 | Image *image = NULL; 49 | //*thumbnail=NULL; 50 | 51 | image = new Image(charToWChar(argv[1])); 52 | if(image && (Ok == image->GetLastStatus())) { 53 | //printf("Image loaded\n"); 54 | /*thumbnail = image->GetThumbnailImage(100, 100, NULL, NULL); 55 | if(thumbnail && (Ok == thumbnail->GetLastStatus())) { 56 | //printf("Thumbnail created\n"); 57 | }*/ 58 | } 59 | 60 | //printf("Done\n"); 61 | 62 | if(image) delete image; 63 | //if(thumbnail) delete thumbnail; 64 | 65 | GdiplusShutdown(gdiplusToken); 66 | 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - hashing function 3 | ------------------------------------- 4 | 5 | Original AFL code written by Michal Zalewski 6 | 7 | Windows fork written and maintained by Ivan Fratric 8 | 9 | Copyright 2016 Google Inc. 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 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, 19 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | See the License for the specific language governing permissions and 21 | limitations under the License. 22 | 23 | */ 24 | 25 | /* 26 | The hash32() function is a variant of MurmurHash3, a good 27 | non-cryptosafe hashing function developed by Austin Appleby. 28 | 29 | For simplicity, this variant does *NOT* accept buffer lengths 30 | that are not divisible by 8 bytes. The 32-bit version is otherwise 31 | similar to the original; the 64-bit one is a custom hack with 32 | mostly-unproven properties. 33 | 34 | Austin's original code is public domain. 35 | 36 | */ 37 | 38 | #ifndef _HAVE_HASH_H 39 | #define _HAVE_HASH_H 40 | 41 | #include "types.h" 42 | 43 | #ifdef _WIN64 44 | 45 | #define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) 46 | 47 | static inline u32 hash32(const void* key, u32 len, u32 seed) { 48 | 49 | const u64* data = (u64*)key; 50 | u64 h1 = seed ^ len; 51 | 52 | len >>= 3; 53 | 54 | while (len--) { 55 | 56 | u64 k1 = *data++; 57 | 58 | k1 *= 0x87c37b91114253d5ULL; 59 | k1 = ROL64(k1, 31); 60 | k1 *= 0x4cf5ad432745937fULL; 61 | 62 | h1 ^= k1; 63 | h1 = ROL64(h1, 27); 64 | h1 = h1 * 5 + 0x52dce729; 65 | 66 | } 67 | 68 | h1 ^= h1 >> 33; 69 | h1 *= 0xff51afd7ed558ccdULL; 70 | h1 ^= h1 >> 33; 71 | h1 *= 0xc4ceb9fe1a85ec53ULL; 72 | h1 ^= h1 >> 33; 73 | 74 | return h1; 75 | 76 | } 77 | 78 | #else 79 | 80 | #define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) 81 | 82 | static inline u32 hash32(const void* key, u32 len, u32 seed) { 83 | 84 | const u32* data = (u32*)key; 85 | u32 h1 = seed ^ len; 86 | 87 | len >>= 2; 88 | 89 | while (len--) { 90 | 91 | u32 k1 = *data++; 92 | 93 | k1 *= 0xcc9e2d51; 94 | k1 = ROL32(k1, 15); 95 | k1 *= 0x1b873593; 96 | 97 | h1 ^= k1; 98 | h1 = ROL32(h1, 13); 99 | h1 = h1 * 5 + 0xe6546b64; 100 | 101 | } 102 | 103 | h1 ^= h1 >> 16; 104 | h1 *= 0x85ebca6b; 105 | h1 ^= h1 >> 13; 106 | h1 *= 0xc2b2ae35; 107 | h1 ^= h1 >> 16; 108 | 109 | return h1; 110 | 111 | } 112 | 113 | #endif /* ^_WIN64 */ 114 | 115 | #endif /* !_HAVE_HASH_H */ 116 | -------------------------------------------------------------------------------- /ipttool.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/ipttool.c -------------------------------------------------------------------------------- /ipttool.h: -------------------------------------------------------------------------------- 1 | BOOL EnableAndValidateIptServices(VOID); 2 | BOOL ConfigureBufferSize(_In_ DWORD dwSize, _Inout_ PIPT_OPTIONS pOptions); 3 | BOOL ConfigureTraceFlags(_In_ DWORD dwFlags, _Inout_ PIPT_OPTIONS pOptions); 4 | PIPT_TRACE_DATA GetIptTrace(HANDLE hProcess); 5 | -------------------------------------------------------------------------------- /modules.h: -------------------------------------------------------------------------------- 1 | /* *************************************************************************** 2 | * Copyright (c) 2012-2013 Google, Inc. All rights reserved. 3 | * ***************************************************************************/ 4 | 5 | /* 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of Google, Inc. nor the names of its contributors may be 17 | * used to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | * DAMAGE. 31 | */ 32 | 33 | /* 34 | Utilities for keeping track of (un)loaded modules in DynamoRIO clients. 35 | Copied from the DyanmoRIO project, http://dynamorio.org/ 36 | */ 37 | 38 | #ifndef CLIENTS_COMMON_MODULES_H_ 39 | #define CLIENTS_COMMON_MODULES_H_ 40 | 41 | #include "dr_api.h" 42 | #include "drvector.h" 43 | 44 | #define NUM_GLOBAL_MODULE_CACHE 8 45 | 46 | typedef struct _module_entry_t { 47 | int id; 48 | bool unload; /* if the module is unloaded */ 49 | module_data_t *data; 50 | } module_entry_t; 51 | 52 | typedef struct _module_table_t { 53 | drvector_t vector; 54 | /* for quick query without lock, assuming pointer-aligned */ 55 | module_entry_t *cache[NUM_GLOBAL_MODULE_CACHE]; 56 | } module_table_t; 57 | 58 | void 59 | module_table_load(module_table_t *table, const module_data_t *data); 60 | 61 | /* To avoid data race, proper sychronization on module table is required for 62 | * accessing module table entry. 63 | */ 64 | module_entry_t * 65 | module_table_lookup(module_entry_t **cache, int cache_size, 66 | module_table_t *table, app_pc pc); 67 | 68 | /* To avoid data race, proper sychronization on module table is required for 69 | * accessing module table entry. 70 | */ 71 | void 72 | module_table_entry_print(module_entry_t *entry, file_t log, bool print_all_info); 73 | 74 | void 75 | module_table_unload(module_table_t *table, const module_data_t *data); 76 | 77 | void 78 | module_table_print(module_table_t *table, file_t log, bool print_all_info); 79 | 80 | module_table_t * 81 | module_table_create(); 82 | 83 | void 84 | module_table_destroy(module_table_t *table); 85 | 86 | #endif /* CLIENTS_COMMON_MODULES_H_ */ 87 | -------------------------------------------------------------------------------- /ptdecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL - Intel PT decoding 3 | ------------------------------------------------ 4 | 5 | Written and maintained by Ivan Fratric 6 | 7 | Copyright 2016 Google Inc. All Rights Reserved. 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | typedef struct _address_range { 22 | uint64_t start; 23 | uint64_t end; 24 | char collect; // collect coverage for range or not 25 | } address_range; 26 | 27 | int check_trace_start(unsigned char *data, size_t size, uint64_t expected_ip); 28 | 29 | void tracelet_cache_init(size_t max_entries, size_t max_size); 30 | 31 | void analyze_trace_full_reference(unsigned char *trace_data, size_t trace_size, int coverage_kind, struct pt_image *image, bool skip_first_bb); 32 | void analyze_trace_full_fast(unsigned char *trace_data, size_t trace_size, int coverage_kind, struct pt_image *image, bool skip_first_bb); 33 | void decode_trace_tip_fast(unsigned char *data, size_t size, int coverage_kind); 34 | void decode_trace_tip_reference(unsigned char *trace_data, size_t trace_size, int coverage_kind); -------------------------------------------------------------------------------- /readme_syzygy.md: -------------------------------------------------------------------------------- 1 | # Statically instrument a binary via [syzygy](https://github.com/google/syzygy) 2 | 3 | ## Background 4 | 5 | [syzygy](https://github.com/google/syzygy) provides a framework able to _decompose_ 6 | PE32 binaries with full PDB. _Decomposing_ a binary is the term used to mean taking 7 | in input a PE32 binary and its PDB, analyze and decompose every functions, every blocks 8 | of code / data in a safe way and present it to transformation "passes". 9 | A transformation pass is a class that transforms the binary in some way; an example is the [syzyasan](https://github.com/google/syzygy/blob/master/syzygy/instrument/transforms/asan_transform.h) 10 | transformation for example. Once the pass has transformed the binary, it passes it back 11 | to the framework which is able to _relink_ an output binary (with the transformations applied 12 | of course). 13 | 14 | [AFL instrumentation](https://github.com/google/syzygy/blob/master/syzygy/instrument/transforms/afl_transform.cc) has been added to [syzygy](https://github.com/google/syzygy)'s instrumenter allowing users to instrument PE32 15 | binaries with private symbols statically. 16 | 17 | 18 | 19 | 20 | 21 | ## How to write a target function 22 | 23 | In order to prepare your target, you need to first include `afl-staticinstr.h` then invoke `__afl_persistent_loop` like in `test_static.cpp`: 24 | 25 | ``` 26 | int fuzz(int argc, char**argv) { 27 | while(__afl_persistent_loop()) { 28 | test(argc, argv); 29 | } 30 | return 1; 31 | } 32 | ``` 33 | 34 | `__afl_persistent_loop`'s implementation lives inside `afl-staticinstr.c` and basically reproduces what the DynamoRIO plugin is doing in `pre_fuzz_handler` and `post_fuzz_handler`. Every points mentioned in "How to select a target function" applies here too. 35 | 36 | You can invoke AFL tools with the flag `-Y` to enable the static instrumentation mode during fuzzing, corpus minimizing or during test-case minimizing: 37 | 38 | ``` 39 | afl-fuzz.exe -Y -i minset -o o1 -t 10000 -- -fuzz_iterations 5000 -- test_static.instr.exe @@ 40 | winafl-cmin.py -Y -t 100000 -i in -o minset -- test_static.instr.exe @@ 41 | afl-tmin.exe -Y -i ..\testcases\tests\big.txt -o big.min.txt -- test_static.instr.exe @@ 42 | ``` 43 | 44 | ## Building instrument.exe 45 | 46 | For convenience, a version of instrument.exe confirmed to work with WinAFL is included in the bin32 directory. If you want to build it yourself follow the instructions below. 47 | 48 | In order to clone [syzygy](https://github.com/google/syzygy/)'s repository you can follow the instructions outlined here: [SyzygyDevelopmentGuide](https://github.com/google/syzygy/wiki/SyzygyDevelopmentGuide). Once you have `depot_tools` and the repository cloned, you can compile instrument.exe like this: 49 | 50 | ``` 51 | C:\syzygy\src>ninja -C out\Release instrument 52 | ``` 53 | 54 | The current recommended revision of the instrumenter is the following: [190dbfe](https://github.com/google/syzygy/commit/190dbfe74c6f5b5913820fa66d9176877924d7c5)(v0.8.32.0). 55 | 56 | ## Registering msdia140 57 | 58 | Make sure to register `msdia140.dll` on your system by executing once the below command: 59 | 60 | ``` 61 | regsvr32 /s msdia140.dll 62 | ``` 63 | 64 | ## Instrumenting a target 65 | 66 | Your target binary must have been compiled with the [/PROFILE](https://msdn.microsoft.com/en-us/library/ays5x7b0.aspx) linker flag in order to generate a full PDB. 67 | 68 | ``` 69 | C:\>instrument.exe --mode=afl --input-image=test_static.exe --output-image=test_static.instr.exe --force-decompose --multithread --cookie-check-hook 70 | [0718/224840:INFO:application_impl.h(46)] Syzygy Instrumenter Version 0.8.32.0 (0000000). 71 | [0718/224840:INFO:application_impl.h(48)] Copyright (c) Google Inc. All rights reserved. 72 | [0718/224840:INFO:afl_instrumenter.cc(116)] Force decomposition mode enabled. 73 | [0718/224840:INFO:afl_instrumenter.cc(122)] Thread-safe instrumentation mode enabled. 74 | [0718/224840:INFO:afl_instrumenter.cc(128)] Cookie check hook mode enabled. 75 | [...] 76 | [0718/224840:INFO:security_cookie_check_hook_transform.cc(67)] Found a __report_gsfailure implementation, hooking it now. 77 | [0718/224840:INFO:add_implicit_tls_transform.cc(77)] The binary doesn't have any implicit TLS slot defined, injecting one. 78 | [0718/224840:INFO:afl_transform.cc(144)] Placing TLS slot at offset +4. 79 | [0718/224840:INFO:afl_transform.cc(237)] Code Blocks instrumented: 92 (95%) 80 | [...] 81 | [0718/224841:INFO:pe_relinker.cc(240)] PE relinker finished. 82 | 83 | C:\>test_static.instr.exe test 84 | Persistent loop implementation by <0vercl0k@tuxfamily.org> 85 | Based on WinAFL by 86 | [+] Found a statically instrumented module: test_static.instr.exe (multi thread mode). 87 | [-] Not running under afl-fuzz.exe. 88 | [+] Enabling the no fuzzing mode. 89 | Error opening file 90 | ``` 91 | 92 | ### Available options 93 | 94 | ``` 95 | --config= Specifies a JSON file describing, either 96 | a whitelist of functions to instrument or 97 | a blacklist of functions to not instrument. 98 | --cookie-check-hook Hooks __security_cookie_check. 99 | --force-decompose Forces block decomposition. 100 | --multithread Uses a thread-safe instrumentation. 101 | ``` 102 | 103 | * config: The JSON file allows you to scope down the instrumentation to a set of function 104 | names. You can either [white list](https://github.com/google/syzygy/blob/master/syzygy/instrument/test_data/afl-good-whitelist.json), or [black list](https://github.com/google/syzygy/blob/master/syzygy/instrument/test_data/afl-good-blacklist.json) functions. It can be very useful to blacklist 105 | functions generating variable behaviors. 106 | 107 | * cookie-check-hook: This ensures that the /GS cookie check function generates an exception that 108 | our [VEH](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681420(v=vs.85).aspx) can catch. Failfast exceptions are not catchable by any EH mechanisms in-proc, so we leverage 109 | [syzygy](https://github.com/google/syzygy) to rewrite the cookie check function in order to generate 110 | [an exception we can catch](https://github.com/google/syzygy/blob/master/syzygy/instrument/transforms/security_cookie_check_hook_transform.cc#L81). 111 | 112 | * force-decompose: This switch lets you override the decision that [syzygy](https://github.com/google/syzygy/blob/master/syzygy/pe/pe_transform_policy.cc#L175) makes when evaluating 113 | if a function is safe to decompose. If you turn on this flag, your instrumentation coverage will be 114 | higher but you might end-up in an executable that *crashes* in weird ways. Only use if you know what you 115 | are doing. 116 | 117 | * multithread: This switch turns on the thread-safe instrumentation. The major difference with the single 118 | thread instrumentation is that `__afl_prev_loc` will be stored in a TLS slot. 119 | 120 | ## Limitations 121 | 122 | With great power comes great responsibility, so here is the list of limitations: 123 | 124 | 1. Instrumentation is limited to PE 32bits binaries with full PDB symbols (linker flag `/PROFILE`). 125 | 126 | 2. [syzygy](https://github.com/google/syzygy/) defines [several pre-requirements](https://github.com/google/syzygy/blob/master/syzygy/pe/pe_transform_policy.cc#L175) for being able to decompose safely a block; this might explain why your instrumentation percentage is low. 127 | 128 | -------------------------------------------------------------------------------- /readme_tinyinst.md: -------------------------------------------------------------------------------- 1 | # TinyInst instrumentation 2 | 3 | TinyInst is a lightweight dynamic instrumentation library that can be used to instrument only selected module(s) in the process, while leaving the rest of the process to run natively. WinAFL includes a custom TinyInst client that can collect both basic block and edge coverage into an AFL coverage map. 4 | 5 | ## Building and using 6 | 7 | To build WinAFL with TinyInst support, `-DTINYINST=1` must be added to the build options. For the full building instructions, see the main readme. 8 | 9 | Similar to other modes, the usage is 10 | 11 | ``` 12 | afl-fuzz -y [afl options] -- [instrumentation options] -- target_cmd_line 13 | ``` 14 | 15 | where the `-y` flag is used to select TinyInst mode. 16 | 17 | The full list of instrumentation options can be found in the [TinyInst readme](https://github.com/googleprojectzero/TinyInst). Note that, while these options are mostly similar to instrumentation options in DynamoRIO mode: 18 | - Some flags have differen names, e.g. `-instrument_module` (TinyInst) vs. `-coverage_module` (DynamoRIO). 19 | - Some additional flags are needed to take advantage of persistence mode, specifically `-persist` and `-loop` flags. 20 | 21 | Instead of listing all of the options from TinyInst readme, let's examine a basic usage example 22 | 23 | ``` 24 | afl-fuzz.exe -y -i in -o out -t 20000 -- -instrument_module gdiplus.dll -instrument_module WindowsCodecs.dll -target_module test_gdiplus.exe -target_method main -nargs 2 -iterations 5000 -persist -loop -- C:\work\winafl\build64\bin\RelWithDebInfo\test_gdiplus.exe @@ 25 | ``` 26 | 27 | which fuzzes the `test_gdiplus` harness included with WinAFL. As stated previously, `-y` is used to select the TinyInst mode. `-i in -o out -t 20000` are standard afl flags used to set input and output directories as well as the timeout, respectively. 28 | 29 | `-instrument_module` specifies which module to instrument. This is similar to `-coverage_module` flag in DynamoRIO mode. There can be multiple `-instrument_module` flags for different modules. In our example, we'll be instrumenting (collecting coverage from) two modules, `gdiplus.dll` and `WindowsCodecs.dll` 30 | 31 | `-target_module` and `-target_method` specify which function to run in WinAFL's persistent mode. `-target_module` identifies the module where the function is located (`test_gdiplus.exe` in the example), while `-target_method` specifies the name of the function (main in this case). In case where the symbols (function names) aren't available for the target module, `-target_offset` can be used instead, which specifies the offset in memory from start of the module to the target function (for example `-target_offset 0x16a0`). 32 | 33 | `nargs` specifies how many arguments the target function takes in order to be able to restore the arguments for every run. 34 | 35 | `-persist` instructs TinyInst to use the persistent mode and keep the target process alive when the target function returns. 36 | 37 | `-loop` instructs TinyInst to jump to the start of target function after it returns. `-persist` and `-loop` together enable the "classic" WinAFL persistent mode. However there might be cases where one of these flags is desirable without the other, for example in case where the target process calls the target function repeatedly on its own, `-persist` flag can be used without `-loop` 38 | 39 | `-iterations` specifies how many times to run the target function in persistent mode without restarting the target process. 40 | 41 | To debug issues, it might be useful to run the target under TinyInst but without the fuzzer. This can be done using `litecov.exe` tool that comes with TinyInst. For example, running `litecov.exe` with the same instrumentation optios as above (except the number of iteration reduced) 42 | 43 | ``` 44 | litecov.exe -instrument_module gdiplus.dll -instrument_module WindowsCodecs.dll -target_module test_gdiplus.exe -target_method main -nargs 2 -iterations 10 -persist -loop -- C:\work\winafl\build64\bin\RelWithDebInfo\test_gdiplus.exe in\in.txt 45 | ``` 46 | 47 | might produce the following output 48 | 49 | ``` 50 | Instrumented module gdiplus.dll, code size: 1409024 51 | Target function returned normally 52 | Found 1094 new offsets in gdiplus.dll 53 | Target function returned normally 54 | Found 1 new offsets in gdiplus.dll 55 | Target function returned normally 56 | Target function returned normally 57 | Target function returned normally 58 | Target function returned normally 59 | Target function returned normally 60 | Target function returned normally 61 | Target function returned normally 62 | Target function returned normally 63 | ``` 64 | 65 | This lets us know that 66 | - There was code executing in the gdiplus.dll module and TinyInst collected some coverage from it. 67 | - The target function ran 10 times (as expected) and returned normally every time (i.e. no crashes or hangs) 68 | 69 | So it gives us a good indication that the instrumentation options are set correctly and the target is running correctly under TinyInst. 70 | 71 | There are additional flags that can be useful for debugging such as `-trace_debug_events` which, among other things, lists modules loaded by the target process. Note that `-trace_debug_events` might report exceptions in the target process, but these don't necessarily mean crashes or errors (as long as you don't see a message about the process crashing) as TinyInst uses exceptions under the hood. 72 | 73 | -------------------------------------------------------------------------------- /screenshots/afl-fuzz.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/screenshots/afl-fuzz.gif -------------------------------------------------------------------------------- /screenshots/afl-instr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/screenshots/afl-instr.png -------------------------------------------------------------------------------- /screenshots/winafl-cmin.py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleprojectzero/winafl/31c0b17aed592f429c2ded00fbe315dcee8bc52c/screenshots/winafl-cmin.py.png -------------------------------------------------------------------------------- /test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL - A simple test binary that crashes on certain inputs: 3 | - 'test1' with a normal write access violation at NULL 4 | - 'test2' with a /GS stack cookie violation 5 | ------------------------------------------------------------- 6 | 7 | Written and maintained by Ivan Fratric 8 | 9 | Copyright 2016 Google Inc. 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 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, 19 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | See the License for the specific language governing permissions and 21 | limitations under the License. 22 | 23 | */ 24 | 25 | #define _CRT_SECURE_NO_WARNINGS 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | int __declspec(noinline) test_target(char* input_file_path, char* argv_0) 32 | { 33 | char *crash = NULL; 34 | FILE *fp = fopen(input_file_path, "rb"); 35 | char c; 36 | if (!fp) { 37 | printf("Error opening file\n"); 38 | return 0; 39 | } 40 | if (fread(&c, 1, 1, fp) != 1) { 41 | printf("Error reading file\n"); 42 | fclose(fp); 43 | return 0; 44 | } 45 | if (c != 't') { 46 | printf("Error 1\n"); 47 | fclose(fp); 48 | return 0; 49 | } 50 | if (fread(&c, 1, 1, fp) != 1) { 51 | printf("Error reading file\n"); 52 | fclose(fp); 53 | return 0; 54 | } 55 | if (c != 'e') { 56 | printf("Error 2\n"); 57 | fclose(fp); 58 | return 0; 59 | } 60 | if (fread(&c, 1, 1, fp) != 1) { 61 | printf("Error reading file\n"); 62 | fclose(fp); 63 | return 0; 64 | } 65 | if (c != 's') { 66 | printf("Error 3\n"); 67 | fclose(fp); 68 | return 0; 69 | } 70 | if (fread(&c, 1, 1, fp) != 1) { 71 | printf("Error reading file\n"); 72 | fclose(fp); 73 | return 0; 74 | } 75 | if (c != 't') { 76 | printf("Error 4\n"); 77 | fclose(fp); 78 | return 0; 79 | } 80 | printf("!!!!!!!!!!OK!!!!!!!!!!\n"); 81 | 82 | if (fread(&c, 1, 1, fp) != 1) { 83 | printf("Error reading file\n"); 84 | fclose(fp); 85 | return 0; 86 | } 87 | if (c == '1') { 88 | // cause a crash 89 | crash[0] = 1; 90 | } 91 | else if (c == '2') { 92 | char buffer[5] = { 0 }; 93 | // stack-based overflow to trigger the GS cookie corruption 94 | for (int i = 0; i < 5; ++i) 95 | strcat(buffer, argv_0); 96 | printf("buffer: %s\n", buffer); 97 | } 98 | else { 99 | printf("Error 5\n"); 100 | } 101 | fclose(fp); 102 | return 0; 103 | } 104 | 105 | int main(int argc, char** argv) 106 | { 107 | if(argc < 2) { 108 | printf("Usage: %s \n", argv[0]); 109 | return 0; 110 | } 111 | 112 | if (argc == 3 && !strcmp(argv[2], "loop")) 113 | { 114 | //loop inside application and call target infinitey 115 | while (true) 116 | { 117 | test_target(argv[1], argv[0]); 118 | } 119 | } 120 | else 121 | { 122 | //regular single target call 123 | return test_target(argv[1], argv[0]); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /test_netmode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL - A simple binary to test winAFL ability perform fuzzing over network: 3 | ------------------------------------------------------------- 4 | 5 | Written and maintained by Maksim Shudrak 6 | 7 | Copyright 2018 Salesforce Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | /* cmd line to find the crash: 24 | * set AFL_CUSTOM_DLL_ARGS=-U -p 7714 -a 127.0.0.1 -w 1000 25 | * C:\Users\max\Desktop\winafl\winafl_fork\build\Debug>afl-fuzz.exe -l custom_net_fuzzer.dll 26 | * -i in -o out -D ..\..\dr_release\bin32 -t 20000 -- -target_module test_netmode.exe -target_method 27 | * recv_func -coverage_module test_netmode.exe -fuzz_iterations 5000 -nargs 1 -- test_netmode.exe 28 | */ 29 | 30 | #define _CRT_SECURE_NO_WARNINGS 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #pragma comment(lib,"ws2_32.lib") //Winsock Library 37 | 38 | #define DEFAULT_PORT 7714 39 | #define BUFSIZE 4096 40 | 41 | /* TODO: test for TCP */ 42 | 43 | void error(const char *msg) { 44 | printf("[ERROR] %s %d\n", msg, WSAGetLastError()); 45 | exit(-1); 46 | } 47 | 48 | struct sockaddr_in serveraddr; /* server's addr */ 49 | 50 | void recv_func(int sockfd) 51 | { 52 | char *buf; 53 | struct sockaddr_in clientaddr; /* client addr */ 54 | int clientlen = sizeof(clientaddr); 55 | int n = 0; 56 | 57 | buf = (char *)malloc(BUFSIZE); 58 | 59 | /* receiving over UDP */ 60 | n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&clientaddr, &clientlen); 61 | if (n < 0) 62 | error("ERROR in recvfrom"); 63 | 64 | if (buf[0] == 'P') { 65 | if (buf[1] == 'W') { 66 | if (buf[2] == 'N') { 67 | if (buf[3] == 'I') { 68 | if (buf[4] == 'T') { 69 | printf("Found it!\n"); 70 | ((VOID(*)())0x0)(); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | printf("Received %d bytes, content = %s\n", n, buf); 78 | free(buf); 79 | } 80 | 81 | int main(int argc, char** argv) 82 | { 83 | int sockfd; 84 | int portno = DEFAULT_PORT; 85 | int optval; 86 | static WSADATA wsaData; 87 | static int iResult; 88 | 89 | // Initialize Winsock 90 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 91 | 92 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 93 | if (sockfd < 0) 94 | error("ERROR opening socket"); 95 | 96 | optval = 1; 97 | /* UDP */ 98 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(int)); 99 | 100 | memset((char *)&serveraddr, 0, sizeof(serveraddr)); 101 | serveraddr.sin_family = AF_INET; 102 | serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 103 | serveraddr.sin_port = htons((unsigned short)portno); 104 | 105 | if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) 106 | error("ERROR on binding"); 107 | while (1) { 108 | recv_func(sockfd); 109 | } 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /test_simple_winsock_client.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | A client to test winAFL ability act as a TCP/IP fuzzing server: 3 | ------------------------------------------------------------- 4 | 5 | Written and maintained by Maksim Shudrak 6 | 7 | Copyright 2018 Salesforce Inc. All Rights Reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | /* cmd line to launch the fuzzer: 24 | * set AFL_CUSTOM_DLL_ARGS=1337 25 | * afl-fuzz.exe -l custom_winafl_server.dll -i in -o out -D ..\..\dr_release\bin32 26 | * -t 20000 -- -target_module test_servermode.exe -target_method main -coverage_module 27 | * test_servermode.exe -fuzz_iterations 5000 -nargs 2 -- test_servermode.exe 127.0.0.1 28 | */ 29 | 30 | /* TODO: improve performance of this client under fuzzer */ 31 | 32 | #pragma once 33 | 34 | #define WIN32_LEAN_AND_MEAN 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib 44 | #pragma comment (lib, "Ws2_32.lib") 45 | #pragma comment (lib, "Mswsock.lib") 46 | #pragma comment (lib, "AdvApi32.lib") 47 | 48 | #define DEFAULT_BUFLEN 512 49 | #define DEFAULT_PORT "1337" 50 | 51 | void parse_buffer(char *buf) { 52 | if (buf[0] == 'P') { 53 | if (buf[1] == 'W') { 54 | if (buf[2] == 'N') { 55 | if (buf[3] == 'I') { 56 | if (buf[4] == 'T') { 57 | printf("Found it!\n"); 58 | ((VOID(*)())0x0)(); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | void recv_loop(SOCKET ConnectSocket) { 67 | char recvbuf[DEFAULT_BUFLEN]; 68 | int iResult; 69 | int recvbuflen = DEFAULT_BUFLEN; 70 | // Receive until the peer closes the connection 71 | do { 72 | 73 | iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); 74 | if (iResult > 0) 75 | printf("Bytes received: %d\n", iResult); 76 | else if (iResult == 0) 77 | printf("Connection closed\n"); 78 | else 79 | printf("recv failed with error: %d\n", WSAGetLastError()); 80 | 81 | } while (iResult > 0); 82 | parse_buffer(recvbuf); 83 | 84 | } 85 | 86 | typedef struct _test_case_struct { 87 | long size; 88 | char *data; 89 | } test_case_struct; 90 | 91 | int __cdecl main(int argc, char **argv) 92 | { 93 | WSADATA wsaData; 94 | SOCKET ConnectSocket = INVALID_SOCKET; 95 | struct addrinfo *result = NULL, 96 | *ptr = NULL, 97 | hints; 98 | char *sendbuf = "this is a test"; 99 | int iResult; 100 | 101 | // Validate the parameters 102 | if (argc != 2) { 103 | printf("usage: %s server-name\n", argv[0]); 104 | return 1; 105 | } 106 | 107 | // Initialize Winsock 108 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 109 | if (iResult != 0) { 110 | printf("WSAStartup failed with error: %d\n", iResult); 111 | return 1; 112 | } 113 | ZeroMemory(&hints, sizeof(hints)); 114 | hints.ai_family = AF_UNSPEC; 115 | hints.ai_socktype = SOCK_STREAM; 116 | hints.ai_protocol = IPPROTO_TCP; 117 | 118 | // Resolve the server address and port 119 | iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result); 120 | if (iResult != 0) { 121 | printf("getaddrinfo failed with error: %d\n", iResult); 122 | WSACleanup(); 123 | return 1; 124 | } 125 | // Attempt to connect to an address until one succeeds 126 | for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { 127 | 128 | // Create a SOCKET for connecting to server 129 | ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 130 | ptr->ai_protocol); 131 | if (ConnectSocket == INVALID_SOCKET) { 132 | printf("socket failed with error: %ld\n", WSAGetLastError()); 133 | WSACleanup(); 134 | return 1; 135 | } 136 | 137 | // Connect to server. 138 | iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 139 | if (iResult == SOCKET_ERROR) { 140 | closesocket(ConnectSocket); 141 | ConnectSocket = INVALID_SOCKET; 142 | continue; 143 | } 144 | break; 145 | } 146 | 147 | freeaddrinfo(result); 148 | 149 | if (ConnectSocket == INVALID_SOCKET) { 150 | printf("Unable to connect to server!\n"); 151 | WSACleanup(); 152 | return 1; 153 | } 154 | 155 | // Send an initial buffer 156 | iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); 157 | if (iResult == SOCKET_ERROR) { 158 | printf("send failed with error: %d\n", WSAGetLastError()); 159 | closesocket(ConnectSocket); 160 | WSACleanup(); 161 | return 1; 162 | } 163 | 164 | printf("Bytes Sent: %ld\n", iResult); 165 | 166 | // shutdown the connection since no more data will be sent 167 | iResult = shutdown(ConnectSocket, SD_SEND); 168 | if (iResult == SOCKET_ERROR) { 169 | printf("shutdown failed with error: %d\n", WSAGetLastError()); 170 | closesocket(ConnectSocket); 171 | WSACleanup(); 172 | return 1; 173 | } 174 | 175 | recv_loop(ConnectSocket); 176 | 177 | // cleanup 178 | closesocket(ConnectSocket); 179 | WSACleanup(); 180 | 181 | return 0; 182 | } 183 | 184 | -------------------------------------------------------------------------------- /test_static.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinAFL - A simple test binary that exercises various behaviors 3 | depending on inputs: 4 | - 'test1' crashes with a normal write access violation at NULL 5 | - 'test2' crashes with a /GS stack cookie violation 6 | - 'test3' triggers a hang 7 | - 'test4' triggers an exception that is caught and handled 8 | - 'test5' triggers an OutputDebugString 9 | - 'test6' triggers an allocation of 120MB (and a crash if the 10 | allocation fails) 11 | ------------------------------------------------------------- 12 | 13 | Written by Axel "0vercl0k" Souchet <0vercl0k@tuxfamily.org> 14 | 15 | Copyright 2017 Google Inc. 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 | Unless required by applicable law or agreed to in writing, software 24 | distributed under the License is distributed on an "AS IS" BASIS, 25 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | See the License for the specific language governing permissions and 27 | limitations under the License. 28 | */ 29 | 30 | #define _CRT_SECURE_NO_WARNINGS 31 | #include 32 | #include 33 | #include 34 | #include "afl-staticinstr.h" 35 | 36 | int test(int argc, char **argv) { 37 | char *crash = NULL; 38 | FILE *fp = fopen(argv[1], "rb"); 39 | char c; 40 | if (!fp) { 41 | printf("Error opening file\n"); 42 | goto end; 43 | } 44 | if (fread(&c, 1, 1, fp) != 1) { 45 | printf("Error reading file\n"); 46 | goto clean; 47 | } 48 | if (c != 't') { 49 | printf("Error 1\n"); 50 | goto clean; 51 | } 52 | if (fread(&c, 1, 1, fp) != 1) { 53 | printf("Error reading file\n"); 54 | goto clean; 55 | } 56 | if (c != 'e') { 57 | printf("Error 2\n"); 58 | goto clean; 59 | } 60 | if (fread(&c, 1, 1, fp) != 1) { 61 | printf("Error reading file\n"); 62 | goto clean; 63 | } 64 | if (c != 's') { 65 | printf("Error 3\n"); 66 | goto clean; 67 | } 68 | if (fread(&c, 1, 1, fp) != 1) { 69 | printf("Error reading file\n"); 70 | goto clean; 71 | } 72 | if (c != 't') { 73 | printf("Error 4\n"); 74 | goto clean; 75 | } 76 | printf("!!!!!!!!!!OK!!!!!!!!!!\n"); 77 | 78 | if (fread(&c, 1, 1, fp) != 1) { 79 | printf("Error reading file\n"); 80 | goto clean; 81 | } 82 | if (c == '1') { 83 | crash[0] = 1; 84 | } 85 | else if (c == '2') { 86 | char buffer[5] = { 0 }; 87 | strcat(buffer, argv[0]); 88 | } 89 | else if (c == '3') { 90 | printf("triggering a hang\n"); 91 | Sleep(50 * 1000); 92 | } 93 | else if (c == '4') { 94 | try { 95 | throw int(1337); 96 | } 97 | catch (...) { 98 | printf("Caught its ok!\n"); 99 | } 100 | } 101 | else if (c == '5') { 102 | OutputDebugString(TEXT("hello!")); 103 | } 104 | else if (c == '6') { 105 | printf("allocating 120MB\n"); 106 | char *buffer = (char*)malloc((1024 * 1024) * 120); 107 | *buffer = 0; 108 | free(buffer); 109 | } 110 | else { 111 | printf("Error 5\n"); 112 | } 113 | 114 | clean: 115 | fclose(fp); 116 | 117 | end: 118 | return EXIT_SUCCESS; 119 | } 120 | 121 | #pragma optimize("", off) 122 | int fuzz(int argc, char**argv) { 123 | while(__afl_persistent_loop()) { 124 | test(argc, argv); 125 | } 126 | return 1; 127 | } 128 | #pragma optimize("", on) 129 | 130 | int main(int argc, char** argv) 131 | { 132 | if(argc < 2) { 133 | printf("Usage: %s \n", argv[0]); 134 | return 0; 135 | } 136 | 137 | return fuzz(argc, argv); 138 | } 139 | -------------------------------------------------------------------------------- /testcases/README.testcases: -------------------------------------------------------------------------------- 1 | =============================== 2 | AFL test cases and dictionaries 3 | =============================== 4 | 5 | (See ../docs/README for the general instruction manual.) 6 | 7 | 1) Starting test cases 8 | ---------------------- 9 | 10 | The archives/, images/, multimedia/, and others/ subdirectories contain small, 11 | standalone files that can be used to seed afl-fuzz when testing parsers for a 12 | variety of common data formats. 13 | 14 | There is probably not much to be said about these files, except that they were 15 | optimized for size and stripped of any non-essential fluff. Some directories 16 | contain several examples that exercise various features of the underlying format. 17 | For example, there is a PNG file with and without a color profile. 18 | 19 | Additional test cases are always welcome; the current "most wanted" list 20 | includes: 21 | 22 | - JBIG, 23 | - Ogg Vorbis, 24 | - Ogg Theora, 25 | - MP3, 26 | - AAC, 27 | - WebM, 28 | - Small JPEG with a color profile, 29 | - Small fonts. 30 | 31 | 2) Dictionaries 32 | --------------- 33 | 34 | The _extras/ subdirectory contains a set of dictionaries that can be used in 35 | conjunction with the -x option to allow the fuzzer to effortlessly explore the 36 | grammar of some of the more verbose data formats or languages. The basic 37 | principle behind the operation of fuzzer dictionaries is outlined in section 9 38 | of the "main" README for the project. 39 | 40 | Custom dictionaries can be added at will. They should consist of a 41 | reasonably-sized set of rudimentary syntax units that the fuzzer will then try 42 | to clobber together in various ways. Snippets between 2 and 16 bytes are usually 43 | the sweet spot. 44 | 45 | Custom dictionaries can be created in two ways: 46 | 47 | - By creating a new directory and placing each token in a separate file, in 48 | which case, there is no need to escape or otherwise format the data. 49 | 50 | - By creating a flat text file where tokens are listed one per line in the 51 | format of name="value". The alphanumeric name is ignored and can be omitted, 52 | although it is a convenient way to document the meaning of a particular 53 | token. The value must appear in quotes, with hex escaping (\xNN) applied to 54 | all non-printable, high-bit, or otherwise problematic characters (\\ and \" 55 | shorthands are recognized, too). 56 | 57 | The fuzzer auto-selects the appropriate mode depending on whether the -x 58 | parameter is a file or a directory. 59 | 60 | In the file mode, every name field can be optionally followed by @, e.g.: 61 | 62 | keyword_foo@1 = "foo" 63 | 64 | Such entries will be loaded only if the requested dictionary level is equal or 65 | higher than this number. The default level is zero; a higher value can be set 66 | by appending @ to the dictionary file name, like so: 67 | 68 | -x path/to/dictionary.dct@2 69 | 70 | Good examples of dictionaries can be found in _extras/xml.dict and 71 | _extras/png.dict. 72 | -------------------------------------------------------------------------------- /testcases/_extras/gif.dict: -------------------------------------------------------------------------------- 1 | # 2 | # AFL dictionary for GIF images 3 | # ----------------------------- 4 | # 5 | # Created by Michal Zalewski 6 | # 7 | 8 | header_87a="87a" 9 | header_89a="89a" 10 | header_gif="GIF" 11 | 12 | marker_2c="," 13 | marker_3b=";" 14 | 15 | section_2101="!\x01\x12" 16 | section_21f9="!\xf9\x04" 17 | section_21fe="!\xfe" 18 | section_21ff="!\xff\x11" 19 | -------------------------------------------------------------------------------- /testcases/_extras/html_tags.dict: -------------------------------------------------------------------------------- 1 | # 2 | # AFL dictionary for HTML parsers (tags only) 3 | # ------------------------------------------- 4 | # 5 | # A basic collection of HTML tags likely to matter to HTML parsers. Does *not* 6 | # include any attributes or attribute values. 7 | # 8 | # Created by Michal Zalewski 9 | # 10 | 11 | tag_a="" 12 | tag_abbr="" 13 | tag_acronym="" 14 | tag_address="" 15 | tag_annotation_xml="" 16 | tag_applet="" 17 | tag_area="" 18 | tag_article="" 19 | tag_aside="
18 | 19 |