From ca734fd906b59a690206b42ae1536319f49c48fb Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 18 Jun 2020 15:30:29 +0200 Subject: [PATCH 01/74] Created basics of AFL-SWAM interface --- README.md | 43 +++++++++++++++ in/first_test.txt | 1 + interface.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 README.md create mode 100644 in/first_test.txt create mode 100644 interface.cpp diff --git a/README.md b/README.md new file mode 100644 index 00000000..a654c77c --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# AFL Plugin for SWAM + +## Disclaimer + +This is still in a prototyping stage. There are still many assumptions made on how AFL (and C++ and Scala and shared memory) works. + +## Introduction + +This plugin aims to act as an interface between SWAM and AFLplusplus. Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide spin-off that applies AFL to WASM binaries. + +The interface.cpp file fakes the behaviour of the instrumented binary and instead forwards the fuzzed inputs given by AFL to the SWAM engine, which in turn forwards it to the WASM binary. + +Therefore, instead of using the C++-compiler provided by AFLplusplus (afl-clang-fast++), we use the "standard" g++ compiler and instead mimic the instrumentation behaviour in the interface. + +AFL communicates with the target binary with a shared memory by default. Since Scala does not seem suitable for such low-level operations, we have instead created a low-level wrapper for SWAM, interface.cpp. Whilst the code coverage plugin for SWAM writes it's results to a fixed file, our interface wrapper reads from this file and then feeds the content into the shared memory used by AFL. + +## Run + +1. Run AFL with Docker + +```bash +docker pull aflplusplus/aflplusplus +docker run -ti -v /fuzzer:/src aflplusplus/aflplusplus +``` + +1. Compile + +```bash +cd /src +g++ interface.cpp +``` + +1. Run AFL + +```bash +afl-fuzz -i /src/in -o out -m none -d -- /src/a.out @@ +``` + +1. View /src/interface.log for custom logs and /src/out/ for AFL output + +## Credits + +- Initial idea and implementation (for Java): [Kelinci](https://github.com/isstac/kelinci) diff --git a/in/first_test.txt b/in/first_test.txt new file mode 100644 index 00000000..be83f48d --- /dev/null +++ b/in/first_test.txt @@ -0,0 +1 @@ +one two three \ No newline at end of file diff --git a/interface.cpp b/interface.cpp new file mode 100644 index 00000000..34b868ac --- /dev/null +++ b/interface.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SHM_ENV_VAR "__AFL_SHM_ID" +#define LOGFILE "interface.log" + +int LOG(std::string some_string) +{ + std::ofstream logfile; + logfile.open(LOGFILE, std::ios_base::app); + logfile << some_string + "\n"; + logfile.close(); + return 0; +} + +std::vector readFileToVector(const std::string &filename) +{ + std::ifstream source; + source.open(filename); + std::vector lines; + std::string line; + while (std::getline(source, line)) + { + lines.push_back(line); + } + return lines; +} + +uint8_t *get_shm() +{ + // putenv((char *)"SHM_ENV_VAR=5"); + + char *shm_name = std::getenv(SHM_ENV_VAR); + if (!shm_name) + { + LOG("SHM_ENV_VAR not found!"); + exit(1); + } + + LOG("shm_name: " + std::string(shm_name)); + key_t key = atoi(shm_name); + uint8_t *trace_bits = (uint8_t *)shmat(key, 0, 0); + if (trace_bits == (uint8_t *)-1) + { + LOG("Failed to access shared memory"); + exit(1); + } + LOG("Shared memory attached. Value at loc 3 = " + trace_bits[3]); + return trace_bits; +} + +void fork_server() +{ + // The Fork server: + // https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html + + int status = 0; + + LOG("Phone home and tell the parent that we're OK."); + if (write(199, &status, 4) != 4) + { + LOG("Write failed"); + exit(1); + } + + // This will block until the parent sends us something. Abort if read fails. + LOG("Wait for parent by reading from the pipe."); + if (read(198, &status, 4) != 4) + { + LOG("Read failed"); + exit(1); + } + LOG("Status: " + std::to_string(status)); + + // Programm runs concurrently in two forks from here + // Returns 0 if in the child process and returns the + // child's pid if in the parent process. + int pid = fork(); + if (pid < 0) + { + LOG("Fork failed\n"); + exit(1); + } + else if (pid == 0) + { + LOG("This is the child process."); + // TODO: Do something proper here... + return; + } + + LOG("Writing child pid to parent: " + std::to_string(pid)); + write(199, &pid, 4); + + LOG("Waiting for child..."); + if (waitpid(pid, &status, 0) <= 0) + { + LOG("Child fork crashed"); + exit(1); + } + + LOG("Status: " + std::to_string(status)); + write(199, &status, 4); + + close(198); + close(199); +} + +int main(int argc, char *argv[]) +{ + uint8_t *trace_bits = get_shm(); + + // Mark a location to show we are instrumented + trace_bits[0]++; + + std::vector vector = readFileToVector(argv[1]); + for (int i = 0; i < vector.size(); ++i) + { + LOG(vector[i]); + } + + for (int i = 0; i < argc; ++i) + { + LOG("argv[" + std::to_string(i) + "]: " + std::string(argv[i])); + } + + return 0; +} From 70251b76b045538d9837cd1c7fc77915d8c5399f Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 18 Jun 2020 20:11:35 +0200 Subject: [PATCH 02/74] Working interface.cpp with dummy coverage data --- README.md | 2 +- interface.cpp | 183 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 137 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index a654c77c..3c9b0ccb 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This is still in a prototyping stage. There are still many assumptions made on h ## Introduction -This plugin aims to act as an interface between SWAM and AFLplusplus. Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide spin-off that applies AFL to WASM binaries. +This plugin aims to act as an interface between SWAM and AFLplusplus. Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide a spin-off that applies AFL to WASM binaries. The interface.cpp file fakes the behaviour of the instrumented binary and instead forwards the fuzzed inputs given by AFL to the SWAM engine, which in turn forwards it to the WASM binary. diff --git a/interface.cpp b/interface.cpp index 34b868ac..01d79b08 100644 --- a/interface.cpp +++ b/interface.cpp @@ -5,7 +5,10 @@ #include #include #include +#include +#include +#define AFL_SHM_SIZE 65536 #define SHM_ENV_VAR "__AFL_SHM_ID" #define LOGFILE "interface.log" @@ -54,79 +57,165 @@ uint8_t *get_shm() return trace_bits; } -void fork_server() +void log_file(char *filename) { - // The Fork server: - // https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html - - int status = 0; - - LOG("Phone home and tell the parent that we're OK."); - if (write(199, &status, 4) != 4) + std::vector vector = readFileToVector(filename); + for (int i = 0; i < vector.size(); ++i) { - LOG("Write failed"); - exit(1); + LOG(vector[i]); } +} - // This will block until the parent sends us something. Abort if read fails. - LOG("Wait for parent by reading from the pipe."); - if (read(198, &status, 4) != 4) - { - LOG("Read failed"); - exit(1); - } - LOG("Status: " + std::to_string(status)); +void execute_swam(char *fuzzed_input) +{ + // TODO: Do something proper here... +} + +void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) +{ - // Programm runs concurrently in two forks from here - // Returns 0 if in the child process and returns the - // child's pid if in the parent process. - int pid = fork(); - if (pid < 0) + // Dummy: + srand(time(NULL)); + for (int i = 0; i < 10; i++) { - LOG("Fork failed\n"); - exit(1); + int random_branch = rand() % AFL_SHM_SIZE; + trace_bits[random_branch] += 1; } - else if (pid == 0) + + // TODO: Read an actual file with branch coverage + + /* + for (int i = 0; i < AFL_SHM_SIZE; i++) { - LOG("This is the child process."); - // TODO: Do something proper here... - return; + if (execution_data[i] != 0) + { + LOG(i + " -> " + execution_data[i]); + trace_bits[i] += execution_data[i]; + } } + */ +} - LOG("Writing child pid to parent: " + std::to_string(pid)); - write(199, &pid, 4); +void main_fuzz(char *fuzzed_input, uint8_t *trace_bits) +{ + log_file(fuzzed_input); + + execute_swam(fuzzed_input); + + // Read "shared memory" over TCP + uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); - LOG("Waiting for child..."); - if (waitpid(pid, &status, 0) <= 0) + // TODO: Read path coverage from file + + pass_data_to_afl(execution_data, trace_bits); + + free(execution_data); +} + +void fork_server(char *fuzzed_input, uint8_t *trace_bits) +{ + // The Fork server (Prototype of this code in Assembly): + // https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html + + /* + ASSUMPTION: + Numbered file descriptos are relative and accessible to a process and + all it's child processes. In this case, 198 and 199 seem to be + hard-coded by AFL and thereby accessible here. + */ + + int status = 0; + + LOG("Starting the 'Fork server handshake'."); + LOG("Phone home and tell AFL that we're OK."); + if (write(199, &status, 4) != 4) { - LOG("Child fork crashed"); + LOG("Write failed"); + close(199); exit(1); } - LOG("Status: " + std::to_string(status)); - write(199, &status, 4); + while (true) + { + LOG("##### NEW FORK RUN #####"); + + // This will block until AFL sends us something. Abort if read fails. + LOG("Wait for AFL by reading from the pipe."); + if (read(198, &status, 4) != 4) + { + LOG("Read failed"); + close(198); + close(199); + exit(1); + } + LOG("Status: " + std::to_string(status)); + + /* + Programm runs concurrently in two forks from here + Returns 0 if in the child process and returns the + child's pid if in the parent process. + */ + int pid = fork(); + if (pid < 0) + { + LOG("Fork failed"); + close(198); + close(199); + exit(1); + } + else if (pid == 0) + { + LOG("This is the child process."); + close(198); + close(199); + main_fuzz(fuzzed_input, trace_bits); + exit(0); + } + + LOG("Writing child pid to parent: " + std::to_string(pid)); + write(199, &pid, 4); + + /* + The fuzzer is no longer an immediate parent of the fuzzed process, + and as a grandparent, it can't directly use waitpid(); there is + also no other simple, portable API to get notified about the + process' exit status. We fix that simply by having the shim do + the waiting, then send the status code to the fuzzer. + */ + + LOG("Waiting for child..."); + if (waitpid(pid, &status, 0) <= 0) + { + LOG("Child fork crashed"); + close(198); + close(199); + exit(1); + } + + LOG("Status: " + std::to_string(status)); + write(199, &status, 4); + } +} - close(198); - close(199); +void log_args(int argc, char *argv[]) +{ + for (int i = 0; i < argc; ++i) + { + LOG("argv[" + std::to_string(i) + "]: " + std::string(argv[i])); + } } int main(int argc, char *argv[]) { + LOG("########## NEW MAIN ##########"); uint8_t *trace_bits = get_shm(); // Mark a location to show we are instrumented trace_bits[0]++; - std::vector vector = readFileToVector(argv[1]); - for (int i = 0; i < vector.size(); ++i) - { - LOG(vector[i]); - } + log_args(argc, argv); - for (int i = 0; i < argc; ++i) - { - LOG("argv[" + std::to_string(i) + "]: " + std::string(argv[i])); - } + fork_server(argv[1], trace_bits); return 0; } From f6559ccd837373278c7579742cdb97619a42da7b Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 22 Jun 2020 15:16:22 +0200 Subject: [PATCH 03/74] Translated return value of waitpid to recognize crashes. --- interface.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/interface.cpp b/interface.cpp index 01d79b08..711feb36 100644 --- a/interface.cpp +++ b/interface.cpp @@ -74,7 +74,7 @@ void execute_swam(char *fuzzed_input) void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) { - // Dummy: + // Dummy with random coverage: srand(time(NULL)); for (int i = 0; i < 10; i++) { @@ -96,20 +96,50 @@ void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) */ } +void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) +{ + // Function to test how AFL reacts to code coverage. Runs + // code execution and feeds data to AFL in one go. + + std::vector vector = readFileToVector(fuzzed_input); + + if (vector[0].rfind("one", 0) == 0) + { + trace_bits[1] += 1; + if (vector[0].rfind("oneone", 0) == 0) + { + trace_bits[2] += 1; + if (vector[0].rfind("oneoneone", 0) == 0) + { + trace_bits[3] += 1; + + if (vector[0].rfind("oneoneonetwo", 0) == 0) + { + trace_bits[4] += 1; + if (vector[0].rfind("oneoneonetwotwo", 0) == 0) + { + trace_bits[5] += 1; + exit(1); + } + } + } + } + } +} + void main_fuzz(char *fuzzed_input, uint8_t *trace_bits) { log_file(fuzzed_input); + // Real application execute_swam(fuzzed_input); - - // Read "shared memory" over TCP uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); - - // TODO: Read path coverage from file - + // TODO: Read path coverage from file into execution_data pass_data_to_afl(execution_data, trace_bits); - free(execution_data); + + // Test application + // test_nested_if(fuzzed_input, trace_bits); } void fork_server(char *fuzzed_input, uint8_t *trace_bits) @@ -135,6 +165,8 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) exit(1); } + // The parent process that continuously runs through this while-loop + // and is creating forks of itself is called the "fork server". while (true) { LOG("##### NEW FORK RUN #####"); @@ -148,7 +180,7 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) close(199); exit(1); } - LOG("Status: " + std::to_string(status)); + LOG("Read status: " + std::to_string(status)); /* Programm runs concurrently in two forks from here @@ -184,16 +216,27 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) */ LOG("Waiting for child..."); - if (waitpid(pid, &status, 0) <= 0) + if (waitpid(pid, &status, 0) <= 0) // Technically only fails at -1; 0 means still running { - LOG("Child fork crashed"); + LOG("waitpid() failed."); + close(198); + close(199); + exit(1); + } + + if (!WIFEXITED(status)) + { // Not sure how this could happen + LOG("WIFEXITED(status): " + std::to_string(WIFEXITED(status))); close(198); close(199); exit(1); } - LOG("Status: " + std::to_string(status)); - write(199, &status, 4); + // Need to translate return value of waitpid to exit code + int exit_status = WEXITSTATUS(status); + LOG("Exit code status: " + std::to_string(exit_status)); + + write(199, &exit_status, 4); } } @@ -215,6 +258,10 @@ int main(int argc, char *argv[]) log_args(argc, argv); + // Since it is not entirely clear how AFL modifies the args in the middle of + // the function call, we can do a test. + // TODO: Copy args, modify slightly (avoid compiler optimization) and use for fork_server input + fork_server(argv[1], trace_bits); return 0; From 50bd2455929be997e03bf84b59b5460b632b9bed Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 3 Jul 2020 13:12:54 +0200 Subject: [PATCH 04/74] Added debugging to interface for status from waitpid() --- interface.cpp | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/interface.cpp b/interface.cpp index 711feb36..e170ff4f 100644 --- a/interface.cpp +++ b/interface.cpp @@ -82,8 +82,6 @@ void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) trace_bits[random_branch] += 1; } - // TODO: Read an actual file with branch coverage - /* for (int i = 0; i < AFL_SHM_SIZE; i++) { @@ -109,6 +107,7 @@ void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) if (vector[0].rfind("oneone", 0) == 0) { trace_bits[2] += 1; + exit(1); if (vector[0].rfind("oneoneone", 0) == 0) { trace_bits[3] += 1; @@ -132,14 +131,14 @@ void main_fuzz(char *fuzzed_input, uint8_t *trace_bits) log_file(fuzzed_input); // Real application - execute_swam(fuzzed_input); - uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); - // TODO: Read path coverage from file into execution_data - pass_data_to_afl(execution_data, trace_bits); - free(execution_data); + // execute_swam(fuzzed_input); + // uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); + // // TODO: Read path coverage from file into execution_data + // pass_data_to_afl(execution_data, trace_bits); + // free(execution_data); // Test application - // test_nested_if(fuzzed_input, trace_bits); + test_nested_if(fuzzed_input, trace_bits); } void fork_server(char *fuzzed_input, uint8_t *trace_bits) @@ -224,19 +223,29 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) exit(1); } - if (!WIFEXITED(status)) - { // Not sure how this could happen - LOG("WIFEXITED(status): " + std::to_string(WIFEXITED(status))); + LOG("Waitpid status: " + std::to_string(status)); + + if (WIFEXITED(status)) + { + // Need to translate return value of waitpid to exit code (e.g. 256 translates to 1) + int exit_status = WEXITSTATUS(status); + LOG("exit_status: " + std::to_string(exit_status)); + write(199, &exit_status, 4); + } + 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))); + write(199, &status, 4); + } + else + { + LOG("Weird status: " + std::to_string(status)); close(198); close(199); exit(1); } - - // Need to translate return value of waitpid to exit code - int exit_status = WEXITSTATUS(status); - LOG("Exit code status: " + std::to_string(exit_status)); - - write(199, &exit_status, 4); } } From 1d98be0d78336a7089e1a3693b162d9dc4f21f11 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 3 Jul 2020 13:14:15 +0200 Subject: [PATCH 05/74] Added basic C++ socket client with fixed Int64 input. Works with fib.wat and cli.run_server. --- socket_client.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 socket_client.cpp diff --git a/socket_client.cpp b/socket_client.cpp new file mode 100644 index 00000000..0617d4a7 --- /dev/null +++ b/socket_client.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SOCKET_PORT 9999 +#define SOCKET_HOST "localhost" + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + +int connectToServer() +{ + int sockfd; + struct hostent *server; + struct sockaddr_in serv_addr; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + error("ERROR opening socket"); + + server = gethostbyname(SOCKET_HOST); + + if (server == NULL) + { + fprintf(stderr, "ERROR, no such host\n"); + exit(0); + } + + bzero((char *)&serv_addr, sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + + serv_addr.sin_port = htons(SOCKET_PORT); + + if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + error("ERROR connecting"); + + return sockfd; +} + +// This was C#!!!! WTF! +enum WasmType +{ + Int32 = 'Int32', + Int64 = 'Int64', + Float32 = 'Float32', + Float64 = 'Float64' +}; + +class WasmValue +{ + + // char [64] buffer; +}; + +int main(int argc, char *argv[]) +{ + // TODO: Parse arguments + + int requiredBytes = getRequiredBytes(); + runClient(requiredBytes); + exit(0); +}; + +int getRequiredBytes(std::vector types) +{ + int requiredBytes = 0; + for ( auto i = types.begin(); i != types.end(); i++ ) { + { + switch (types[i]) + { + case "Int32": + requiredBytes += 4; + break; + case "Int64": + requiredBytes += 8; + break; + case "Float32": + requiredBytes += 4; + break; + case "Float64": + requiredBytes += 8; + break; + default: + error("Type does not exist!"); + } + } + return requiredBytes + 1; // For new line +} + +int runClient(int requiredBytes) +{ + int n; + char sendBuffer[requiredBytes]; + char readBuffer[4096]; + int sockfd = connectToServer(); + + // printf("Please enter the message: "); + // bzero(buffer, 256); + // fgets(buffer, 255, stdin); + + int64_t fiboNumber = 20; + int8_t newLine = 10; + + for (int i = 0; i < (requiredBytes - 1); i++) + { + sendBuffer[(requiredBytes - 2) - i] = fiboNumber & 0xFF; + fiboNumber = fiboNumber >> 8; + } + sendBuffer[(requiredBytes - 1)] = newLine; + + for (int i = 0; i < (requiredBytes - 1); i++) + { + printf("buffer %i: %i \n", i, sendBuffer[i]); + } + + n = write(sockfd, sendBuffer, requiredBytes); + std::cout << "Wrote to server!" << std::endl; + + if (n < 0) + error("ERROR writing to socket"); + + bzero(sendBuffer, requiredBytes); + n = read(sockfd, readBuffer, (4096)); + + if (n < 0) + error("ERROR reading from socket"); + + printf("%s\n", readBuffer); + + close(sockfd); + return 0; +}; From e23b4dd77af4b800df14187366c249342dea652f Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 3 Jul 2020 13:16:42 +0200 Subject: [PATCH 06/74] Slight README changes --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3c9b0ccb..754f5bcd 100644 --- a/README.md +++ b/README.md @@ -18,23 +18,23 @@ AFL communicates with the target binary with a shared memory by default. Since S 1. Run AFL with Docker -```bash -docker pull aflplusplus/aflplusplus -docker run -ti -v /fuzzer:/src aflplusplus/aflplusplus -``` + ```bash + docker pull aflplusplus/aflplusplus + docker run -ti -v /fuzzer:/src aflplusplus/aflplusplus + ``` 1. Compile -```bash -cd /src -g++ interface.cpp -``` + ```bash + cd /src + g++ interface.cpp + ``` 1. Run AFL -```bash -afl-fuzz -i /src/in -o out -m none -d -- /src/a.out @@ -``` + ```bash + afl-fuzz -i /src/in -o out -m none -d -- /src/a.out @@ + ``` 1. View /src/interface.log for custom logs and /src/out/ for AFL output From 4708179369ffe4b0ab7ebffc11af84e928440f84 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 3 Jul 2020 17:26:44 +0200 Subject: [PATCH 07/74] Integrated socket_client.cpp in interface.cpp. --- interface.cpp | 65 +++++++++++++---------- prepare_wasm_input.cpp | 18 +++++++ socket_client.cpp | 116 +++++++++++++++++------------------------ socket_client.h | 10 ++++ 4 files changed, 112 insertions(+), 97 deletions(-) create mode 100644 prepare_wasm_input.cpp create mode 100644 socket_client.h diff --git a/interface.cpp b/interface.cpp index e170ff4f..66919054 100644 --- a/interface.cpp +++ b/interface.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -66,23 +68,17 @@ void log_file(char *filename) } } -void execute_swam(char *fuzzed_input) -{ - // TODO: Do something proper here... -} - void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) { // Dummy with random coverage: - srand(time(NULL)); - for (int i = 0; i < 10; i++) - { - int random_branch = rand() % AFL_SHM_SIZE; - trace_bits[random_branch] += 1; - } + // srand(time(NULL)); + // for (int i = 0; i < 10; i++) + // { + // int random_branch = rand() % AFL_SHM_SIZE; + // trace_bits[random_branch] += 1; + // } - /* for (int i = 0; i < AFL_SHM_SIZE; i++) { if (execution_data[i] != 0) @@ -91,7 +87,6 @@ void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) trace_bits[i] += execution_data[i]; } } - */ } void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) @@ -126,19 +121,32 @@ void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) } } -void main_fuzz(char *fuzzed_input, uint8_t *trace_bits) +void main_fuzz( + char *fuzzed_input, + uint8_t *trace_bits, + int requiredBytes) { log_file(fuzzed_input); - // Real application - // execute_swam(fuzzed_input); - // uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); - // // TODO: Read path coverage from file into execution_data - // pass_data_to_afl(execution_data, trace_bits); - // free(execution_data); + // ######## Real application ######## - // Test application - test_nested_if(fuzzed_input, trace_bits); + char sendBuffer[requiredBytes]; + char readBuffer[4096]; + int sockfd = connectToServer(); + // TODO: Fill buffer with fuzzed_input & new line (using requiredBytes) + clientWrite(sockfd, sendBuffer); + clientRead(sockfd, readBuffer); + close(sockfd); + + uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); + // TODO: Read path coverage from readBuffer into execution_data + + pass_data_to_afl(execution_data, trace_bits); + free(execution_data); + + // ######## Test application ######## + + // test_nested_if(fuzzed_input, trace_bits); } void fork_server(char *fuzzed_input, uint8_t *trace_bits) @@ -164,6 +172,9 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) exit(1); } + int requiredBytes = sizeof(fuzzed_input) + 1; + // int requiredBytes = getRequiredBytes(inputFilePath); + // The parent process that continuously runs through this while-loop // and is creating forks of itself is called the "fork server". while (true) @@ -199,7 +210,7 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) LOG("This is the child process."); close(198); close(199); - main_fuzz(fuzzed_input, trace_bits); + main_fuzz(fuzzed_input, trace_bits, requiredBytes); exit(0); } @@ -233,7 +244,8 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) write(199, &exit_status, 4); } else if (WIFSIGNALED(status)) // Process was stopped/terminated by signal; - { // TODO: Find out why this branch gets triggered + { + // 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))); @@ -260,6 +272,7 @@ void log_args(int argc, char *argv[]) int main(int argc, char *argv[]) { LOG("########## NEW MAIN ##########"); + uint8_t *trace_bits = get_shm(); // Mark a location to show we are instrumented @@ -267,10 +280,6 @@ int main(int argc, char *argv[]) log_args(argc, argv); - // Since it is not entirely clear how AFL modifies the args in the middle of - // the function call, we can do a test. - // TODO: Copy args, modify slightly (avoid compiler optimization) and use for fork_server input - fork_server(argv[1], trace_bits); return 0; diff --git a/prepare_wasm_input.cpp b/prepare_wasm_input.cpp new file mode 100644 index 00000000..32bbfc37 --- /dev/null +++ b/prepare_wasm_input.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +/* +Since WebAssembly only takes Int, Long, Float & Double as input parameters, +we want our first input parameters to be of this format as well. This helper +will parse numbers written as strings with according types written as strings +and write the resulting number to a file, which then can be accessed and +manipulated by AFL. +*/ + +int main(int argc, char *argv[]) +{ + + + exit(0); +}; \ No newline at end of file diff --git a/socket_client.cpp b/socket_client.cpp index 0617d4a7..ec304fc0 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -1,9 +1,10 @@ +#include + #include #include #include #include #include -#include #include #include #include @@ -53,96 +54,73 @@ int connectToServer() return sockfd; } -// This was C#!!!! WTF! -enum WasmType -{ - Int32 = 'Int32', - Int64 = 'Int64', - Float32 = 'Float32', - Float64 = 'Float64' -}; - -class WasmValue -{ - - // char [64] buffer; -}; - -int main(int argc, char *argv[]) -{ - // TODO: Parse arguments - - int requiredBytes = getRequiredBytes(); - runClient(requiredBytes); - exit(0); -}; - -int getRequiredBytes(std::vector types) +// The input file is supposed to have the correct number of +// bytes. Only call this in the beginning. +int getRequiredBytes(std::string pathToInput) { int requiredBytes = 0; - for ( auto i = types.begin(); i != types.end(); i++ ) { - { - switch (types[i]) - { - case "Int32": - requiredBytes += 4; - break; - case "Int64": - requiredBytes += 8; - break; - case "Float32": - requiredBytes += 4; - break; - case "Float64": - requiredBytes += 8; - break; - default: - error("Type does not exist!"); - } - } - return requiredBytes + 1; // For new line -} -int runClient(int requiredBytes) -{ - int n; - char sendBuffer[requiredBytes]; - char readBuffer[4096]; - int sockfd = connectToServer(); + // TODO: Read input file - // printf("Please enter the message: "); - // bzero(buffer, 256); - // fgets(buffer, 255, stdin); + return requiredBytes + 1; // For new line +}; +// This function aims to write a basic integer to a buffer. +void fillDummyBuffer(char* buffer) { int64_t fiboNumber = 20; - int8_t newLine = 10; + int8_t newLine = 10; // New line - for (int i = 0; i < (requiredBytes - 1); i++) + for (int i = 0; i < (sizeof(buffer) - 1); i++) { - sendBuffer[(requiredBytes - 2) - i] = fiboNumber & 0xFF; + buffer[(sizeof(buffer) - 2) - i] = fiboNumber & 0xFF; fiboNumber = fiboNumber >> 8; } - sendBuffer[(requiredBytes - 1)] = newLine; + buffer[(sizeof(buffer) - 1)] = newLine; - for (int i = 0; i < (requiredBytes - 1); i++) + for (int i = 0; i < (sizeof(buffer) - 1); i++) { - printf("buffer %i: %i \n", i, sendBuffer[i]); + printf("buffer %i: %i \n", i, buffer[i]); } +}; - n = write(sockfd, sendBuffer, requiredBytes); +void clientWrite(int sockfd, char* sendBuffer) { + int n = write(sockfd, sendBuffer, sizeof(sendBuffer)); std::cout << "Wrote to server!" << std::endl; - if (n < 0) error("ERROR writing to socket"); + bzero(sendBuffer, sizeof(sendBuffer)); +} - bzero(sendBuffer, requiredBytes); - n = read(sockfd, readBuffer, (4096)); - +void clientRead(int sockfd, char* readBuffer) { + int n = read(sockfd, readBuffer, sizeof(readBuffer)); if (n < 0) error("ERROR reading from socket"); - printf("%s\n", readBuffer); + bzero(readBuffer, sizeof(readBuffer)); +} + +int runClient(char* sendBuffer, char* readBuffer) +{ + int sockfd = connectToServer(); + + fillDummyBuffer(sendBuffer); + + clientWrite(sockfd, sendBuffer); + + clientRead(sockfd, readBuffer); close(sockfd); + return 0; }; + +int main(int argc, char *argv[]) +{ + // TODO: Parse input file from args + + int requiredBytes = getRequiredBytes("/path/to/input/file"); + char sendBuffer[requiredBytes]; + char readBuffer[4096]; + runClient(sendBuffer, readBuffer); + exit(0); +}; diff --git a/socket_client.h b/socket_client.h new file mode 100644 index 00000000..26a5e50c --- /dev/null +++ b/socket_client.h @@ -0,0 +1,10 @@ +#include +#include +#include + +void error(const char *); +int connectToServer(); +int getRequiredBytes(std::string); +void clientWrite(int, char*); +void clientRead(int, char*); +int runClient(char*, char*); \ No newline at end of file From 3956191eacb52c8855ae8520e29ad5699cd8ae3e Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 6 Jul 2020 18:48:21 +0200 Subject: [PATCH 08/74] Basic script to save Wasm inputs as bytecode --- interface.cpp | 3 +- prepare_wasm_input.cpp | 156 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 2 deletions(-) diff --git a/interface.cpp b/interface.cpp index 66919054..f447209a 100644 --- a/interface.cpp +++ b/interface.cpp @@ -172,8 +172,9 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) exit(1); } + // At the very beginning the fuzzed_input should have the correct number + // of bytes. int requiredBytes = sizeof(fuzzed_input) + 1; - // int requiredBytes = getRequiredBytes(inputFilePath); // The parent process that continuously runs through this while-loop // and is creating forks of itself is called the "fork server". diff --git a/prepare_wasm_input.cpp b/prepare_wasm_input.cpp index 32bbfc37..49c7ab0b 100644 --- a/prepare_wasm_input.cpp +++ b/prepare_wasm_input.cpp @@ -1,6 +1,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include /* Since WebAssembly only takes Int, Long, Float & Double as input parameters, @@ -10,9 +16,157 @@ and write the resulting number to a file, which then can be accessed and manipulated by AFL. */ +std::vector split(const std::string &s, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} + +enum TypeOptions +{ + Option_Invalid, + Int32, + Int64, + Float32, + Float64 +}; + +TypeOptions resolveOption(std::string input) +{ + if (input == "Int32") + return Int32; + if (input == "Int64") + return Int64; + if (input == "Float32") + return Float32; + if (input == "Float64") + return Float64; + return Option_Invalid; +} + +template +void writeToFile(T numberToWrite) +{ + std::ofstream wf("prepared_input.dat", std::ios::out | std::ios::binary); + if (!wf) + { + printf("Cannot open prepared_input.dat!\n"); + exit(1); + } + wf.write((char *)&numberToWrite, sizeof(numberToWrite)); + wf.close(); + if (!wf.good()) + { + printf("Error occurred at writing time!\n"); + exit(1); + } +} + +int translateArg(std::string arg, std::string argType) +{ + int bytesRequired = 0; + std::string::size_type sz; // alias of size_t + double doubleNumber = std::stod(arg, &sz); + + switch (resolveOption(argType)) + { + case Int32: + { + int intNumber = std::round(doubleNumber); + writeToFile(intNumber); + bytesRequired += 4; + break; + } + case Int64: + { + long longNumber = lround(doubleNumber); + writeToFile(longNumber); + bytesRequired += 8; + break; + } + case Float32: + { + float floatNumber = (float)doubleNumber; + writeToFile(floatNumber); + bytesRequired += 4; + break; + } + case Float64: + { + writeToFile(doubleNumber); + bytesRequired += 8; + break; + } + default: + { + printf("No support for type %s\n", argType.c_str()); + exit(1); + } + } + return bytesRequired; +} + +void printOutcome(int totalBytes) +{ + std::ifstream rf("prepared_input.dat", std::ios::out | std::ios::binary); + if (!rf) + { + printf("Cannot open prepared_input.dat to read it!\n"); + exit(1); + } + char allNumbers[totalBytes]; + rf.read(allNumbers, totalBytes); + rf.close(); + if (rf.bad()) + { + // Because has not reached end of file. + printf("Error occurred at reading time!\n"); + exit(1); + } + for (int i = 0; i < sizeof(allNumbers); ++i) + { + std::cout << allNumbers[i]; + } + std::cout << std::endl; +} + int main(int argc, char *argv[]) { + // TODO: Parse input file from args (./prepared_input.dat) + + char *WASM_ARG_TYPES_LIST_char = std::getenv("WASM_ARG_TYPES_LIST"); + char *WASM_ARG_LIST_char = std::getenv("WASM_ARG_LIST"); + + if (!WASM_ARG_LIST_char || !WASM_ARG_TYPES_LIST_char) + { + printf("WASM_ARG_TYPES_LIST or WASM_ARG_LIST not defined.\n"); + exit(1); + } + + std::string WASM_ARG_TYPES_LIST = std::string(WASM_ARG_TYPES_LIST_char); + std::string WASM_ARG_LIST = std::string(WASM_ARG_LIST_char); + std::vector typeArray = split(WASM_ARG_TYPES_LIST, ','); + std::vector argArray = split(WASM_ARG_LIST, ','); + + if (typeArray.size() != argArray.size()) + { + printf("Not the same amount of types and args. typeArray.size() = %lu; argArray.size() = %lu \n", typeArray.size(), argArray.size()); + exit(1); + } + int totalBytes = 0; + for (int i = 0; i < typeArray.size(); ++i) + { + totalBytes += translateArg(argArray[i], typeArray[i]); + } + printf("Total bytes written: %i\n", totalBytes); + printOutcome(totalBytes); exit(0); -}; \ No newline at end of file +}; From 3cd021f7bd6c7fddd7d6490d9ba2a97d30b4e1bf Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 6 Jul 2020 18:49:36 +0200 Subject: [PATCH 09/74] Reading input from file (bytecode) in socket_client --- run_test.sh | 17 ++++++++++++++ socket_client.cpp | 59 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 run_test.sh diff --git a/run_test.sh b/run_test.sh new file mode 100644 index 00000000..bbcacc00 --- /dev/null +++ b/run_test.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# For testing the integration of prepare_wasm_input.cpp and socket_client.cpp. + +# Configured for fibo.wat. + +# Run server in Swam first: +# >> mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /Users/vincent/not_in_cloud/Codes/KTH/swam/examples/docs/fibo.wat + +export WASM_ARG_TYPES_LIST=Int64; +export WASM_ARG_LIST=8; + +g++ -o prepare_wasm_input.out prepare_wasm_input.cpp +./prepare_wasm_input.out + +g++ -o socket_client.out socket_client.cpp +./socket_client.out diff --git a/socket_client.cpp b/socket_client.cpp index ec304fc0..d1181583 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -1,4 +1,4 @@ -#include +#include "socket_client.h" #include #include @@ -9,10 +9,13 @@ #include #include #include +#include #define SOCKET_PORT 9999 #define SOCKET_HOST "localhost" +// Most code based on: https://www.bogotobogo.com/cplusplus/sockets_server_client.php + void error(const char *msg) { perror(msg); @@ -54,7 +57,7 @@ int connectToServer() return sockfd; } -// The input file is supposed to have the correct number of +// The input file is supposed to have the correct number of // bytes. Only call this in the beginning. int getRequiredBytes(std::string pathToInput) { @@ -66,9 +69,10 @@ int getRequiredBytes(std::string pathToInput) }; // This function aims to write a basic integer to a buffer. -void fillDummyBuffer(char* buffer) { +void fillDummyBuffer(char *buffer) +{ int64_t fiboNumber = 20; - int8_t newLine = 10; // New line + int8_t newLine = 10; // New line for (int i = 0; i < (sizeof(buffer) - 1); i++) { @@ -83,7 +87,33 @@ void fillDummyBuffer(char* buffer) { } }; -void clientWrite(int sockfd, char* sendBuffer) { +void readFileToBuffer(char *buffer, std::string pathToInput) +{ + std::ifstream rf(pathToInput, std::ios::out | std::ios::binary); + if (!rf) + { + printf("Cannot open prepared_input.dat to read it!\n"); + exit(1); + } + rf.read(buffer, sizeof(buffer)); + rf.close(); + if (rf.bad()) + { + // Because has not reached end of file. + printf("Error occurred at reading time!\n"); + exit(1); + } + int8_t newLine = 10; // New line + buffer[(sizeof(buffer) - 1)] = newLine; + + for (int i = 0; i < (sizeof(buffer) - 1); i++) + { + printf("buffer %i: %i \n", i, buffer[i]); + } +} + +void clientWrite(int sockfd, char *sendBuffer) +{ int n = write(sockfd, sendBuffer, sizeof(sendBuffer)); std::cout << "Wrote to server!" << std::endl; if (n < 0) @@ -91,7 +121,8 @@ void clientWrite(int sockfd, char* sendBuffer) { bzero(sendBuffer, sizeof(sendBuffer)); } -void clientRead(int sockfd, char* readBuffer) { +void clientRead(int sockfd, char *readBuffer) +{ int n = read(sockfd, readBuffer, sizeof(readBuffer)); if (n < 0) error("ERROR reading from socket"); @@ -99,28 +130,26 @@ void clientRead(int sockfd, char* readBuffer) { bzero(readBuffer, sizeof(readBuffer)); } -int runClient(char* sendBuffer, char* readBuffer) +int runClient(char *sendBuffer, char *readBuffer) { int sockfd = connectToServer(); - - fillDummyBuffer(sendBuffer); - clientWrite(sockfd, sendBuffer); - clientRead(sockfd, readBuffer); - close(sockfd); - return 0; }; int main(int argc, char *argv[]) { - // TODO: Parse input file from args + // TODO: Parse input file from args (./prepared_input.dat) - int requiredBytes = getRequiredBytes("/path/to/input/file"); + int requiredBytes = getRequiredBytes("./prepared_input.dat"); char sendBuffer[requiredBytes]; char readBuffer[4096]; + + readFileToBuffer(sendBuffer, "./prepared_input.dat"); + // fillDummyBuffer(sendBuffer); + runClient(sendBuffer, readBuffer); exit(0); }; From 96d37270cd7f877b76922a22d35f1a93f038a660 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 7 Jul 2020 15:21:26 +0200 Subject: [PATCH 10/74] Header files for all. Common functions moved to utils. Fibonacci works. --- interface.cpp | 55 ++++++++------------ interface.h | 17 +++++++ prepare_wasm_input.cpp | 104 ++++++++------------------------------ prepare_wasm_input.h | 15 ++++++ run_test.sh | 8 +-- socket_client.cpp | 109 ++++++++++----------------------------- socket_client.h | 21 ++++++-- utils.cpp | 112 +++++++++++++++++++++++++++++++++++++++++ utils.h | 25 +++++++++ 9 files changed, 258 insertions(+), 208 deletions(-) create mode 100644 interface.h create mode 100644 prepare_wasm_input.h mode change 100644 => 100755 run_test.sh create mode 100644 utils.cpp create mode 100644 utils.h diff --git a/interface.cpp b/interface.cpp index f447209a..e7f4c37d 100644 --- a/interface.cpp +++ b/interface.cpp @@ -1,14 +1,4 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "interface.h" #define AFL_SHM_SIZE 65536 #define SHM_ENV_VAR "__AFL_SHM_ID" @@ -36,19 +26,13 @@ std::vector readFileToVector(const std::string &filename) return lines; } -uint8_t *get_shm() +uint8_t *getShm() { - // putenv((char *)"SHM_ENV_VAR=5"); + std::string shmStr = parseEnvVariables((char *)SHM_ENV_VAR); + LOG("shmStr: " + std::string(shmStr)); - char *shm_name = std::getenv(SHM_ENV_VAR); - if (!shm_name) - { - LOG("SHM_ENV_VAR not found!"); - exit(1); - } + key_t key = std::stoi(shmStr); - LOG("shm_name: " + std::string(shm_name)); - key_t key = atoi(shm_name); uint8_t *trace_bits = (uint8_t *)shmat(key, 0, 0); if (trace_bits == (uint8_t *)-1) { @@ -130,12 +114,18 @@ void main_fuzz( // ######## Real application ######## - char sendBuffer[requiredBytes]; - char readBuffer[4096]; int sockfd = connectToServer(); - // TODO: Fill buffer with fuzzed_input & new line (using requiredBytes) - clientWrite(sockfd, sendBuffer); - clientRead(sockfd, readBuffer); + + char tempBuffer[requiredBytes]; + std::memcpy(tempBuffer, fuzzed_input, sizeof(tempBuffer)); // Read first x bytes of fuzzed_input into tempBuffer + std::reverse(tempBuffer, &tempBuffer[sizeof(tempBuffer)]); // Reverse order of tempBuffer + char sendBuffer[requiredBytes + 1]; + extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); + clientWrite(sockfd, sendBuffer, sizeof(sendBuffer)); + + char readBuffer[4096]; + clientRead(sockfd, readBuffer, sizeof(readBuffer)); + close(sockfd); uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); @@ -149,7 +139,7 @@ void main_fuzz( // test_nested_if(fuzzed_input, trace_bits); } -void fork_server(char *fuzzed_input, uint8_t *trace_bits) +void fork_server(char *fuzzed_input, uint8_t *trace_bits, int requiredBytes) { // The Fork server (Prototype of this code in Assembly): // https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html @@ -172,10 +162,6 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits) exit(1); } - // At the very beginning the fuzzed_input should have the correct number - // of bytes. - int requiredBytes = sizeof(fuzzed_input) + 1; - // The parent process that continuously runs through this while-loop // and is creating forks of itself is called the "fork server". while (true) @@ -274,14 +260,17 @@ int main(int argc, char *argv[]) { LOG("########## NEW MAIN ##########"); - uint8_t *trace_bits = get_shm(); + uint8_t *trace_bits = getShm(); // Mark a location to show we are instrumented trace_bits[0]++; log_args(argc, argv); - fork_server(argv[1], trace_bits); + // TODO: Make sure requiredBytes is passed along; sizeof(fuzzed_input) will not work as it's a char *. + int requiredBytes = (int) argv[2]; + + fork_server(argv[1], trace_bits, requiredBytes); return 0; } diff --git a/interface.h b/interface.h new file mode 100644 index 00000000..b9cb4259 --- /dev/null +++ b/interface.h @@ -0,0 +1,17 @@ +#ifndef INTERFACE_H +#define INTERFACE_H + +#include "socket_client.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif \ No newline at end of file diff --git a/prepare_wasm_input.cpp b/prepare_wasm_input.cpp index 49c7ab0b..50af0112 100644 --- a/prepare_wasm_input.cpp +++ b/prepare_wasm_input.cpp @@ -1,12 +1,4 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "prepare_wasm_input.h" /* Since WebAssembly only takes Int, Long, Float & Double as input parameters, @@ -16,18 +8,6 @@ and write the resulting number to a file, which then can be accessed and manipulated by AFL. */ -std::vector split(const std::string &s, char delimiter) -{ - std::vector tokens; - std::string token; - std::istringstream tokenStream(s); - while (std::getline(tokenStream, token, delimiter)) - { - tokens.push_back(token); - } - return tokens; -} - enum TypeOptions { Option_Invalid, @@ -50,27 +30,8 @@ TypeOptions resolveOption(std::string input) return Option_Invalid; } -template -void writeToFile(T numberToWrite) -{ - std::ofstream wf("prepared_input.dat", std::ios::out | std::ios::binary); - if (!wf) - { - printf("Cannot open prepared_input.dat!\n"); - exit(1); - } - wf.write((char *)&numberToWrite, sizeof(numberToWrite)); - wf.close(); - if (!wf.good()) - { - printf("Error occurred at writing time!\n"); - exit(1); - } -} - -int translateArg(std::string arg, std::string argType) +void translateArg(std::string arg, std::string argType, std::string pathName) { - int bytesRequired = 0; std::string::size_type sz; // alias of size_t double doubleNumber = std::stod(arg, &sz); @@ -79,28 +40,24 @@ int translateArg(std::string arg, std::string argType) case Int32: { int intNumber = std::round(doubleNumber); - writeToFile(intNumber); - bytesRequired += 4; + writeNumberToFile(intNumber, pathName); break; } case Int64: { long longNumber = lround(doubleNumber); - writeToFile(longNumber); - bytesRequired += 8; + writeNumberToFile(longNumber, pathName); break; } case Float32: { float floatNumber = (float)doubleNumber; - writeToFile(floatNumber); - bytesRequired += 4; + writeNumberToFile(floatNumber, pathName); break; } case Float64: { - writeToFile(doubleNumber); - bytesRequired += 8; + writeNumberToFile(doubleNumber, pathName); break; } default: @@ -109,48 +66,27 @@ int translateArg(std::string arg, std::string argType) exit(1); } } - return bytesRequired; } -void printOutcome(int totalBytes) +void printResult(std::string filepath) { - std::ifstream rf("prepared_input.dat", std::ios::out | std::ios::binary); - if (!rf) - { - printf("Cannot open prepared_input.dat to read it!\n"); - exit(1); - } - char allNumbers[totalBytes]; - rf.read(allNumbers, totalBytes); - rf.close(); - if (rf.bad()) - { - // Because has not reached end of file. - printf("Error occurred at reading time!\n"); - exit(1); - } - for (int i = 0; i < sizeof(allNumbers); ++i) - { - std::cout << allNumbers[i]; - } - std::cout << std::endl; + printf("Finished prepare_wasm_input.main(). Checking result..\n"); + int fileSize = (int)getFileSize(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"); } int main(int argc, char *argv[]) { // TODO: Parse input file from args (./prepared_input.dat) - char *WASM_ARG_TYPES_LIST_char = std::getenv("WASM_ARG_TYPES_LIST"); - char *WASM_ARG_LIST_char = std::getenv("WASM_ARG_LIST"); - - if (!WASM_ARG_LIST_char || !WASM_ARG_TYPES_LIST_char) - { - printf("WASM_ARG_TYPES_LIST or WASM_ARG_LIST not defined.\n"); - exit(1); - } + std::string WASM_ARG_TYPES_LIST = parseEnvVariables((char *)"WASM_ARG_TYPES_LIST"); + std::string WASM_ARG_LIST = parseEnvVariables((char *)"WASM_ARG_LIST"); - std::string WASM_ARG_TYPES_LIST = std::string(WASM_ARG_TYPES_LIST_char); - std::string WASM_ARG_LIST = std::string(WASM_ARG_LIST_char); std::vector typeArray = split(WASM_ARG_TYPES_LIST, ','); std::vector argArray = split(WASM_ARG_LIST, ','); @@ -163,10 +99,10 @@ int main(int argc, char *argv[]) int totalBytes = 0; for (int i = 0; i < typeArray.size(); ++i) { - totalBytes += translateArg(argArray[i], typeArray[i]); + translateArg(argArray[i], typeArray[i], "./prepared_input.dat"); } - printf("Total bytes written: %i\n", totalBytes); - printOutcome(totalBytes); + + printResult("./prepared_input.dat"); exit(0); }; diff --git a/prepare_wasm_input.h b/prepare_wasm_input.h new file mode 100644 index 00000000..cc3deaea --- /dev/null +++ b/prepare_wasm_input.h @@ -0,0 +1,15 @@ +#ifndef PREPARE_WASM_INPUT_H +#define PREPARE_WASM_INPUT_H + +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif \ No newline at end of file diff --git a/run_test.sh b/run_test.sh old mode 100644 new mode 100755 index bbcacc00..4581912d --- a/run_test.sh +++ b/run_test.sh @@ -7,11 +7,11 @@ # Run server in Swam first: # >> mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /Users/vincent/not_in_cloud/Codes/KTH/swam/examples/docs/fibo.wat -export WASM_ARG_TYPES_LIST=Int64; -export WASM_ARG_LIST=8; +export WASM_ARG_TYPES_LIST=Int64 +export WASM_ARG_LIST=8 -g++ -o prepare_wasm_input.out prepare_wasm_input.cpp +g++ -o prepare_wasm_input.out prepare_wasm_input.cpp utils.cpp ./prepare_wasm_input.out -g++ -o socket_client.out socket_client.cpp +g++ -o socket_client.out socket_client.cpp utils.cpp ./socket_client.out diff --git a/socket_client.cpp b/socket_client.cpp index d1181583..18652351 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -1,16 +1,5 @@ #include "socket_client.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #define SOCKET_PORT 9999 #define SOCKET_HOST "localhost" @@ -41,7 +30,7 @@ int connectToServer() exit(0); } - bzero((char *)&serv_addr, sizeof(serv_addr)); + bzero((char *)&serv_addr, sizeof(serv_addr)); // Maybe use memset serv_addr.sin_family = AF_INET; @@ -57,84 +46,29 @@ int connectToServer() return sockfd; } -// The input file is supposed to have the correct number of -// bytes. Only call this in the beginning. -int getRequiredBytes(std::string pathToInput) -{ - int requiredBytes = 0; - - // TODO: Read input file - - return requiredBytes + 1; // For new line -}; - -// This function aims to write a basic integer to a buffer. -void fillDummyBuffer(char *buffer) -{ - int64_t fiboNumber = 20; - int8_t newLine = 10; // New line - - for (int i = 0; i < (sizeof(buffer) - 1); i++) - { - buffer[(sizeof(buffer) - 2) - i] = fiboNumber & 0xFF; - fiboNumber = fiboNumber >> 8; - } - buffer[(sizeof(buffer) - 1)] = newLine; - - for (int i = 0; i < (sizeof(buffer) - 1); i++) - { - printf("buffer %i: %i \n", i, buffer[i]); - } -}; - -void readFileToBuffer(char *buffer, std::string pathToInput) -{ - std::ifstream rf(pathToInput, std::ios::out | std::ios::binary); - if (!rf) - { - printf("Cannot open prepared_input.dat to read it!\n"); - exit(1); - } - rf.read(buffer, sizeof(buffer)); - rf.close(); - if (rf.bad()) - { - // Because has not reached end of file. - printf("Error occurred at reading time!\n"); - exit(1); - } - int8_t newLine = 10; // New line - buffer[(sizeof(buffer) - 1)] = newLine; - - for (int i = 0; i < (sizeof(buffer) - 1); i++) - { - printf("buffer %i: %i \n", i, buffer[i]); - } -} - -void clientWrite(int sockfd, char *sendBuffer) +void clientWrite(int sockfd, char *sendBuffer, int sizeBuffer) { - int n = write(sockfd, sendBuffer, sizeof(sendBuffer)); + int n = write(sockfd, sendBuffer, sizeBuffer); std::cout << "Wrote to server!" << std::endl; if (n < 0) error("ERROR writing to socket"); - bzero(sendBuffer, sizeof(sendBuffer)); + bzero(sendBuffer, sizeBuffer); } -void clientRead(int sockfd, char *readBuffer) +void clientRead(int sockfd, char *readBuffer, int sizeBuffer) { - int n = read(sockfd, readBuffer, sizeof(readBuffer)); + int n = read(sockfd, readBuffer, sizeBuffer); if (n < 0) error("ERROR reading from socket"); - printf("%s\n", readBuffer); - bzero(readBuffer, sizeof(readBuffer)); + printf("Message received: %s\n", readBuffer); + bzero(readBuffer, sizeBuffer); } -int runClient(char *sendBuffer, char *readBuffer) +int runClient(int sizeSendBuffer, char *sendBuffer, int sizeReadBuffer, char *readBuffer) { int sockfd = connectToServer(); - clientWrite(sockfd, sendBuffer); - clientRead(sockfd, readBuffer); + clientWrite(sockfd, sendBuffer, sizeSendBuffer); + clientRead(sockfd, readBuffer, sizeReadBuffer); close(sockfd); return 0; }; @@ -143,13 +77,22 @@ int main(int argc, char *argv[]) { // TODO: Parse input file from args (./prepared_input.dat) - int requiredBytes = getRequiredBytes("./prepared_input.dat"); - char sendBuffer[requiredBytes]; char readBuffer[4096]; - readFileToBuffer(sendBuffer, "./prepared_input.dat"); - // fillDummyBuffer(sendBuffer); - - runClient(sendBuffer, readBuffer); + int fileSize = (int)getFileSize("./prepared_input.dat"); + char tempBuffer[fileSize]; + readBinaryToBuffer(tempBuffer, fileSize, "./prepared_input.dat"); + std::reverse(tempBuffer, &tempBuffer[sizeof(tempBuffer)]); // Reverse order of tempBuffer + char sendBuffer[fileSize + 1]; + extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); + + // ## For Testing: + // int requiredBytes = 12 + // char tempBuffer[requiredBytes]; + // char sendBuffer[requiredBytes + 1]; + // fillDummyBuffer(tempBuffer, sizeof(tempBuffer)); + // extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); + + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); exit(0); }; diff --git a/socket_client.h b/socket_client.h index 26a5e50c..790d553f 100644 --- a/socket_client.h +++ b/socket_client.h @@ -1,10 +1,23 @@ +#ifndef SOCKET_CLIENT_H +#define SOCKET_CLIENT_H + +#include "utils.h" + #include #include #include +#include +#include +#include +#include +#include +#include +#include void error(const char *); int connectToServer(); -int getRequiredBytes(std::string); -void clientWrite(int, char*); -void clientRead(int, char*); -int runClient(char*, char*); \ No newline at end of file +void clientWrite(int, char*, int); +void clientRead(int, char*, int); +int runClient(int, char*, int, char*); + +#endif \ No newline at end of file diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 00000000..bfa91731 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,112 @@ +#include "./utils.h" + +#include +#include +#include +#include +#include +#include + +void printBuffer(int sizeBuffer, char *buffer) +{ + for (int i = 0; i < sizeBuffer; i++) + { + printf("buffer %i: %i \n", i, buffer[i]); + } +} + +long getFileSize(std::string filename) +{ + struct stat stat_buf; + int rc = stat(filename.c_str(), &stat_buf); + return rc == 0 ? stat_buf.st_size : -1; +} + +void readBinaryToBuffer(char *buffer, int fileSize, std::string pathToInput) +{ + std::ifstream rf(pathToInput, std::ios::out | std::ios::binary); + if (!rf) + { + printf("Cannot open %s to read it!\n", pathToInput.c_str()); + exit(1); + } + + rf.read(buffer, fileSize); + rf.close(); + if (rf.bad()) + { + // Because has not reached end of file. + printf("Error occurred at reading time!\n"); + exit(1); + } +} + +void extendBufferNewLine(int sizeInitialBuffer, char *buffer, char *extendedBuffer) +{ + int8_t newLine = 10; // New line + + for (int i = 0; i < sizeInitialBuffer; i++) + { + extendedBuffer[i] = buffer[i]; + } + extendedBuffer[sizeInitialBuffer] = newLine; +} + +// This function aims to write a basic integer to a buffer. +void fillDummyBuffer(char *buffer, int bufferSize) +{ + int64_t fiboNumber = 20; + int8_t newLine = 10; // New line + + for (int i = 0; i < bufferSize; i++) + { + buffer[(sizeof(buffer) - 2) - i] = fiboNumber & 0xFF; + fiboNumber = fiboNumber >> 8; + } +}; + +std::string parseEnvVariables(char *envName) +{ + char *envChar = std::getenv(envName); + if (!envChar) + { + printf("%s not defined.\n", envName); + exit(1); + } + return std::string(envChar); +} + +std::vector split(const std::string &s, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} + +template void writeNumberToFile(double, std::string); +template void writeNumberToFile(float, std::string); +template void writeNumberToFile(long, std::string); +template void writeNumberToFile(int, std::string); + +template +void writeNumberToFile(T numberToWrite, std::string pathName) +{ + std::ofstream wf(pathName, std::ios::out | std::ios::binary); + if (!wf) + { + printf("Cannot open %s to write in it!\n", pathName.c_str()); + exit(1); + } + wf.write((char *)&numberToWrite, sizeof(numberToWrite)); + wf.close(); + if (!wf.good()) + { + printf("Error occurred at writing time!\n"); + exit(1); + } +} diff --git a/utils.h b/utils.h new file mode 100644 index 00000000..2ccccd99 --- /dev/null +++ b/utils.h @@ -0,0 +1,25 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#include +#include + +void printBuffer(int, char *); +long getFileSize(std::string); + +void readBinaryToBuffer(char *, int, std::string); +void extendBufferNewLine(int, char *, char *); + +void fillDummyBuffer(char *, int); + +std::string parseEnvVariables(char *); +std::vector split(const std::string &, char); + +template +void writeNumberToFile(T, std::string); + +#endif \ No newline at end of file From ae48cf0197316aef579b40d1cfb294294fcf5cd2 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 7 Jul 2020 17:53:47 +0200 Subject: [PATCH 11/74] Deleted function fillDummyBuffer --- socket_client.cpp | 7 ------- utils.cpp | 13 ------------- utils.h | 2 -- 3 files changed, 22 deletions(-) diff --git a/socket_client.cpp b/socket_client.cpp index 18652351..82bf9436 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -86,13 +86,6 @@ int main(int argc, char *argv[]) char sendBuffer[fileSize + 1]; extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); - // ## For Testing: - // int requiredBytes = 12 - // char tempBuffer[requiredBytes]; - // char sendBuffer[requiredBytes + 1]; - // fillDummyBuffer(tempBuffer, sizeof(tempBuffer)); - // extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); - runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); exit(0); }; diff --git a/utils.cpp b/utils.cpp index bfa91731..e216598e 100644 --- a/utils.cpp +++ b/utils.cpp @@ -52,19 +52,6 @@ void extendBufferNewLine(int sizeInitialBuffer, char *buffer, char *extendedBuff extendedBuffer[sizeInitialBuffer] = newLine; } -// This function aims to write a basic integer to a buffer. -void fillDummyBuffer(char *buffer, int bufferSize) -{ - int64_t fiboNumber = 20; - int8_t newLine = 10; // New line - - for (int i = 0; i < bufferSize; i++) - { - buffer[(sizeof(buffer) - 2) - i] = fiboNumber & 0xFF; - fiboNumber = fiboNumber >> 8; - } -}; - std::string parseEnvVariables(char *envName) { char *envChar = std::getenv(envName); diff --git a/utils.h b/utils.h index 2ccccd99..88ec3852 100644 --- a/utils.h +++ b/utils.h @@ -14,8 +14,6 @@ long getFileSize(std::string); void readBinaryToBuffer(char *, int, std::string); void extendBufferNewLine(int, char *, char *); -void fillDummyBuffer(char *, int); - std::string parseEnvVariables(char *); std::vector split(const std::string &, char); From 8d43aa2cdc5110999d885a30e495ed94d0845b39 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 7 Jul 2020 19:49:31 +0200 Subject: [PATCH 12/74] Fixed byte conversion C++ to Scala --- interface.cpp | 36 ++++++++++++------------------------ prepare_wasm_input.cpp | 4 ++++ run_test.sh | 7 +++---- socket_client.cpp | 8 +++----- utils.cpp | 11 ----------- utils.h | 1 - 6 files changed, 22 insertions(+), 45 deletions(-) diff --git a/interface.cpp b/interface.cpp index e7f4c37d..30e9cbab 100644 --- a/interface.cpp +++ b/interface.cpp @@ -52,25 +52,19 @@ void log_file(char *filename) } } -void pass_data_to_afl(uint8_t *execution_data, uint8_t *trace_bits) +void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits) { + // TODO: Read path coverage from readBuffer into trace_bits + // TODO: Read exit code from readBuffer and exit with same code // Dummy with random coverage: - // srand(time(NULL)); - // for (int i = 0; i < 10; i++) - // { - // int random_branch = rand() % AFL_SHM_SIZE; - // trace_bits[random_branch] += 1; - // } - - for (int i = 0; i < AFL_SHM_SIZE; i++) + srand(time(NULL)); + for (int i = 0; i < 10; i++) { - if (execution_data[i] != 0) - { - LOG(i + " -> " + execution_data[i]); - trace_bits[i] += execution_data[i]; - } + int random_branch = rand() % AFL_SHM_SIZE; + trace_bits[random_branch] += 1; } + } void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) @@ -116,11 +110,9 @@ void main_fuzz( int sockfd = connectToServer(); - char tempBuffer[requiredBytes]; - std::memcpy(tempBuffer, fuzzed_input, sizeof(tempBuffer)); // Read first x bytes of fuzzed_input into tempBuffer - std::reverse(tempBuffer, &tempBuffer[sizeof(tempBuffer)]); // Reverse order of tempBuffer - char sendBuffer[requiredBytes + 1]; - extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); + char sendBuffer[requiredBytes]; + std::memcpy(sendBuffer, fuzzed_input, sizeof(sendBuffer)); // Read first x bytes of fuzzed_input into tempBuffer + std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer clientWrite(sockfd, sendBuffer, sizeof(sendBuffer)); char readBuffer[4096]; @@ -128,11 +120,7 @@ void main_fuzz( close(sockfd); - uint8_t *execution_data = (uint8_t *)malloc(AFL_SHM_SIZE); - // TODO: Read path coverage from readBuffer into execution_data - - pass_data_to_afl(execution_data, trace_bits); - free(execution_data); + pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); // ######## Test application ######## diff --git a/prepare_wasm_input.cpp b/prepare_wasm_input.cpp index 50af0112..e6ec952b 100644 --- a/prepare_wasm_input.cpp +++ b/prepare_wasm_input.cpp @@ -40,24 +40,28 @@ void translateArg(std::string arg, std::string argType, std::string pathName) case Int32: { int intNumber = std::round(doubleNumber); + printf("Resulting int: %i\n", intNumber); writeNumberToFile(intNumber, pathName); break; } case Int64: { long longNumber = lround(doubleNumber); + printf("Resulting long: %li\n", longNumber); writeNumberToFile(longNumber, pathName); break; } case Float32: { float floatNumber = (float)doubleNumber; + printf("Resulting float: %f\n", floatNumber); writeNumberToFile(floatNumber, pathName); break; } case Float64: { writeNumberToFile(doubleNumber, pathName); + printf("Resulting double: %f\n", doubleNumber); break; } default: diff --git a/run_test.sh b/run_test.sh index 4581912d..901e6fde 100755 --- a/run_test.sh +++ b/run_test.sh @@ -2,13 +2,12 @@ # For testing the integration of prepare_wasm_input.cpp and socket_client.cpp. -# Configured for fibo.wat. - -# Run server in Swam first: +# Run server in Swam first (example with fibo.wat): # >> mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /Users/vincent/not_in_cloud/Codes/KTH/swam/examples/docs/fibo.wat +# Configured for fibo.wat: export WASM_ARG_TYPES_LIST=Int64 -export WASM_ARG_LIST=8 +export WASM_ARG_LIST=15 g++ -o prepare_wasm_input.out prepare_wasm_input.cpp utils.cpp ./prepare_wasm_input.out diff --git a/socket_client.cpp b/socket_client.cpp index 82bf9436..f3824b97 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -80,11 +80,9 @@ int main(int argc, char *argv[]) char readBuffer[4096]; int fileSize = (int)getFileSize("./prepared_input.dat"); - char tempBuffer[fileSize]; - readBinaryToBuffer(tempBuffer, fileSize, "./prepared_input.dat"); - std::reverse(tempBuffer, &tempBuffer[sizeof(tempBuffer)]); // Reverse order of tempBuffer - char sendBuffer[fileSize + 1]; - extendBufferNewLine(sizeof(tempBuffer), tempBuffer, sendBuffer); + char sendBuffer[fileSize]; + readBinaryToBuffer(sendBuffer, fileSize, "./prepared_input.dat"); + std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of sendBuffer runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); exit(0); diff --git a/utils.cpp b/utils.cpp index e216598e..0c5728e2 100644 --- a/utils.cpp +++ b/utils.cpp @@ -41,17 +41,6 @@ void readBinaryToBuffer(char *buffer, int fileSize, std::string pathToInput) } } -void extendBufferNewLine(int sizeInitialBuffer, char *buffer, char *extendedBuffer) -{ - int8_t newLine = 10; // New line - - for (int i = 0; i < sizeInitialBuffer; i++) - { - extendedBuffer[i] = buffer[i]; - } - extendedBuffer[sizeInitialBuffer] = newLine; -} - std::string parseEnvVariables(char *envName) { char *envChar = std::getenv(envName); diff --git a/utils.h b/utils.h index 88ec3852..4d9796cf 100644 --- a/utils.h +++ b/utils.h @@ -12,7 +12,6 @@ void printBuffer(int, char *); long getFileSize(std::string); void readBinaryToBuffer(char *, int, std::string); -void extendBufferNewLine(int, char *, char *); std::string parseEnvVariables(char *); std::vector split(const std::string &, char); From 8108b5bd63d408cfc755fef78559d8681393c749 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 8 Jul 2020 18:30:44 +0200 Subject: [PATCH 13/74] Wrote entrypoint.sh for AFLplusplus --- entrypoint_afl.sh | 17 +++++++++++++++++ getFileSize.cpp | 11 +++++++++++ prepare_wasm_input.cpp | 7 +++---- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 entrypoint_afl.sh create mode 100644 getFileSize.cpp diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh new file mode 100644 index 00000000..41423c67 --- /dev/null +++ b/entrypoint_afl.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Run server in Swam first (example with fibo.wat): +# >> mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /Users/vincent/not_in_cloud/Codes/KTH/swam/examples/docs/fibo.wat + +cd /src/ + +# TODO: Put this into build of new image with AFLPlusPlus as base +g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp +g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp +g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp + +PREPARED_INPUT_PATH="./prepared_input.dat" +./prepare_wasm_input.out $PREPARED_INPUT_PATH +REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) + +afl-fuzz -i /src/in -o out -m none -d -- /src/interface.out @@ $REQUIRED_BYTES diff --git a/getFileSize.cpp b/getFileSize.cpp new file mode 100644 index 00000000..aa6d38f6 --- /dev/null +++ b/getFileSize.cpp @@ -0,0 +1,11 @@ +#include "utils.h" + +#include + +int main(int argc, char *argv[]) +{ + std::string filePath = (std::string) argv[1]; + printf("%li\n", getFileSize(filePath)); + + exit(0); +}; \ No newline at end of file diff --git a/prepare_wasm_input.cpp b/prepare_wasm_input.cpp index e6ec952b..33c72b9b 100644 --- a/prepare_wasm_input.cpp +++ b/prepare_wasm_input.cpp @@ -86,7 +86,7 @@ void printResult(std::string filepath) int main(int argc, char *argv[]) { - // TODO: Parse input file from args (./prepared_input.dat) + std::string filePath = (std::string) argv[1]; std::string WASM_ARG_TYPES_LIST = parseEnvVariables((char *)"WASM_ARG_TYPES_LIST"); std::string WASM_ARG_LIST = parseEnvVariables((char *)"WASM_ARG_LIST"); @@ -100,13 +100,12 @@ int main(int argc, char *argv[]) exit(1); } - int totalBytes = 0; for (int i = 0; i < typeArray.size(); ++i) { - translateArg(argArray[i], typeArray[i], "./prepared_input.dat"); + translateArg(argArray[i], typeArray[i], filePath); } - printResult("./prepared_input.dat"); + printResult(filePath); exit(0); }; From 3f7611de6a86192e47ca27f2717f4c35b816b3eb Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 8 Jul 2020 18:33:42 +0200 Subject: [PATCH 14/74] Extracted main() from socket_client.cpp --- run_client.cpp | 17 +++++++++++++++++ run_test.sh | 8 ++++---- socket_client.cpp | 24 +++--------------------- 3 files changed, 24 insertions(+), 25 deletions(-) create mode 100644 run_client.cpp diff --git a/run_client.cpp b/run_client.cpp new file mode 100644 index 00000000..ea6c7a27 --- /dev/null +++ b/run_client.cpp @@ -0,0 +1,17 @@ +#include "socket_client.h" +#define AFL_SHM_SIZE 65536 + +int main(int argc, char *argv[]) +{ + 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); + exit(0); +}; \ No newline at end of file diff --git a/run_test.sh b/run_test.sh index 901e6fde..27d7da2a 100755 --- a/run_test.sh +++ b/run_test.sh @@ -9,8 +9,8 @@ export WASM_ARG_TYPES_LIST=Int64 export WASM_ARG_LIST=15 -g++ -o prepare_wasm_input.out prepare_wasm_input.cpp utils.cpp -./prepare_wasm_input.out +g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp +g++ -o ./run_client.out ./run_client.cpp ./socket_client.cpp ./utils.cpp -g++ -o socket_client.out socket_client.cpp utils.cpp -./socket_client.out +./prepare_wasm_input.out "./prepared_input.dat" +./run_client.out "./prepared_input.dat" diff --git a/socket_client.cpp b/socket_client.cpp index f3824b97..0990b612 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -49,10 +49,9 @@ int connectToServer() void clientWrite(int sockfd, char *sendBuffer, int sizeBuffer) { int n = write(sockfd, sendBuffer, sizeBuffer); - std::cout << "Wrote to server!" << std::endl; if (n < 0) error("ERROR writing to socket"); - bzero(sendBuffer, sizeBuffer); + printf("Wrote to server!\n"); } void clientRead(int sockfd, char *readBuffer, int sizeBuffer) @@ -60,30 +59,13 @@ void clientRead(int sockfd, char *readBuffer, int sizeBuffer) int n = read(sockfd, readBuffer, sizeBuffer); if (n < 0) error("ERROR reading from socket"); - printf("Message received: %s\n", readBuffer); - bzero(readBuffer, sizeBuffer); + printf("Received message!\n"); } -int runClient(int sizeSendBuffer, char *sendBuffer, int sizeReadBuffer, char *readBuffer) +void runClient(int sizeSendBuffer, char *sendBuffer, int sizeReadBuffer, char *readBuffer) { int sockfd = connectToServer(); clientWrite(sockfd, sendBuffer, sizeSendBuffer); clientRead(sockfd, readBuffer, sizeReadBuffer); close(sockfd); - return 0; -}; - -int main(int argc, char *argv[]) -{ - // TODO: Parse input file from args (./prepared_input.dat) - - char readBuffer[4096]; - - int fileSize = (int)getFileSize("./prepared_input.dat"); - char sendBuffer[fileSize]; - readBinaryToBuffer(sendBuffer, fileSize, "./prepared_input.dat"); - std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of sendBuffer - - runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); - exit(0); }; From a7e99734b3f68ed1e201dd26917c79d38c436f9e Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 8 Jul 2020 18:38:05 +0200 Subject: [PATCH 15/74] Interface: Parse readBuffer to traceBits; log() -> utils; Read reqBytes; use runClient(); --- interface.cpp | 80 ++++++++++++------------------------------------- socket_client.h | 2 +- utils.cpp | 8 +++++ utils.h | 1 + 4 files changed, 29 insertions(+), 62 deletions(-) diff --git a/interface.cpp b/interface.cpp index 30e9cbab..85ed5360 100644 --- a/interface.cpp +++ b/interface.cpp @@ -2,15 +2,10 @@ #define AFL_SHM_SIZE 65536 #define SHM_ENV_VAR "__AFL_SHM_ID" -#define LOGFILE "interface.log" -int LOG(std::string some_string) +void LOG(std::string some_string) { - std::ofstream logfile; - logfile.open(LOGFILE, std::ios_base::app); - logfile << some_string + "\n"; - logfile.close(); - return 0; + log("interface.log", some_string); } std::vector readFileToVector(const std::string &filename) @@ -29,7 +24,7 @@ std::vector readFileToVector(const std::string &filename) uint8_t *getShm() { std::string shmStr = parseEnvVariables((char *)SHM_ENV_VAR); - LOG("shmStr: " + std::string(shmStr)); + LOG("shmStr: " + shmStr); key_t key = std::stoi(shmStr); @@ -52,53 +47,25 @@ void log_file(char *filename) } } -void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits) -{ - // TODO: Read path coverage from readBuffer into trace_bits - // TODO: Read exit code from readBuffer and exit with same code - - // Dummy with random coverage: +void fillTraceDummyData(uint8_t *trace_bits) { srand(time(NULL)); for (int i = 0; i < 10; i++) { int random_branch = rand() % AFL_SHM_SIZE; trace_bits[random_branch] += 1; } - } -void test_nested_if(char *fuzzed_input, uint8_t *trace_bits) +void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits) { - // Function to test how AFL reacts to code coverage. Runs - // code execution and feeds data to AFL in one go. - - std::vector vector = readFileToVector(fuzzed_input); - - if (vector[0].rfind("one", 0) == 0) + // Read path coverage from readBuffer into trace_bits + for (int i = 1; i < sizeReadBuffer; i++) { - trace_bits[1] += 1; - if (vector[0].rfind("oneone", 0) == 0) - { - trace_bits[2] += 1; - exit(1); - if (vector[0].rfind("oneoneone", 0) == 0) - { - trace_bits[3] += 1; - - if (vector[0].rfind("oneoneonetwo", 0) == 0) - { - trace_bits[4] += 1; - if (vector[0].rfind("oneoneonetwotwo", 0) == 0) - { - trace_bits[5] += 1; - exit(1); - } - } - } - } + trace_bits[i-1] += readBuffer[i]; } } + void main_fuzz( char *fuzzed_input, uint8_t *trace_bits, @@ -106,25 +73,18 @@ void main_fuzz( { log_file(fuzzed_input); - // ######## Real application ######## - - int sockfd = connectToServer(); - char sendBuffer[requiredBytes]; std::memcpy(sendBuffer, fuzzed_input, sizeof(sendBuffer)); // Read first x bytes of fuzzed_input into tempBuffer std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer - clientWrite(sockfd, sendBuffer, sizeof(sendBuffer)); - - char readBuffer[4096]; - clientRead(sockfd, readBuffer, sizeof(readBuffer)); + char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code - close(sockfd); + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); - // ######## Test application ######## + // Read exit code from readBuffer and exit with same code + exit(readBuffer[0]); - // test_nested_if(fuzzed_input, trace_bits); } void fork_server(char *fuzzed_input, uint8_t *trace_bits, int requiredBytes) @@ -248,17 +208,15 @@ int main(int argc, char *argv[]) { LOG("########## NEW MAIN ##########"); - uint8_t *trace_bits = getShm(); - - // Mark a location to show we are instrumented - trace_bits[0]++; - log_args(argc, argv); + + char *fuzzed_input = argv[1]; + int requiredBytes = atoi(argv[2]); - // TODO: Make sure requiredBytes is passed along; sizeof(fuzzed_input) will not work as it's a char *. - int requiredBytes = (int) argv[2]; + uint8_t *trace_bits = getShm(); + trace_bits[0]++; // Mark a location to show we are instrumented - fork_server(argv[1], trace_bits, requiredBytes); + fork_server(fuzzed_input, trace_bits, requiredBytes); return 0; } diff --git a/socket_client.h b/socket_client.h index 790d553f..80ba2139 100644 --- a/socket_client.h +++ b/socket_client.h @@ -18,6 +18,6 @@ void error(const char *); int connectToServer(); void clientWrite(int, char*, int); void clientRead(int, char*, int); -int runClient(int, char*, int, char*); +void runClient(int, char*, int, char*); #endif \ No newline at end of file diff --git a/utils.cpp b/utils.cpp index 0c5728e2..c6793d17 100644 --- a/utils.cpp +++ b/utils.cpp @@ -7,6 +7,14 @@ #include #include +void log(std::string filename, std::string some_string) +{ + std::ofstream logfile; + logfile.open(filename, std::ios_base::app); + logfile << some_string + "\n"; + logfile.close(); +} + void printBuffer(int sizeBuffer, char *buffer) { for (int i = 0; i < sizeBuffer; i++) diff --git a/utils.h b/utils.h index 4d9796cf..44c6e9cb 100644 --- a/utils.h +++ b/utils.h @@ -8,6 +8,7 @@ #include #include +void log(std::string, std::string); void printBuffer(int, char *); long getFileSize(std::string); From db25357e79066479311d4751624ae082b12071b1 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 8 Jul 2020 18:38:32 +0200 Subject: [PATCH 16/74] Updated README --- README.md | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 754f5bcd..7fa11750 100644 --- a/README.md +++ b/README.md @@ -14,29 +14,42 @@ Therefore, instead of using the C++-compiler provided by AFLplusplus (afl-clang- AFL communicates with the target binary with a shared memory by default. Since Scala does not seem suitable for such low-level operations, we have instead created a low-level wrapper for SWAM, interface.cpp. Whilst the code coverage plugin for SWAM writes it's results to a fixed file, our interface wrapper reads from this file and then feeds the content into the shared memory used by AFL. -## Run +## Test socket connection + SWAM with sample input (for fibo.wat) -1. Run AFL with Docker +1. Start the SWAM socket server ```bash - docker pull aflplusplus/aflplusplus - docker run -ti -v /fuzzer:/src aflplusplus/aflplusplus + mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /examples/docs/fibo.wat + ``` + +1. Start socket client and communicate input/output with server + + ```bash + ./run_test.sh ``` -1. Compile +## Run AFL on example ./examples/docs/fibo.wat + +**Disclaimer - this does not work yet, since the hosts & ports are not adjusted yet! Will be done in a later implementation using docker-compose.** + +1. Start the SWAM Socket Server ```bash - cd /src - g++ interface.cpp + mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /examples/docs/fibo.wat ``` -1. Run AFL +1. Run AFL with Docker ```bash - afl-fuzz -i /src/in -o out -m none -d -- /src/a.out @@ + docker pull aflplusplus/aflplusplus + docker run + --volume /fuzzer:/src aflplusplus/aflplusplus + --entrypoint="/src/entrypoint_afl.sh" + -e "WASM_ARG_TYPES_LIST=Int64" + -e "WASM_ARG_LIST=15" ``` -1. View /src/interface.log for custom logs and /src/out/ for AFL output +1. View ./interface.log for logs and ./out/ for AFL output ## Credits From 03ec0fea72e49d1493c5922616b115c0525c8731 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 9 Jul 2020 14:37:36 +0200 Subject: [PATCH 17/74] Deleted fuzzer/in --- in/first_test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 in/first_test.txt diff --git a/in/first_test.txt b/in/first_test.txt deleted file mode 100644 index be83f48d..00000000 --- a/in/first_test.txt +++ /dev/null @@ -1 +0,0 @@ -one two three \ No newline at end of file From 2f4878f3116d86b673dc1d61743b542e099becad Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 9 Jul 2020 16:36:17 +0200 Subject: [PATCH 18/74] Initialisation fuzzer docker-compose (not tested) --- .env | 8 ++++++++ Dockerfile | 17 +++++++++++++++++ docker-compose.fuzzing.yml | 26 ++++++++++++++++++++++++++ entrypoint_afl.sh | 14 +++----------- entrypoint_mill_server.sh | 32 ++++++++++++++++++++++++++++++++ socket_client.cpp | 1 + 6 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 .env create mode 100644 Dockerfile create mode 100644 docker-compose.fuzzing.yml create mode 100644 entrypoint_mill_server.sh diff --git a/.env b/.env new file mode 100644 index 00000000..c6e27a4e --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +WASM_PATH_LOCAL="" # Path to our local .wasm/.wat executable +AFL_OUTPUT_LOCAL="" # Path on our local machine for us to read AFL's output +SWAM_OUTPUT_LOCAL="" # Path on our local machine for us to read SWAM's output (if any) +TARGET_FUNCTION="_start" # Function to be executed in .wasm/.wat ("_start" is default) +WASM_ARG_TYPES_LIST="Int64,Int32" # Parameter types for target function +WASM_ARG_LIST="14,2000" # Sample input for target function +WAT="True" # Executable is .wat or .wasm +WASI="False" # Executable has wasi format diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..ecacbb06 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM aflplusplus/aflplusplus + +ENV INTERFACE_PATH=/home/interface/ +ENV AFL_INPUT_DOCKER=/home/in/ +ENV AFL_OUTPUT_DOCKER=/home/out/ + +# Create the appropriate directories +RUN mkdir -p $INTERFACE_PATH +RUN mkdir -p $AFL_INPUT_DOCKER +RUN mkdir -p $AFL_OUTPUT_DOCKER +WORKDIR $INTERFACE_PATH + +ADD ./ $INTERFACE_PATH + +RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp +RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp +RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp diff --git a/docker-compose.fuzzing.yml b/docker-compose.fuzzing.yml new file mode 100644 index 00000000..46e17e22 --- /dev/null +++ b/docker-compose.fuzzing.yml @@ -0,0 +1,26 @@ +# 1. Configure ./.env file +# 2. docker-compose -f docker-compose.fuzzing.yml up --build + +version: '3.7' + +services: + swam_server: + build: ../ + entrypoint: ${REPO_PATH_DOCKER}/fuzzer/entrypoint_mill_server.sh + env_file: + - ./.env + volumes: + - ${WASM_PATH_LOCAL}:${WASM_PATH_DOCKER} + - ${SWAM_OUTPUT_LOCAL}:${SWAM_OUTPUT_DOCKER} + expose: + - 9999 # TODO: Pass this to afl_interface + + afl_interface: + build: ./ + entrypoint: /src/entrypoint_afl.sh + env_file: + - ./.env + volumes: + - ${AFL_OUTPUT_LOCAL}:${AFL_OUTPUT_DOCKER} + depends_on: + - swam_server diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh index 41423c67..9b80fbae 100644 --- a/entrypoint_afl.sh +++ b/entrypoint_afl.sh @@ -1,17 +1,9 @@ #!/bin/bash -# Run server in Swam first (example with fibo.wat): -# >> mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /Users/vincent/not_in_cloud/Codes/KTH/swam/examples/docs/fibo.wat +cd $INTERFACE_PATH -cd /src/ - -# TODO: Put this into build of new image with AFLPlusPlus as base -g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp -g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp -g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp - -PREPARED_INPUT_PATH="./prepared_input.dat" +PREPARED_INPUT_PATH="$AFL_INPUT_DOCKER/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) -afl-fuzz -i /src/in -o out -m none -d -- /src/interface.out @@ $REQUIRED_BYTES +afl-fuzz -i $AFL_INPUT_DOCKER -o $AFL_OUTPUT_DOCKER -m none -d -- "${INTERFACE_PATH}interface.out" @@ $REQUIRED_BYTES diff --git a/entrypoint_mill_server.sh b/entrypoint_mill_server.sh new file mode 100644 index 00000000..08f893d2 --- /dev/null +++ b/entrypoint_mill_server.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# REPO_PATH_DOCKER=/home/swam/ +# SWAM_OUTPUT_DOCKER=/home/out/ +# WASM_PATH_DOCKER=/home/wasm + +# Get first wasm/wat from $WASM_PATH_DOCKER directory +WASM_OR_WAT_FILE="" +if [ $WAT == "True" ]; then + wat_files=( ${WASM_PATH_DOCKER}*.wat ) + WASM_OR_WAT_FILE=${wat_files[0]} +else + wasm_files=( ${WASM_PATH_DOCKER}*.wasm ) + WASM_OR_WAT_FILE=${wasm_files[0]} +fi +echo "WASM_OR_WAT_FILE: $WASM_OR_WAT_FILE" + +# Parse WASM_ARG_TYPES_LIST: "Int64,Int32" to "--argType Int64 --argType Int32" +ALL_ARG_TYPES="" +IFS=',' read -r -a array <<< "$WASM_ARG_TYPES_LIST" +for element in "${array[@]}" +do + ALL_ARG_TYPES="$ALL_ARG_TYPES --argType $element" +done +echo "ALL_ARG_TYPES: $ALL_ARG_TYPES" + +if [ $WAT == "True" ]; then WAT_ARG="--wat"; fi +if [ $WASI == "True" ]; then WASI_ARG="--wasi"; fi + +cd $REPO_PATH_DOCKER + +mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE' diff --git a/socket_client.cpp b/socket_client.cpp index 0990b612..ee98d291 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -11,6 +11,7 @@ void error(const char *msg) exit(0); } +// TODO: Use input parameters (port & host) here int connectToServer() { int sockfd; From cae8c3f7cd59dd40abdae1186f9cf8e760659a20 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 10 Jul 2020 17:44:47 +0200 Subject: [PATCH 19/74] Exchanged nightscape/scala-mill with custom scala/mill image. Took out mill compilation step in Dockerfile. --- entrypoint_mill_server.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/entrypoint_mill_server.sh b/entrypoint_mill_server.sh index 08f893d2..3cdf1561 100644 --- a/entrypoint_mill_server.sh +++ b/entrypoint_mill_server.sh @@ -1,16 +1,12 @@ #!/bin/bash -# REPO_PATH_DOCKER=/home/swam/ -# SWAM_OUTPUT_DOCKER=/home/out/ -# WASM_PATH_DOCKER=/home/wasm - # Get first wasm/wat from $WASM_PATH_DOCKER directory WASM_OR_WAT_FILE="" if [ $WAT == "True" ]; then - wat_files=( ${WASM_PATH_DOCKER}*.wat ) + wat_files=( ${WASM_PATH_DOCKER}/*.wat ) WASM_OR_WAT_FILE=${wat_files[0]} else - wasm_files=( ${WASM_PATH_DOCKER}*.wasm ) + wasm_files=( ${WASM_PATH_DOCKER}/*.wasm ) WASM_OR_WAT_FILE=${wasm_files[0]} fi echo "WASM_OR_WAT_FILE: $WASM_OR_WAT_FILE" @@ -29,4 +25,4 @@ if [ $WASI == "True" ]; then WASI_ARG="--wasi"; fi cd $REPO_PATH_DOCKER -mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE' +mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE From 25598c8a005b1d5c1360152ed22ce89149e48035 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 10 Jul 2020 17:49:00 +0200 Subject: [PATCH 20/74] Added volumes for scala compile steps. Mounted custom logs for AFL container. --- .env | 37 +++++++++++++++++++++++++++++-------- Dockerfile | 10 +++++++--- docker-compose.fuzzing.yml | 20 ++++++++++++++------ entrypoint_afl.sh | 2 +- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/.env b/.env index c6e27a4e..4a84d039 100644 --- a/.env +++ b/.env @@ -1,8 +1,29 @@ -WASM_PATH_LOCAL="" # Path to our local .wasm/.wat executable -AFL_OUTPUT_LOCAL="" # Path on our local machine for us to read AFL's output -SWAM_OUTPUT_LOCAL="" # Path on our local machine for us to read SWAM's output (if any) -TARGET_FUNCTION="_start" # Function to be executed in .wasm/.wat ("_start" is default) -WASM_ARG_TYPES_LIST="Int64,Int32" # Parameter types for target function -WASM_ARG_LIST="14,2000" # Sample input for target function -WAT="True" # Executable is .wat or .wasm -WASI="False" # Executable has wasi format +# Path to our local .wasm/.wat executable +WASM_PATH_LOCAL=/Users/vincent/not_in_cloud/folder_with_wat_file + +# Path on our local machine for us to read AFL's output +AFL_OUTPUT_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/out + +# Path on our local machine for us to read our own logs +LOGS_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/logs + +# Path on our local machine for us to read SWAM's output (if any) +# SWAM_OUTPUT_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/out + +# Function to be executed in .wasm/.wat ("_start" is default) +TARGET_FUNCTION=clever + +# Parameter types for target function +WASM_ARG_TYPES_LIST=Int64 + +# Sample input for target function +WASM_ARG_LIST=14 + +# Executable is .wat or .wasm +WAT=True + +# Executable has wasi format +WASI=False + +##### No need to change: ##### +SWAM_SOCKET_PORT=9999 diff --git a/Dockerfile b/Dockerfile index ecacbb06..4b1971d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,15 @@ FROM aflplusplus/aflplusplus -ENV INTERFACE_PATH=/home/interface/ -ENV AFL_INPUT_DOCKER=/home/in/ -ENV AFL_OUTPUT_DOCKER=/home/out/ +ENV INTERFACE_PATH=/home/interface +ENV AFL_INPUT_DOCKER=/home/in +ENV AFL_OUTPUT_DOCKER=/home/out +ENV LOGS_DOCKER=/home/logs # Create the appropriate directories RUN mkdir -p $INTERFACE_PATH RUN mkdir -p $AFL_INPUT_DOCKER RUN mkdir -p $AFL_OUTPUT_DOCKER +RUN mkdir -p $LOGS_DOCKER WORKDIR $INTERFACE_PATH ADD ./ $INTERFACE_PATH @@ -15,3 +17,5 @@ ADD ./ $INTERFACE_PATH RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp + +RUN chmod +x $INTERFACE_PATH/entrypoint_afl.sh diff --git a/docker-compose.fuzzing.yml b/docker-compose.fuzzing.yml index 46e17e22..26df6c40 100644 --- a/docker-compose.fuzzing.yml +++ b/docker-compose.fuzzing.yml @@ -6,21 +6,29 @@ version: '3.7' services: swam_server: build: ../ - entrypoint: ${REPO_PATH_DOCKER}/fuzzer/entrypoint_mill_server.sh + entrypoint: /home/swam/fuzzer/entrypoint_mill_server.sh env_file: - ./.env volumes: - - ${WASM_PATH_LOCAL}:${WASM_PATH_DOCKER} - - ${SWAM_OUTPUT_LOCAL}:${SWAM_OUTPUT_DOCKER} + - ${WASM_PATH_LOCAL}:/home/wasm/ + - compiled_sources:/home/swam/out/ + - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 expose: - - 9999 # TODO: Pass this to afl_interface + - ${SWAM_SOCKET_PORT} afl_interface: build: ./ - entrypoint: /src/entrypoint_afl.sh + entrypoint: /home/interface/entrypoint_afl.sh env_file: - ./.env + environment: + SWAM_CONTAINER: swam_server volumes: - - ${AFL_OUTPUT_LOCAL}:${AFL_OUTPUT_DOCKER} + - ${AFL_OUTPUT_LOCAL}:/home/out/ + - ${LOGS_LOCAL}:/home/logs/ depends_on: - swam_server + +volumes: + compiled_sources: + maven_data: diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh index 9b80fbae..4a28a0d6 100644 --- a/entrypoint_afl.sh +++ b/entrypoint_afl.sh @@ -6,4 +6,4 @@ PREPARED_INPUT_PATH="$AFL_INPUT_DOCKER/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) -afl-fuzz -i $AFL_INPUT_DOCKER -o $AFL_OUTPUT_DOCKER -m none -d -- "${INTERFACE_PATH}interface.out" @@ $REQUIRED_BYTES +afl-fuzz -i $AFL_INPUT_DOCKER -o $AFL_OUTPUT_DOCKER -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES From ca8f8fd51478810435d19af004844dc9eddca017 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 10 Jul 2020 17:52:16 +0200 Subject: [PATCH 21/74] Created wait_for_swam_socket(). Made host & port socket variable. --- interface.cpp | 45 ++++++++++++++++++++++++++++++++++---------- interface.h | 3 +++ prepare_wasm_input.h | 1 + run_client.cpp | 2 +- socket_client.cpp | 19 +++++++++++-------- socket_client.h | 7 ++++--- 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/interface.cpp b/interface.cpp index 85ed5360..8b0dff3d 100644 --- a/interface.cpp +++ b/interface.cpp @@ -5,7 +5,8 @@ void LOG(std::string some_string) { - log("interface.log", some_string); + std::string LOGS_DOCKER = parseEnvVariables((char *)"LOGS_DOCKER"); + log(LOGS_DOCKER + "/interface.log", some_string); } std::vector readFileToVector(const std::string &filename) @@ -47,7 +48,8 @@ void log_file(char *filename) } } -void fillTraceDummyData(uint8_t *trace_bits) { +void fillTraceDummyData(uint8_t *trace_bits) +{ srand(time(NULL)); for (int i = 0; i < 10; i++) { @@ -61,11 +63,10 @@ void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits) // Read path coverage from readBuffer into trace_bits for (int i = 1; i < sizeReadBuffer; i++) { - trace_bits[i-1] += readBuffer[i]; + trace_bits[i - 1] += readBuffer[i]; } } - void main_fuzz( char *fuzzed_input, uint8_t *trace_bits, @@ -74,17 +75,19 @@ void main_fuzz( log_file(fuzzed_input); char sendBuffer[requiredBytes]; - std::memcpy(sendBuffer, fuzzed_input, sizeof(sendBuffer)); // Read first x bytes of fuzzed_input into tempBuffer + memcpy(sendBuffer, fuzzed_input, sizeof(sendBuffer)); // Read first x bytes of fuzzed_input into tempBuffer std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer - char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code + char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code + + std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); + std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); - runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); // Read exit code from readBuffer and exit with same code exit(readBuffer[0]); - } void fork_server(char *fuzzed_input, uint8_t *trace_bits, int requiredBytes) @@ -204,17 +207,39 @@ void log_args(int argc, char *argv[]) } } +void wait_for_swam_socket() +{ + std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); + std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); + LOG("SWAM_CONTAINER: " + SWAM_CONTAINER); + LOG("SWAM_SOCKET_PORT: " + SWAM_SOCKET_PORT); + + LOG("Waiting for Swam server..."); + while (true) { + try { + int sockfd = connectToServer(&SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); + close(sockfd); + break; + } catch (...) { + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + } + } + LOG("Swam is online!"); +} + int main(int argc, char *argv[]) { LOG("########## NEW MAIN ##########"); log_args(argc, argv); - + char *fuzzed_input = argv[1]; int requiredBytes = atoi(argv[2]); uint8_t *trace_bits = getShm(); - trace_bits[0]++; // Mark a location to show we are instrumented + trace_bits[0]++; // Mark a location to show we are instrumented + + void wait_for_swam_socket(); fork_server(fuzzed_input, trace_bits, requiredBytes); diff --git a/interface.h b/interface.h index b9cb4259..bbfa0379 100644 --- a/interface.h +++ b/interface.h @@ -13,5 +13,8 @@ #include #include #include +#include +#include +#include #endif \ No newline at end of file diff --git a/prepare_wasm_input.h b/prepare_wasm_input.h index cc3deaea..29fb1355 100644 --- a/prepare_wasm_input.h +++ b/prepare_wasm_input.h @@ -11,5 +11,6 @@ #include #include #include +#include #endif \ No newline at end of file diff --git a/run_client.cpp b/run_client.cpp index ea6c7a27..448d2247 100644 --- a/run_client.cpp +++ b/run_client.cpp @@ -12,6 +12,6 @@ int main(int argc, char *argv[]) readBinaryToBuffer(sendBuffer, fileSize, inputFile); std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of sendBuffer - runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer); + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, "localhost", 9999); exit(0); }; \ No newline at end of file diff --git a/socket_client.cpp b/socket_client.cpp index ee98d291..aa4fdeef 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -1,7 +1,5 @@ #include "socket_client.h" -#define SOCKET_PORT 9999 -#define SOCKET_HOST "localhost" // Most code based on: https://www.bogotobogo.com/cplusplus/sockets_server_client.php @@ -11,8 +9,7 @@ void error(const char *msg) exit(0); } -// TODO: Use input parameters (port & host) here -int connectToServer() +int connectToServer(char *socket_hostname, int socket_port) { int sockfd; struct hostent *server; @@ -23,7 +20,7 @@ int connectToServer() if (sockfd < 0) error("ERROR opening socket"); - server = gethostbyname(SOCKET_HOST); + server = gethostbyname(socket_hostname); if (server == NULL) { @@ -39,7 +36,7 @@ int connectToServer() (char *)&serv_addr.sin_addr.s_addr, server->h_length); - serv_addr.sin_port = htons(SOCKET_PORT); + serv_addr.sin_port = htons(socket_port); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) error("ERROR connecting"); @@ -63,9 +60,15 @@ void clientRead(int sockfd, char *readBuffer, int sizeBuffer) printf("Received message!\n"); } -void runClient(int sizeSendBuffer, char *sendBuffer, int sizeReadBuffer, char *readBuffer) +void runClient( + int sizeSendBuffer, + char *sendBuffer, + int sizeReadBuffer, + char *readBuffer, + char *socket_hostname, + int socket_port) { - int sockfd = connectToServer(); + int sockfd = connectToServer(socket_hostname, socket_port); clientWrite(sockfd, sendBuffer, sizeSendBuffer); clientRead(sockfd, readBuffer, sizeReadBuffer); close(sockfd); diff --git a/socket_client.h b/socket_client.h index 80ba2139..f99c2521 100644 --- a/socket_client.h +++ b/socket_client.h @@ -13,11 +13,12 @@ #include #include #include +#include void error(const char *); -int connectToServer(); +int connectToServer(char *, int); void clientWrite(int, char*, int); void clientRead(int, char*, int); -void runClient(int, char*, int, char*); +void runClient(int, char*, int, char*, char *, int); -#endif \ No newline at end of file +#endif From 518ac092d758af97b27f5a60fcc6bd9af682bef7 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 13 Jul 2020 14:26:53 +0200 Subject: [PATCH 22/74] Renamed AFL env vars --- .env | 2 +- Dockerfile | 8 ++++---- docker-compose.fuzzing.yml | 2 +- entrypoint_afl.sh | 5 +++-- interface.cpp | 5 ++--- run_client.cpp | 4 +++- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.env b/.env index 4a84d039..899366ef 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ WASM_PATH_LOCAL=/Users/vincent/not_in_cloud/folder_with_wat_file # Path on our local machine for us to read AFL's output -AFL_OUTPUT_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/out +OUTPUT_LOCAL_AFL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/out # Path on our local machine for us to read our own logs LOGS_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/logs diff --git a/Dockerfile b/Dockerfile index 4b1971d8..aa29d8f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,14 @@ FROM aflplusplus/aflplusplus ENV INTERFACE_PATH=/home/interface -ENV AFL_INPUT_DOCKER=/home/in -ENV AFL_OUTPUT_DOCKER=/home/out +ENV INPUT_DOCKER_AFL=/home/in +ENV OUTPUT_DOCKER_AFL=/home/out ENV LOGS_DOCKER=/home/logs # Create the appropriate directories RUN mkdir -p $INTERFACE_PATH -RUN mkdir -p $AFL_INPUT_DOCKER -RUN mkdir -p $AFL_OUTPUT_DOCKER +RUN mkdir -p $INPUT_DOCKER_AFL +RUN mkdir -p $OUTPUT_DOCKER_AFL RUN mkdir -p $LOGS_DOCKER WORKDIR $INTERFACE_PATH diff --git a/docker-compose.fuzzing.yml b/docker-compose.fuzzing.yml index 26df6c40..322ced81 100644 --- a/docker-compose.fuzzing.yml +++ b/docker-compose.fuzzing.yml @@ -24,7 +24,7 @@ services: environment: SWAM_CONTAINER: swam_server volumes: - - ${AFL_OUTPUT_LOCAL}:/home/out/ + - ${OUTPUT_LOCAL_AFL}:/home/out/ - ${LOGS_LOCAL}:/home/logs/ depends_on: - swam_server diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh index 4a28a0d6..71f85227 100644 --- a/entrypoint_afl.sh +++ b/entrypoint_afl.sh @@ -2,8 +2,9 @@ cd $INTERFACE_PATH -PREPARED_INPUT_PATH="$AFL_INPUT_DOCKER/prepared_input.dat" +PREPARED_INPUT_PATH="$INPUT_DOCKER_AFL/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) -afl-fuzz -i $AFL_INPUT_DOCKER -o $AFL_OUTPUT_DOCKER -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES +echo "afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- ${INTERFACE_PATH}/interface.out @@ $REQUIRED_BYTES" +afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES diff --git a/interface.cpp b/interface.cpp index 8b0dff3d..009ad859 100644 --- a/interface.cpp +++ b/interface.cpp @@ -1,7 +1,6 @@ #include "interface.h" #define AFL_SHM_SIZE 65536 -#define SHM_ENV_VAR "__AFL_SHM_ID" void LOG(std::string some_string) { @@ -24,7 +23,7 @@ std::vector readFileToVector(const std::string &filename) uint8_t *getShm() { - std::string shmStr = parseEnvVariables((char *)SHM_ENV_VAR); + std::string shmStr = parseEnvVariables((char *)"__AFL_SHM_ID"); LOG("shmStr: " + shmStr); key_t key = std::stoi(shmStr); @@ -239,7 +238,7 @@ int main(int argc, char *argv[]) uint8_t *trace_bits = getShm(); trace_bits[0]++; // Mark a location to show we are instrumented - void wait_for_swam_socket(); + wait_for_swam_socket(); fork_server(fuzzed_input, trace_bits, requiredBytes); diff --git a/run_client.cpp b/run_client.cpp index 448d2247..d5a86c14 100644 --- a/run_client.cpp +++ b/run_client.cpp @@ -1,6 +1,8 @@ #include "socket_client.h" #define AFL_SHM_SIZE 65536 +// This is to test whether the SWAM Server is able to receive and read +// data sent by the client properly int main(int argc, char *argv[]) { std::string inputFile = (std::string) argv[1]; @@ -14,4 +16,4 @@ int main(int argc, char *argv[]) runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, "localhost", 9999); exit(0); -}; \ No newline at end of file +}; From b71f7402ab9475ce69bfcb38a8d60481cb3aa2f6 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 13 Jul 2020 14:28:48 +0200 Subject: [PATCH 23/74] Extracted wait_for_server to afl-entrypoint; Added AFL dummy-testing setting. --- .dockerignore | 2 ++ .env | 3 +++ Dockerfile | 1 + entrypoint_afl.sh | 2 ++ interface.cpp | 28 ++++++---------------------- interface.h | 2 -- socket_client.cpp | 3 ++- wait_for_server.cpp | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 .dockerignore create mode 100644 wait_for_server.cpp diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..0ccb0e5f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +*.out +*.dat \ No newline at end of file diff --git a/.env b/.env index 899366ef..25e0bf40 100644 --- a/.env +++ b/.env @@ -1,3 +1,6 @@ +# Whether we are using AFL with Swam or just using dummy data +DUMMY_TESTING_AFL=False + # Path to our local .wasm/.wat executable WASM_PATH_LOCAL=/Users/vincent/not_in_cloud/folder_with_wat_file diff --git a/Dockerfile b/Dockerfile index aa29d8f9..7b4ca7bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,7 @@ ADD ./ $INTERFACE_PATH RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp +RUN g++ -o ./wait_for_server.out ./wait_for_server.cpp ./utils.cpp ./socket_client.cpp RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp RUN chmod +x $INTERFACE_PATH/entrypoint_afl.sh diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh index 71f85227..4e09f900 100644 --- a/entrypoint_afl.sh +++ b/entrypoint_afl.sh @@ -6,5 +6,7 @@ PREPARED_INPUT_PATH="$INPUT_DOCKER_AFL/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) +./wait_for_server.out + echo "afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- ${INTERFACE_PATH}/interface.out @@ $REQUIRED_BYTES" afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES diff --git a/interface.cpp b/interface.cpp index 009ad859..5e96acb5 100644 --- a/interface.cpp +++ b/interface.cpp @@ -81,6 +81,12 @@ void main_fuzz( std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); + std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL"); + if (DUMMY_TESTING_AFL == "True") { + fillTraceDummyData(trace_bits); + exit(0); + } + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); @@ -206,26 +212,6 @@ void log_args(int argc, char *argv[]) } } -void wait_for_swam_socket() -{ - std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); - std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); - LOG("SWAM_CONTAINER: " + SWAM_CONTAINER); - LOG("SWAM_SOCKET_PORT: " + SWAM_SOCKET_PORT); - - LOG("Waiting for Swam server..."); - while (true) { - try { - int sockfd = connectToServer(&SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); - close(sockfd); - break; - } catch (...) { - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); - } - } - LOG("Swam is online!"); -} - int main(int argc, char *argv[]) { LOG("########## NEW MAIN ##########"); @@ -238,8 +224,6 @@ int main(int argc, char *argv[]) uint8_t *trace_bits = getShm(); trace_bits[0]++; // Mark a location to show we are instrumented - wait_for_swam_socket(); - fork_server(fuzzed_input, trace_bits, requiredBytes); return 0; diff --git a/interface.h b/interface.h index bbfa0379..58a1b63a 100644 --- a/interface.h +++ b/interface.h @@ -14,7 +14,5 @@ #include #include #include -#include -#include #endif \ No newline at end of file diff --git a/socket_client.cpp b/socket_client.cpp index aa4fdeef..422f8086 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -6,7 +6,8 @@ void error(const char *msg) { perror(msg); - exit(0); + // exit(0); + throw std::runtime_error(msg); } int connectToServer(char *socket_hostname, int socket_port) diff --git a/wait_for_server.cpp b/wait_for_server.cpp new file mode 100644 index 00000000..a5749ae8 --- /dev/null +++ b/wait_for_server.cpp @@ -0,0 +1,34 @@ +#include "utils.h" +#include "socket_client.h" +#include +#include +#include + +void LOG(std::string some_string) +{ + std::string LOGS_DOCKER = parseEnvVariables((char *)"LOGS_DOCKER"); + log(LOGS_DOCKER + "/wait_for_server.log", some_string); +} + +int main(int argc, char *argv[]) +{ + std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); + std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); + LOG("SWAM_CONTAINER: " + SWAM_CONTAINER); + LOG("SWAM_SOCKET_PORT: " + SWAM_SOCKET_PORT); + + LOG("Waiting for Swam server..."); + int sockfd; + while (true) { + try { + sockfd = connectToServer(&SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); + LOG("sockfd: " + std::to_string(sockfd)); + close(sockfd); + break; + } catch (...) { + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + } + } + LOG("Swam is online!"); + exit(0); +} From a903c45f18235fa40d2e59606849c60a04d1071d Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 13 Jul 2020 16:59:12 +0200 Subject: [PATCH 24/74] Created logBuffer function in utils --- utils.cpp | 8 ++++++++ utils.h | 1 + wait_for_server.cpp | 3 +-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/utils.cpp b/utils.cpp index c6793d17..d9fc52c0 100644 --- a/utils.cpp +++ b/utils.cpp @@ -23,6 +23,14 @@ void printBuffer(int sizeBuffer, char *buffer) } } +void logBuffer(std::string filename, int sizeBuffer, char *buffer) +{ + for (int i = 0; i < sizeBuffer; i++) + { + log(filename, "buffer " + std::to_string(i) + ": " + buffer[i]); + } +} + long getFileSize(std::string filename) { struct stat stat_buf; diff --git a/utils.h b/utils.h index 44c6e9cb..eae42d7f 100644 --- a/utils.h +++ b/utils.h @@ -10,6 +10,7 @@ void log(std::string, std::string); void printBuffer(int, char *); +void logBuffer(std::string, int, char *); long getFileSize(std::string); void readBinaryToBuffer(char *, int, std::string); diff --git a/wait_for_server.cpp b/wait_for_server.cpp index a5749ae8..18e6eff9 100644 --- a/wait_for_server.cpp +++ b/wait_for_server.cpp @@ -22,11 +22,10 @@ int main(int argc, char *argv[]) while (true) { try { sockfd = connectToServer(&SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); - LOG("sockfd: " + std::to_string(sockfd)); close(sockfd); break; } catch (...) { - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + std::this_thread::sleep_for(std::chrono::milliseconds(4000)); } } LOG("Swam is online!"); From ace913f18d352f84cd7c0c54f619bf607a4b0eb7 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 13 Jul 2020 17:16:42 +0200 Subject: [PATCH 25/74] Using readBinaryToBuffer on fuzzed_input, since it is a filename.. --- interface.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/interface.cpp b/interface.cpp index 5e96acb5..db64fd8d 100644 --- a/interface.cpp +++ b/interface.cpp @@ -21,6 +21,15 @@ std::vector readFileToVector(const std::string &filename) return lines; } +void log_file(char *filename) +{ + std::vector vector = readFileToVector(filename); + for (int i = 0; i < vector.size(); ++i) + { + LOG(vector[i]); + } +} + uint8_t *getShm() { std::string shmStr = parseEnvVariables((char *)"__AFL_SHM_ID"); @@ -34,19 +43,10 @@ uint8_t *getShm() LOG("Failed to access shared memory"); exit(1); } - LOG("Shared memory attached. Value at loc 3 = " + trace_bits[3]); + LOG("Shared memory attached."); return trace_bits; } -void log_file(char *filename) -{ - std::vector vector = readFileToVector(filename); - for (int i = 0; i < vector.size(); ++i) - { - LOG(vector[i]); - } -} - void fillTraceDummyData(uint8_t *trace_bits) { srand(time(NULL)); @@ -71,21 +71,21 @@ void main_fuzz( uint8_t *trace_bits, int requiredBytes) { - log_file(fuzzed_input); + + std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL"); + if (DUMMY_TESTING_AFL == "True") { + fillTraceDummyData(trace_bits); + exit(0); + } char sendBuffer[requiredBytes]; - memcpy(sendBuffer, fuzzed_input, sizeof(sendBuffer)); // Read first x bytes of fuzzed_input into tempBuffer + readBinaryToBuffer(sendBuffer, sizeof(sendBuffer), (std::string)fuzzed_input); std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer + char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); - - std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL"); - if (DUMMY_TESTING_AFL == "True") { - fillTraceDummyData(trace_bits); - exit(0); - } runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); From 1b690d0b1faecc7ae01740d5142d74c23f288227 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 13 Jul 2020 17:47:58 +0200 Subject: [PATCH 26/74] Added catch for java.net.SocketException in Server.scala --- socket_client.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/socket_client.cpp b/socket_client.cpp index 422f8086..c571a934 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -50,7 +50,6 @@ void clientWrite(int sockfd, char *sendBuffer, int sizeBuffer) int n = write(sockfd, sendBuffer, sizeBuffer); if (n < 0) error("ERROR writing to socket"); - printf("Wrote to server!\n"); } void clientRead(int sockfd, char *readBuffer, int sizeBuffer) @@ -58,7 +57,6 @@ void clientRead(int sockfd, char *readBuffer, int sizeBuffer) int n = read(sockfd, readBuffer, sizeBuffer); if (n < 0) error("ERROR reading from socket"); - printf("Received message!\n"); } void runClient( From fee343a15ca4d1407a9060494fb3cccfe8bc23dd Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 14 Jul 2020 14:24:32 +0200 Subject: [PATCH 27/74] Updated README with proper Intro --- README.md | 59 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 7fa11750..59787d73 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,47 @@ ## Disclaimer -This is still in a prototyping stage. There are still many assumptions made on how AFL (and C++ and Scala and shared memory) works. +This is still in a prototyping stage. There are still many assumptions made on how AFL (and C++ and Scala and shared memory) works. Also, the coverage tool on which this plugin depends is currently still being developed. ## Introduction This plugin aims to act as an interface between SWAM and AFLplusplus. Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide a spin-off that applies AFL to WASM binaries. -The interface.cpp file fakes the behaviour of the instrumented binary and instead forwards the fuzzed inputs given by AFL to the SWAM engine, which in turn forwards it to the WASM binary. +In the standard AFL setup, C++ source code is compiled using the C++-compiler provided by AFLplusplus (afl-clang-fast++), which "instruments" the code to do additional operations during run-time. The instrumentation that AFL's compiler usually injects into the target source code includes accessing a shared memory, which serves as a communication channel between AFL and the resulting binary. This channel is used to report the coverage data of each execution to AFL, so that AFL can make smarter decisions on the upcoming input parameters. -Therefore, instead of using the C++-compiler provided by AFLplusplus (afl-clang-fast++), we use the "standard" g++ compiler and instead mimic the instrumentation behaviour in the interface. +In our case, we are given a WASM binary and an interpreter built with Scala - in other words, no code that we can instrument with afl-clang-fast++. The workaround we provide to deal with this problem, is that we have built an interface (interface.cpp), which fakes the behaviour of the instrumented binary and instead forwards the fuzzed inputs given by AFL to the SWAM engine via a socket. The SWAM engine then in turn forwards it to the instantiated WASM function. By hard-coding the instrumentation into the interface, we can use the "standard" g++ compiler to compile it. -AFL communicates with the target binary with a shared memory by default. Since Scala does not seem suitable for such low-level operations, we have instead created a low-level wrapper for SWAM, interface.cpp. Whilst the code coverage plugin for SWAM writes it's results to a fixed file, our interface wrapper reads from this file and then feeds the content into the shared memory used by AFL. +In SWAM, code coverage is handled in the package 'optin'. The socket server for SWAM on the other hand, is found in the package 'cli' and is executed with `mill cli.runserver `. The cli makes use of the 'optin' package and returns the coverage results including an exit code of the WASM file through the socket. Interface.cpp then parses this data and feeds the content into the shared memory used by AFL. Even though AFL provides modes to work without using coverage data from executions it has triggered (see qemo mode), it is more efficient when provided it. -## Test socket connection + SWAM with sample input (for fibo.wat) +## Parsing AFL's fuzzed inputs -1. Start the SWAM socket server +One major difference between C++ and WASM is that WASM only works with Int32/int, Int64/long, Float32/float and Float64/double. This matters, since AFL most commonly takes a config file as an input parameter, which is then first parsed from chars/strings to the corresponding type by the C++ code. Since a WASM function cannot simply receive a char or string and parse it to the int/long/float/double it needs, we need to do this manually beforehand. + +To do this, we explicitly specify what argument types are required by the WASM function in the ./env file and also pass corresponding initial test parameters that work (also in the ./env file). We can then use the prepare_wasm_input.cpp file to write these initial input parameters into an input file with the correct bit representation. By reading this file at the beginning of the execution, the interface is also aware of how many bytes are exactly required by the WASM function, which helps when sending the correct data size towards the server socket or printing output. Furthermore, since the way AFL finds errors in the code is by flipping "random" bits in the config file, these bits need to be preserved without any changes when they are forwarded to SWAM through the socket. + +Since the argument types for the WASM function are written as environmental variables, we can also parse them before initialising the SWAM socket server. The server then also knows exactly how to interpret the incoming bytes and how to feed them to the instantiated WASM function. + +## Optimisations + +### Done + +1. **#SPEED**: SWAM is continuously running. It is not required to re-boot the JVM for every socket message it receives. + +1. **#SPEED**: The SWAM socket server only instantiates the given WASM file/function once. Executing the instantiated function when receiving a message through the socket is equivalent to executing a fixed Scala function in the source code. + +1. **#PORTABILITY**: Both the SWAM engine and AFLplusplus are dockerized in two separate containers and are given a corresponding docker-compose.fuzzing.yml setup. All required configuration is to be found in fuzzing/.env. + +### To Do + +1. **#SPEED**: Currently, the socket server is working synchronously and is incapable of handling multiple requests at the same time. There is also no setup built yet for multiple AFL instances to share the same output and work concurrently either. + +## Requirements + +To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see the main page of this repository on how to set up SWAM. + +## Test SWAM's socket server with sample input (for fibo.wat) + +1. Start the SWAM socket server. We want to run the "naive" function in the fibo.wat file. Since the function takes one long/Int64 as an input parameter, we need to specify this with the "--argType" option. ```bash mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /examples/docs/fibo.wat @@ -28,28 +54,17 @@ AFL communicates with the target binary with a shared memory by default. Since S ./run_test.sh ``` -## Run AFL on example ./examples/docs/fibo.wat - -**Disclaimer - this does not work yet, since the hosts & ports are not adjusted yet! Will be done in a later implementation using docker-compose.** +## Run -1. Start the SWAM Socket Server - - ```bash - mill -i cli.run run_server --wat --argType Int64 --main naive --out ./ /examples/docs/fibo.wat - ``` +1. Configure ./.env file -1. Run AFL with Docker +2. Execute docker-compose configuration ```bash - docker pull aflplusplus/aflplusplus - docker run - --volume /fuzzer:/src aflplusplus/aflplusplus - --entrypoint="/src/entrypoint_afl.sh" - -e "WASM_ARG_TYPES_LIST=Int64" - -e "WASM_ARG_LIST=15" + docker-compose -f docker-compose.fuzzing.yml up --build ``` -1. View ./interface.log for logs and ./out/ for AFL output +3. View ./logs/ for own logs and ./out/ for AFL output ## Credits From b66f45f8ed85e4a8c2131127e1dc8f5503930eba Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 14 Jul 2020 14:31:22 +0200 Subject: [PATCH 28/74] Renamed fuzzed_input --- interface.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface.cpp b/interface.cpp index db64fd8d..7514d814 100644 --- a/interface.cpp +++ b/interface.cpp @@ -67,7 +67,7 @@ void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits) } void main_fuzz( - char *fuzzed_input, + char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes) { @@ -79,7 +79,7 @@ void main_fuzz( } char sendBuffer[requiredBytes]; - readBinaryToBuffer(sendBuffer, sizeof(sendBuffer), (std::string)fuzzed_input); + 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 @@ -95,7 +95,7 @@ void main_fuzz( exit(readBuffer[0]); } -void fork_server(char *fuzzed_input, uint8_t *trace_bits, int requiredBytes) +void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes) { // The Fork server (Prototype of this code in Assembly): // https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html @@ -153,7 +153,7 @@ void fork_server(char *fuzzed_input, uint8_t *trace_bits, int requiredBytes) LOG("This is the child process."); close(198); close(199); - main_fuzz(fuzzed_input, trace_bits, requiredBytes); + main_fuzz(fuzzed_input_path, trace_bits, requiredBytes); exit(0); } @@ -218,13 +218,13 @@ int main(int argc, char *argv[]) log_args(argc, argv); - char *fuzzed_input = argv[1]; + char *fuzzed_input_path = argv[1]; int requiredBytes = atoi(argv[2]); uint8_t *trace_bits = getShm(); trace_bits[0]++; // Mark a location to show we are instrumented - fork_server(fuzzed_input, trace_bits, requiredBytes); + fork_server(fuzzed_input_path, trace_bits, requiredBytes); return 0; } From 2f2db85dcb881005e915c732f6e5b7ec0e650a84 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 14 Jul 2020 14:31:48 +0200 Subject: [PATCH 29/74] Small comments --- .env | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.env b/.env index 25e0bf40..02c6bdc3 100644 --- a/.env +++ b/.env @@ -1,6 +1,9 @@ # 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 our local .wasm/.wat executable WASM_PATH_LOCAL=/Users/vincent/not_in_cloud/folder_with_wat_file From 2ec99ea53b4dff0276960792acfc76ffad6ff8ba Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 15 Jul 2020 13:43:44 +0200 Subject: [PATCH 30/74] Added log examples to README --- README.md | 18 ++++++++++++++++++ docs/fibo_log_failing.png | Bin 0 -> 169111 bytes docs/fibo_log_working.png | Bin 0 -> 157671 bytes 3 files changed, 18 insertions(+) create mode 100644 docs/fibo_log_failing.png create mode 100644 docs/fibo_log_working.png diff --git a/README.md b/README.md index 59787d73..98202308 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,24 @@ To be able to run this on your machine, only Docker is required. If you want to 3. View ./logs/ for own logs and ./out/ for AFL output +## Example logs for fibo.wat with docker-compose configuration + +The following the Docker logs of the SWAM server + +1. receiving and parsing a message + +2. calculating the instantiated WASM function (clever fibonacci) with the received inputs + +3. gathering the coverage of the execution (currently still entirely random) + +4. sending back the coverage along with the exit code + +Fibonacci working | Fibonacci failing (number too high) +:-------------------------:|:-------------------------: +![pass](./docs/fibo_log_working.png) | ![pass](./docs/fibo_log_failing.png) + +In the case of running fibo.wat, a lot of crashes are registered by AFL, since essentially any "high" number causes the call stack to exhaust, which is not accounted for by the function in fibo.wat. + ## Credits - Initial idea and implementation (for Java): [Kelinci](https://github.com/isstac/kelinci) diff --git a/docs/fibo_log_failing.png b/docs/fibo_log_failing.png new file mode 100644 index 0000000000000000000000000000000000000000..f4e1bc16dffbd8aa9c02477df8829fb78ae67fa0 GIT binary patch literal 169111 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%0Dl(k&f2l+qxL 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 bTTI{NSNgzF`dd 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 z%0D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 Date: Wed, 15 Jul 2020 14:20:49 +0200 Subject: [PATCH 31/74] Added section on how to run without Docker in README --- .env | 4 ++-- README.md | 42 ++++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/.env b/.env index 02c6bdc3..a5953e9d 100644 --- a/.env +++ b/.env @@ -19,10 +19,10 @@ LOGS_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/logs # Function to be executed in .wasm/.wat ("_start" is default) TARGET_FUNCTION=clever -# Parameter types for target function +# Parameter types for target function. Comma-separated list of types Int32, Int64, Float32, Float64. WASM_ARG_TYPES_LIST=Int64 -# Sample input for target function +# Sample input for target function. Comma-separated list of numbers. WASM_ARG_LIST=14 # Executable is .wat or .wasm diff --git a/README.md b/README.md index 98202308..8d980fc9 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ This is still in a prototyping stage. There are still many assumptions made on h ## Introduction -This plugin aims to act as an interface between SWAM and AFLplusplus. Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide a spin-off that applies AFL to WASM binaries. +This plugin aims to act as an interface between SWAM and [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide a spin-off that applies AFL to WASM binaries. -In the standard AFL setup, C++ source code is compiled using the C++-compiler provided by AFLplusplus (afl-clang-fast++), which "instruments" the code to do additional operations during run-time. The instrumentation that AFL's compiler usually injects into the target source code includes accessing a shared memory, which serves as a communication channel between AFL and the resulting binary. This channel is used to report the coverage data of each execution to AFL, so that AFL can make smarter decisions on the upcoming input parameters. +In the standard AFL setup, C++ source code is compiled using the C++ compiler provided by AFLplusplus (afl-clang-fast++), which "instruments" the code to do additional operations during run-time. The instrumentation that AFL's compiler usually injects into the target source code includes accessing a shared memory, which serves as a communication channel between AFL and the resulting binary. This channel is used to report the coverage data of each execution to AFL, so that AFL can make smarter decisions on the upcoming input parameters. In our case, we are given a WASM binary and an interpreter built with Scala - in other words, no code that we can instrument with afl-clang-fast++. The workaround we provide to deal with this problem, is that we have built an interface (interface.cpp), which fakes the behaviour of the instrumented binary and instead forwards the fuzzed inputs given by AFL to the SWAM engine via a socket. The SWAM engine then in turn forwards it to the instantiated WASM function. By hard-coding the instrumentation into the interface, we can use the "standard" g++ compiler to compile it. @@ -22,23 +22,27 @@ To do this, we explicitly specify what argument types are required by the WASM f Since the argument types for the WASM function are written as environmental variables, we can also parse them before initialising the SWAM socket server. The server then also knows exactly how to interpret the incoming bytes and how to feed them to the instantiated WASM function. -## Optimisations +## Requirements -### Done +To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see the main page of this repository on how to set up SWAM. -1. **#SPEED**: SWAM is continuously running. It is not required to re-boot the JVM for every socket message it receives. +## Running with docker-compose -1. **#SPEED**: The SWAM socket server only instantiates the given WASM file/function once. Executing the instantiated function when receiving a message through the socket is equivalent to executing a fixed Scala function in the source code. +1. Configure ./.env file -1. **#PORTABILITY**: Both the SWAM engine and AFLplusplus are dockerized in two separate containers and are given a corresponding docker-compose.fuzzing.yml setup. All required configuration is to be found in fuzzing/.env. +2. Execute docker-compose configuration -### To Do + ```bash + docker-compose -f docker-compose.fuzzing.yml up --build + ``` -1. **#SPEED**: Currently, the socket server is working synchronously and is incapable of handling multiple requests at the same time. There is also no setup built yet for multiple AFL instances to share the same output and work concurrently either. +3. View ./logs/ for own logs and ./out/ for AFL output -## Requirements +## Running without Docker -To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see the main page of this repository on how to set up SWAM. +If you wish to run this plugin without using Docker, you will be required to install [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) and build SWAM with mill (see README of the root of this repository). Concerning AFLplusplus, running `make source-only` on the cloned repository along with installing the dependencies should suffice. + +All other setup steps are best documented in the Dockerfile in the root of this repository, the Dockerfile in this folder and in entrypoint_afl.sh + entrypoint_mill_server.sh. ## Test SWAM's socket server with sample input (for fibo.wat) @@ -54,17 +58,19 @@ To be able to run this on your machine, only Docker is required. If you want to ./run_test.sh ``` -## Run +## Optimisations -1. Configure ./.env file +### Done -2. Execute docker-compose configuration +1. **#SPEED**: SWAM is continuously running. It is not required to re-boot the JVM for every socket message it receives. - ```bash - docker-compose -f docker-compose.fuzzing.yml up --build - ``` +1. **#SPEED**: The SWAM socket server only instantiates the given WASM file/function once. Executing the instantiated function when receiving a message through the socket is equivalent to executing a fixed Scala function in the source code. -3. View ./logs/ for own logs and ./out/ for AFL output +1. **#PORTABILITY**: Both the SWAM engine and AFLplusplus are dockerized in two separate containers and are given a corresponding docker-compose.fuzzing.yml setup. All required configuration is to be found in fuzzing/.env. + +### To Do + +1. **#SPEED**: Currently, the socket server is working synchronously and is incapable of handling multiple requests at the same time. There is also no setup built yet for multiple AFL instances to share the same output and work concurrently either. ## Example logs for fibo.wat with docker-compose configuration From 052fd5cf47a7779600cd19328d1ceb33e1c601c8 Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Thu, 16 Jul 2020 08:02:19 +0200 Subject: [PATCH 32/74] up --- .env | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.env b/.env index a5953e9d..5b3bd342 100644 --- a/.env +++ b/.env @@ -5,16 +5,16 @@ DUMMY_TESTING_AFL=False LOG_LEVEL=Error # Path to our local .wasm/.wat executable -WASM_PATH_LOCAL=/Users/vincent/not_in_cloud/folder_with_wat_file +WASM_PATH_LOCAL=/tmp/fuzzer-wat_files # Path on our local machine for us to read AFL's output -OUTPUT_LOCAL_AFL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/out +OUTPUT_LOCAL_AFL=/tmp/fuzzer-out # Path on our local machine for us to read our own logs -LOGS_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/fuzzer/logs +LOGS_LOCAL=/tmp/fuzzer/fuzzerlogs # Path on our local machine for us to read SWAM's output (if any) -# SWAM_OUTPUT_LOCAL=/Users/vincent/not_in_cloud/Codes/KTH/swam/out +# SWAM_OUTPUT_LOCAL=/tmp/swam-out # Function to be executed in .wasm/.wat ("_start" is default) TARGET_FUNCTION=clever From d92a36dafc45c0d019066361129f5930b48ea83b Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 12:24:15 +0200 Subject: [PATCH 33/74] Using printf instead of LOG for wait_for_server --- wait_for_server.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/wait_for_server.cpp b/wait_for_server.cpp index 18e6eff9..aff62bf8 100644 --- a/wait_for_server.cpp +++ b/wait_for_server.cpp @@ -4,20 +4,14 @@ #include #include -void LOG(std::string some_string) -{ - std::string LOGS_DOCKER = parseEnvVariables((char *)"LOGS_DOCKER"); - log(LOGS_DOCKER + "/wait_for_server.log", some_string); -} int main(int argc, char *argv[]) { + setbuf(stdout, NULL); // For some reason stdout gets buffered until exit otherwise std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); - LOG("SWAM_CONTAINER: " + SWAM_CONTAINER); - LOG("SWAM_SOCKET_PORT: " + SWAM_SOCKET_PORT); - LOG("Waiting for Swam server..."); + printf("Waiting for Swam server...\n"); int sockfd; while (true) { try { @@ -25,9 +19,10 @@ int main(int argc, char *argv[]) close(sockfd); break; } catch (...) { + printf("Trying to connect again in 4 seconds...\n"); std::this_thread::sleep_for(std::chrono::milliseconds(4000)); } } - LOG("Swam is online!"); + printf("Can connect to Swam!\n"); exit(0); } From 1c7c9927ea18b381a2e95440ca816ac2513fb97e Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 12:26:51 +0200 Subject: [PATCH 34/74] Minor changes in prints in socket_client.cpp --- socket_client.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/socket_client.cpp b/socket_client.cpp index c571a934..cf7fa40f 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -5,8 +5,8 @@ void error(const char *msg) { + // fprintf("Socket: %s\n", msg); perror(msg); - // exit(0); throw std::runtime_error(msg); } @@ -19,13 +19,14 @@ int connectToServer(char *socket_hostname, int socket_port) sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) - error("ERROR opening socket"); + error("Error opening socket"); server = gethostbyname(socket_hostname); if (server == NULL) { - fprintf(stderr, "ERROR, no such host\n"); + // fprintf(stderr, "Error, no such host\n"); + perror("Error, no such host"); exit(0); } @@ -40,7 +41,7 @@ int connectToServer(char *socket_hostname, int socket_port) serv_addr.sin_port = htons(socket_port); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - error("ERROR connecting"); + error("Error connecting"); return sockfd; } @@ -49,14 +50,14 @@ void clientWrite(int sockfd, char *sendBuffer, int sizeBuffer) { int n = write(sockfd, sendBuffer, sizeBuffer); if (n < 0) - error("ERROR writing to socket"); + error("Error writing to socket"); } void clientRead(int sockfd, char *readBuffer, int sizeBuffer) { int n = read(sockfd, readBuffer, sizeBuffer); if (n < 0) - error("ERROR reading from socket"); + error("Error reading from socket"); } void runClient( From 5e11725522a851eaf3affa6d341c2167ea003921 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 13:33:58 +0200 Subject: [PATCH 35/74] Exiting with code 1 when socket host has crashed --- entrypoint_afl.sh | 4 ++++ socket_client.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/entrypoint_afl.sh b/entrypoint_afl.sh index 4e09f900..4f39ba55 100644 --- a/entrypoint_afl.sh +++ b/entrypoint_afl.sh @@ -8,5 +8,9 @@ REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) ./wait_for_server.out +if [ $? != 0 ]; then + exit 1 +fi + echo "afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- ${INTERFACE_PATH}/interface.out @@ $REQUIRED_BYTES" afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES diff --git a/socket_client.cpp b/socket_client.cpp index cf7fa40f..e2d93c36 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -27,7 +27,7 @@ int connectToServer(char *socket_hostname, int socket_port) { // fprintf(stderr, "Error, no such host\n"); perror("Error, no such host"); - exit(0); + exit(1); } bzero((char *)&serv_addr, sizeof(serv_addr)); // Maybe use memset From 644b9b2d2968e472011839e479a9bc8c08f93359 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 13:50:14 +0200 Subject: [PATCH 36/74] Added name of WASM executable as env var --- .env | 5 ++++- entrypoint_mill_server.sh | 11 ++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.env b/.env index 5b3bd342..dfe1ef5c 100644 --- a/.env +++ b/.env @@ -4,9 +4,12 @@ DUMMY_TESTING_AFL=False # (Not being used yet..) Error, Warn, Info, Debug LOG_LEVEL=Error -# Path to our local .wasm/.wat executable +# Path to the parent directory of our local .wasm/.wat executable WASM_PATH_LOCAL=/tmp/fuzzer-wat_files +# Name of our local .wasm/.wat executable +WASM_EXECUTABLE=fibo.wat + # Path on our local machine for us to read AFL's output OUTPUT_LOCAL_AFL=/tmp/fuzzer-out diff --git a/entrypoint_mill_server.sh b/entrypoint_mill_server.sh index 3cdf1561..0dad0202 100644 --- a/entrypoint_mill_server.sh +++ b/entrypoint_mill_server.sh @@ -1,14 +1,7 @@ #!/bin/bash -# Get first wasm/wat from $WASM_PATH_DOCKER directory -WASM_OR_WAT_FILE="" -if [ $WAT == "True" ]; then - wat_files=( ${WASM_PATH_DOCKER}/*.wat ) - WASM_OR_WAT_FILE=${wat_files[0]} -else - wasm_files=( ${WASM_PATH_DOCKER}/*.wasm ) - WASM_OR_WAT_FILE=${wasm_files[0]} -fi +# Get wasm/wat from $WASM_PATH_DOCKER directory +WASM_OR_WAT_FILE=${WASM_PATH_DOCKER}/${WASM_EXECUTABLE} echo "WASM_OR_WAT_FILE: $WASM_OR_WAT_FILE" # Parse WASM_ARG_TYPES_LIST: "Int64,Int32" to "--argType Int64 --argType Int32" From 6345c1d85b85bb7358bf099aecef30a893b978fc Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 15:09:51 +0200 Subject: [PATCH 37/74] Take out redundant env var WAT --- .env | 3 --- entrypoint_mill_server.sh | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.env b/.env index dfe1ef5c..ed7666ce 100644 --- a/.env +++ b/.env @@ -28,9 +28,6 @@ WASM_ARG_TYPES_LIST=Int64 # Sample input for target function. Comma-separated list of numbers. WASM_ARG_LIST=14 -# Executable is .wat or .wasm -WAT=True - # Executable has wasi format WASI=False diff --git a/entrypoint_mill_server.sh b/entrypoint_mill_server.sh index 0dad0202..b9e55276 100644 --- a/entrypoint_mill_server.sh +++ b/entrypoint_mill_server.sh @@ -13,9 +13,10 @@ do done echo "ALL_ARG_TYPES: $ALL_ARG_TYPES" -if [ $WAT == "True" ]; then WAT_ARG="--wat"; fi -if [ $WASI == "True" ]; then WASI_ARG="--wasi"; fi +if [[ $WASM_OR_WAT_FILE == *.wat ]]; then WAT_ARG="--wat"; fi +if [[ $WASI == "True" ]]; then WASI_ARG="--wasi"; fi cd $REPO_PATH_DOCKER +echo "mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE" mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE From e975212247ed01cd0de5855945e32ec824ff0ecd Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 15:27:50 +0200 Subject: [PATCH 38/74] Throw error when docker-compose env vars are empty --- docker-compose.fuzzing.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docker-compose.fuzzing.yml b/docker-compose.fuzzing.yml index 322ced81..5270dc5f 100644 --- a/docker-compose.fuzzing.yml +++ b/docker-compose.fuzzing.yml @@ -1,3 +1,7 @@ +# WARNING: +# The env variables used in this file (e.g. WASM_PATH_LOCAL) can only +# be read by a file named ".env". This is standard Docker behaviour. + # 1. Configure ./.env file # 2. docker-compose -f docker-compose.fuzzing.yml up --build @@ -10,11 +14,11 @@ services: env_file: - ./.env volumes: - - ${WASM_PATH_LOCAL}:/home/wasm/ + - ${WASM_PATH_LOCAL:?err}:/home/wasm/ - compiled_sources:/home/swam/out/ - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 expose: - - ${SWAM_SOCKET_PORT} + - ${SWAM_SOCKET_PORT:?err} afl_interface: build: ./ @@ -24,8 +28,8 @@ services: environment: SWAM_CONTAINER: swam_server volumes: - - ${OUTPUT_LOCAL_AFL}:/home/out/ - - ${LOGS_LOCAL}:/home/logs/ + - ${OUTPUT_LOCAL_AFL:?err}:/home/out/ + - ${LOGS_LOCAL:?err}:/home/logs/ depends_on: - swam_server From 8816b1a28826169d7c9a17168c7b8638f32e7ebf Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 16 Jul 2020 16:20:54 +0200 Subject: [PATCH 39/74] Folders for out-files (added in gitignore) --- .env | 2 +- README.md | 2 +- run_test.sh | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.env b/.env index ed7666ce..76bd5b95 100644 --- a/.env +++ b/.env @@ -11,7 +11,7 @@ WASM_PATH_LOCAL=/tmp/fuzzer-wat_files WASM_EXECUTABLE=fibo.wat # Path on our local machine for us to read AFL's output -OUTPUT_LOCAL_AFL=/tmp/fuzzer-out +OUTPUT_LOCAL_AFL=/tmp/afl_out # Path on our local machine for us to read our own logs LOGS_LOCAL=/tmp/fuzzer/fuzzerlogs diff --git a/README.md b/README.md index 8d980fc9..991b23a3 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ To be able to run this on your machine, only Docker is required. If you want to ## Running with docker-compose -1. Configure ./.env file +1. Configure ./.env file. Do not rename it or reference a different *.env file in docker-compose.fuzzing.yml! 2. Execute docker-compose configuration diff --git a/run_test.sh b/run_test.sh index 27d7da2a..3a504b62 100755 --- a/run_test.sh +++ b/run_test.sh @@ -9,8 +9,10 @@ export WASM_ARG_TYPES_LIST=Int64 export WASM_ARG_LIST=15 -g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp -g++ -o ./run_client.out ./run_client.cpp ./socket_client.cpp ./utils.cpp +mkdir -p ./cpp_out -./prepare_wasm_input.out "./prepared_input.dat" -./run_client.out "./prepared_input.dat" +g++ -o ./cpp_out/prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp +g++ -o ./cpp_out/run_client.out ./run_client.cpp ./socket_client.cpp ./utils.cpp + +./cpp_out/prepare_wasm_input.out "./cpp_out/prepared_input.dat" +./cpp_out/run_client.out "./cpp_out/prepared_input.dat" From b7f80f8090a3fc9a529557e0ee114269742322c6 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 17 Jul 2020 11:59:21 +0200 Subject: [PATCH 40/74] README: More details on building the tool with Docker --- README.md | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 991b23a3..a19d78f7 100644 --- a/README.md +++ b/README.md @@ -26,19 +26,39 @@ Since the argument types for the WASM function are written as environmental vari To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see the main page of this repository on how to set up SWAM. +## Building with docker-compose + +This tool creates two Docker containers, as specified in the docker-compose.fuzzing.yml file - one for the SWAM socket server (Dockerfile in the root of this repository) and one for the AFL socket client (Dockerfile in this directory). The only configuration parameters to building this are currently the SCALA_VERSION and the MILL_VERSION in SWAM's Dockerfile. Nonetheless, it should not be required to change these parameters as they are fitted to the code of this repostory. + +How to build: + +```bash +docker-compose -f docker-compose.fuzzing.yml build +``` + +### Mechanics of SWAM's Dockerfile + +We are not using the standard base image for the Scala Mill Build Tool [(nightscape/scala-mill)](https://hub.docker.com/r/nightscape/scala-mill/dockerfile), since it uses an older version of Scala and Mill. Our Dockerfile is however strongly based on theirs. + +Mill currently does not provide any command to [simply install dependencies without compiling the source code](https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code). Compiling the source code is done with `mill .compile` and the reason why this is not included in the Dockerfile is to avoid the overhead of downloading all the same dependencies everytime source code is altered. The current workaround is to store the compiled sources along with the dependencies in volumes, which can be accessed during runtime and are specified in the docker-compose.fuzzing.yml file ("compiled_sources" & "maven_data"). + +### Mechanics of AFL's Dockerfile + +This image uses the [official image of AFLplusplus](https://hub.docker.com/r/aflplusplus/aflplusplus/) as a base, which contains the full configuration of AFL pre-installed. It then builds the C++ files of this folder with the standard Ubuntu g++ compiler (not the one provided by AFL). The C++ files are therefore not instrumented. The resulting executables are later accessed during run-time. + ## Running with docker-compose -1. Configure ./.env file. Do not rename it or reference a different *.env file in docker-compose.fuzzing.yml! +1. Configure ./.env file. This is where you specify which .wasm/.wat file & function you want to fuzzing and of what types it's input parameters are. Furthermore, it requires to provide a set of working input parameters, which are used in AFL test-runs and can be regarded as AFL's "seed" to random input. *WARNING: Do not rename this file or reference a different \*.env file in docker-compose.fuzzing.yml!* 2. Execute docker-compose configuration ```bash - docker-compose -f docker-compose.fuzzing.yml up --build + docker-compose -f docker-compose.fuzzing.yml up ``` -3. View ./logs/ for own logs and ./out/ for AFL output +3. View AFL's results and own logs in the folders which were specified in the .env file. -## Running without Docker +## Building & running without Docker If you wish to run this plugin without using Docker, you will be required to install [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) and build SWAM with mill (see README of the root of this repository). Concerning AFLplusplus, running `make source-only` on the cloned repository along with installing the dependencies should suffice. @@ -84,9 +104,9 @@ The following the Docker logs of the SWAM server 4. sending back the coverage along with the exit code -Fibonacci working | Fibonacci failing (number too high) -:-------------------------:|:-------------------------: -![pass](./docs/fibo_log_working.png) | ![pass](./docs/fibo_log_failing.png) +| Fibonacci working | Fibonacci failing (number too high) | +| :----------------------------------: | :----------------------------------: | +| ![pass](./docs/fibo_log_working.png) | ![pass](./docs/fibo_log_failing.png) | In the case of running fibo.wat, a lot of crashes are registered by AFL, since essentially any "high" number causes the call stack to exhaust, which is not accounted for by the function in fibo.wat. From f14d4e906f4884d67f14986601fbf0752d736c16 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 17 Jul 2020 12:28:33 +0200 Subject: [PATCH 41/74] Note on where exactly SWAM is compiled --- README.md | 2 +- entrypoint_mill_server.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a19d78f7..1a9ecbad 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ docker-compose -f docker-compose.fuzzing.yml build We are not using the standard base image for the Scala Mill Build Tool [(nightscape/scala-mill)](https://hub.docker.com/r/nightscape/scala-mill/dockerfile), since it uses an older version of Scala and Mill. Our Dockerfile is however strongly based on theirs. -Mill currently does not provide any command to [simply install dependencies without compiling the source code](https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code). Compiling the source code is done with `mill .compile` and the reason why this is not included in the Dockerfile is to avoid the overhead of downloading all the same dependencies everytime source code is altered. The current workaround is to store the compiled sources along with the dependencies in volumes, which can be accessed during runtime and are specified in the docker-compose.fuzzing.yml file ("compiled_sources" & "maven_data"). +Mill currently does not provide any command to [simply install dependencies without compiling the source code](https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code). Compiling the source code is done with `mill .compile` and the reason why this is not included in the Dockerfile is to avoid the overhead of downloading all the same dependencies everytime source code is altered. The current workaround is to store the compiled sources along with the dependencies in volumes, which can be accessed during runtime and are specified in the docker-compose.fuzzing.yml file ("compiled_sources" & "maven_data"). SWAM's compilation is therefore delayed to the entrypoint (./entrypoint_mill_server.sh) and is encompassed in the `mill -i cli.run run_server ` command. ### Mechanics of AFL's Dockerfile diff --git a/entrypoint_mill_server.sh b/entrypoint_mill_server.sh index b9e55276..2ce6c72a 100644 --- a/entrypoint_mill_server.sh +++ b/entrypoint_mill_server.sh @@ -18,5 +18,6 @@ if [[ $WASI == "True" ]]; then WASI_ARG="--wasi"; fi cd $REPO_PATH_DOCKER +# This also compiles the cli package in case source code / dependencies have changed: echo "mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE" mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE From 055e62c7b357b2fc9a470671c1151aa7d7971c02 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Fri, 24 Jul 2020 15:40:28 +0200 Subject: [PATCH 42/74] Removed logs in interface.cpp --- interface.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/interface.cpp b/interface.cpp index 7514d814..20ce02d4 100644 --- a/interface.cpp +++ b/interface.cpp @@ -109,8 +109,9 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes int status = 0; - LOG("Starting the 'Fork server handshake'."); - LOG("Phone home and tell AFL that we're OK."); + // Starting the 'Fork server handshake' + + // Phone home and tell AFL that we're OK if (write(199, &status, 4) != 4) { LOG("Write failed"); @@ -122,10 +123,8 @@ 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) { - LOG("##### NEW FORK RUN #####"); - + // Wait for AFL by reading from the pipe. // This will block until AFL sends us something. Abort if read fails. - LOG("Wait for AFL by reading from the pipe."); if (read(198, &status, 4) != 4) { LOG("Read failed"); @@ -133,7 +132,6 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes close(199); exit(1); } - LOG("Read status: " + std::to_string(status)); /* Programm runs concurrently in two forks from here @@ -150,14 +148,14 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes } else if (pid == 0) { - LOG("This is the child process."); + // This is the child process close(198); close(199); main_fuzz(fuzzed_input_path, trace_bits, requiredBytes); exit(0); } - LOG("Writing child pid to parent: " + std::to_string(pid)); + // Writing child pid to parent write(199, &pid, 4); /* @@ -168,7 +166,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes the waiting, then send the status code to the fuzzer. */ - LOG("Waiting for child..."); + // Waiting for child if (waitpid(pid, &status, 0) <= 0) // Technically only fails at -1; 0 means still running { LOG("waitpid() failed."); @@ -214,8 +212,6 @@ void log_args(int argc, char *argv[]) int main(int argc, char *argv[]) { - LOG("########## NEW MAIN ##########"); - log_args(argc, argv); char *fuzzed_input_path = argv[1]; From 1952fddbe78e8eac656a18baf75c2e39b09b9f55 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 27 Jul 2020 16:02:19 +0200 Subject: [PATCH 43/74] Looping read() in socket_client.cpp, so no connection errors --- socket_client.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/socket_client.cpp b/socket_client.cpp index e2d93c36..314bd7ce 100644 --- a/socket_client.cpp +++ b/socket_client.cpp @@ -1,6 +1,5 @@ #include "socket_client.h" - // Most code based on: https://www.bogotobogo.com/cplusplus/sockets_server_client.php void error(const char *msg) @@ -16,6 +15,12 @@ int connectToServer(char *socket_hostname, int socket_port) struct hostent *server; struct sockaddr_in serv_addr; + /* + SOCK_STREAM: TCP (reliable, connection oriented) + SOCK_DGRAM: UDP (unreliable, connectionless) + AF_INET: IPv4 protocol + AF_INET6: IPv6 protocol + */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) @@ -55,9 +60,17 @@ void clientWrite(int sockfd, char *sendBuffer, int sizeBuffer) void clientRead(int sockfd, char *readBuffer, int sizeBuffer) { - int n = read(sockfd, readBuffer, sizeBuffer); - if (n < 0) - error("Error reading from socket"); + int n = 0; + while (n < sizeBuffer) + { + // Occasionally, read() finishes reading before all the data has + // been written to the socket by the SWAM server. Therefore, this + // is in a loop. + int nNew = read(sockfd, readBuffer + n, sizeBuffer - n); + if (nNew < 0) + error("Error reading from socket"); + n = n + nNew; + } } void runClient( From 62171fe481706061be56380cd898bb9651eff09b Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 27 Jul 2020 18:40:16 +0200 Subject: [PATCH 44/74] Minor comments --- docker-compose.fuzzing.yml | 1 + interface.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docker-compose.fuzzing.yml b/docker-compose.fuzzing.yml index 5270dc5f..1b97ab25 100644 --- a/docker-compose.fuzzing.yml +++ b/docker-compose.fuzzing.yml @@ -32,6 +32,7 @@ services: - ${LOGS_LOCAL:?err}:/home/logs/ depends_on: - swam_server + # tty: true volumes: compiled_sources: diff --git a/interface.cpp b/interface.cpp index 20ce02d4..458834c1 100644 --- a/interface.cpp +++ b/interface.cpp @@ -73,7 +73,8 @@ void main_fuzz( { std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL"); - if (DUMMY_TESTING_AFL == "True") { + if (DUMMY_TESTING_AFL == "True") + { fillTraceDummyData(trace_bits); exit(0); } @@ -82,11 +83,11 @@ void main_fuzz( 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 + char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); - + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); @@ -175,13 +176,10 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes exit(1); } - LOG("Waitpid status: " + std::to_string(status)); - if (WIFEXITED(status)) { // Need to translate return value of waitpid to exit code (e.g. 256 translates to 1) int exit_status = WEXITSTATUS(status); - LOG("exit_status: " + std::to_string(exit_status)); write(199, &exit_status, 4); } else if (WIFSIGNALED(status)) // Process was stopped/terminated by signal; From 923726da51cdb793da938f67889b3c1543476b20 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Mon, 27 Jul 2020 18:54:14 +0200 Subject: [PATCH 45/74] Created docker-compose.stack.yml to use multiple AFL instances --- README.md | 4 +-- ...ose.fuzzing.yml => docker-compose.base.yml | 12 +------ docker-compose.stack.yml | 34 +++++++++++++++++++ docker-compose.yml | 17 ++++++++++ 4 files changed, 54 insertions(+), 13 deletions(-) rename docker-compose.fuzzing.yml => docker-compose.base.yml (65%) create mode 100644 docker-compose.stack.yml create mode 100644 docker-compose.yml diff --git a/README.md b/README.md index 1a9ecbad..29cff71b 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ This tool creates two Docker containers, as specified in the docker-compose.fuzz How to build: ```bash -docker-compose -f docker-compose.fuzzing.yml build +docker-compose -f docker-compose.base.yml -f docker-compose.yml build ``` ### Mechanics of SWAM's Dockerfile @@ -53,7 +53,7 @@ This image uses the [official image of AFLplusplus](https://hub.docker.com/r/afl 2. Execute docker-compose configuration ```bash - docker-compose -f docker-compose.fuzzing.yml up + docker-compose -f docker-compose.base.yml -f docker-compose.yml up ``` 3. View AFL's results and own logs in the folders which were specified in the .env file. diff --git a/docker-compose.fuzzing.yml b/docker-compose.base.yml similarity index 65% rename from docker-compose.fuzzing.yml rename to docker-compose.base.yml index 1b97ab25..1854b41d 100644 --- a/docker-compose.fuzzing.yml +++ b/docker-compose.base.yml @@ -1,15 +1,9 @@ -# WARNING: -# The env variables used in this file (e.g. WASM_PATH_LOCAL) can only -# be read by a file named ".env". This is standard Docker behaviour. - -# 1. Configure ./.env file -# 2. docker-compose -f docker-compose.fuzzing.yml up --build +# This file does not work by itself version: '3.7' services: swam_server: - build: ../ entrypoint: /home/swam/fuzzer/entrypoint_mill_server.sh env_file: - ./.env @@ -17,11 +11,8 @@ services: - ${WASM_PATH_LOCAL:?err}:/home/wasm/ - compiled_sources:/home/swam/out/ - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 - expose: - - ${SWAM_SOCKET_PORT:?err} afl_interface: - build: ./ entrypoint: /home/interface/entrypoint_afl.sh env_file: - ./.env @@ -32,7 +23,6 @@ services: - ${LOGS_LOCAL:?err}:/home/logs/ depends_on: - swam_server - # tty: true volumes: compiled_sources: diff --git a/docker-compose.stack.yml b/docker-compose.stack.yml new file mode 100644 index 00000000..d5be88e3 --- /dev/null +++ b/docker-compose.stack.yml @@ -0,0 +1,34 @@ +# WARNING: +# This is still in testing! It still requires to set up AFL's Master-Slave mechanism. +# Also, the Socket Server does not seem to be running concurrently yet (even with a +# thread per request). + +# Create/update stack on the swarm: +# set -a +# source .env +# set +a +# docker stack deploy --compose-file docker-compose.base.yml -c docker-compose.stack.yml afl_swam + +# View all (multi-instance) services of stack: +# docker service ls + +# View live logs of (multi-instance) service: +# docker service logs -f {NAME_OF_THE_SERVICE} + +# Remove stack from the swarm +# docker stack rm afl_swam + +version: '3.7' + +services: + swam_server: + image: fuzzer_swam_server + + afl_interface: + image: fuzzer_afl_interface + deploy: + replicas: 6 + +volumes: + compiled_sources: + maven_data: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..63281f75 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +# WARNING: +# The env variables used in this file (e.g. WASM_PATH_LOCAL) can only +# be read by a file named ".env". This is standard Docker behaviour. + +# 1. Configure ./.env file +# 2. docker-compose -f docker-compose.base.yml -f docker-compose.yml up --build + +version: '3.7' + +services: + swam_server: + build: ../ + expose: + - ${SWAM_SOCKET_PORT:?err} + + afl_interface: + build: ./ From bc1e579ef8a24eab6e7ef07b6f7b6b79e155f85e Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Tue, 28 Jul 2020 06:33:20 +0000 Subject: [PATCH 46/74] up --- wasm-fuzzer/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 wasm-fuzzer/README.md diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md new file mode 100644 index 00000000..c511313f --- /dev/null +++ b/wasm-fuzzer/README.md @@ -0,0 +1,3 @@ +# WAFL + +WAFL is a fuzzer for WebAssembly. It is based on [Swam](https://github.com/satabin/swam/) and [AFL](http://lcamtuf.coredump.cx/afl/). From 9f40471dafcb7ab7729dd1fa644daf98cb4cb6b9 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 11:13:24 +0200 Subject: [PATCH 47/74] Collected the data I need to move --- Dockerfile => wasm-fuzzer/Dockerfile | 0 README.md => wasm-fuzzer/README.md | 0 .../docker-compose.base.yml | 0 .../docker-compose.stack.yml | 0 .../docker-compose.yml | 0 {docs => wasm-fuzzer/docs}/fibo_log_failing.png | Bin {docs => wasm-fuzzer/docs}/fibo_log_working.png | Bin entrypoint_afl.sh => wasm-fuzzer/entrypoint_afl.sh | 0 .../entrypoint_mill_server.sh | 0 getFileSize.cpp => wasm-fuzzer/getFileSize.cpp | 0 interface.cpp => wasm-fuzzer/interface.cpp | 0 interface.h => wasm-fuzzer/interface.h | 0 .../prepare_wasm_input.cpp | 0 .../prepare_wasm_input.h | 0 run_client.cpp => wasm-fuzzer/run_client.cpp | 0 run_test.sh => wasm-fuzzer/run_test.sh | 0 socket_client.cpp => wasm-fuzzer/socket_client.cpp | 0 socket_client.h => wasm-fuzzer/socket_client.h | 0 utils.cpp => wasm-fuzzer/utils.cpp | 0 utils.h => wasm-fuzzer/utils.h | 0 .../wait_for_server.cpp | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename Dockerfile => wasm-fuzzer/Dockerfile (100%) rename README.md => wasm-fuzzer/README.md (100%) rename docker-compose.base.yml => wasm-fuzzer/docker-compose.base.yml (100%) rename docker-compose.stack.yml => wasm-fuzzer/docker-compose.stack.yml (100%) rename docker-compose.yml => wasm-fuzzer/docker-compose.yml (100%) rename {docs => wasm-fuzzer/docs}/fibo_log_failing.png (100%) rename {docs => wasm-fuzzer/docs}/fibo_log_working.png (100%) rename entrypoint_afl.sh => wasm-fuzzer/entrypoint_afl.sh (100%) rename entrypoint_mill_server.sh => wasm-fuzzer/entrypoint_mill_server.sh (100%) rename getFileSize.cpp => wasm-fuzzer/getFileSize.cpp (100%) rename interface.cpp => wasm-fuzzer/interface.cpp (100%) rename interface.h => wasm-fuzzer/interface.h (100%) rename prepare_wasm_input.cpp => wasm-fuzzer/prepare_wasm_input.cpp (100%) rename prepare_wasm_input.h => wasm-fuzzer/prepare_wasm_input.h (100%) rename run_client.cpp => wasm-fuzzer/run_client.cpp (100%) rename run_test.sh => wasm-fuzzer/run_test.sh (100%) rename socket_client.cpp => wasm-fuzzer/socket_client.cpp (100%) rename socket_client.h => wasm-fuzzer/socket_client.h (100%) rename utils.cpp => wasm-fuzzer/utils.cpp (100%) rename utils.h => wasm-fuzzer/utils.h (100%) rename wait_for_server.cpp => wasm-fuzzer/wait_for_server.cpp (100%) diff --git a/Dockerfile b/wasm-fuzzer/Dockerfile similarity index 100% rename from Dockerfile rename to wasm-fuzzer/Dockerfile diff --git a/README.md b/wasm-fuzzer/README.md similarity index 100% rename from README.md rename to wasm-fuzzer/README.md diff --git a/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml similarity index 100% rename from docker-compose.base.yml rename to wasm-fuzzer/docker-compose.base.yml diff --git a/docker-compose.stack.yml b/wasm-fuzzer/docker-compose.stack.yml similarity index 100% rename from docker-compose.stack.yml rename to wasm-fuzzer/docker-compose.stack.yml diff --git a/docker-compose.yml b/wasm-fuzzer/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to wasm-fuzzer/docker-compose.yml diff --git a/docs/fibo_log_failing.png b/wasm-fuzzer/docs/fibo_log_failing.png similarity index 100% rename from docs/fibo_log_failing.png rename to wasm-fuzzer/docs/fibo_log_failing.png diff --git a/docs/fibo_log_working.png b/wasm-fuzzer/docs/fibo_log_working.png similarity index 100% rename from docs/fibo_log_working.png rename to wasm-fuzzer/docs/fibo_log_working.png diff --git a/entrypoint_afl.sh b/wasm-fuzzer/entrypoint_afl.sh similarity index 100% rename from entrypoint_afl.sh rename to wasm-fuzzer/entrypoint_afl.sh diff --git a/entrypoint_mill_server.sh b/wasm-fuzzer/entrypoint_mill_server.sh similarity index 100% rename from entrypoint_mill_server.sh rename to wasm-fuzzer/entrypoint_mill_server.sh diff --git a/getFileSize.cpp b/wasm-fuzzer/getFileSize.cpp similarity index 100% rename from getFileSize.cpp rename to wasm-fuzzer/getFileSize.cpp diff --git a/interface.cpp b/wasm-fuzzer/interface.cpp similarity index 100% rename from interface.cpp rename to wasm-fuzzer/interface.cpp diff --git a/interface.h b/wasm-fuzzer/interface.h similarity index 100% rename from interface.h rename to wasm-fuzzer/interface.h diff --git a/prepare_wasm_input.cpp b/wasm-fuzzer/prepare_wasm_input.cpp similarity index 100% rename from prepare_wasm_input.cpp rename to wasm-fuzzer/prepare_wasm_input.cpp diff --git a/prepare_wasm_input.h b/wasm-fuzzer/prepare_wasm_input.h similarity index 100% rename from prepare_wasm_input.h rename to wasm-fuzzer/prepare_wasm_input.h diff --git a/run_client.cpp b/wasm-fuzzer/run_client.cpp similarity index 100% rename from run_client.cpp rename to wasm-fuzzer/run_client.cpp diff --git a/run_test.sh b/wasm-fuzzer/run_test.sh similarity index 100% rename from run_test.sh rename to wasm-fuzzer/run_test.sh diff --git a/socket_client.cpp b/wasm-fuzzer/socket_client.cpp similarity index 100% rename from socket_client.cpp rename to wasm-fuzzer/socket_client.cpp diff --git a/socket_client.h b/wasm-fuzzer/socket_client.h similarity index 100% rename from socket_client.h rename to wasm-fuzzer/socket_client.h diff --git a/utils.cpp b/wasm-fuzzer/utils.cpp similarity index 100% rename from utils.cpp rename to wasm-fuzzer/utils.cpp diff --git a/utils.h b/wasm-fuzzer/utils.h similarity index 100% rename from utils.h rename to wasm-fuzzer/utils.h diff --git a/wait_for_server.cpp b/wasm-fuzzer/wait_for_server.cpp similarity index 100% rename from wait_for_server.cpp rename to wasm-fuzzer/wait_for_server.cpp From 4787ce1418b69664261fa75247a3bab58df434bb Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 13:58:13 +0200 Subject: [PATCH 48/74] Added SWAM as submodule --- .gitmodules | 3 +++ wasm-fuzzer/fuzzing-server | 1 + 2 files changed, 4 insertions(+) create mode 160000 wasm-fuzzer/fuzzing-server diff --git a/.gitmodules b/.gitmodules index 89da18ef..0246a03c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,6 @@ path = wabt url = git://github.com/WebAssembly/wabt.git branch = master +[submodule "wasm-fuzzer/fuzzing-server"] + path = wasm-fuzzer/fuzzing-server + url = https://github.com/olapiv/swam.git diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server new file mode 160000 index 00000000..1a833d33 --- /dev/null +++ b/wasm-fuzzer/fuzzing-server @@ -0,0 +1 @@ +Subproject commit 1a833d335537a27427b6f1b08ed670aa129820ad From a6a30cdca71d6e60e49e2084d981e159abe3ce69 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 13:58:55 +0200 Subject: [PATCH 49/74] Moved .dockerignore & .env into /wasm-fuzzer --- .dockerignore => wasm-fuzzer/.dockerignore | 0 .env => wasm-fuzzer/.env | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .dockerignore => wasm-fuzzer/.dockerignore (100%) rename .env => wasm-fuzzer/.env (100%) diff --git a/.dockerignore b/wasm-fuzzer/.dockerignore similarity index 100% rename from .dockerignore rename to wasm-fuzzer/.dockerignore diff --git a/.env b/wasm-fuzzer/.env similarity index 100% rename from .env rename to wasm-fuzzer/.env From e194fde49b0bf82901d1f5bb0680d6d4836c34a7 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 14:02:17 +0200 Subject: [PATCH 50/74] Moved cpp into fuzzing-client-afl directory --- wasm-fuzzer/{ => fuzzing-client-afl}/Dockerfile | 0 wasm-fuzzer/{ => fuzzing-client-afl}/entrypoint_afl.sh | 0 wasm-fuzzer/{ => fuzzing-client-afl}/getFileSize.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/interface.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/interface.h | 0 wasm-fuzzer/{ => fuzzing-client-afl}/prepare_wasm_input.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/prepare_wasm_input.h | 0 wasm-fuzzer/{ => fuzzing-client-afl}/run_client.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/run_test.sh | 0 wasm-fuzzer/{ => fuzzing-client-afl}/socket_client.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/socket_client.h | 0 wasm-fuzzer/{ => fuzzing-client-afl}/utils.cpp | 0 wasm-fuzzer/{ => fuzzing-client-afl}/utils.h | 0 wasm-fuzzer/{ => fuzzing-client-afl}/wait_for_server.cpp | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename wasm-fuzzer/{ => fuzzing-client-afl}/Dockerfile (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/entrypoint_afl.sh (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/getFileSize.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/interface.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/interface.h (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/prepare_wasm_input.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/prepare_wasm_input.h (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/run_client.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/run_test.sh (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/socket_client.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/socket_client.h (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/utils.cpp (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/utils.h (100%) rename wasm-fuzzer/{ => fuzzing-client-afl}/wait_for_server.cpp (100%) diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/fuzzing-client-afl/Dockerfile similarity index 100% rename from wasm-fuzzer/Dockerfile rename to wasm-fuzzer/fuzzing-client-afl/Dockerfile diff --git a/wasm-fuzzer/entrypoint_afl.sh b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh similarity index 100% rename from wasm-fuzzer/entrypoint_afl.sh rename to wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh diff --git a/wasm-fuzzer/getFileSize.cpp b/wasm-fuzzer/fuzzing-client-afl/getFileSize.cpp similarity index 100% rename from wasm-fuzzer/getFileSize.cpp rename to wasm-fuzzer/fuzzing-client-afl/getFileSize.cpp diff --git a/wasm-fuzzer/interface.cpp b/wasm-fuzzer/fuzzing-client-afl/interface.cpp similarity index 100% rename from wasm-fuzzer/interface.cpp rename to wasm-fuzzer/fuzzing-client-afl/interface.cpp diff --git a/wasm-fuzzer/interface.h b/wasm-fuzzer/fuzzing-client-afl/interface.h similarity index 100% rename from wasm-fuzzer/interface.h rename to wasm-fuzzer/fuzzing-client-afl/interface.h diff --git a/wasm-fuzzer/prepare_wasm_input.cpp b/wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.cpp similarity index 100% rename from wasm-fuzzer/prepare_wasm_input.cpp rename to wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.cpp diff --git a/wasm-fuzzer/prepare_wasm_input.h b/wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.h similarity index 100% rename from wasm-fuzzer/prepare_wasm_input.h rename to wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.h diff --git a/wasm-fuzzer/run_client.cpp b/wasm-fuzzer/fuzzing-client-afl/run_client.cpp similarity index 100% rename from wasm-fuzzer/run_client.cpp rename to wasm-fuzzer/fuzzing-client-afl/run_client.cpp diff --git a/wasm-fuzzer/run_test.sh b/wasm-fuzzer/fuzzing-client-afl/run_test.sh similarity index 100% rename from wasm-fuzzer/run_test.sh rename to wasm-fuzzer/fuzzing-client-afl/run_test.sh diff --git a/wasm-fuzzer/socket_client.cpp b/wasm-fuzzer/fuzzing-client-afl/socket_client.cpp similarity index 100% rename from wasm-fuzzer/socket_client.cpp rename to wasm-fuzzer/fuzzing-client-afl/socket_client.cpp diff --git a/wasm-fuzzer/socket_client.h b/wasm-fuzzer/fuzzing-client-afl/socket_client.h similarity index 100% rename from wasm-fuzzer/socket_client.h rename to wasm-fuzzer/fuzzing-client-afl/socket_client.h diff --git a/wasm-fuzzer/utils.cpp b/wasm-fuzzer/fuzzing-client-afl/utils.cpp similarity index 100% rename from wasm-fuzzer/utils.cpp rename to wasm-fuzzer/fuzzing-client-afl/utils.cpp diff --git a/wasm-fuzzer/utils.h b/wasm-fuzzer/fuzzing-client-afl/utils.h similarity index 100% rename from wasm-fuzzer/utils.h rename to wasm-fuzzer/fuzzing-client-afl/utils.h diff --git a/wasm-fuzzer/wait_for_server.cpp b/wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp similarity index 100% rename from wasm-fuzzer/wait_for_server.cpp rename to wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp From f846728331ea6edeea9558d079a07a49b1504fd3 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 14:13:42 +0200 Subject: [PATCH 51/74] Adjusted docker-compose.yml to new directories --- wasm-fuzzer/docker-compose.yml | 4 ++-- wasm-fuzzer/entrypoint_mill_server.sh | 23 ----------------------- 2 files changed, 2 insertions(+), 25 deletions(-) delete mode 100644 wasm-fuzzer/entrypoint_mill_server.sh diff --git a/wasm-fuzzer/docker-compose.yml b/wasm-fuzzer/docker-compose.yml index 63281f75..d92498f0 100644 --- a/wasm-fuzzer/docker-compose.yml +++ b/wasm-fuzzer/docker-compose.yml @@ -9,9 +9,9 @@ version: '3.7' services: swam_server: - build: ../ + build: ./fuzzing-server expose: - ${SWAM_SOCKET_PORT:?err} afl_interface: - build: ./ + build: ./fuzzing-client-afl diff --git a/wasm-fuzzer/entrypoint_mill_server.sh b/wasm-fuzzer/entrypoint_mill_server.sh deleted file mode 100644 index 2ce6c72a..00000000 --- a/wasm-fuzzer/entrypoint_mill_server.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Get wasm/wat from $WASM_PATH_DOCKER directory -WASM_OR_WAT_FILE=${WASM_PATH_DOCKER}/${WASM_EXECUTABLE} -echo "WASM_OR_WAT_FILE: $WASM_OR_WAT_FILE" - -# Parse WASM_ARG_TYPES_LIST: "Int64,Int32" to "--argType Int64 --argType Int32" -ALL_ARG_TYPES="" -IFS=',' read -r -a array <<< "$WASM_ARG_TYPES_LIST" -for element in "${array[@]}" -do - ALL_ARG_TYPES="$ALL_ARG_TYPES --argType $element" -done -echo "ALL_ARG_TYPES: $ALL_ARG_TYPES" - -if [[ $WASM_OR_WAT_FILE == *.wat ]]; then WAT_ARG="--wat"; fi -if [[ $WASI == "True" ]]; then WASI_ARG="--wasi"; fi - -cd $REPO_PATH_DOCKER - -# This also compiles the cli package in case source code / dependencies have changed: -echo "mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE" -mill -i cli.run run_server $WAT_ARG $WASI_ARG $ALL_ARG_TYPES --main $TARGET_FUNCTION --out $SWAM_OUTPUT_DOCKER $WASM_OR_WAT_FILE From 7c9fa7d93707c7cb71d14a09bb8ebc40d5fc5b41 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 14:26:09 +0200 Subject: [PATCH 52/74] Updated gitignore --- wasm-fuzzer/.gitignore | 7 +++++++ wasm-fuzzer/fuzzing-server | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 wasm-fuzzer/.gitignore diff --git a/wasm-fuzzer/.gitignore b/wasm-fuzzer/.gitignore new file mode 100644 index 00000000..87db1316 --- /dev/null +++ b/wasm-fuzzer/.gitignore @@ -0,0 +1,7 @@ + +fuzzer-client-afl/*.log +fuzzer-client-afl/*.dat +**/fuzzer-client-afl/in +**/fuzzer-client-afl/afl_out +**/fuzzer-client-afl/cpp_out +**/fuzzer-client-afl/logs/* diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server index 1a833d33..1ff00d55 160000 --- a/wasm-fuzzer/fuzzing-server +++ b/wasm-fuzzer/fuzzing-server @@ -1 +1 @@ -Subproject commit 1a833d335537a27427b6f1b08ed670aa129820ad +Subproject commit 1ff00d556ff99fed350fc5e273558dea8f32e164 From 0fa9d8024e3c3039067ed6c93223f77ab458b939 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 14:50:53 +0200 Subject: [PATCH 53/74] Lifted fuzzer .gitignore into root --- .gitignore | 7 ++++++- wasm-fuzzer/.gitignore | 7 ------- 2 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 wasm-fuzzer/.gitignore diff --git a/.gitignore b/.gitignore index 89e1c91e..b280ca63 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,9 @@ crow_out dist -*egg-info \ No newline at end of file +*egg-info + +### Wasm-Fuzzer ### +wasm-fuzzer/fuzzing-client-afl/afl_out +wasm-fuzzer/fuzzing-client-afl/cpp_out +wasm-fuzzer/fuzzing-client-afl/logs/* diff --git a/wasm-fuzzer/.gitignore b/wasm-fuzzer/.gitignore deleted file mode 100644 index 87db1316..00000000 --- a/wasm-fuzzer/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ - -fuzzer-client-afl/*.log -fuzzer-client-afl/*.dat -**/fuzzer-client-afl/in -**/fuzzer-client-afl/afl_out -**/fuzzer-client-afl/cpp_out -**/fuzzer-client-afl/logs/* From 6abd681ba7c4e3b844290ddd08741b6962e26e0d Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 14:52:56 +0200 Subject: [PATCH 54/74] Changed path of entrypoint in docker-comp, since fuzzer/ is deleted --- wasm-fuzzer/docker-compose.base.yml | 2 +- wasm-fuzzer/fuzzing-server | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wasm-fuzzer/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml index 1854b41d..0bc5b18e 100644 --- a/wasm-fuzzer/docker-compose.base.yml +++ b/wasm-fuzzer/docker-compose.base.yml @@ -4,7 +4,7 @@ version: '3.7' services: swam_server: - entrypoint: /home/swam/fuzzer/entrypoint_mill_server.sh + entrypoint: /home/swam/entrypoint_mill_server.sh env_file: - ./.env volumes: diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server index 1ff00d55..0d1f93f5 160000 --- a/wasm-fuzzer/fuzzing-server +++ b/wasm-fuzzer/fuzzing-server @@ -1 +1 @@ -Subproject commit 1ff00d556ff99fed350fc5e273558dea8f32e164 +Subproject commit 0d1f93f596986b7e962cb33aa858f378c6f369b3 From e9298e37f87ce9ae14805cdd81fc92fb2caaa5b2 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 17:43:15 +0200 Subject: [PATCH 55/74] First attempt in merged Dockerfile & entrypoint --- .gitignore | 2 +- wasm-fuzzer/Dockerfile | 102 ++++++++++++++++++++++++++++++++++++++ wasm-fuzzer/entrypoint.sh | 36 ++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 wasm-fuzzer/Dockerfile create mode 100644 wasm-fuzzer/entrypoint.sh diff --git a/.gitignore b/.gitignore index b280ca63..908bc4d5 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ dist ### Wasm-Fuzzer ### wasm-fuzzer/fuzzing-client-afl/afl_out wasm-fuzzer/fuzzing-client-afl/cpp_out -wasm-fuzzer/fuzzing-client-afl/logs/* +wasm-fuzzer/logs/* diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile new file mode 100644 index 00000000..499379f2 --- /dev/null +++ b/wasm-fuzzer/Dockerfile @@ -0,0 +1,102 @@ +# This Dockerfile aims to substitute the docker-compose configuration + +FROM aflplusplus/aflplusplus + +RUN yes | apt-get install curl +RUN apt-get update + +######################### +##### Scala & Mill ###### +######################### + +RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata +RUN yes | apt-get install software-properties-common +RUN apt-get update +RUN yes | add-apt-repository ppa:openjdk-r/ppa +RUN apt-get update +RUN yes | apt-get install openjdk-12-jdk-headless + +# RUN yes | apt-get install openjdk-12-jdk-headless + +# Env variables +ENV SCALA_VERSION 2.13.2 +ENV MILL_VERSION 0.7.0 + +# Define working directory +WORKDIR /root + +# Install Scala +## Piping curl directly in tar +RUN \ + curl -fsL https://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz | tar xfz - -C /root/ && \ + echo >> /root/.bashrc && \ + echo "export PATH=~/scala-$SCALA_VERSION/bin:$PATH" >> /root/.bashrc + +# Install mill +RUN \ + curl -L -o /usr/local/bin/mill https://github.com/lihaoyi/mill/releases/download/$MILL_VERSION/$MILL_VERSION && \ + chmod +x /usr/local/bin/mill && \ + touch build.sc && \ + mill -i resolve _ && \ + rm build.sc + +################################ +#### fuzzing-server (SWAM) ##### +################################ + +ENV REPO_PATH_DOCKER=/home/server/src +ENV SWAM_OUTPUT_DOCKER=/home/server/out +ENV WASM_PATH_DOCKER=/home/server/wasm + +# Create the appropriate directories +RUN mkdir -p $REPO_PATH_DOCKER +RUN mkdir -p $SWAM_OUTPUT_DOCKER +RUN mkdir -p $WASM_PATH_DOCKER + +WORKDIR $REPO_PATH_DOCKER + +# TODO: Find way of installing dependencies with Mill without copying over entire repo +# See: https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code + +ADD ./fuzzing-server $REPO_PATH_DOCKER + +RUN chmod +x $REPO_PATH_DOCKER/entrypoint_mill_server.sh + +############################# +#### fuzzing-client-afl ##### +############################# + +ENV INTERFACE_PATH=/home/client/interface +ENV INPUT_DOCKER_AFL=/home/client/in +ENV OUTPUT_DOCKER_AFL=/home/client/out + +# Create the appropriate directories +RUN mkdir -p $INTERFACE_PATH +RUN mkdir -p $INPUT_DOCKER_AFL +RUN mkdir -p $OUTPUT_DOCKER_AFL +WORKDIR $INTERFACE_PATH + +ADD ./fuzzing-client-afl $INTERFACE_PATH + +RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp +RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp +RUN g++ -o ./wait_for_server.out ./wait_for_server.cpp ./utils.cpp ./socket_client.cpp +RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp + +RUN chmod +x $INTERFACE_PATH/entrypoint_afl.sh + +######################### +######## Shared ######### +######################### + +ENV SHARED_DOCKER=/home/shared +ENV LOGS_DOCKER=$SHARED_DOCKER/logs + +# RUN mkdir -p $SHARED_DOCKER +RUN mkdir -p $LOGS_DOCKER + +ADD ./entrypoint.sh $SHARED_DOCKER + +RUN chmod +x $SHARED_DOCKER/entrypoint.sh + +ENTRYPOINT $SHARED_DOCKER/entrypoint.sh \ No newline at end of file diff --git a/wasm-fuzzer/entrypoint.sh b/wasm-fuzzer/entrypoint.sh new file mode 100644 index 00000000..a4d7dba7 --- /dev/null +++ b/wasm-fuzzer/entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Start the first process +$REPO_PATH_DOCKER/entrypoint_mill_server.sh -D +status=$? +if [ $status -ne 0 ]; then + echo "Failed to start my_first_process: $status" + exit $status +fi + +# Start the second process +$INTERFACE_PATH/entrypoint_afl.sh -D +status=$? +if [ $status -ne 0 ]; then + echo "Failed to start my_second_process: $status" + exit $status +fi + +# Naive check runs checks once a minute to see if either of the processes exited. +# This illustrates part of the heavy lifting you need to do if you want to run +# more than one service in a container. The container exits with an error +# if it detects that either of the processes has exited. +# Otherwise it loops forever, waking up every 60 seconds + +while sleep 60; do + ps aux |grep my_first_process |grep -q -v grep + PROCESS_1_STATUS=$? + ps aux |grep my_second_process |grep -q -v grep + PROCESS_2_STATUS=$? + # If the greps above find anything, they exit with 0 status + # If they are not both 0, then something is wrong + if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then + echo "One of the processes has already exited." + exit 1 + fi +done \ No newline at end of file From 65591146ea1ee4e80eb7e53ed1ed90303e831cc9 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 18:00:28 +0200 Subject: [PATCH 56/74] Streamlined env variables --- wasm-fuzzer/.env | 6 +-- wasm-fuzzer/Dockerfile | 49 +++++++++---------- wasm-fuzzer/docker-compose.base.yml | 6 +-- wasm-fuzzer/docker-compose.yml | 2 +- wasm-fuzzer/entrypoint.sh | 4 +- wasm-fuzzer/fuzzing-client-afl/Dockerfile | 22 ++++----- .../fuzzing-client-afl/entrypoint_afl.sh | 8 +-- wasm-fuzzer/fuzzing-client-afl/interface.cpp | 4 +- 8 files changed, 50 insertions(+), 51 deletions(-) diff --git a/wasm-fuzzer/.env b/wasm-fuzzer/.env index 76bd5b95..dc31ac1c 100644 --- a/wasm-fuzzer/.env +++ b/wasm-fuzzer/.env @@ -5,16 +5,16 @@ DUMMY_TESTING_AFL=False LOG_LEVEL=Error # Path to the parent directory of our local .wasm/.wat executable -WASM_PATH_LOCAL=/tmp/fuzzer-wat_files +LOCAL_WASM=/tmp/fuzzer-wat_files # Name of our local .wasm/.wat executable WASM_EXECUTABLE=fibo.wat # Path on our local machine for us to read AFL's output -OUTPUT_LOCAL_AFL=/tmp/afl_out +LOCAL_AFL_OUTPUT=/tmp/afl_out # Path on our local machine for us to read our own logs -LOGS_LOCAL=/tmp/fuzzer/fuzzerlogs +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 diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index 499379f2..b3d949a2 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -44,59 +44,58 @@ RUN \ #### fuzzing-server (SWAM) ##### ################################ -ENV REPO_PATH_DOCKER=/home/server/src -ENV SWAM_OUTPUT_DOCKER=/home/server/out -ENV WASM_PATH_DOCKER=/home/server/wasm +ENV DOCKER_SWAM_SRC=/home/server/src +ENV DOCKER_SWAM_OUTPUT=/home/server/out +ENV DOCKER_WASM=/home/server/wasm # Create the appropriate directories -RUN mkdir -p $REPO_PATH_DOCKER -RUN mkdir -p $SWAM_OUTPUT_DOCKER -RUN mkdir -p $WASM_PATH_DOCKER +RUN mkdir -p $DOCKER_SWAM_SRC +RUN mkdir -p $DOCKER_SWAM_OUTPUT +RUN mkdir -p $DOCKER_WASM -WORKDIR $REPO_PATH_DOCKER +WORKDIR $DOCKER_SWAM_SRC # TODO: Find way of installing dependencies with Mill without copying over entire repo # See: https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code -ADD ./fuzzing-server $REPO_PATH_DOCKER +ADD ./fuzzing-server $DOCKER_SWAM_SRC -RUN chmod +x $REPO_PATH_DOCKER/entrypoint_mill_server.sh +RUN chmod +x $DOCKER_SWAM_SRC/entrypoint_mill_server.sh ############################# #### fuzzing-client-afl ##### ############################# -ENV INTERFACE_PATH=/home/client/interface -ENV INPUT_DOCKER_AFL=/home/client/in -ENV OUTPUT_DOCKER_AFL=/home/client/out +ENV DOCKER_INTERFACE_SRC=/home/client/interface +ENV DOCKER_AFL_INPUT=/home/client/in +ENV DOCKER_AFL_OUTPUT=/home/client/out # Create the appropriate directories -RUN mkdir -p $INTERFACE_PATH -RUN mkdir -p $INPUT_DOCKER_AFL -RUN mkdir -p $OUTPUT_DOCKER_AFL -WORKDIR $INTERFACE_PATH +RUN mkdir -p $DOCKER_INTERFACE_SRC +RUN mkdir -p $DOCKER_AFL_INPUT +RUN mkdir -p $DOCKER_AFL_OUTPUT +WORKDIR $DOCKER_INTERFACE_SRC -ADD ./fuzzing-client-afl $INTERFACE_PATH +ADD ./fuzzing-client-afl $DOCKER_INTERFACE_SRC RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp RUN g++ -o ./wait_for_server.out ./wait_for_server.cpp ./utils.cpp ./socket_client.cpp RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp -RUN chmod +x $INTERFACE_PATH/entrypoint_afl.sh +RUN chmod +x $DOCKER_INTERFACE_SRC/entrypoint_afl.sh ######################### ######## Shared ######### ######################### -ENV SHARED_DOCKER=/home/shared -ENV LOGS_DOCKER=$SHARED_DOCKER/logs +ENV DOCKER_SHARED=/home/shared +ENV DOCKER_LOGS=$DOCKER_SHARED/logs -# RUN mkdir -p $SHARED_DOCKER -RUN mkdir -p $LOGS_DOCKER +RUN mkdir -p $DOCKER_LOGS -ADD ./entrypoint.sh $SHARED_DOCKER +ADD ./entrypoint.sh $DOCKER_SHARED -RUN chmod +x $SHARED_DOCKER/entrypoint.sh +RUN chmod +x $DOCKER_SHARED/entrypoint.sh -ENTRYPOINT $SHARED_DOCKER/entrypoint.sh \ No newline at end of file +ENTRYPOINT $DOCKER_SHARED/entrypoint.sh \ No newline at end of file diff --git a/wasm-fuzzer/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml index 0bc5b18e..26599c1a 100644 --- a/wasm-fuzzer/docker-compose.base.yml +++ b/wasm-fuzzer/docker-compose.base.yml @@ -8,7 +8,7 @@ services: env_file: - ./.env volumes: - - ${WASM_PATH_LOCAL:?err}:/home/wasm/ + - ${LOCAL_WASM:?err}:/home/wasm/ - compiled_sources:/home/swam/out/ - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 @@ -19,8 +19,8 @@ services: environment: SWAM_CONTAINER: swam_server volumes: - - ${OUTPUT_LOCAL_AFL:?err}:/home/out/ - - ${LOGS_LOCAL:?err}:/home/logs/ + - ${LOCAL_AFL_OUTPUT:?err}:/home/out/ + - ${LOCAL_LOGS:?err}:/home/logs/ depends_on: - swam_server diff --git a/wasm-fuzzer/docker-compose.yml b/wasm-fuzzer/docker-compose.yml index d92498f0..64bece66 100644 --- a/wasm-fuzzer/docker-compose.yml +++ b/wasm-fuzzer/docker-compose.yml @@ -1,5 +1,5 @@ # WARNING: -# The env variables used in this file (e.g. WASM_PATH_LOCAL) can only +# The env variables used in this file (e.g. LOCAL_WASM) can only # be read by a file named ".env". This is standard Docker behaviour. # 1. Configure ./.env file diff --git a/wasm-fuzzer/entrypoint.sh b/wasm-fuzzer/entrypoint.sh index a4d7dba7..57ce6d94 100644 --- a/wasm-fuzzer/entrypoint.sh +++ b/wasm-fuzzer/entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/bash # Start the first process -$REPO_PATH_DOCKER/entrypoint_mill_server.sh -D +$DOCKER_SWAM_SRC/entrypoint_mill_server.sh -D status=$? if [ $status -ne 0 ]; then echo "Failed to start my_first_process: $status" @@ -9,7 +9,7 @@ if [ $status -ne 0 ]; then fi # Start the second process -$INTERFACE_PATH/entrypoint_afl.sh -D +$DOCKER_INTERFACE_SRC/entrypoint_afl.sh -D status=$? if [ $status -ne 0 ]; then echo "Failed to start my_second_process: $status" diff --git a/wasm-fuzzer/fuzzing-client-afl/Dockerfile b/wasm-fuzzer/fuzzing-client-afl/Dockerfile index 7b4ca7bf..86ddeb15 100644 --- a/wasm-fuzzer/fuzzing-client-afl/Dockerfile +++ b/wasm-fuzzer/fuzzing-client-afl/Dockerfile @@ -1,22 +1,22 @@ FROM aflplusplus/aflplusplus -ENV INTERFACE_PATH=/home/interface -ENV INPUT_DOCKER_AFL=/home/in -ENV OUTPUT_DOCKER_AFL=/home/out -ENV LOGS_DOCKER=/home/logs +ENV DOCKER_INTERFACE_SRC=/home/interface +ENV DOCKER_AFL_INPUT=/home/in +ENV DOCKER_AFL_OUTPUT=/home/out +ENV DOCKER_LOGS=/home/logs # Create the appropriate directories -RUN mkdir -p $INTERFACE_PATH -RUN mkdir -p $INPUT_DOCKER_AFL -RUN mkdir -p $OUTPUT_DOCKER_AFL -RUN mkdir -p $LOGS_DOCKER -WORKDIR $INTERFACE_PATH +RUN mkdir -p $DOCKER_INTERFACE_SRC +RUN mkdir -p $DOCKER_AFL_INPUT +RUN mkdir -p $DOCKER_AFL_OUTPUT +RUN mkdir -p $DOCKER_LOGS +WORKDIR $DOCKER_INTERFACE_SRC -ADD ./ $INTERFACE_PATH +ADD ./ $DOCKER_INTERFACE_SRC RUN g++ -o ./prepare_wasm_input.out ./prepare_wasm_input.cpp ./utils.cpp RUN g++ -o ./getFileSize.out ./getFileSize.cpp ./utils.cpp RUN g++ -o ./wait_for_server.out ./wait_for_server.cpp ./utils.cpp ./socket_client.cpp RUN g++ -o ./interface.out ./interface.cpp ./socket_client.cpp ./utils.cpp -RUN chmod +x $INTERFACE_PATH/entrypoint_afl.sh +RUN chmod +x $DOCKER_INTERFACE_SRC/entrypoint_afl.sh diff --git a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh index 4f39ba55..9576a31a 100644 --- a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh +++ b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh @@ -1,8 +1,8 @@ #!/bin/bash -cd $INTERFACE_PATH +cd $DOCKER_INTERFACE_SRC -PREPARED_INPUT_PATH="$INPUT_DOCKER_AFL/prepared_input.dat" +PREPARED_INPUT_PATH="$DOCKER_AFL_INPUT/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) @@ -12,5 +12,5 @@ if [ $? != 0 ]; then exit 1 fi -echo "afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- ${INTERFACE_PATH}/interface.out @@ $REQUIRED_BYTES" -afl-fuzz -i $INPUT_DOCKER_AFL -o $OUTPUT_DOCKER_AFL -m none -d -- "${INTERFACE_PATH}/interface.out" @@ $REQUIRED_BYTES +echo "afl-fuzz -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT -m none -d -- ${DOCKER_INTERFACE_SRC}/interface.out @@ $REQUIRED_BYTES" +afl-fuzz -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT -m none -d -- "${DOCKER_INTERFACE_SRC}/interface.out" @@ $REQUIRED_BYTES diff --git a/wasm-fuzzer/fuzzing-client-afl/interface.cpp b/wasm-fuzzer/fuzzing-client-afl/interface.cpp index 458834c1..06a7285a 100644 --- a/wasm-fuzzer/fuzzing-client-afl/interface.cpp +++ b/wasm-fuzzer/fuzzing-client-afl/interface.cpp @@ -4,8 +4,8 @@ void LOG(std::string some_string) { - std::string LOGS_DOCKER = parseEnvVariables((char *)"LOGS_DOCKER"); - log(LOGS_DOCKER + "/interface.log", some_string); + std::string DOCKER_LOGS = parseEnvVariables((char *)"DOCKER_LOGS"); + log(DOCKER_LOGS + "/interface.log", some_string); } std::vector readFileToVector(const std::string &filename) From 886c9863305419244c4e023d0c0fa8630b049f3c Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 18:01:13 +0200 Subject: [PATCH 57/74] git submodule fuzzing-server new commit --- wasm-fuzzer/fuzzing-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server index 0d1f93f5..a50f417c 160000 --- a/wasm-fuzzer/fuzzing-server +++ b/wasm-fuzzer/fuzzing-server @@ -1 +1 @@ -Subproject commit 0d1f93f596986b7e962cb33aa858f378c6f369b3 +Subproject commit a50f417cc997f72d863b5c031f91fa86703229bd From 87923a70e11beb18a8fc695b1bf913bb7d5e881f Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 18:26:17 +0200 Subject: [PATCH 58/74] Renamed SWAM_CONTAINER to SWAM_SOCKET_HOST --- wasm-fuzzer/docker-compose.base.yml | 2 +- wasm-fuzzer/entrypoint.sh | 2 ++ wasm-fuzzer/fuzzing-client-afl/interface.cpp | 4 ++-- wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/wasm-fuzzer/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml index 26599c1a..3f420947 100644 --- a/wasm-fuzzer/docker-compose.base.yml +++ b/wasm-fuzzer/docker-compose.base.yml @@ -17,7 +17,7 @@ services: env_file: - ./.env environment: - SWAM_CONTAINER: swam_server + SWAM_SOCKET_HOST: swam_server volumes: - ${LOCAL_AFL_OUTPUT:?err}:/home/out/ - ${LOCAL_LOGS:?err}:/home/logs/ diff --git a/wasm-fuzzer/entrypoint.sh b/wasm-fuzzer/entrypoint.sh index 57ce6d94..16a02e37 100644 --- a/wasm-fuzzer/entrypoint.sh +++ b/wasm-fuzzer/entrypoint.sh @@ -1,5 +1,7 @@ #!/bin/bash +# Initial script: https://docs.docker.com/config/containers/multi-service_container/ + # Start the first process $DOCKER_SWAM_SRC/entrypoint_mill_server.sh -D status=$? diff --git a/wasm-fuzzer/fuzzing-client-afl/interface.cpp b/wasm-fuzzer/fuzzing-client-afl/interface.cpp index 06a7285a..924e0f46 100644 --- a/wasm-fuzzer/fuzzing-client-afl/interface.cpp +++ b/wasm-fuzzer/fuzzing-client-afl/interface.cpp @@ -85,10 +85,10 @@ void main_fuzz( char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code - std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); + 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_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); + runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT)); pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits); diff --git a/wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp b/wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp index aff62bf8..30d7c14c 100644 --- a/wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp +++ b/wasm-fuzzer/fuzzing-client-afl/wait_for_server.cpp @@ -8,14 +8,14 @@ int main(int argc, char *argv[]) { setbuf(stdout, NULL); // For some reason stdout gets buffered until exit otherwise - std::string SWAM_CONTAINER = parseEnvVariables((char *)"SWAM_CONTAINER"); + std::string SWAM_SOCKET_HOST = parseEnvVariables((char *)"SWAM_SOCKET_HOST"); std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT"); printf("Waiting for Swam server...\n"); int sockfd; while (true) { try { - sockfd = connectToServer(&SWAM_CONTAINER[0], std::stoi(SWAM_SOCKET_PORT)); + sockfd = connectToServer(&SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT)); close(sockfd); break; } catch (...) { From 890e1779e8c7e46a87b7a643f175bbb8d44b1054 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Tue, 28 Jul 2020 19:11:26 +0200 Subject: [PATCH 59/74] Detached afl & swam entrypoints in main entrypoint --- wasm-fuzzer/Dockerfile | 2 -- wasm-fuzzer/entrypoint.sh | 22 ++++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index b3d949a2..7c757dd1 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -16,8 +16,6 @@ RUN yes | add-apt-repository ppa:openjdk-r/ppa RUN apt-get update RUN yes | apt-get install openjdk-12-jdk-headless -# RUN yes | apt-get install openjdk-12-jdk-headless - # Env variables ENV SCALA_VERSION 2.13.2 ENV MILL_VERSION 0.7.0 diff --git a/wasm-fuzzer/entrypoint.sh b/wasm-fuzzer/entrypoint.sh index 16a02e37..d499b210 100644 --- a/wasm-fuzzer/entrypoint.sh +++ b/wasm-fuzzer/entrypoint.sh @@ -3,7 +3,7 @@ # Initial script: https://docs.docker.com/config/containers/multi-service_container/ # Start the first process -$DOCKER_SWAM_SRC/entrypoint_mill_server.sh -D +$DOCKER_SWAM_SRC/entrypoint_mill_server.sh & disown status=$? if [ $status -ne 0 ]; then echo "Failed to start my_first_process: $status" @@ -11,7 +11,7 @@ if [ $status -ne 0 ]; then fi # Start the second process -$DOCKER_INTERFACE_SRC/entrypoint_afl.sh -D +$DOCKER_INTERFACE_SRC/entrypoint_afl.sh & disown status=$? if [ $status -ne 0 ]; then echo "Failed to start my_second_process: $status" @@ -22,17 +22,19 @@ fi # This illustrates part of the heavy lifting you need to do if you want to run # more than one service in a container. The container exits with an error # if it detects that either of the processes has exited. -# Otherwise it loops forever, waking up every 60 seconds +# Otherwise it loops forever, waking up every 30 seconds -while sleep 60; do - ps aux |grep my_first_process |grep -q -v grep - PROCESS_1_STATUS=$? - ps aux |grep my_second_process |grep -q -v grep - PROCESS_2_STATUS=$? +while sleep 30s; do + ps aux | grep entrypoint_mill_server.sh |grep -q -v grep + MILL_STATUS=$? + ps aux | grep entrypoint_afl.sh |grep -q -v grep + AFL_STATUS=$? # If the greps above find anything, they exit with 0 status # If they are not both 0, then something is wrong - if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then + if [ $MILL_STATUS -ne 0 -o $AFL_STATUS -ne 0 ]; then echo "One of the processes has already exited." + echo "mill status: $MILL_STATUS" + echo "afl status: $AFL_STATUS" exit 1 fi -done \ No newline at end of file +done From a2b9b64c72d21e28553470361d669e4dacfda34f Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 29 Jul 2020 12:19:30 +0200 Subject: [PATCH 60/74] Moved volumes to Dockerfile --- wasm-fuzzer/Dockerfile | 5 +++++ wasm-fuzzer/docker-compose.base.yml | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index 7c757dd1..a97f0ae7 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -60,6 +60,11 @@ ADD ./fuzzing-server $DOCKER_SWAM_SRC RUN chmod +x $DOCKER_SWAM_SRC/entrypoint_mill_server.sh +# For maven data: +VOLUME /root/.cache/coursier/v1/https/repo1.maven.org/maven2 +# For compiled sources: +VOLUME $DOCKER_SWAM_SRC/out/ + ############################# #### fuzzing-client-afl ##### ############################# diff --git a/wasm-fuzzer/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml index 3f420947..44c88fa0 100644 --- a/wasm-fuzzer/docker-compose.base.yml +++ b/wasm-fuzzer/docker-compose.base.yml @@ -9,8 +9,6 @@ services: - ./.env volumes: - ${LOCAL_WASM:?err}:/home/wasm/ - - compiled_sources:/home/swam/out/ - - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 afl_interface: entrypoint: /home/interface/entrypoint_afl.sh @@ -23,7 +21,3 @@ services: - ${LOCAL_LOGS:?err}:/home/logs/ depends_on: - swam_server - -volumes: - compiled_sources: - maven_data: From fe9def40dc6941bfab650627d3fca867742d84c6 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 29 Jul 2020 12:20:18 +0200 Subject: [PATCH 61/74] Update fuzzer-server pointer --- wasm-fuzzer/fuzzing-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server index a50f417c..a2999147 160000 --- a/wasm-fuzzer/fuzzing-server +++ b/wasm-fuzzer/fuzzing-server @@ -1 +1 @@ -Subproject commit a50f417cc997f72d863b5c031f91fa86703229bd +Subproject commit a2999147b9d606eb6ad702a238f059be295162c6 From dcc5eb23073e3bf100cea7ad5543a443a29b12f9 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 29 Jul 2020 14:22:48 +0200 Subject: [PATCH 62/74] Updated README for single Dockerfile and new structure --- wasm-fuzzer/Dockerfile | 13 ++++--- wasm-fuzzer/README.md | 88 +++++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index a97f0ae7..af7f5192 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -2,13 +2,12 @@ FROM aflplusplus/aflplusplus +################ +##### JVM ###### +################ + RUN yes | apt-get install curl RUN apt-get update - -######################### -##### Scala & Mill ###### -######################### - RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata RUN yes | apt-get install software-properties-common RUN apt-get update @@ -16,6 +15,10 @@ RUN yes | add-apt-repository ppa:openjdk-r/ppa RUN apt-get update RUN yes | apt-get install openjdk-12-jdk-headless +######################### +##### Scala & Mill ###### +######################### + # Env variables ENV SCALA_VERSION 2.13.2 ENV MILL_VERSION 0.7.0 diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md index 29cff71b..3bc480f9 100644 --- a/wasm-fuzzer/README.md +++ b/wasm-fuzzer/README.md @@ -1,12 +1,12 @@ -# AFL Plugin for SWAM +# WAFL - Fuzz your WASM with AFLplusplus ## Disclaimer -This is still in a prototyping stage. There are still many assumptions made on how AFL (and C++ and Scala and shared memory) works. Also, the coverage tool on which this plugin depends is currently still being developed. +This is still in a prototyping stage. There are still many assumptions made on how AFL (and C++ and Scala and shared memory) works. Also, SWAM's coverage functionality on which this tool depends is currently still being developed. ## Introduction -This plugin aims to act as an interface between SWAM and [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). Since AFL is built to fuzz C++ programs, but nonetheless provides a generic algorithm, which is not only bound to this language, we aim to provide a spin-off that applies AFL to WASM binaries. +This tool aims to act as an interface between [SWAM](https://github.com/satabin/swam) and [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). Whilst SWAM is a Scala interpreter for WebAssembly, AFL is a fuzzing tool for C++ programs. Since AFL provides a generic fuzzing algorithm which is not necessarily bound to C++, we aim to provide a spin-off that applies it to WASM binaries. In the standard AFL setup, C++ source code is compiled using the C++ compiler provided by AFLplusplus (afl-clang-fast++), which "instruments" the code to do additional operations during run-time. The instrumentation that AFL's compiler usually injects into the target source code includes accessing a shared memory, which serves as a communication channel between AFL and the resulting binary. This channel is used to report the coverage data of each execution to AFL, so that AFL can make smarter decisions on the upcoming input parameters. @@ -18,17 +18,23 @@ In SWAM, code coverage is handled in the package 'optin'. The socket server for One major difference between C++ and WASM is that WASM only works with Int32/int, Int64/long, Float32/float and Float64/double. This matters, since AFL most commonly takes a config file as an input parameter, which is then first parsed from chars/strings to the corresponding type by the C++ code. Since a WASM function cannot simply receive a char or string and parse it to the int/long/float/double it needs, we need to do this manually beforehand. -To do this, we explicitly specify what argument types are required by the WASM function in the ./env file and also pass corresponding initial test parameters that work (also in the ./env file). We can then use the prepare_wasm_input.cpp file to write these initial input parameters into an input file with the correct bit representation. By reading this file at the beginning of the execution, the interface is also aware of how many bytes are exactly required by the WASM function, which helps when sending the correct data size towards the server socket or printing output. Furthermore, since the way AFL finds errors in the code is by flipping "random" bits in the config file, these bits need to be preserved without any changes when they are forwarded to SWAM through the socket. +To do this, we explicitly specify what argument types are required by the WASM function in the ./env file and also pass corresponding initial test parameters that work (also in the ./env file). We can then use the ./fuzzing-client-afl/prepare_wasm_input.cpp file to write these initial input parameters into an input file with the correct bit representation. By reading this file at the beginning of the execution, the interface is also aware of how many bytes are exactly required by the WASM function, which helps when sending the correct data size towards the server socket or printing output. Furthermore, since the way AFL finds errors in the code is by flipping "random" bits in the config file, these bits need to be preserved without any changes when they are forwarded to SWAM through the socket. Since the argument types for the WASM function are written as environmental variables, we can also parse them before initialising the SWAM socket server. The server then also knows exactly how to interpret the incoming bytes and how to feed them to the instantiated WASM function. ## Requirements -To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see the main page of this repository on how to set up SWAM. +To be able to run this on your machine, only Docker is required. If you want to test SWAM's socket server without AFL, see ./fuzzing-server on how to install SWAM. -## Building with docker-compose +## Configuration -This tool creates two Docker containers, as specified in the docker-compose.fuzzing.yml file - one for the SWAM socket server (Dockerfile in the root of this repository) and one for the AFL socket client (Dockerfile in this directory). The only configuration parameters to building this are currently the SCALA_VERSION and the MILL_VERSION in SWAM's Dockerfile. Nonetheless, it should not be required to change these parameters as they are fitted to the code of this repostory. +All configuration options are to visible in the .env file. This is where you specify which .wasm/.wat file & function you want to fuzzing and of what types it's input parameters are. Furthermore, it requires to provide a set of working input parameters, which are used in AFL test-runs and can be regarded as AFL's "seed" to random input. + +## Using docker-compose + +### Building + +This tool creates two Docker containers, as specified in the docker-compose.base.yml file - one for the SWAM socket server (Dockerfile in ./fuzzing-server) and one for the AFL socket client (Dockerfile in ./fuzzing-client-afl). The only configuration parameters to building this are currently the SCALA_VERSION and the MILL_VERSION in SWAM's Dockerfile. Nonetheless, it should not be required to change these parameters as they are fitted to the code of this repostory. How to build: @@ -36,19 +42,19 @@ How to build: docker-compose -f docker-compose.base.yml -f docker-compose.yml build ``` -### Mechanics of SWAM's Dockerfile +#### Mechanics of SWAM's Dockerfile We are not using the standard base image for the Scala Mill Build Tool [(nightscape/scala-mill)](https://hub.docker.com/r/nightscape/scala-mill/dockerfile), since it uses an older version of Scala and Mill. Our Dockerfile is however strongly based on theirs. -Mill currently does not provide any command to [simply install dependencies without compiling the source code](https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code). Compiling the source code is done with `mill .compile` and the reason why this is not included in the Dockerfile is to avoid the overhead of downloading all the same dependencies everytime source code is altered. The current workaround is to store the compiled sources along with the dependencies in volumes, which can be accessed during runtime and are specified in the docker-compose.fuzzing.yml file ("compiled_sources" & "maven_data"). SWAM's compilation is therefore delayed to the entrypoint (./entrypoint_mill_server.sh) and is encompassed in the `mill -i cli.run run_server ` command. +Mill currently does not provide any command to [simply install dependencies without compiling the source code](https://stackoverflow.com/questions/62834693/mill-build-tool-install-dependencies-without-compiling-source-code). Compiling the source code is done with `mill .compile` and the reason why this is not included in the Dockerfile is to avoid the overhead of downloading all the same dependencies everytime source code is altered. The current workaround is to store the compiled sources along with the dependencies in volumes, which can be accessed during runtime and are specified in the docker-compose.base.yml file ("compiled_sources" & "maven_data"). SWAM's compilation is therefore delayed to the entrypoint (./entrypoint_mill_server.sh) and is encompassed in the `mill -i cli.run run_server ` command. -### Mechanics of AFL's Dockerfile +#### Mechanics of AFL's Dockerfile This image uses the [official image of AFLplusplus](https://hub.docker.com/r/aflplusplus/aflplusplus/) as a base, which contains the full configuration of AFL pre-installed. It then builds the C++ files of this folder with the standard Ubuntu g++ compiler (not the one provided by AFL). The C++ files are therefore not instrumented. The resulting executables are later accessed during run-time. -## Running with docker-compose +### Running -1. Configure ./.env file. This is where you specify which .wasm/.wat file & function you want to fuzzing and of what types it's input parameters are. Furthermore, it requires to provide a set of working input parameters, which are used in AFL test-runs and can be regarded as AFL's "seed" to random input. *WARNING: Do not rename this file or reference a different \*.env file in docker-compose.fuzzing.yml!* +1. Configure the ./.env file. See [Configuration](#Configuration) for details. *WARNING: Do not rename this file or reference a different \*.env file in docker-compose.base.yml! The docker-compose files use [variable substitution](https://docs.docker.com/compose/compose-file/#variable-substitution), which by default only read from ".env".* 2. Execute docker-compose configuration @@ -58,11 +64,63 @@ This image uses the [official image of AFLplusplus](https://hub.docker.com/r/afl 3. View AFL's results and own logs in the folders which were specified in the .env file. +## Using a single Dockerfile + +### Pros over docker-compose + +1. Both the AFL and the SWAM image only work together. Thereby it may make sense to bundle them into one image. + +1. It is more straightforward to just pull a single image without having to clone the repository (except the ./env file). + +### Cons over docker-compose + +1. Docker images are not meant to run multiple "main" processes. In this case both AFL and SWAM are detached - when they crash, the container does not automatically stop as well. Also, manually stopping the container becomes more difficult as well. + +2. We are interlinking two builds and therefore making one caching process in the Dockerfile dependent on the other. If the first changes, the second will have to rebuild as well. + +### Building + +This build uses the Dockerfile in the root of this directory. It is essentially a merge of the Dockerfiles in ./fuzzing-client-afl and ./fuzzing-server. However, since the SWAM Dockerfile uses openjdk as the base image, the JDK is installed manually in this Dockerfile. It's entrypoint also only references the entrypoints of the client and the server. + +How to build: + +```bash +docker build -t wafl . +``` + +### Running + +1. Configure the ./.env file. See [Configuration](#Configuration) for details. + +2. Source the ./.env file. + + ```bash + set -a + source ./.env + set +a + ``` + +3. Run the Docker image. + + ```bash + docker run --env-file=./.env \ + -e SWAM_SOCKET_HOST=localhost \ + -v ${LOCAL_WASM:?err}:/home/server/wasm/ \ + -v ${LOCAL_AFL_OUTPUT:?err}:/home/client/out/ \ + -v ${LOCAL_LOGS:?err}:/home/shared/logs/ \ + wafl:latest + ``` + ## Building & running without Docker -If you wish to run this plugin without using Docker, you will be required to install [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) and build SWAM with mill (see README of the root of this repository). Concerning AFLplusplus, running `make source-only` on the cloned repository along with installing the dependencies should suffice. +If you wish to run this tool without using Docker, you will be required to install [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) and build SWAM with mill (see README ./fuzzing-server). Concerning AFLplusplus, running `make source-only` on the cloned repository along with installing the dependencies should suffice. + +All other setup steps are best documented in: -All other setup steps are best documented in the Dockerfile in the root of this repository, the Dockerfile in this folder and in entrypoint_afl.sh + entrypoint_mill_server.sh. +- ./fuzzing-server/Dockerfile +- ./fuzzing-server/entrypoint_mill_server.sh +- ./fuzzing-client-afl/Dockerfile +- ./fuzzing-client-afl/entrypoint_afl.sh ## Test SWAM's socket server with sample input (for fibo.wat) @@ -86,7 +144,7 @@ All other setup steps are best documented in the Dockerfile in the root of this 1. **#SPEED**: The SWAM socket server only instantiates the given WASM file/function once. Executing the instantiated function when receiving a message through the socket is equivalent to executing a fixed Scala function in the source code. -1. **#PORTABILITY**: Both the SWAM engine and AFLplusplus are dockerized in two separate containers and are given a corresponding docker-compose.fuzzing.yml setup. All required configuration is to be found in fuzzing/.env. +1. **#PORTABILITY**: Both the SWAM engine and AFLplusplus are dockerized in two separate containers and are given a corresponding service in docker-compose.base.yml setup. All required configuration is to be found in ./.env. ### To Do From 29266f126deb79f097a08b9cf84f8da6029e1a4f Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Wed, 29 Jul 2020 14:39:43 +0200 Subject: [PATCH 63/74] Minor changes gitignore/README --- .gitignore | 3 +++ wasm-fuzzer/README.md | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 908bc4d5..0d101c66 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ ### Intellij ### .idea +### VSCode ### +.metals + ### Python ### venv *.pyc diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md index 3bc480f9..3faa4739 100644 --- a/wasm-fuzzer/README.md +++ b/wasm-fuzzer/README.md @@ -28,7 +28,7 @@ To be able to run this on your machine, only Docker is required. If you want to ## Configuration -All configuration options are to visible in the .env file. This is where you specify which .wasm/.wat file & function you want to fuzzing and of what types it's input parameters are. Furthermore, it requires to provide a set of working input parameters, which are used in AFL test-runs and can be regarded as AFL's "seed" to random input. +All configuration options are visible in the .env file. This is where you specify which .wasm/.wat file & function you want to be fuzzing and of what types it's input parameters are. Furthermore, it requires to provide a set of working input parameters, which are used in AFL test-runs and can be regarded as AFL's "seed" to random input. ## Using docker-compose @@ -54,7 +54,7 @@ This image uses the [official image of AFLplusplus](https://hub.docker.com/r/afl ### Running -1. Configure the ./.env file. See [Configuration](#Configuration) for details. *WARNING: Do not rename this file or reference a different \*.env file in docker-compose.base.yml! The docker-compose files use [variable substitution](https://docs.docker.com/compose/compose-file/#variable-substitution), which by default only read from ".env".* +1. Configure the ./.env file. See [Configuration](#Configuration) for details. *WARNING: Do not rename this file or reference a different \*.env file in docker-compose.base.yml! The docker-compose files use [variable substitution](https://docs.docker.com/compose/compose-file/#variable-substitution), which by default only reads from ".env".* 2. Execute docker-compose configuration From 56fdcab00becdf82591687a5fb1028ff899f1005 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 11:33:11 +0200 Subject: [PATCH 64/74] Back to named volumes again --- wasm-fuzzer/Dockerfile | 5 ----- wasm-fuzzer/README.md | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index af7f5192..a41bbc58 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -63,11 +63,6 @@ ADD ./fuzzing-server $DOCKER_SWAM_SRC RUN chmod +x $DOCKER_SWAM_SRC/entrypoint_mill_server.sh -# For maven data: -VOLUME /root/.cache/coursier/v1/https/repo1.maven.org/maven2 -# For compiled sources: -VOLUME $DOCKER_SWAM_SRC/out/ - ############################# #### fuzzing-client-afl ##### ############################# diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md index 3faa4739..1c0e2d50 100644 --- a/wasm-fuzzer/README.md +++ b/wasm-fuzzer/README.md @@ -105,6 +105,9 @@ docker build -t wafl . ```bash docker run --env-file=./.env \ -e SWAM_SOCKET_HOST=localhost \ + -e MASTER_AFL_NODE=True \ + -v maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 \ + -v compiled_sources:/home/server/src/out/ \ -v ${LOCAL_WASM:?err}:/home/server/wasm/ \ -v ${LOCAL_AFL_OUTPUT:?err}:/home/client/out/ \ -v ${LOCAL_LOGS:?err}:/home/shared/logs/ \ From 473fff75a9f1d6272fd99237fff1b357821759a4 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 11:36:25 +0200 Subject: [PATCH 65/74] Use Supervisord instead of shared entrypoint.sh --- wasm-fuzzer/Dockerfile | 14 ++++++++----- wasm-fuzzer/entrypoint.sh | 40 ------------------------------------ wasm-fuzzer/supervisord.conf | 17 +++++++++++++++ 3 files changed, 26 insertions(+), 45 deletions(-) delete mode 100644 wasm-fuzzer/entrypoint.sh create mode 100644 wasm-fuzzer/supervisord.conf diff --git a/wasm-fuzzer/Dockerfile b/wasm-fuzzer/Dockerfile index a41bbc58..358b502a 100644 --- a/wasm-fuzzer/Dockerfile +++ b/wasm-fuzzer/Dockerfile @@ -15,6 +15,12 @@ RUN yes | add-apt-repository ppa:openjdk-r/ppa RUN apt-get update RUN yes | apt-get install openjdk-12-jdk-headless +####################### +##### Supervisor ###### +####################### + +RUN apt-get install -y supervisor + ######################### ##### Scala & Mill ###### ######################### @@ -90,13 +96,11 @@ RUN chmod +x $DOCKER_INTERFACE_SRC/entrypoint_afl.sh ######## Shared ######### ######################### +ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf + ENV DOCKER_SHARED=/home/shared ENV DOCKER_LOGS=$DOCKER_SHARED/logs RUN mkdir -p $DOCKER_LOGS -ADD ./entrypoint.sh $DOCKER_SHARED - -RUN chmod +x $DOCKER_SHARED/entrypoint.sh - -ENTRYPOINT $DOCKER_SHARED/entrypoint.sh \ No newline at end of file +ENTRYPOINT ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/wasm-fuzzer/entrypoint.sh b/wasm-fuzzer/entrypoint.sh deleted file mode 100644 index d499b210..00000000 --- a/wasm-fuzzer/entrypoint.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# Initial script: https://docs.docker.com/config/containers/multi-service_container/ - -# Start the first process -$DOCKER_SWAM_SRC/entrypoint_mill_server.sh & disown -status=$? -if [ $status -ne 0 ]; then - echo "Failed to start my_first_process: $status" - exit $status -fi - -# Start the second process -$DOCKER_INTERFACE_SRC/entrypoint_afl.sh & disown -status=$? -if [ $status -ne 0 ]; then - echo "Failed to start my_second_process: $status" - exit $status -fi - -# Naive check runs checks once a minute to see if either of the processes exited. -# This illustrates part of the heavy lifting you need to do if you want to run -# more than one service in a container. The container exits with an error -# if it detects that either of the processes has exited. -# Otherwise it loops forever, waking up every 30 seconds - -while sleep 30s; do - ps aux | grep entrypoint_mill_server.sh |grep -q -v grep - MILL_STATUS=$? - ps aux | grep entrypoint_afl.sh |grep -q -v grep - AFL_STATUS=$? - # If the greps above find anything, they exit with 0 status - # If they are not both 0, then something is wrong - if [ $MILL_STATUS -ne 0 -o $AFL_STATUS -ne 0 ]; then - echo "One of the processes has already exited." - echo "mill status: $MILL_STATUS" - echo "afl status: $AFL_STATUS" - exit 1 - fi -done diff --git a/wasm-fuzzer/supervisord.conf b/wasm-fuzzer/supervisord.conf new file mode 100644 index 00000000..cbaf9839 --- /dev/null +++ b/wasm-fuzzer/supervisord.conf @@ -0,0 +1,17 @@ +[supervisord] +nodaemon=true +user=root + +[program:mill_server] +command=%(ENV_DOCKER_SWAM_SRC)s/entrypoint_mill_server.sh +stdout_logfile=/dev/stdout +stderr_logfile=/dev/stderr +stdout_logfile_maxbytes=0 +stderr_logfile_maxbytes=0 + +[program:afl_client] +command=%(ENV_DOCKER_INTERFACE_SRC)s/entrypoint_afl.sh +stdout_logfile=/dev/stdout +stderr_logfile=/dev/stderr +stdout_logfile_maxbytes=0 +stderr_logfile_maxbytes=0 From 013a49b6c2d4b22e2b87e1ecdb47c0093f7a4a24 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 11:46:23 +0200 Subject: [PATCH 66/74] Included Master/Secondary logic in entrypoint_afl.sh --- .../fuzzing-client-afl/entrypoint_afl.sh | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh index 9576a31a..ff696309 100644 --- a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh +++ b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh @@ -6,11 +6,30 @@ PREPARED_INPUT_PATH="$DOCKER_AFL_INPUT/prepared_input.dat" ./prepare_wasm_input.out $PREPARED_INPUT_PATH REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH) +# Parallel fuzzing: https://github.com/mirrorer/afl/blob/master/docs/parallel_fuzzing.txt +if [[ ! -z "$MASTER_AFL_NODE" ]] +then + DOCKER_CONTAINER_ID=$( Date: Thu, 30 Jul 2020 11:52:53 +0200 Subject: [PATCH 67/74] Back to named volume in docker-compose as well --- wasm-fuzzer/docker-compose.base.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wasm-fuzzer/docker-compose.base.yml b/wasm-fuzzer/docker-compose.base.yml index 44c88fa0..0553860d 100644 --- a/wasm-fuzzer/docker-compose.base.yml +++ b/wasm-fuzzer/docker-compose.base.yml @@ -8,6 +8,8 @@ services: env_file: - ./.env volumes: + - maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 + - compiled_sources:/home/server/src/out/ - ${LOCAL_WASM:?err}:/home/wasm/ afl_interface: @@ -21,3 +23,7 @@ services: - ${LOCAL_LOGS:?err}:/home/logs/ depends_on: - swam_server + +volumes: + maven_data: + compiled_sources: \ No newline at end of file From 4fc7ec69593e025bcde40807a966108cad722253 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 11:54:17 +0200 Subject: [PATCH 68/74] Using exec to run mill; no detaching; better with supervisord --- wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh index ff696309..a79cf7ec 100644 --- a/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh +++ b/wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh @@ -32,4 +32,4 @@ fi # 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" -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 From 24047cdd3647e486c4fe1ced1b6abc325eef86ed Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 11:55:06 +0200 Subject: [PATCH 69/74] Updated fuzzing-server git pointer --- wasm-fuzzer/fuzzing-server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm-fuzzer/fuzzing-server b/wasm-fuzzer/fuzzing-server index a2999147..759e41a9 160000 --- a/wasm-fuzzer/fuzzing-server +++ b/wasm-fuzzer/fuzzing-server @@ -1 +1 @@ -Subproject commit a2999147b9d606eb6ad702a238f059be295162c6 +Subproject commit 759e41a9cd778981c2009764a2236b22c2975646 From d02f0e8f68a57714fe7177ed56903cf9f19b5be7 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 13:44:34 +0200 Subject: [PATCH 70/74] Exclude wasm-fuzzer from build_souper.yml CI --- .github/workflows/build_souper.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_souper.yml b/.github/workflows/build_souper.yml index cbffd04c..1063d2c6 100644 --- a/.github/workflows/build_souper.yml +++ b/.github/workflows/build_souper.yml @@ -2,7 +2,11 @@ name: Build souper on: push: + paths-ignore: + - 'wasm-fuzzer/**' pull_request: + paths-ignore: + - 'wasm-fuzzer/**' jobs: build-macos: @@ -28,4 +32,4 @@ jobs: run: cd souper && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release ../ && make - name: Zip folder - run: cd souper && tar -zcvf souper-mac.tar.gz build && ls -la | grep -i souper-mac.tar.gz \ No newline at end of file + run: cd souper && tar -zcvf souper-mac.tar.gz build && ls -la | grep -i souper-mac.tar.gz From adb8c70e08f99dd253dbb9ea70255fdd672b0e83 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 17:20:38 +0200 Subject: [PATCH 71/74] Added script for multi-processing single Docker image --- wasm-fuzzer/multi-processing.sh | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 wasm-fuzzer/multi-processing.sh diff --git a/wasm-fuzzer/multi-processing.sh b/wasm-fuzzer/multi-processing.sh new file mode 100755 index 00000000..a39df618 --- /dev/null +++ b/wasm-fuzzer/multi-processing.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +if [ -z "$1" ] +then + echo "Specifiy the number of AFL instances as argument!" + exit 1 +fi + +echo "Running $1 AFL instance(s)." + +set -a +source ./.env +set +a + +echo "Running #1" +docker run --env-file=./.env \ + -e SWAM_SOCKET_HOST=localhost \ + -e MASTER_AFL_NODE=True \ + -v maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 \ + -v compiled_sources:/home/server/src/out/ \ + -v ${LOCAL_WASM:?err}:/home/server/wasm/ \ + -v ${LOCAL_AFL_OUTPUT:?err}:/home/client/out/ \ + -v ${LOCAL_LOGS:?err}:/home/shared/logs/ \ + -d \ + wafl:latest + +if [ $1 -lt 2 ] +then + exit 0 +fi + +for i in $(seq 2 $1) +do + echo "Waiting for previous mill server to compile..." + sleep 90s + echo "Running #${i}" + docker run --env-file=./.env \ + -e SWAM_SOCKET_HOST=localhost \ + -e MASTER_AFL_NODE=False \ + -v maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 \ + -v compiled_sources:/home/server/src/out/ \ + -v ${LOCAL_WASM:?err}:/home/server/wasm/ \ + -v ${LOCAL_AFL_OUTPUT:?err}:/home/client/out/ \ + -v ${LOCAL_LOGS:?err}:/home/shared/logs/ \ + -d \ + wafl:latest +done +exit 0 From dd2f1fa8703e8ce8ce62e3cce54f29f5bb239a10 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 17:39:18 +0200 Subject: [PATCH 72/74] Added multi-processing section in README --- wasm-fuzzer/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md index 1c0e2d50..e7072919 100644 --- a/wasm-fuzzer/README.md +++ b/wasm-fuzzer/README.md @@ -105,7 +105,6 @@ docker build -t wafl . ```bash docker run --env-file=./.env \ -e SWAM_SOCKET_HOST=localhost \ - -e MASTER_AFL_NODE=True \ -v maven_data:/root/.cache/coursier/v1/https/repo1.maven.org/maven2 \ -v compiled_sources:/home/server/src/out/ \ -v ${LOCAL_WASM:?err}:/home/server/wasm/ \ @@ -114,6 +113,15 @@ docker build -t wafl . wafl:latest ``` +### Multi-processing + +AFLplusplus is encouraged to be run with multiple instances if multiple cores are available. More information is available [here](https://github.com/mirrorer/afl/blob/master/docs/parallel_fuzzing.txt). To automatically run multiple instances in their master/secondary configuration, you can run the following command. Do not forget to build the image first! + +```bash +# 3 for the number of AFL instances. +./multi-processing.sh 3 +``` + ## Building & running without Docker If you wish to run this tool without using Docker, you will be required to install [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) and build SWAM with mill (see README ./fuzzing-server). Concerning AFLplusplus, running `make source-only` on the cloned repository along with installing the dependencies should suffice. From 23e20f911df8b187eb223e6d218c4c7df86f90f4 Mon Sep 17 00:00:00 2001 From: Vincent Lohse Date: Thu, 30 Jul 2020 17:48:46 +0200 Subject: [PATCH 73/74] Excluding wasm-fuzzer branch in CI as well... --- .github/workflows/build_souper.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build_souper.yml b/.github/workflows/build_souper.yml index 1063d2c6..f050608b 100644 --- a/.github/workflows/build_souper.yml +++ b/.github/workflows/build_souper.yml @@ -4,9 +4,13 @@ on: push: paths-ignore: - 'wasm-fuzzer/**' + branches: + - '!wasm-fuzzer' pull_request: paths-ignore: - 'wasm-fuzzer/**' + branches: + - '!wasm-fuzzer' jobs: build-macos: From 212df97dac29752d6c6f7276ed4a1f9047ed71b5 Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Tue, 18 Aug 2020 15:29:20 +0000 Subject: [PATCH 74/74] Update README.md --- wasm-fuzzer/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wasm-fuzzer/README.md b/wasm-fuzzer/README.md index e7072919..c0b477a1 100644 --- a/wasm-fuzzer/README.md +++ b/wasm-fuzzer/README.md @@ -14,6 +14,13 @@ In our case, we are given a WASM binary and an interpreter built with Scala - in In SWAM, code coverage is handled in the package 'optin'. The socket server for SWAM on the other hand, is found in the package 'cli' and is executed with `mill cli.runserver `. The cli makes use of the 'optin' package and returns the coverage results including an exit code of the WASM file through the socket. Interface.cpp then parses this data and feeds the content into the shared memory used by AFL. Even though AFL provides modes to work without using coverage data from executions it has triggered (see qemo mode), it is more efficient when provided it. +Right now, we support fuzzing of four data types as function parameter: + +* int32 +* int64 +* float32 +* float 64 + ## Parsing AFL's fuzzed inputs One major difference between C++ and WASM is that WASM only works with Int32/int, Int64/long, Float32/float and Float64/double. This matters, since AFL most commonly takes a config file as an input parameter, which is then first parsed from chars/strings to the corresponding type by the C++ code. Since a WASM function cannot simply receive a char or string and parse it to the int/long/float/double it needs, we need to do this manually beforehand.