advanced
C/C++ Targets Instrumented with AFL/AFL++¶
Need to compile a C/C++ target with either Google's AFL instrumentation or the more enhanced AFL++ instrumentation? In this lesson, we'll walk you through how to compile C/C++ targets with AFL/AFL++ instrumentation and test the resulting binaries in Mayhem!
Estimated Time: 15 minutes
By the end of this lesson, you will be able to:
- Compile and fuzz a C target with AFL instrumentation.
- Compile and fuzz a C target with AFL++ instrumentation.
- Compile and fuzz a C++ target with AFL instrumentation.
Run through the lesson:
See prerequisites before beginning.
-
Download the c-afl-gcc.tgz, build the
c-afl-gcc
Docker image, and push it to the specified Docker registry:docker build -t <DOCKERHUB_USERNAME>/c-afl-gcc . docker push <DOCKERHUB_USERNAME>/c-afl-gcc
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc
-
Execute a Mayhem run on the
c-afl-gcc
Docker image using either the Mayhem UI or Mayhem CLI with the following Mayhemfile:1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-afl-gcc:latest duration: 90 project: mayhem-examples target: c-afl-gcc cmds: - cmd: /mayhemit @@ afl: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc:latest duration: 90 project: mayhem-examples target: c-afl-gcc cmds: - cmd: /mayhemit @@ afl: 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 AFL 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 test a C target instrumented with AFL, let's now walk through how to compile and test the c-afl-gcc
target that you just executed a Mayhem run for!
Compiling and Testing a C Target with AFL Instrumentation¶
File: c-afl-gcc.tgz
Download and extract the above c-afl-gcc.tgz
and take a look at the following source code for 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 27 28 29 30 31 32 33 34 35 36 |
|
Note
If you're already familiar with the c-uninstrumented
target, then you'll notice that the source code is the exact same! So what makes a C-AFL target different? The difference lies in how the program is compiled (at least for AFL).
Taking a look at the associated Dockerfile
, we see the following operations:
1 2 3 4 5 6 7 8 |
|
- Line 1: The
fuzzers/afl:2.52
image is imported as the base image to the new Docker container. - Line 2: The
mayhemit.c
source code is copied over into the Docker container. - Line 3: The
afl-gcc
C compiler compiles themayhemit.c
and adds AFL instrumentation to become themayhemit
executable. - Line 8: The
/mayhemit @@
command is set as the default executable for the resulting Docker container.
Note
The entrypoint code on line 7 is included to allow AFL to fuzz the mayhemit
executable locally within the Docker container when the container is run (for debugging purposes). After building the Docker container, try the following command to see it in action docker run -it <container>
. See Docker Entrypoint Support in Mayhem for more information on how to run entrypoint scripts in Mayhem specifically.
Now we just need to build and push the Docker image to a Docker registry as before:
docker build -t <DOCKERHUB_USERNAME>/c-afl-gcc .
docker push <DOCKERHUB_USERNAME>/c-afl-gcc
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc
And finally, search for the <DOCKERHUB_USERNAME>/c-afl-gcc
Docker image and follow the create new run flow in the Mayhem UI to fuzz the new Docker image in Mayhem!
And finally, search for the forallsecure/c-afl-gcc
Docker image and follow the create new run flow in the Mayhem UI to fuzz the new Docker image in Mayhem!
Make sure the underlying Mayhemfile
for the run looks similar to the following:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
Nice job! You just compiled and fuzzed a C target with AFL instrumentation!
Compiling and Testing a C Target with AFL++ Instrumentation¶
File: c-aflpp-gcc.tgz
Let's now compile our previous mayhemit.c
source code with AFL++ instrumentation instead. Since the source code is just about the same, we'll just need to use the afl-g++-fast
compiler instead.
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 27 28 29 30 31 32 33 34 35 36 |
|
Navigate to the c-aflpp-gcc
folder and take a look at the associated Dockerfile
for the c-aflpp-gcc
target.
You'll notice that the process for building the c-aflpp-gcc
target is much of the same as building the c-afl-gcc
target, with the exception of line 1 importing the fuzzers/aflplusplus:3.12c
base image containing the AFL++ dependencies, and line 3 compiling the mayhemit.c
source code with the afl-gcc-fast
compiler instead.
1 2 3 4 5 6 7 8 |
|
Next, we'll need to just build and push the resulting mayhemit/c-aflpp-gcc
Docker image to the Mayhem Docker registry.
Next, we'll need to just build and push the resulting mayhemit/c-aflpp-gcc
Docker image to the Mayhem Docker registry.
docker build -t <DOCKERHUB_USERNAME>/c-aflpp-gcc .
docker push <DOCKERHUB_USERNAME>/c-aflpp-gcc
docker build -t $DOCKER_REGISTRY/forallsecure/c-aflpp-gcc .
docker push $DOCKER_REGISTRY/forallsecure/c-aflpp-gcc
Then, select the <DOCKERHUB_USERNAME>/c-aflpp-gcc
Docker image as the source for a new Mayhem run and verify that the underlying Mayhemfile
looks similar to the following:
Then, select the forallsecure/c-aflpp-gcc
Docker image as the source for a new Mayhem run and verify that the underlying Mayhemfile
looks similar to the following:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
And lastly, fuzz the new <DOCKERHUB_USERNAME>/c-aflpp-gcc
Docker image in the Mayhem UI!
And lastly, fuzz the new forallsecure/c-aflpp-gcc
Docker image in the Mayhem UI!
⚡ Real World Exercise: Compiling and Testing a C++ Target with AFL Instrumentation¶
File: cpp-afl-gcc.tgz
Now that you're familiar with the steps for compiling and testing a C target with both AFL and AFL++ instrumentation, let's see if you can do the same for a C++ target!
Instructions:
- Download the above
cpp-afl-gcc.tgz
and extract thecpp-afl-gcc
folder. - Navigate to the
cpp-afl-gcc
folder and build and push the<DOCKERHUB_USERNAME>/cpp-afl-gcc
target to Docker Hub. -
Lastly, fuzz the newly uploaded
<DOCKERHUB_USERNAME>/cpp-afl-gc
Docker image using the Mayhem UI. -
Download the above
cpp-afl-gcc.tgz
and extract thecpp-afl-gcc
folder. - Navigate to the
cpp-afl-gcc
folder and build and push theforallsecure/cpp-afl-gcc
target to Mayhem to be fuzzed. - Lastly, test the newly uploaded
forallsecure/cpp-afl-gc
Docker image using the Mayhem UI.
🔍 Review It! Compiling and Testing a C++ Target with AFL Instrumentation¶
Solution
Let's see how you did! First things first, let's take a look at the mayhemit.cpp
source code for the cpp-afl-gcc
target:
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 27 28 29 30 31 32 33 34 35 36 |
|
The source code looks just about the same as our previous c-afl-gcc
and c-aflpp-gcc
targets, with the exception of the C++ iostream
header file.
Looking at the associated Dockerfile
, we can see that to compile the mayhemit.cpp
source file with AFL instrumentation, you needed to use the afl-g++
compiler.
1 2 3 4 5 6 7 8 |
|
Then, just build and push the Docker image to the public Docker Hub registry:
Then, just build and push the Docker image to the Mayhem Docker Registry:
docker build -t <DOCKERHUB_USERNAME>/cpp-afl-gcc .
docker push <DOCKERHUB_USERNAME>/cpp-afl-gcc
docker build -t $MAYHEM_DOCKER_REGISTRY/mayhemit/cpp-afl-gcc .
docker push $MAYHEM_DOCKER_REGISTRY/mayhemit/cpp-afl-gcc
Once pushed to Docker Hub, you simply needed to use the Mayhem UI to create a new run and choose your <DOCKERHUB_USERNAME>/cpp-afl-gcc
Docker image as the source, with an underlying Mayhemfile
looking similar to the following:
Once pushed to the Mayhem Docker Registry, you simply needed to use the Mayhem UI to create a new run and choose the forallsecure/cpp-afl-gcc
Docker image as the source, with an underlying Mayhemfile
looking similar to the following:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
Finally, after initiating the Mayhem run, you should have seen a Run page similar to the following! Great job!
✏️ Summary and Recap¶
In this lesson, we walked you through how to compile C/C++ targets with AFL/AFL++ instrumentation and fuzz them in Mayhem!
I learned how to...
1. Compile and test a C target with AFL instrumentation.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10 11
int mayhemit(char *buf) { if(strlen(buf) >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { printf("You've got it!"); abort(); // Defect: SIGABRT. } return 0; }
-
Then, to fuzz the C AFL target, use the following
Dockerfile
andMayhemfile
to build the Docker image containing the C program and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8
FROM fuzzers/afl:2.52 COPY mayhemit.c . RUN afl-gcc mayhemit.c -o /mayhemit RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["afl-fuzz", "-i", "/testsuite", "-o", "/out"] CMD ["/mayhemit", "@@"]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-afl-gcc:latest duration: 90 project: mayhem-examples target: c-afl-gcc cmds: - cmd: /mayhemit @@ afl: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-afl-gcc:latest duration: 90 project: mayhem-examples target: c-afl-gcc cmds: - cmd: /mayhemit @@ afl: true
2. Compile and fuzz a C target with AFL++ instrumentation.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10 11
int mayhemit(char *buf) { if(strlen(buf) >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { printf("You've got it!"); abort(); // Defect: SIGABRT. } return 0; }
-
Then, to fuzz the C AFL++ target, use the following
Dockerfile
andMayhemfile
to build the Docker image containing the C program and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8
FROM fuzzers/aflplusplus:3.12c COPY mayhemit.c . RUN afl-gcc-fast mayhemit.c -o /mayhemit RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["afl-fuzz", "-i", "/testsuite", "-o", "/out"] CMD ["/mayhemit", "@@"]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/c-aflpp-gcc:latest duration: 90 project: mayhem-examples target: c-aflpp-gcc cmds: - cmd: /AFLplusplus/mayhemit @@ afl: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-aflpp-gcc:latest duration: 90 project: mayhem-examples target: c-aflpp-gcc cmds: - cmd: /AFLplusplus/mayhemit @@ afl: true
3. Compile and fuzz a C++ target with AFL instrumentation.
-
The source code should contain the following defect:
1 2 3 4 5 6 7 8 9 10 11
int mayhemit(char *buf) { if(strlen(buf) >= 3) if(buf[0] == 'b') if(buf[1] == 'u') if(buf[2] == 'g') { printf("You've got it!"); abort(); // Defect: SIGABRT. } return 0; }
-
Then, to fuzz the C++ AFL target, use the following
Dockerfile
andMayhemfile
to build the Docker image containing the C++ program and fuzz it in Mayhem, respectively:1 2 3 4 5 6 7 8
FROM fuzzers/afl:2.52 COPY mayhemit.cpp . RUN afl-g++ mayhemit.cpp -o /mayhemit RUN mkdir /testsuite && echo seed > /testsuite/seed # Set to fuzz! ENTRYPOINT ["afl-fuzz", "-i", "/testsuite", "-o", "/out"] CMD ["/mayhemit", "@@"]
1 2 3 4 5 6 7
image: <DOCKERHUB_USERNAME>/cpp-afl-gcc:latest duration: 90 project: mayhem-examples target: cpp-afl-gcc cmds: - cmd: /mayhemit @@ afl: true
1 2 3 4 5 6 7
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-afl-gcc:latest duration: 90 project: mayhem-examples target: cpp-afl-gcc cmds: - cmd: /mayhemit @@ afl: true