advanced
Go Targets with LibFuzzer Instrumentation via Go-Fuzz¶

Need a Go target with libFuzzer instrumentation? In this lesson, we'll walk through how to compile Go targets with libFuzzer instrumentation using Go-Fuzz!
Estimated Time: 15 minutes
By the end of this lesson, you will be able to:
- Compile and fuzz a Go target with libFuzzer instrumentation via go-fuzz for an reachable assertion defect.
- Compile and fuzz a Go target with libFuzzer instrumentation via go-fuzz for an index-out-of-bounds defect.
Run through the lesson:
See prerequisites before beginning.
-
Download the go-go-fuzz.tgz and build the
go-go-fuzzDocker image, and push it to the specified Docker registry:docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/go-go-fuzz . docker push <DOCKERHUB_USERNAME>/go-go-fuzzdocker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz -
Execute a Mayhem run on the
go-go-fuzzDocker image using either the Mayhem UI or Mayhem CLI with the following Mayhemfile:1 2 3 4 5
image: <DOCKERHUB_USERNAME>/go-go-fuzz:latest project: mayhem-examples target: go-go-fuzz cmds: - cmd: /go/mayhemit.libfuzzer1 2 3 4 5
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz:latest project: mayhem-examples target: go-go-fuzz cmds: - cmd: /go/mayhemit.libfuzzer
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 Go target instrumented with go-fuzz! 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 testing a libFuzzer instrumented Go target, let's now walk through how to compile and fuzz the go-go-fuzz target that you just executed a Mayhem run for!
Compiling and Testing a Go Target with LibFuzzer Instrumentation via Go-Fuzz¶
File: go-go-fuzz.tgz
Download and extract the above go-go-fuzz.tgz and take a look at the following bugged mayhemit.go program.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Here we see that there are two functions of interest: Fuzz and mayhemit. The Fuzz function serves as the entrypoint for the go-fuzz fuzzer and invokes the mayhemit function on line 18 to check if the input test case reads "bug". If so, the program crashes via a reachable assertion error produced by the panic() function on line 9.
Let's now see how this program will end up being compiled:
1 2 3 4 5 6 7 8 | |
- Line 1: The
fuzzers/go-fuzz:1.2.0base image is set as the base environment for the Docker container, providing access togo-fuzzand its dependencies. - Line 2: The
mayhemit.gosource code is copied over into the Docker container. - Line 3: The
go-fuzz-buildcompiler is used to compile themayhemitexecutable. In this particular case, thego-fuzz-buildcompiler outputs a libFuzzer archive file that can then be used with libFuzzer. - Line 8: The executable
/go/mayhemit.libfuzzeris set as the default executable for the resulting Docker image.
Then, within the go-go-fuzz folder, execute the following docker commands to build and push the <DOCKERHUB_USERNAME>/go-go-fuzz Docker image to the Docker Hub registry.
Then, within the go-go-fuzz folder, execute the following docker commands to build and push the forallsecure/go-go-fuzz Docker image to the Mayhem Docker Registry.
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/go-go-fuzz .
docker push <DOCKERHUB_USERNAME>/go-go-fuzz
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz
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.
Once the Docker image is successfully pushed, navigate to the Mayhem UI and select Docker Hub as the source to your new Mayhem run. Search for the <DOCKERHUB_USERNAME>/go-go-fuzz Docker image you just uploaded and confirm the Mayhemfile looks similar to the following:
Once the Docker image is successfully pushed, navigate to the Mayhem UI and select the Mayhem Docker Registry as the source to your new Mayhem run. Search for the forallsecure/go-go-fuzz Docker image you just uploaded and confirm the Mayhemfile looks similar to the following:
1 2 3 4 5 | |
1 2 3 4 5 | |
Then just click Next to the end of the Create New Run flow and hit the Click Start button to begin testing your new Go target! You should see a Run page similar to the following:
Congratulations! You just fuzzed a Go target with go-fuzz instrumentation!
⚡ Real World Exercise: Building and Testing the mayhemit-out-of-bounds LibFuzzer Go Target via Go-Fuzz¶
Now that you know how to build and test a Go target with libFuzzer instrumentation using go-fuzz, let's see if you can modify the source code to use an index out-of-bounds error instead of a reachable assertion defect!
Files: mayhemit-out-of-bounds-unsolved.zip
Instructions:
-
Modify the
mayhemit.gosource code and add the array out-of-bounds defect:1 2 3 4 5 6 7 8 9 10 11 12 13 14
func mayhemit(bytes []byte) int { content := string(bytes) if len(content) >= 3 && len(content) < 5 { if string(content[0]) == "b" { if string(content[1]) == "u" { if string(content[2]) == "g" { var x = content[10] fmt.Println(x) } } } } return 0 } -
Rebuild the Dockerfile using the
docker buildcommand and tag the resulting Docker image as<DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds. - Push the
<DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-boundsDocker image to the public Docker Hub registry using thedocker pushcommand. - Fuzz the
<DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-boundsDocker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associatedMayhemfileaccordingly.
- Rebuild the Dockerfile using the
docker buildcommand and tag the resulting Docker image as$MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds. - Push the
$MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-boundsDocker image to the private Mayhem Docker registry using thedocker pushcommand. - Test the
$MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-boundsDocker image using either the Mayhem UI or Mayhem CLI. Make sure to set the associatedMayhemfileaccordingly.
🔍 Review It! Building and Testing the mayhemit-out-of-bounds LibFuzzer Go Target via Go-Fuzz¶
Solution
Solution: mayhemit-out-of-bounds-solved.zip
First things first, you needed to add the max length constraint len(content) < 5 and the erroneous call for content[10] so that when the mayhemit function is fuzzed, the input test case "bug" will trigger the index out-of-bounds error.
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 | |
Then, you needed to run the docker build command in the same directory as the Dockerfile and simultaneously tag the resulting Docker image as <DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds.
Then, you needed to run the docker build command in the same directory as the Dockerfile and simultaneously tag the resulting Docker image as $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds.
docker build -f Dockerfile -t <DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds .
docker build -f Dockerfile -t $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds .
Next, you had to tag and push the <DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds Docker image to the public Docker Hub registry.
Next, you had to tag and push the $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds Docker image to the private Mayhem Docker registry.
docker push <DOCKERHUB_USERNAME>/tutorial/go-go-fuzz-mayhemit-out-of-bounds
docker push $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds
Note
Here we uploaded the go-go-fuzz-mayhemit-out-of-bounds Docker image to our tutorial.forallsecure.com Mayhem deployment, specifically at the internal Docker registry located at port 5000. For your Docker image to have successfully uploaded, you would have had to adjust the URL for your Mayhem deployment Docker registry accordingly.
Alternatively, you could have also used the included Makefile to easily build and push the resulting Docker image by setting a MAYHEM_DOCKER_REGISTRY environment variable and running the following commands:
make build
make push
Lastly, you needed to execute a Mayhem run on the uploaded <DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds 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 $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds 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 | |
Your final Run page should have looked like the following:
Congratulations! Mayhem found the index out-of-bounds defect that you added! You just built a libFuzzer instrumented Go target using go-fuzz and added a bug that was detected in Mayhem!
✏️ Summary and Recap¶
In this lesson, you learned how to compile libFuzzer instrumented Go targets with go-fuzz and fuzz them in Mayhem!
I learned how to...
1. Compile and test a Go target with libFuzzer instrumentation via go-fuzz for a reachable assertion defect.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10 11 12 13
func mayhemit(bytes []byte) int { content := string(bytes) if len(content) >= 3 { if string(content[0]) == "b" { if string(content[1]) == "u" { if string(content[2]) == "g" { panic("found a bug!") } } } } return 0 } -
Then, to fuzz the libFuzzer Go target, use the following
DockerfileandMayhemfileto build the Docker image containing the Go executable and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8
FROM fuzzers/go-fuzz:1.2.0 COPY mayhemit.go . RUN go-fuzz-build -libfuzzer -o mayhemit.a && \ clang -fsanitize=fuzzer mayhemit.a -o mayhemit.libfuzzer # Set to fuzz! ENTRYPOINT [] CMD ["/go/mayhemit.libfuzzer"]1 2 3 4 5
image: <DOCKERHUB_USERNAME>/go-go-fuzz:latest project: mayhem-examples target: go-go-fuzz cmds: - cmd: /go/mayhemit.libfuzzer1 2 3 4 5
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/go-go-fuzz:latest project: mayhem-examples target: go-go-fuzz cmds: - cmd: /go/mayhemit.libfuzzer
2. Compile and fuzz a Go target with libFuzzer instrumentation via go-fuzz for an index-out-of-bounds defect.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
func mayhemit(bytes []byte) int { content := string(bytes) if len(content) >= 3 && len(content) < 5 { if string(content[0]) == "b" { if string(content[1]) == "u" { if string(content[2]) == "g" { var x = content[10] fmt.Println(x) } } } } return 0 } -
Then, to fuzz the libFuzzer Go target, use the following
DockerfileandMayhemfileto build the Docker image containing the Go executable and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8
FROM fuzzers/go-fuzz:1.2.0 COPY mayhemit.go . RUN go-fuzz-build -libfuzzer -o mayhemit.a && \ clang -fsanitize=fuzzer mayhemit.a -o mayhemit.libfuzzer # Set to fuzz! ENTRYPOINT [] CMD ["/go/mayhemit.libfuzzer"]1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/go-go-fuzz-mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: go-go-fuzz-mayhemit-out-of-bounds cmds: - cmd: /go/mayhemit.libfuzzer libfuzzer: true1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/go-go-fuzz-mayhemit-out-of-bounds:latest duration: 90 project: mayhem-examples target: go-go-fuzz-mayhemit-out-of-bounds cmds: - cmd: /go/mayhemit.libfuzzer libfuzzer: true

