Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: support the real coverage in fuzzer #59

Merged
merged 37 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
95ce04f
Executing no docker wafl
Jacarte Aug 21, 2020
d07abf8
Building locally script
Jacarte Aug 21, 2020
b7c4623
Adding timeout and killng the server at the end
Jacarte Aug 21, 2020
4269c9f
WIP
Jacarte Aug 25, 2020
2be9760
RM swam as submodule
Jacarte Aug 25, 2020
b34001e
Downloading and building swam in wafl
Jacarte Aug 25, 2020
7e15592
Infering init values from seed all equal
Jacarte Aug 25, 2020
4e3ee3e
Merge branch 'wasm-fuzzer' into feature/handle-crashed-server
Jacarte Aug 25, 2020
b52053c
Merge pull request #60 from KTH/feature/handle-crashed-server
Jacarte Aug 25, 2020
e333f3d
HOTFIX: LOG function not found
Jacarte Aug 25, 2020
b176502
Removed everything related to docker-compose
olapiv Aug 27, 2020
3998e1a
Put SWAM_SOCKET_HOST into ./env
olapiv Aug 27, 2020
167bf64
Being sure about CURRENT_DIR in build.sh && included run_client.cpp
olapiv Aug 27, 2020
e513bdd
Renamed DOCKER_ envs && put wafl.sh as entrypoint
olapiv Aug 27, 2020
100055f
Placed all directory preparations from wafl to prepare_env && placed …
olapiv Aug 27, 2020
90bbbca
Added arguments to docker run; Adjusted README; Re-did .env for Docke…
olapiv Aug 27, 2020
cafea9e
Using default temp DIR when running locally; Also parsing arguments w…
olapiv Aug 27, 2020
2f5740a
Uncommented multi-processing again
olapiv Aug 27, 2020
2a7fd0f
Moved all cpp_out into wafl-temp folder
olapiv Aug 27, 2020
87be841
Sourcing prepare_env.sh
olapiv Aug 27, 2020
2d1c564
Fixed supervisord path in Dockerfile
olapiv Aug 28, 2020
653f195
Changed SWAM_CMD
olapiv Aug 28, 2020
b4e3860
Adjusted references to files
olapiv Aug 28, 2020
d55f941
SWAM in master branch
Jacarte Aug 28, 2020
bbcf302
Fixed Code references in build.sh
olapiv Aug 28, 2020
b872bf5
Using pwd for mounting Docker volumes
olapiv Aug 28, 2020
743ccb9
Merge branch 'wasm-fuzzer' of https://github.com/KTH/slumps into wasm…
Jacarte Aug 28, 2020
5a2238e
HOTFIX: build script looking for server-wasm swam
Jacarte Aug 28, 2020
1c066ca
Merge branch 'feature/handle-crashed-server' into wasm-fuzzer
olapiv Aug 28, 2020
930e4bd
Merge branch 'wasm-fuzzer' of https://github.com/KTH/slumps into wasm…
olapiv Aug 28, 2020
982f9ff
FIX
Jacarte Aug 28, 2020
b816879
FIX: Fixing mill-server-entrypoint script with logs
Jacarte Aug 28, 2020
321b2f9
Changing supervisord entrypoin script location
Jacarte Aug 28, 2020
5891f92
Updating Dockerfile for wafl
Jacarte Aug 28, 2020
b9b1a4d
Adjusted entrypoint_mill_server.sh reference in Dockerfile
olapiv Aug 28, 2020
6ccd3bc
Adjusted multi-processing.sh with wafl-temp dir
olapiv Aug 28, 2020
08dc80b
Merge branch 'master' into wasm-fuzzer
olapiv Aug 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ utils/reports
wasm-fuzzer/fuzzing-client-afl/afl_out
wasm-fuzzer/fuzzing-client-afl/cpp_out
wasm-fuzzer/logs/*

*.log
*.log.txt
6 changes: 1 addition & 5 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,4 @@
[submodule "llvm"]
path = llvm
url = https://github.com/Jacarte/llvm-project
branch = master
[submodule "wasm-fuzzer/fuzzing-server-swam"]
path = wasm-fuzzer/fuzzing-server-swam
url = https://github.com/KTH/swam
branch = feature/swam-server
branch = master
25 changes: 2 additions & 23 deletions wasm-fuzzer/.env
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
# Whether we are using AFL with Swam or just using dummy data
DUMMY_TESTING_AFL=False

# (Not being used yet..) Error, Warn, Info, Debug
LOG_LEVEL=Error

# Path to the parent directory of our local .wasm/.wat executable
LOCAL_WASM=/tmp/fuzzer-wat_files

# Name of our local .wasm/.wat executable
WASM_EXECUTABLE=fibo.wat
# Enum: ERROR, WARNING, INFO, DEBUG
LOG_LEVEL=INFO

# Path on our local machine for us to read AFL's output
LOCAL_AFL_OUTPUT=/tmp/afl_out

# Path on our local machine for us to read our own logs
LOCAL_LOGS=/tmp/fuzzer/fuzzerlogs

# Path on our local machine for us to read SWAM's output (if any)
# SWAM_OUTPUT_LOCAL=/tmp/swam-out

# Function to be executed in .wasm/.wat ("_start" is default)
TARGET_FUNCTION=clever

# Parameter types for target function. Comma-separated list of types Int32, Int64, Float32, Float64.
WASM_ARG_TYPES_LIST=Int64

# Sample input for target function. Comma-separated list of numbers.
WASM_ARG_LIST=14

# Executable has wasi format
WASI=False

##### No need to change: #####
SWAM_SOCKET_PORT=9999

Expand Down
4 changes: 4 additions & 0 deletions wasm-fuzzer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
aflpp
wafl
out*
fuzzing-server-swam
42 changes: 42 additions & 0 deletions wasm-fuzzer/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

echo "Cloning swam"


if [ ! -d fuzzing-server-swam ]; then
git clone --single-branch --branch feature/swam-server https://github.com/KTH/swam.git fuzzing-server-swam
fi

echo "Building SWAM..."

cd fuzzing-server-swam
git pull
./millw cli.assembly
export SWAM_JAR=$(pwd)/fuzzing-server-swam/out/cli/assembly/dest/out.jar
echo $SWAM_JAR
cd ..


# Download afl plus plus
if [ ! -d aflpp ]; then
echo "Downloading aflplusplus..."
git clone https://github.com/AFLplusplus/AFLplusplus.git aflpp

echo "Building aflplusplus..."
cd aflpp
make distrib
sudo make install
cd ..
fi


echo "Building the wafl interface..."

mkdir -p wafl

g++ -o wafl/prepare_wasm_input.out ./fuzzing-client-afl/prepare_wasm_input.cpp ./fuzzing-client-afl/utils.cpp
g++ -o wafl/getFileSize.out ./fuzzing-client-afl/getFileSize.cpp ./fuzzing-client-afl/utils.cpp
g++ -o wafl/wait_for_server.out ./fuzzing-client-afl/wait_for_server.cpp ./fuzzing-client-afl/utils.cpp ./fuzzing-client-afl/socket_client.cpp
g++ -o wafl/interface.out ./fuzzing-client-afl/interface.cpp ./fuzzing-client-afl/socket_client.cpp ./fuzzing-client-afl/utils.cpp


echo "DONE !"
10 changes: 8 additions & 2 deletions wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ if [ $? != 0 ]; then
exit 1
fi

if [[ $LOCAL_AFL != "True" ]]; then
AFL='afl-fuzz'
fi

# AFL Docs:
# afl-fuzz starts by performing an array of deterministic fuzzing steps,
# which can take several days, but tend to produce neat test cases.
# If you want quick & dirty results right away - akin to zzuf and other
# traditional fuzzers - add the -d option to the command line.

echo "afl-fuzz -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT $RANK -d -- ${DOCKER_INTERFACE_SRC}/interface.out @@ $REQUIRED_BYTES"
exec afl-fuzz -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT $RANK -d -- "${DOCKER_INTERFACE_SRC}/interface.out" @@ $REQUIRED_BYTES

echo "$AFL -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT $RANK -d -- ${DOCKER_INTERFACE_SRC}/interface.out @@ $REQUIRED_BYTES"
$AFL -i "$DOCKER_AFL_INPUT" -o $DOCKER_AFL_OUTPUT $RANK -t 12000 -d -- "${DOCKER_INTERFACE_SRC}/interface.out" @@ $REQUIRED_BYTES
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "exec" is actually quite important for it to work properly with supervisord in Docker. You can't "supervise" detached processes. If I recall correctly, the script will just start again if the main process exits.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This timeout should not be in master imo. According to AFL it really screws the performance. The timeout is a multiple of the time taken of the first test cases anyways, so we shouldn't worry about it.


98 changes: 69 additions & 29 deletions wasm-fuzzer/fuzzing-client-afl/interface.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
#include "interface.h"
#include <errno.h>

#define AFL_SHM_SIZE 65536

void LOG(std::string some_string)
{
std::string DOCKER_LOGS = parseEnvVariables((char *)"DOCKER_LOGS");
log(DOCKER_LOGS + "/interface.log", some_string);
}

std::vector<std::string> readFileToVector(const std::string &filename)
{
std::ifstream source;
Expand All @@ -26,24 +21,24 @@ void log_file(char *filename)
std::vector<std::string> vector = readFileToVector(filename);
for (int i = 0; i < vector.size(); ++i)
{
LOG(vector[i]);
log_default(vector[i], DEBUG);
}
}

uint8_t *getShm()
{
std::string shmStr = parseEnvVariables((char *)"__AFL_SHM_ID");
LOG("shmStr: " + shmStr);
log_default("shmStr: " + shmStr, INFO);

key_t key = std::stoi(shmStr);

uint8_t *trace_bits = (uint8_t *)shmat(key, 0, 0);
if (trace_bits == (uint8_t *)-1)
{
LOG("Failed to access shared memory");
log_default("Failed to access shared memory", ERROR);
exit(1);
}
LOG("Shared memory attached.");
log_default("Shared memory attached.", INFO);
return trace_bits;
}

Expand All @@ -69,28 +64,59 @@ void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits)
void main_fuzz(
char *fuzzed_input_path,
uint8_t *trace_bits,
int requiredBytes)
int requiredBytes,
pid_t forkServerPID)
{

//LOG("Entering");
std::string DOCKER_LOGS = parseEnvVariables((char *)"DOCKER_LOGS");
std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL");

if (DUMMY_TESTING_AFL == "True")
{
fillTraceDummyData(trace_bits);
exit(0);
}

// TODO: Replace sendBuffer by

char sendBuffer[requiredBytes];
readBinaryToBuffer(sendBuffer, sizeof(sendBuffer), (std::string)fuzzed_input_path);
// std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer


char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code
///logBuffer(DOCKER_LOGS + "/interface.log", AFL_SHM_SIZE + 1, readBuffer);

std::string SWAM_SOCKET_HOST = parseEnvVariables((char *)"SWAM_SOCKET_HOST");
std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT");

runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT));
while (true)
{
try
{
runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT));
break;
}
catch (...)
{
try
{

// TODO: AFL explicitly advises not to have it's timeout too high. Therefore think about:
// 1) Do this step in the forkserver before every fork
// 2) Kill AFL directly and let supervisord restart it. Doesn't work when running locally though.
// However, SWAM won't be restarted anyways locally, so might as well kill AFL entirely as well.
// 3) !!! Just do 1 retry without wait_for_server/timeout. If still doesn't work, kill AFL.

// Be sure that AFL's timeout is larger than here, otherwise there's no point in this:
wait_for_server(&SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT), 1000, 10000);
}
catch (...)
{
kill(forkServerPID, 6);
exit(1);
}
}
}

//LOG("Passing data to afl...");
pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits);

// Read exit code from readBuffer and exit with same code
Expand All @@ -109,14 +135,28 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
hard-coded by AFL and thereby accessible here.
*/

int status = 0;
// Just for logging:
pid_t aflPID = getppid();
char aflPIDChar[6];
sprintf(aflPIDChar, "%d", aflPID);
std::string aflPIDString = aflPIDChar;
log_default("AFL's PID: " + aflPIDString, INFO);

pid_t forkServerPID = getpid();
char forkServerPIDChar[6];
sprintf(forkServerPIDChar, "%d", forkServerPID);
std::string forkServerPIDString = forkServerPIDChar;
log_default("Forkserver's PID: " + forkServerPIDString, INFO);

int status = 0;
// Starting the 'Fork server handshake'

// Phone home and tell AFL that we're OK
if (write(199, &status, 4) != 4)

int w = write(199, &status, 4);
if ( w != 4)
{
LOG("Write failed");
log_default("Write failed", ERROR);
close(199);
exit(1);
}
Expand All @@ -125,11 +165,12 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// and is creating forks of itself is called the "fork server".
while (true)
{

// Wait for AFL by reading from the pipe.
// This will block until AFL sends us something. Abort if read fails.
if (read(198, &status, 4) != 4)
{
LOG("Read failed");
log_default("Read failed", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -143,7 +184,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
int pid = fork();
if (pid < 0)
{
LOG("Fork failed");
log_default("Fork failed", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -153,7 +194,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// This is the child process
close(198);
close(199);
main_fuzz(fuzzed_input_path, trace_bits, requiredBytes);
main_fuzz(fuzzed_input_path, trace_bits, requiredBytes, forkServerPID);
exit(0);
}

Expand All @@ -171,7 +212,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// Waiting for child
if (waitpid(pid, &status, 0) <= 0) // Technically only fails at -1; 0 means still running
{
LOG("waitpid() failed.");
log_default("waitpid() failed.", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -186,14 +227,14 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
else if (WIFSIGNALED(status)) // Process was stopped/terminated by signal;
{
// TODO: Find out why this branch gets triggered
LOG("Signal status: " + std::to_string(status));
LOG("WTERMSIG(status): " + std::to_string(WTERMSIG(status)));
LOG("WSTOPSIG(status): " + std::to_string(WSTOPSIG(status)));
log_default("Signal status: " + std::to_string(status), ERROR);
log_default("WTERMSIG(status): " + std::to_string(WTERMSIG(status)), ERROR);
log_default("WSTOPSIG(status): " + std::to_string(WSTOPSIG(status)), ERROR);
write(199, &status, 4);
}
else
{
LOG("Weird status: " + std::to_string(status));
log_default("Weird status: " + std::to_string(status), ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -205,13 +246,12 @@ void log_args(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i)
{
LOG("argv[" + std::to_string(i) + "]: " + std::string(argv[i]));
log_default("argv[" + std::to_string(i) + "]: " + std::string(argv[i]), INFO);
}
}

int main(int argc, char *argv[])
{
// TODO: Remove everything related to requiredBytes; not necessary anymore
log_args(argc, argv);

char *fuzzed_input_path = argv[1];
Expand Down
1 change: 1 addition & 0 deletions wasm-fuzzer/fuzzing-client-afl/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
#include <sys/wait.h>
#include <stdlib.h>
#include <algorithm>
#include <signal.h>

#endif
1 change: 0 additions & 1 deletion wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ void printResult(std::string filepath)
printf("Total bytes written: %i\n", fileSize);
char buffer[fileSize];
readBinaryToBuffer(buffer, fileSize, filepath);
// std::reverse(buffer, &buffer[sizeof(buffer)]);

printBuffer(sizeof(buffer), buffer);
printf("-----------------\n");
Expand Down
5 changes: 2 additions & 3 deletions wasm-fuzzer/fuzzing-client-afl/run_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
// data sent by the client properly
int main(int argc, char *argv[])
{
std::string inputFile = (std::string) argv[1];
std::string inputFile = (std::string)argv[1];

char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code

int fileSize = (int)getFileSize(inputFile);
char sendBuffer[fileSize];
readBinaryToBuffer(sendBuffer, fileSize, inputFile);
// std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of sendBuffer

runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, "localhost", 9999);
runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, (char *)"localhost", 9999);
exit(0);
};
2 changes: 2 additions & 0 deletions wasm-fuzzer/fuzzing-client-afl/run_test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

# TODO: Since now all logging is to a file (using env var DOCKER_LOGS), this script cannot be run locally anymore. Fix this.

# For testing the integration of prepare_wasm_input.cpp and socket_client.cpp.

# Run server in Swam first (example with fibo.wat):
Expand Down
Loading