advanced
Base-Executable C/C++ Targets¶
Got an uninstrumented or base-executable C/C++ target? In this lesson, we'll walk you through how to test base-executable C/C++ targets in Mayhem.
Estimated Time: 15 minutes
By the end of this lesson, you will be able to:
- Compile and fuzz a base-executable C target with an improper input validation defect.
- Compile and fuzz a base-executable C++ target with an improper input validation defect.
Run through the lesson:
See prerequisites before beginning.
-
Download the c-base-executable.tgz, build the
c-base-executable
Docker image, and push it to the specified Docker Registry:docker build -t <DOCKERHUB_USERNAME>/c-base-executable . docker push <DOCKERHUB_USERNAME>/c-base-executable
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable . docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable
-
Execute a Mayhem run on the
c-base-executable
Docker image using either the Mayhem UI or Mayhem CLI with the following Mayhemfile:1 2 3 4 5 6
image: <DOCKERHUB_USERNAME>/c-base-executable:latest duration: 90 project: mayhem-examples target: c-base-executable cmds: - cmd: /mayhemit @@
1 2 3 4 5 6
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable:latest duration: 90 project: mayhem-examples target: c-base-executable cmds: - cmd: /mayhemit @@
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 base-executable C target! 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 base-executable C target, let's now walk through how to compile and test the c-base-executable
target that you just executed a Mayhem run for!
Compiling and Testing a Base-Executable C Target¶
File: c-base-executable.tgz
Download and extract the above c-base-executable.tgz
and take a look at the following bugged mayhemit.c
program.
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 |
|
Here we see that the header files stdio.h
and string.h
have been included in the program on lines 1-2 and that there are two functions of interest: main
and mayhemit
.
Info
C programs use the stdio.h
header file while C++ programs use the iostream
header file. If you were to take a look at other C++ programs, their source code would typically use the iostream
header file instead.
The main
function handles file input, and invokes the mayhemit
function if a file has been properly supplied to the program. The mayhemit
function then parses the input file and returns an improper input validation error if the input test case supplied to the program reads "bug". Therefore, for this target, Mayhem should be able to fuzz this program and provide a crashing test case of "bug" to reveal the improper input validation defect.
Before we can fuzz the program, however, we'll need to compile the program and then subsequently upload the target to Mayhem for ingestion. For this first step, we advise using a Docker container that couples the target application with its program dependencies and ensures Mayhem can successfully execute and fuzz the C target.
Taking a look at the associated Dockerfile
, we see the following operations:
1 2 3 4 5 6 7 8 9 10 |
|
- Line 1: The
debian:buster-slim
image is imported as the base image for the new Docker container. - Lines 2-4: The necessary dependencies are downloaded and installed within the new Docker container.
- Line 5: The
mayhemit.c
source code is copied over into the Docker container. - Line 6: The
gcc
C compiler is used to compile themayhemit.c
source code into themayhemit
executable. - Line 10: The
/mayhemit @@
command is set as the default executable for the resulting Docker container.
Next, we need to actually build and push the resulting Docker image to the Docker Hub registry using the docker build
and docker push
commands.
Next, we need to actually build and push the resulting Docker image to the Mayhem server using the docker build
and docker push
commands, where $MAYHEM_DOCKER_REGISTRY
represents an environment variable for the URL of the private Mayhem Docker registry.
Info
For example, we can set our $DOCKER_REGISTRY
environment variable to tutorial.forallsecure.com:5000
by executing the following:
export DOCKER_REGISTRY=tutorial.forallsecure.com:5000
Within the c-base-executable
directory, execute the following commands:
docker build -t <DOCKERHUB_USERNAME>/c-base-executable .
docker push <DOCKERHUB_USERNAME>/c-base-executable
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable
Upon successfully pushing the newly created Docker image to the public Docker Hub registry, create a new run via the Mayhem UI and select your uploaded <DOCKERHUB_USERNAME>/c-base-executable
Docker image. Click Next through the create new run flow and verify that the Mayhemfile looks similar to the following before starting the run:
Upon successfully pushing the newly created Docker image to the private Mayhem Docker registry, create a new run via the Mayhem UI and select your uploaded forallsecure/c-base-executable
Docker image. Click Next through the create new run flow and verify that the Mayhemfile looks similar to the following before starting the run:
1 2 3 4 5 6 |
|
1 2 3 4 5 6 |
|
You should now see that Mayhem was able to find the underlying improper input validation defect! Congratulations on compiling and testing your C target!
⚡ Real World Exercise: Compiling and Testing a Base-Executable C++ Target¶
Now that you're familiar with the steps for compiling and testing a base-executable C target, let's see if you can do the same for a base-executable C++ target!
Files: cpp-base-executable.tgz
Instructions:
- Download and extract the above
cpp-base-executable.tgz
file and use thedocker build
anddocker push
commands to build and push the resulting Docker image so that Mayhem can fuzz your<DOCKERHUB_USERNAME>/cpp-base-executable
target. - Then, fuzz your newly uploaded
<DOCKERHUB_USERNAME>/cpp-base-executable
Docker image using the Mayhem UI!
- Download and extract the above
cpp-base-executable.tgz
file and use thedocker build
anddocker push
commands to build and push the resulting Docker image so that Mayhem can fuzz yourforallsecure/cpp-base-executable
target. - Then, test your newly uploaded
forallsecure/cpp-base-executable
Docker image using the Mayhem UI!
🔍 Review It! Compiling and Testing a Base-Executable C++ Target¶
Solution
Okay let's take a look at how you did! First things first, let's inspect the source code for the mayhemit.cpp
program:
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 |
|
Here we see that aside from the C++ iostream
header file that has replaced the previous C stdio.h
header file, the cpp-base-executable
source code is nearly identical to the c-base-executable
source code.
Next, let's inspect the associated Dockerfile. Here we see the following operations:
1 2 3 4 5 6 7 8 9 10 |
|
- Line 1: The
debian:buster-slim
image is imported as the base image for the new Docker container. - Lines 2-4: The necessary dependencies are downloaded and installed within the new Docker container.
- Line 5: The
mayhemit.cpp
source code is copied over into the Docker container. - Line 6: The
g++
C++ compiler is used to compile themayhemit.cpp
source code into themayhemit
executable. - Line 10: The
/mayhemit @@
command is set as the default executable for the resulting Docker container.
Almost done! Next up, you needed to build and push the Docker image as we've already done before and run the containerized cpp-base-executable
target in Mayhem!
docker build -t <DOCKERHUB_USERNAME>/cpp-base-executable .
docker push <DOCKERHUB_USERNAME>/cpp-base-executable
docker build -t $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-base-executable .
docker push $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-base-executable
Your underlying Mayhemfile
for the run should have looked similar to the following:
1 2 3 4 5 6 |
|
1 2 3 4 5 6 |
|
And finally, you should have seen a run page similar to the following:
If you were able to get the cpp-base-executable
target tested, nice job! You're already building and testing C++ targets all on your own!
✏️ Summary and Recap¶
In this lesson, you learned how to compile and test base-executable C/C++ targets in Mayhem!
I learned how to...
1. Compile and test a base-executable C 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 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 base-executable 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 9 10
FROM debian:buster-slim as builder RUN apt-get update && \ apt-get install -y gcc make libc6-dbg && \ rm -rf /var/lib/apt/lists/* COPY mayhemit.c . RUN gcc -o mayhemit -Wno-div-by-zero -fno-stack-protector -zexecstack -no-pie mayhemit.c # Set to fuzz! ENTRYPOINT [] CMD /mayhemit @@
1 2 3 4 5 6
image: <DOCKERHUB_USERNAME>/c-base-executable:latest duration: 90 project: mayhem-examples target: c-base-executable cmds: - cmd: /mayhemit @@
1 2 3 4 5 6
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/c-base-executable:latest duration: 90 project: mayhem-examples target: c-base-executable cmds: - cmd: /mayhemit @@
2. Compile and fuzz a base-executable C++ 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 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++ base-executable 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 9 10
FROM debian:buster-slim as builder RUN apt-get update && \ apt-get install -y gcc g++ make libc6-dbg && \ rm -rf /var/lib/apt/lists/* COPY mayhemit.cpp . RUN g++ -Wno-div-by-zero -fno-stack-protector -zexecstack -no-pie -o mayhemit mayhemit.cpp # Set to fuzz! ENTRYPOINT [] CMD /mayhemit @@
1 2 3 4 5 6
image: <DOCKERHUB_USERNAME>/cpp-base-executable:latest duration: 90 project: mayhem-examples target: cpp-base-executable cmds: - cmd: /mayhemit @@
1 2 3 4 5 6
image: $MAYHEM_DOCKER_REGISTRY/forallsecure/cpp-base-executable:latest duration: 90 project: mayhem-examples target: cpp-base-executable cmds: - cmd: /mayhemit @@