Build simple fuzzer - part 2

In the previous part of this mini-series we’ve implemented a very simple fuzzer. As the main idea behind it is being an exercise therefore I don’t think it is capable of finding bugs in complex targets. Main reason for that is our mutation strategy. One we are using right now is completely random and lacks any feedback loop to tell us if the changes we are making to an original file are meaningful. In later parts we will try to do something about that but right now let’s talk about some administrative issues first.


Code we wrote in the previous part is not complete but can be easily put together just joining snippets and adding necessary imports. In this part however code changes won’t be implemented in a linear way making following the whole picture bit more difficult. To help you with that I’ve published the whole program on github so you can follow the code in relation to the complete work.


Improved architecture

Original architecture of the fuzzer was sufficient for the early phase but as we move forward it will quickly become a hindrance. Our first goal is to address some of the shortcomings without overengineering the application.


I’ve decided to focus on three separate things. First one is going to be support for runtime flags and global configuration file.


config = {
    'file': 'mutated.jpg', # name of the target file  
    'target': '', # Location of program to execute  
    'corpus': '', # Initial corpus of files to mutate  
    'rounds': 100000, # How many fuzz iterations to run  
    'seed': None, # Seed for PRNG 
    }
    
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--target", help = "target program",
        required=True)
    parser.add_argument("-c", "--corpus", help = "corpus of files",
        required=True)
    parser.add_argument("-r", "--rounds", help = "number of rounds",
        required=False)
    parser.add_argument("-s", "--seed", help = "seed for PRNG",