From 30cd8a8397419b3eedb6ee939e290b4c6b8c2cf1 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 14 Nov 2020 12:28:51 +0100 Subject: fix non instrumented mode, fix check_binary --- unicorn_mode/unicornafl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'unicorn_mode') diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index c6d66471..f44ec48f 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit c6d6647161a32bae88785a618fcd828d1711d9e6 +Subproject commit f44ec48f8d5929f243522c1152b5b3c0985a5548 -- cgit 1.4.1 From f0e81b230146dba93ac265485bbbc5b5c77a0343 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 3 Dec 2020 22:26:28 +0100 Subject: updated unicorn --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'unicorn_mode') diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index c5569fbd..99025a06 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -f44ec48f +8cca4801 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index f44ec48f..8cca4801 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit f44ec48f8d5929f243522c1152b5b3c0985a5548 +Subproject commit 8cca4801adb767dce7cf72202d7d25bdb420cf7d -- cgit 1.4.1 From 330f33a4356f46f25d0930aa61ef18c78a559fea Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 4 Dec 2020 15:40:38 +0100 Subject: updated helper_scripts from battelle/afl-unicorn --- unicorn_mode/helper_scripts/unicorn_dumper_gdb.py | 64 ++--- unicorn_mode/helper_scripts/unicorn_dumper_ida.py | 2 +- unicorn_mode/helper_scripts/unicorn_loader.py | 271 ++++++++++++++++------ 3 files changed, 240 insertions(+), 97 deletions(-) (limited to 'unicorn_mode') diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py index 22b9fd47..8c8f9641 100644 --- a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py +++ b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py @@ -1,13 +1,13 @@ """ unicorn_dumper_gdb.py - + When run with GDB sitting at a debug breakpoint, this dumps the current state (registers/memory/etc) of - the process to a directory consisting of an index - file with register and segment information and + the process to a directory consisting of an index + file with register and segment information and sub-files containing all actual process memory. - - The output of this script is expected to be used + + The output of this script is expected to be used to initialize context for Unicorn emulation. ----------- @@ -44,6 +44,7 @@ MAX_SEG_SIZE = 128 * 1024 * 1024 # Name of the index file INDEX_FILE_NAME = "_index.json" + #---------------------- #---- Helper Functions @@ -59,14 +60,14 @@ def map_arch(): return "arm64be" elif 'armeb' in arch: # check for THUMB mode - cpsr = get_register('cpsr') + cpsr = get_register('$cpsr') if (cpsr & (1 << 5)): return "armbethumb" else: return "armbe" elif 'arm' in arch: # check for THUMB mode - cpsr = get_register('cpsr') + cpsr = get_register('$cpsr') if (cpsr & (1 << 5)): return "armlethumb" else: @@ -88,19 +89,15 @@ def dump_regs(): reg_state = {} for reg in current_arch.all_registers: reg_val = get_register(reg) - # current dumper script looks for register values to be hex strings -# reg_str = "0x{:08x}".format(reg_val) -# if "64" in get_arch(): -# reg_str = "0x{:016x}".format(reg_val) -# reg_state[reg.strip().strip('$')] = reg_str reg_state[reg.strip().strip('$')] = reg_val + return reg_state def dump_process_memory(output_dir): # Segment information dictionary final_segment_list = [] - + # GEF: vmmap = get_process_maps() if not vmmap: @@ -110,7 +107,7 @@ def dump_process_memory(output_dir): for entry in vmmap: if entry.page_start == entry.page_end: continue - + seg_info = {'start': entry.page_start, 'end': entry.page_end, 'name': entry.path, 'permissions': { "r": entry.is_readable() > 0, "w": entry.is_writable() > 0, @@ -129,7 +126,7 @@ def dump_process_memory(output_dir): compressed_seg_content = zlib.compress(seg_content) md5_sum = hashlib.md5(compressed_seg_content).hexdigest() + ".bin" seg_info["content_file"] = md5_sum - + # Write the compressed contents to disk out_file = open(os.path.join(output_dir, md5_sum), 'wb') out_file.write(compressed_seg_content) @@ -143,12 +140,27 @@ def dump_process_memory(output_dir): # Add the segment to the list final_segment_list.append(seg_info) - + return final_segment_list +#--------------------------------------------- +#---- ARM Extention (dump floating point regs) + +def dump_float(rge=32): + reg_convert = "" + if map_arch() == "armbe" or map_arch() == "armle" or map_arch() == "armbethumb" or map_arch() == "armbethumb": + reg_state = {} + for reg_num in range(32): + value = gdb.selected_frame().read_register("d" + str(reg_num)) + reg_state["d" + str(reg_num)] = int(str(value["u64"]), 16) + value = gdb.selected_frame().read_register("fpscr") + reg_state["fpscr"] = int(str(value), 16) + + return reg_state + #---------- -#---- Main - +#---- Main + def main(): print("----- Unicorn Context Dumper -----") print("You must be actively debugging before running this!") @@ -159,32 +171,32 @@ def main(): print("!!! GEF not running in GDB. Please run gef.py by executing:") print('\tpython execfile ("/gef.py")') return - + try: - + # Create the output directory timestamp = datetime.datetime.fromtimestamp(time.time()).strftime('%Y%m%d_%H%M%S') output_path = "UnicornContext_" + timestamp if not os.path.exists(output_path): os.makedirs(output_path) print("Process context will be output to {}".format(output_path)) - + # Get the context context = { "arch": dump_arch_info(), - "regs": dump_regs(), + "regs": dump_regs(), + "regs_extended": dump_float(), "segments": dump_process_memory(output_path), } # Write the index file index_file = open(os.path.join(output_path, INDEX_FILE_NAME), 'w') index_file.write(json.dumps(context, indent=4)) - index_file.close() + index_file.close() print("Done.") - + except Exception as e: print("!!! ERROR:\n\t{}".format(repr(e))) - + if __name__ == "__main__": main() - diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_ida.py b/unicorn_mode/helper_scripts/unicorn_dumper_ida.py index 6cf9f30f..3f955a5c 100644 --- a/unicorn_mode/helper_scripts/unicorn_dumper_ida.py +++ b/unicorn_mode/helper_scripts/unicorn_dumper_ida.py @@ -206,4 +206,4 @@ def main(): print("!!! ERROR:\n\t{}".format(str(e))) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/unicorn_mode/helper_scripts/unicorn_loader.py b/unicorn_mode/helper_scripts/unicorn_loader.py index adf21b64..1914a83d 100644 --- a/unicorn_mode/helper_scripts/unicorn_loader.py +++ b/unicorn_mode/helper_scripts/unicorn_loader.py @@ -1,8 +1,8 @@ """ unicorn_loader.py - - Loads a process context dumped created using a - Unicorn Context Dumper script into a Unicorn Engine + + Loads a process context dumped created using a + Unicorn Context Dumper script into a Unicorn Engine instance. Once this is performed emulation can be started. """ @@ -26,6 +26,13 @@ from unicorn.arm64_const import * from unicorn.x86_const import * from unicorn.mips_const import * +# If Capstone libraries are availible (only check once) +try: + from capstone import * + CAPSTONE_EXISTS = 1 +except: + CAPSTONE_EXISTS = 0 + # Name of the index file INDEX_FILE_NAME = "_index.json" @@ -86,7 +93,7 @@ class UnicornSimpleHeap(object): total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE # Gross but efficient way to find space for the chunk: chunk = None - for addr in xrange(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE): + for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE): try: self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE) chunk = self.HeapChunk(addr, total_chunk_size, size) @@ -97,7 +104,7 @@ class UnicornSimpleHeap(object): continue # Something went very wrong if chunk == None: - return 0 + return 0 self._chunks.append(chunk) return chunk.data_addr @@ -112,8 +119,8 @@ class UnicornSimpleHeap(object): old_chunk = None for chunk in self._chunks: if chunk.data_addr == ptr: - old_chunk = chunk - new_chunk_addr = self.malloc(new_size) + old_chunk = chunk + new_chunk_addr = self.malloc(new_size) if old_chunk != None: self._uc.mem_write(new_chunk_addr, str(self._uc.mem_read(old_chunk.data_addr, old_chunk.data_size))) self.free(old_chunk.data_addr) @@ -184,39 +191,27 @@ class AflUnicornEngine(Uc): # Load the registers regs = context['regs'] reg_map = self.__get_register_map(self._arch_str) - for register, value in regs.iteritems(): - if debug_print: - print("Reg {0} = {1}".format(register, value)) - if not reg_map.has_key(register.lower()): - if debug_print: - print("Skipping Reg: {}".format(register)) - else: - reg_write_retry = True - try: - self.reg_write(reg_map[register.lower()], value) - reg_write_retry = False - except Exception as e: - if debug_print: - print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e))) + self.__load_registers(regs, reg_map, debug_print) + # If we have extra FLOATING POINT regs, load them in! + if 'regs_extended' in context: + if context['regs_extended']: + regs_extended = context['regs_extended'] + reg_map = self.__get_registers_extended(self._arch_str) + self.__load_registers(regs_extended, reg_map, debug_print) + + # For ARM, sometimes the stack pointer is erased ??? (I think I fixed this (issue with ordering of dumper.py, I'll keep the write anyways) + if self.__get_arch_and_mode(self.get_arch_str())[0] == UC_ARCH_ARM: + self.reg_write(UC_ARM_REG_SP, regs['sp']) - if reg_write_retry: - if debug_print: - print("Trying to parse value ({}) as hex string".format(value)) - try: - self.reg_write(reg_map[register.lower()], int(value, 16)) - except Exception as e: - if debug_print: - print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e))) - # Setup the memory map and load memory content self.__map_segments(context['segments'], context_directory, debug_print) - + if enable_trace: self.hook_add(UC_HOOK_BLOCK, self.__trace_block) self.hook_add(UC_HOOK_CODE, self.__trace_instruction) self.hook_add(UC_HOOK_MEM_WRITE | UC_HOOK_MEM_READ, self.__trace_mem_access) self.hook_add(UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_READ_INVALID, self.__trace_mem_invalid_access) - + if debug_print: print("Done loading context.") @@ -228,7 +223,7 @@ class AflUnicornEngine(Uc): def get_arch_str(self): return self._arch_str - + def force_crash(self, uc_error): """ This function should be called to indicate to AFL that a crash occurred during emulation. You can pass the exception received from Uc.emu_start @@ -253,21 +248,76 @@ class AflUnicornEngine(Uc): for reg in sorted(self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]): print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1]))) + def dump_regs_extended(self): + """ Dumps the contents of all the registers to STDOUT """ + try: + for reg in sorted(self.__get_registers_extended(self._arch_str).items(), key=lambda reg: reg[0]): + print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1]))) + except Exception as e: + print("ERROR: Are extended registers loaded?") + # TODO: Make this dynamically get the stack pointer register and pointer width for the current architecture """ def dump_stack(self, window=10): + arch = self.get_arch() + mode = self.get_mode() + # Get stack pointers and bit sizes for given architecture + if arch == UC_ARCH_X86 and mode == UC_MODE_64: + stack_ptr_addr = self.reg_read(UC_X86_REG_RSP) + bit_size = 8 + elif arch == UC_ARCH_X86 and mode == UC_MODE_32: + stack_ptr_addr = self.reg_read(UC_X86_REG_ESP) + bit_size = 4 + elif arch == UC_ARCH_ARM64: + stack_ptr_addr = self.reg_read(UC_ARM64_REG_SP) + bit_size = 8 + elif arch == UC_ARCH_ARM: + stack_ptr_addr = self.reg_read(UC_ARM_REG_SP) + bit_size = 4 + elif arch == UC_ARCH_ARM and mode == UC_MODE_THUMB: + stack_ptr_addr = self.reg_read(UC_ARM_REG_SP) + bit_size = 4 + elif arch == UC_ARCH_MIPS: + stack_ptr_addr = self.reg_read(UC_MIPS_REG_SP) + bit_size = 4 + print("") print(">>> Stack:") stack_ptr_addr = self.reg_read(UC_X86_REG_RSP) for i in xrange(-window, window + 1): addr = stack_ptr_addr + (i*8) print("{0}0x{1:016x}: 0x{2:016x}".format( \ - 'SP->' if i == 0 else ' ', addr, \ + 'SP->' if i == 0 else ' ', addr, \ struct.unpack('>> Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value)) else: - print(" >>> Read: addr=0x{0:016x} size={1}".format(address, size)) + print(" >>> Read: addr=0x{0:016x} size={1}".format(address, size)) def __trace_mem_invalid_access(self, uc, access, address, size, value, user_data): if access == UC_MEM_WRITE_UNMAPPED: print(" >>> INVALID Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format(address, size, value)) else: - print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size)) - + print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size)) + + def bit_size_arch(self): + arch = self.get_arch() + mode = self.get_mode() + # Get bit sizes for given architecture + if arch == UC_ARCH_X86 and mode == UC_MODE_64: + bit_size = 8 + elif arch == UC_ARCH_X86 and mode == UC_MODE_32: + bit_size = 4 + elif arch == UC_ARCH_ARM64: + bit_size = 8 + elif arch == UC_ARCH_ARM: + bit_size = 4 + elif arch == UC_ARCH_MIPS: + bit_size = 4 + return bit_size -- cgit 1.4.1 From 9a7d045897befd0388966ffd1d9c532e4158d096 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 4 Dec 2020 17:59:11 +0100 Subject: build_unicorn_support no longer fetches qemuafl --- unicorn_mode/build_unicorn_support.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'unicorn_mode') diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index b4d2058f..f1306a06 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -149,7 +149,7 @@ git status 1>/dev/null 2>/dev/null if [ $? -eq 0 ]; then echo "[*] initializing unicornafl submodule" git submodule init || exit 1 - git submodule update 2>/dev/null # ignore errors + git submodule update ./unicornafl 2>/dev/null # ignore errors else echo "[*] cloning unicornafl" test -d unicornafl || { -- cgit 1.4.1 From eda068751e1876797e1ec481ece356ecfb63f0cc Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 8 Dec 2020 10:09:35 +0100 Subject: streamlined grammar mutator submodule --- .gitmodules | 2 +- custom_mutators/grammar_mutator | 1 - custom_mutators/grammar_mutator/GRAMMAR_VERSION | 1 + custom_mutators/grammar_mutator/README.md | 6 + .../grammar_mutator/build_grammar_mutator.sh | 141 +++++++++++++++++++++ custom_mutators/grammar_mutator/grammar_mutator | 1 + .../grammar_mutator/update_grammar_ref.sh | 50 ++++++++ qemu_mode/build_qemu_support.sh | 2 +- unicorn_mode/build_unicorn_support.sh | 2 +- 9 files changed, 202 insertions(+), 4 deletions(-) delete mode 160000 custom_mutators/grammar_mutator create mode 100644 custom_mutators/grammar_mutator/GRAMMAR_VERSION create mode 100644 custom_mutators/grammar_mutator/README.md create mode 100644 custom_mutators/grammar_mutator/build_grammar_mutator.sh create mode 160000 custom_mutators/grammar_mutator/grammar_mutator create mode 100644 custom_mutators/grammar_mutator/update_grammar_ref.sh (limited to 'unicorn_mode') diff --git a/.gitmodules b/.gitmodules index 78e9f439..c787ec0e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,7 +2,7 @@ path = unicorn_mode/unicornafl url = https://github.com/AFLplusplus/unicornafl [submodule "custom_mutators/grammar_mutator"] - path = custom_mutators/grammar_mutator + path = custom_mutators/grammar_mutator/grammar_mutator url = https://github.com/AFLplusplus/Grammar-Mutator [submodule "qemu_mode/qemuafl"] path = qemu_mode/qemuafl diff --git a/custom_mutators/grammar_mutator b/custom_mutators/grammar_mutator deleted file mode 160000 index b3c4fcfa..00000000 --- a/custom_mutators/grammar_mutator +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b3c4fcfa6ae28918bc410f7747135eafd4fb7263 diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION new file mode 100644 index 00000000..a3fe6bb1 --- /dev/null +++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION @@ -0,0 +1 @@ +b3c4fcf diff --git a/custom_mutators/grammar_mutator/README.md b/custom_mutators/grammar_mutator/README.md new file mode 100644 index 00000000..a015744c --- /dev/null +++ b/custom_mutators/grammar_mutator/README.md @@ -0,0 +1,6 @@ +# Grammar-Mutator + +This is just a stub directory that will clone the real grammar mutator +directory. + +Execute `./build_grammar_mutator.sh` to set everything up. diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh new file mode 100644 index 00000000..b097ebd3 --- /dev/null +++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh @@ -0,0 +1,141 @@ +#!/bin/sh +# +# american fuzzy lop++ - unicorn mode build script +# ------------------------------------------------ +# +# Originally written by Nathan Voss +# +# Adapted from code by Andrew Griffiths and +# Michal Zalewski +# +# Adapted for AFLplusplus by Dominik Maier +# +# CompareCoverage and NeverZero counters by Andrea Fioraldi +# +# +# Copyright 2017 Battelle Memorial Institute. All rights reserved. +# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# This script downloads, patches, and builds a version of Unicorn with +# minor tweaks to allow Unicorn-emulated binaries to be run under +# afl-fuzz. +# +# The modifications reside in patches/*. The standalone Unicorn library +# will be written to /usr/lib/libunicornafl.so, and the Python bindings +# will be installed system-wide. +# +# You must make sure that Unicorn Engine is not already installed before +# running this script. If it is, please uninstall it first. + +GRAMMAR_VERSION="$(cat ./GRAMMAR_VERSION)" +GRAMMAR_REPO="https://github.com/AFLplusplus/grammar-mutator" + +echo "=================================================" +echo "Grammar Mutator build script" +echo "=================================================" +echo + +echo "[*] Performing basic sanity checks..." + +PLT=`uname -s` + +if [ ! -f "../../config.h" ]; then + + echo "[-] Error: key files not found - wrong working directory?" + exit 1 + +fi + +PYTHONBIN=`command -v python3 || command -v python || command -v python2 || echo python3` +MAKECMD=make +TARCMD=tar + +if [ "$PLT" = "Darwin" ]; then + CORES=`sysctl -n hw.ncpu` + TARCMD=tar +fi + +if [ "$PLT" = "FreeBSD" ]; then + MAKECMD=gmake + CORES=`sysctl -n hw.ncpu` + TARCMD=gtar +fi + +if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then + MAKECMD=gmake + CORES=`sysctl -n hw.ncpu` + TARCMD=gtar +fi + +PREREQ_NOTFOUND= +for i in git $MAKECMD $TARCMD; do + + T=`command -v "$i" 2>/dev/null` + + if [ "$T" = "" ]; then + + echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar." + PREREQ_NOTFOUND=1 + + fi + +done + +if echo "$CC" | grep -qF /afl-; then + + echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool." + PREREQ_NOTFOUND=1 + +fi + +if [ "$PREREQ_NOTFOUND" = "1" ]; then + exit 1 +fi + +echo "[+] All checks passed!" + +echo "[*] Making sure grammar mutator is checked out" + +git status 1>/dev/null 2>/dev/null +if [ $? -eq 0 ]; then + echo "[*] initializing grammar mutator submodule" + git submodule init || exit 1 + git submodule update ./grammar_mutator 2>/dev/null # ignore errors +else + echo "[*] cloning grammar mutator" + test -d grammar_mutator || { + CNT=1 + while [ '!' -d grammar_mutator -a "$CNT" -lt 4 ]; do + echo "Trying to clone grammar_mutator (attempt $CNT/3)" + git clone --depth=1 "$GRAMMAR_REPO" + CNT=`expr "$CNT" + 1` + done + } +fi + +test -d grammar_mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; } +echo "[+] Got grammar mutator." + +cd "grammar_mutator" || exit 1 +echo "[*] Checking out $GRAMMAR_VERSION" +sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null +git checkout "$GRAMMAR_VERSION" || exit 1 +cd .. + +echo "[*] Downloading antlr..." +wget -c https://www.antlr.org/download/antlr-4.8-complete.jar + +echo +echo +echo "[+] All successfully prepared!" +echo "[!] To build for your grammar just do:" +echo " `cd grammar_mutator`" +echo " `make GRAMMAR_FILE=/path/to/your/grammar`" +echo "[+] You will find a JSON and RUBY grammar in grammar_mutator/grammars to play with." +echo diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator new file mode 160000 index 00000000..b3c4fcfa --- /dev/null +++ b/custom_mutators/grammar_mutator/grammar_mutator @@ -0,0 +1 @@ +Subproject commit b3c4fcfa6ae28918bc410f7747135eafd4fb7263 diff --git a/custom_mutators/grammar_mutator/update_grammar_ref.sh b/custom_mutators/grammar_mutator/update_grammar_ref.sh new file mode 100644 index 00000000..478a73a8 --- /dev/null +++ b/custom_mutators/grammar_mutator/update_grammar_ref.sh @@ -0,0 +1,50 @@ +#/bin/sh + +################################################## +# AFL++ tool to update a git ref. +# Usage: ./