1. Documentation
  2. Advanced Techniques

How to fuzz a main function in C/C++

The following fuzz test is an example for how you can fuzz the main function of your target application. This includes creating your own argc+argv arguments and shows how you can call the main function of the target.

Usually it is more effective to fuzz specific interesting functions of your target application directly. However, sometimes you either do not know what your interesting functions are, or you are not sure what needs to be initialized to call the interesting functions directly.

In this case you may want to fuzz the main function, as long as there is a way to inject fuzzing data in your application. The Fuzz Test example below shows how you can fuzz an application that expects a file name as the second parameter in argv and then processes this file:

#include <stdint.h>
#include <stddef.h>
#include <string>

// this is needed for file input fuzzing
#include <file_input.h>

// this is needed for dlsym. using dlsym also means that
// the extra compile argument -ldl needs to be added to the fuzz test config file
#include <dlfcn.h>

extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// declaration of pointer to original main function
int (*original_main)(int, char **);

extern "C" int FUZZ(const uint8_t *Data, size_t Size) {

// define how many arguments you want to pass in argv
int argc = 2;
char ** argv = new char*[ argc ];

// example of how to create an argv "member" for a fixed string
std::string test_str = "test";
char * test_char = new char[ test_str.length()+1 ];
strncpy( test_char, test_str.c_str(), test_str.length()+1 );
argv[0] = test_char;

// example of how to create an argv "member" using a file name
auto ci_file_input = ci::input_file{Data, Size};
char * ci_file_char = new char[ strlen ( ci_file_input.name() )+1 ];
strncpy( ci_file_char, ci_file_input.name(), strlen( ci_file_input.name() )+1 );
argv[1] = ci_file_char;

// using this method we can call the original main function from our target application
// our fuzz test has it's own main function which we do not want to fuzz
original_main = (int (*)(int, char **))dlsym(RTLD_NEXT, "main");
original_main( argc, argv );

// reset state and free all locally allocated resources
delete[] test_char;
delete[] ci_file_char;
delete[] argv;

return 0;