advanced
C/C++ Targets Instrumented with Honggfuzz¶

Need to compile a C/C++ target with honggfuzz instrumentation? In this lesson, we'll walk you through how to compile C/C++ honggfuzz targets and test them in Mayhem.
Estimated Time: 15 minutes
By the end of this lesson, you will be able to:
- Compile and fuzz a C honggfuzz target with an improper input validation defect.
- Compile and fuzz a C++ honggfuzz target with an improper input validation defect.
Run through the lesson:
See prerequisites before beginning.
-
Download the c-honggfuzz-gcc.tgz and build the
c-honggfuzz-gccDocker image, and push it to the specified Docker registry:docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/c-honggfuzz-gcc . docker push <DOCKERHUB_USERNAME>/c-honggfuzz-gccdocker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc -
Execute a Mayhem run on the
forallsecure/c-honggfuzz-gccDocker image using either the Mayhem UI or Mayhem CLI with the following Mayhemfile:1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
You will need the following:
- Docker installed.
- A valid Internet connection (for pulling Docker Hub base images)
One Click Testing¶
Click on the following button and hit Start Run at the end of the Create New Run flow to get a quick start on testing a C target with honggfuzz instrumentation! No need to configure anything, as the underlying Mayhemfile has already been configured for you!
Once the Mayhem run initiates, you should see a Run page similar to the following:
Awesome! Now that you've seen Mayhem can fuzz a C target instrumented with honggfuzz, let's now walk through how to compile and test the C-honggfuzz target that you just executed a Mayhem run for!
Compiling and Testing a C Target with Honggfuzz Instrumentation¶
File: c-honggfuzz-gcc.tgz
Download and extract the above c-honggfuzz-gcc.tgz and take a look at the following source code for hf_iter/src/mayhemit.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Here you'll notice that instead of a typical main function, the source code utilizes the HF_ITER function instead to accept an array of bytes that will be used to fuzz the target function, mayhemit. If the input is then found to spell out the word "bug", the program crashes due to an improper input validation error.
Note
There are two types of fuzzer entrypoints when using honggfuzz: ASAN-style (LLVMFuzzerTestOneInput) or HF_ITER style. Check out the documentation on honggfuzz persistent fuzzing for more information.
HonggFuzz also supports a third mode: Persistent fuzzing through file input. An example of this is included in the provided resources archive, under the c-honggfuzz-gcc/file directory. The same instructions apply both the c-honggfuzz-gcc/file and the c-honggfuzz-gcc/hf_iter target, except that you need to specify @@ as a command line argument in the Mayhemfile.
Taking a look at the corresponding Dockerfile shows us the process for compiling our c-honggfuzz-gcc target:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
- Line 1: The
fuzzers/honggfuzz:1.9base image is imported to provide the necessary honggfuzz dependencies. - Line 2: The
mayhemit.csource file is copied over into the Docker container. - Line 3: The
hfuzz-gccC compiler is to used to compile our C target with honggfuzz instrumentation. - Line 5: The
debian:buster-slimbase image is imported and the compiledmayhemitbinary along with thehonggfuzzfuzzer (and its associated dependencies) are brought over from the previous build stage. - Line 17: The
/mayhemitexecutable is set as the default executable for the Docker container.
Note
On lines 5-13, this is what's known as a multi-stage build and is done to optimize or slim down the size of the resulting Docker image. In addition, the honggfuzz driver must be the same version as the honggfuzz compiled binary. Therefore, by bringing over the honggfuzz executable from the previous build stage, we ensure that the same version of honggfuzz is used as the one that compiled the binary.
Next, we need to build the resulting <DOCKERHUB_USERNAME>/c-honggfuzz-gcc Docker image and push it to the Docker Hub registry:
Next, we need to build the resulting forallsecure/c-honggfuzz-gcc Docker image and push it to the Mayhem Docker registry:
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/c-honggfuzz-gcc .
docker push <DOCKERHUB_USERNAME>/c-honggfuzz-gcc
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc
Info
You can use the mayhem login command to find your internal Mayhem Docker Registry URL and run the following command to set the DOCKER_REGISTRY environment variable, like so:
export DOCKER_REGISTRY=tutorial.forallsecure.com:5000
DOCKER_REGISTRY environment variable for your specific Mayhem Docker Registry URL.
Upon successfully pushing the newly created Docker image to the Docker Hub registry, create a new run via the Mayhem UI and search for the <DOCKERHUB_USERNAME>/c-honggfuzz-gcc Docker image. Confirm that your Mayhemfile looks similar to the following:
Upon successfully pushing the newly created Docker image to the private Mayhem Docker Registry, create a new run via the Mayhem UI and search for the forallsecure/c-honggfuzz-gcc Docker image. Confirm that your Mayhemfile looks similar to the following:
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
Now just click Next until you reach the final confirmation page of the create new run flow and hit Start Run to execute your Mayhem run! You should see a Run page similar to the following:
Congratulations! You just tested a C honggfuzz target with Mayhem!
⚡ Real World Exercise: Compiling and Testing a C++ Target with Honggfuzz Instrumentation¶
Now that you're familiar with the steps for compiling and testing a C target with honggfuzz instrumentation, let's see if you can do the same for a C++ target!
Files cpp-honggfuzz-gcc.tgz
Instructions:
- Use the
Dockerfileand thedocker buildcommand and tag the resulting Docker image as<DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc. - Push the
<DOCKERHUB_USERNAME>/cpp-honggfuzz-gccDocker image to the Docker Hub registry using thedocker taganddocker pushcommands. -
Fuzz the
<DOCKERHUB_USERNAME>/cpp-honggfuzz-gccDocker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associatedMayhemfileaccordingly. -
Use the
Dockerfileand thedocker buildcommand and tag the resulting Docker image asforallsecure/cpp-honggfuzz-gcc. - Push the
forallsecure/cpp-honggfuzz-gccDocker image to the internal Mayhem Docker registry using thedocker taganddocker pushcommands. - Test the
forallsecure/cpp-honggfuzz-gccDocker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associatedMayhemfileaccordingly.
🔍 Review It! Compiling and Testing a C++ Target with Honggfuzz Instrumentation¶
Solution
First things first, let's take a look at the mayhemit.cpp source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
One difference you may have noticed when comparing against the source code of the c-honggfuzz-gcc target is the use of the extern "C" keyword. The extern "C" keyword makes a function-name in C++ have C linkage so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function.
Next up, let's take a look at the associated Dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Here we see that on line 1 we import the fuzzers/honggfuzz:1.9 base image as we've done before and now instead use the hfuzz-g++ compiler on line 3 to compile our C++ target with Honggfuzz instrumentation. Then, on line 5 and onward, the compiled mayhemit binary and honggfuzz fuzzer (with it's associated dependencies) are brought over to the next stage build under the debian:buster-slim base image. Thereby making this Dockerfile a multi-stage build to optimize disk space of the resulting Docker image.
Then, you needed to run the docker build command in the same directory as the Dockerfile and proceed to tag the resulting Docker image as <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc:
Then, you needed to run the docker build command in the same directory as the Dockerfile and proceed to tag the resulting Docker image as forallsecure/cpp-honggfuzz-gcc:
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc .
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc .
Next, you had to push the <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc Docker image to the Docker Hub registry:
Next, you had to push the forallsecure/cpp-honggfuzz-gcc Docker image to the private Mayhem Docker registry:
docker push <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc
Lastly, you needed to execute a Mayhem run on the uploaded <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc Docker image using either the Mayhem UI or Mayhem CLI. As long as your Mayhemfile looked similar to the following:
Lastly, you needed to execute a Mayhem run on the uploaded forallsecure/cpp-honggfuzz-gcc Docker image using either the Mayhem UI or Mayhem CLI. As long as your Mayhemfile looked similar to the following:
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
After initiating the Mayhem run, you should have seen a Run page similar to the following:
Congratulations! Mayhem found the improper input validation defect! You just built a honggfuzz C++ target from scratch and used Mayhem to detect the bug!
✏️ Summary and Recap¶
In this lesson, you learned how to compile C/C++ targets with Honggfuzz instrumentation and fuzz them in Mayhem!
I learned how to...
1. Compile and test a C honggfuzz target with an improper input validation defect.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10
int mayhemit(char *buf, unsigned len) { if(len >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { abort(); // Defect: SIGABRT. } return 0; } -
Then, to fuzz the C honggfuzz target, use the following
DockerfileandMayhemfileto build the Docker image containing the C program and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
FROM fuzzers/honggfuzz:1.9 COPY mayhemit.c . RUN hfuzz-gcc mayhemit.c -o /mayhemit FROM debian:buster-slim COPY --from=0 /mayhemit . COPY --from=0 /usr/local/bin/honggfuzz /usr/local/bin/honggfuzz COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 COPY --from=0 /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind.so.8 /usr/lib/x86_64-linux-gnu/libunwind.so.8 RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["honggfuzz", "-f", "/testsuite", "--"] CMD ["/mayhemit"]1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: c-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true
2. Compile and fuzz a C++ honggfuzz target with an improper input validation defect.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10
int mayhemit(char *buf, unsigned len) { if(len >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { abort(); // Defect: SIGABRT. } return 0; } -
Then, to fuzz the C honggfuzz target, use the following
DockerfileandMayhemfileto build the Docker image containing the C program and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
FROM fuzzers/honggfuzz:1.9 COPY mayhemit.cpp . RUN hfuzz-g++ mayhemit.cpp -o /mayhemit FROM debian:buster-slim COPY --from=0 /mayhemit . COPY --from=0 /usr/local/bin/honggfuzz /usr/local/bin/honggfuzz COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 /usr/lib/x86_64-linux-gnu/libunwind-ptrace.so.0 COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 /usr/lib/x86_64-linux-gnu/libunwind-x86_64.so.8 COPY --from=0 /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libbfd-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so /usr/lib/x86_64-linux-gnu/libopcodes-2.31.1-system.so COPY --from=0 /usr/lib/x86_64-linux-gnu/libunwind.so.8 /usr/lib/x86_64-linux-gnu/libunwind.so.8 RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["honggfuzz", "-f", "/testsuite", "--"] CMD ["/mayhemit"]1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/cpp-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: cpp-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-honggfuzz-gcc:latest duration: 90 project: mayhem-examples target: cpp-honggfuzz-gcc cmds: - cmd: /mayhemit honggfuzz: true

