From 1c8d003fc6f7e732dd750697648657cb0c552e98 Mon Sep 17 00:00:00 2001 From: Robert Sharp <rmsharp@student.unimelb.edu.au> Date: Fri, 18 Oct 2019 17:13:28 +1100 Subject: [PATCH] Created a Brownian Motion Fuzzer. --- fuzzer/Fuzzer.java | 388 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 304 insertions(+), 84 deletions(-) diff --git a/fuzzer/Fuzzer.java b/fuzzer/Fuzzer.java index 7ee264b..792ffb3 100644 --- a/fuzzer/Fuzzer.java +++ b/fuzzer/Fuzzer.java @@ -1,3 +1,8 @@ +import java.io.IOException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.*; + import java.io.IOException; import java.io.FileOutputStream; import java.io.PrintWriter; @@ -8,46 +13,90 @@ import java.util.Random; public class Fuzzer { private static final String OUTPUT_FILE = "fuzz.txt"; - + private static final String CHAR_LOWER = "abcdefghijklmnopqrstuvwxyz"; private static final String CHAR_UPPER = CHAR_LOWER.toUpperCase(); private static final String NUMBER = "0123456789"; - + private static final int MAX_LINE_LENGTH = 1022; - private static final int MAX_URL_LENGTH = 300; + private static final int MAX_URL_LENGTH = 300; private static final int numInputLines = 1024; //Indicates the number of inputs we wish to generate in one file private static ArrayList<String> savedURLs = new ArrayList<String>(); //save put urls here for get and rem private static final String DATA_FOR_RANDOM_STRING = CHAR_LOWER + CHAR_UPPER + NUMBER; //specifies which characters can be in a string - + + //Brownian values + private static boolean USEBROWNIAN = true; + + private static final double PUT_START = 100; + private static final double GET_START = 10; + private static final double REM_START = 10; + private static final double SAVE_START = 10; + private static final double LIST_START = 10; + + private static final double PUT_VAR = 20; + private static final double GET_VAR = 5; + private static final double REM_VAR = 5; + private static final double SAVE_VAR = 5; + private static final double LIST_VAR = 5; + + //public static void Fuzzer() throws IOException { public static void main(String[] args) throws IOException { + + //Rob's code + Double[] freqValues = null; + Double[] varValues = null; + + //System.out.println("Generated frequency values"); + + freqValues = createBrownianList(); + + //System.out.println("Generated variance values"); + + varValues = createVarianceList(); + System.out.println(Instruction.getBNF()); FileOutputStream out = null; PrintWriter pw = null; ArrayList<String> inputs = new ArrayList<String>(); - + try { out = new FileOutputStream(OUTPUT_FILE); pw = new PrintWriter(out); - + /* We just print one instruction. Hint: you might want to make use of the instruction grammar which is effectively encoded in Instruction.java */ - - /**Using generation-based fuzzing and Instruction.java, + + /**Using generation-based fuzzing and Instruction.java, * create random, valid inputs*/ - + for(int i=0; i<numInputLines; i++) { - String input = generateValidInputs(); - //only add the input if it hasn't already been generated - if(inputAlreadyGenerated(input, inputs)) { - i--; - }else { - inputs.add(input); - pw.println(input); - } + + String input = null; + + if (USEBROWNIAN) { + freqValues = updateBrownianList(freqValues, varValues); + input = generateValidBrownianInputs(freqValues); + } + + else { + + input = generateValidInputs(); + + } + + System.out.println(input); + + //only add the input if it hasn't already been generated + if(inputAlreadyGenerated(input, inputs)) { + i--; + }else { + inputs.add(input); + pw.println(input); + } } - + }catch (Exception e){ e.printStackTrace(System.err); System.exit(1); @@ -61,59 +110,230 @@ public class Fuzzer { } } - + + + + + /**Generates random, valid inputs based on Instruction.java*/ + public static String generateValidBrownianInputs(Double[] freqValues) { + + Instruction inst = getRandomBrownianInstruction(freqValues); + + String input = inst.getOpcode(); + + //add the operands + int index =0; + for (OperandType op : inst.getOperands()){ + + if(index==0 && inst == Instruction.PUT) { + //generate a string with URL length for first arg + String url = generateRandomString(MAX_URL_LENGTH); + //store urls in a list of "saved urls" + savedURLs.add(url); + input += " "+url; + + }else if(inst == Instruction.GET){ + //use a saved url if one exists + input += " "+ getRandomSavedURL(); + + }else if(inst == Instruction.REM){ + //use and remove a saved url if one exists + String url = getRandomSavedURL(); + if(savedURLs.contains(url)) { + savedURLs.remove(url); + } + input += " "+ url; + + }else if(op.equals(OperandType.STRING)) { + int maxStringLength = MAX_LINE_LENGTH - input.length() - ((inst.getOperands().length-index)*2); + input += " "+generateRandomString(maxStringLength); + } + index++; + } + //debug + //System.out.println(input); + + return input; + } + /**Generates random, valid inputs based on Instruction.java*/ public static String generateValidInputs() { - - //add the instruction string - Instruction inst = getRandomInstruction(); - String input = inst.getOpcode(); - - //add the operands - int index =0; - for (OperandType op : inst.getOperands()){ - - if(index==0 && inst == Instruction.PUT) { - //generate a string with URL length for first arg - String url = generateRandomString(MAX_URL_LENGTH); - //store urls in a list of "saved urls" - savedURLs.add(url); - input += " "+url; - - }else if(inst == Instruction.GET){ - //use a saved url if one exists - input += " "+ getRandomSavedURL(); - - }else if(inst == Instruction.REM){ - //use and remove a saved url if one exists - String url = getRandomSavedURL(); - if(savedURLs.contains(url)) { - savedURLs.remove(url); - } - input += " "+ url; - - }else if(op.equals(OperandType.STRING)) { - int maxStringLength = MAX_LINE_LENGTH - input.length() - ((inst.getOperands().length-index)*2); - input += " "+generateRandomString(maxStringLength); - } - index++; - } - //debug - //System.out.println(input); - - return input; + + Instruction inst = getRandomInstruction(); + + String input = inst.getOpcode(); + + //add the operands + int index =0; + for (OperandType op : inst.getOperands()){ + + if(index==0 && inst == Instruction.PUT) { + //generate a string with URL length for first arg + String url = generateRandomString(MAX_URL_LENGTH); + //store urls in a list of "saved urls" + savedURLs.add(url); + input += " "+url; + + }else if(inst == Instruction.GET){ + //use a saved url if one exists + input += " "+ getRandomSavedURL(); + + }else if(inst == Instruction.REM){ + //use and remove a saved url if one exists + String url = getRandomSavedURL(); + if(savedURLs.contains(url)) { + savedURLs.remove(url); + } + input += " "+ url; + + }else if(op.equals(OperandType.STRING)) { + int maxStringLength = MAX_LINE_LENGTH - input.length() - ((inst.getOperands().length-index)*2); + input += " "+generateRandomString(maxStringLength); + } + index++; + } + //debug + //System.out.println(input); + + return input; } - + /**Selects a random instruction * Returns any instruction except for masterpassword * */ public static Instruction getRandomInstruction() { - Instruction[] INSTS = Instruction.values(); - int index = new Random().nextInt(INSTS.length-1); - return INSTS[index]; + Instruction[] INSTS = Instruction.values(); + int index = new Random().nextInt(INSTS.length-1); + return INSTS[index]; + } + + + /**Creates a List with different variance values + * + */ + + public static Double[] createVarianceList() { + + /* + double PUT_VAR = 20; + double GET_VAR = 5; + double REM_VAR = 5; + double SAVE_VAR = 5; + double LIST_VAR = 5; + */ + + Double[] varValues = new Double[5]; + varValues[0]=PUT_VAR; + varValues[1]=GET_VAR; + varValues[2]=REM_VAR; + varValues[3]=SAVE_VAR; + varValues[4]=LIST_VAR; + + return(varValues); + + } + + /**Update the frequency values based on + * + */ + + public static Double[] updateBrownianList(Double[] freqValues, Double[] varValues) { + + int i; + + Instruction[] INSTS = Instruction.values(); + + Random random = new Random(); + + for (i = 0; i < INSTS.length-1; i++) { + + freqValues[i] = freqValues[i] + ((random.nextDouble() * 2) -1) * varValues[i]; + //System.out.println("The index of: "+i + "has the frequency values of: "+freqValues[i]); + + } + + return(freqValues); + } - - /**Generates a random string. + + /**Creates a List with different freq values + * + */ + public static Double[] createBrownianList() { + + /* + double PUT_START = 100; + double GET_START = 10; + double REM_START = 10; + double SAVE_START = 10; + double LIST_START = 10; + */ + + Double[] freqValues = new Double[5]; + freqValues[0]=PUT_START; + freqValues[1]=GET_START; + freqValues[2]=REM_START; + freqValues[3]=SAVE_START; + freqValues[4]=LIST_START; + + return(freqValues); + + } + + /**Returns an int between range of number of instructions less 1 + * + */ + public static int getTopInstruction(Double[] freqValues) { + + int i; + + Random random = new Random(); + + double max = 0; + + double temp; + + int max_index = 0; + + + Instruction[] INSTS = Instruction.values(); + + for (i = 0; i < INSTS.length-1; i++) { + + temp = Math.abs(freqValues[i] * random.nextDouble()); + + if (temp > max) { + + max_index = i; + max = temp; + + } + + } + + return(max_index); + + } + + + /**Returns any instruction except for masterpassword + * Generates based on array of random walks + */ + public static Instruction getRandomBrownianInstruction(Double[] freqValues) { + + Instruction[] INSTS = Instruction.values(); + int index = getTopInstruction(freqValues); + + //System.out.println("Returned the index of: "+index); + //System.out.println("Corresponding to: "+INSTS[index]); + + return INSTS[index]; + + } + + + + /**Generates a random string. * Sourced from: https://www.mkyong.com/java/java-how-to-generate-a-random-string/ * and modified*/ public static String generateRandomString(int maxlength) { @@ -121,22 +341,22 @@ public class Fuzzer { Random random = new Random(); int minLength = 1; int length; - + //make a 1/4 chance of picking the max length and a 1/4 chance of picking the min length int chance = random.nextInt(4); if(chance == 1) { - length = maxlength; + length = maxlength; }else if(chance == 2) { - length = minLength; + length = minLength; }else { - length = random.nextInt(maxlength)+1; + length = random.nextInt(maxlength)+1; } - + StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { - // 0-62 (exclusive), random returns 0-61 + // 0-62 (exclusive), random returns 0-61 int rndCharAt = random.nextInt(DATA_FOR_RANDOM_STRING.length()); char rndChar = DATA_FOR_RANDOM_STRING.charAt(rndCharAt); @@ -147,26 +367,26 @@ public class Fuzzer { return sb.toString(); } - + /**Checks whether the input has already been generated*/ public static boolean inputAlreadyGenerated(String newInput, ArrayList<String> inputs) { - for(String input:inputs) { - if(input.equals(newInput)) { - return true; - } - } - - return false; + for(String input:inputs) { + if(input.equals(newInput)) { + return true; + } + } + + return false; } - + /**Selects a random saved URL*/ public static String getRandomSavedURL(){ - if(savedURLs.size()>0) { - int index = new Random().nextInt(savedURLs.size()); - return savedURLs.get(index); - }else { - return generateRandomString(MAX_URL_LENGTH); - } + if(savedURLs.size()>0) { + int index = new Random().nextInt(savedURLs.size()); + return savedURLs.get(index); + }else { + return generateRandomString(MAX_URL_LENGTH); + } } } -- GitLab