diff options
Diffstat (limited to 'socketfuzzer')
-rw-r--r-- | socketfuzzer/Makefile | 2 | ||||
-rw-r--r-- | socketfuzzer/README.md | 62 | ||||
-rwxr-xr-x | socketfuzzer/honggfuzz_socketclient.py | 93 | ||||
-rw-r--r-- | socketfuzzer/unittest.sh | 3 | ||||
-rw-r--r-- | socketfuzzer/vulnserver_cov.c | 57 |
5 files changed, 158 insertions, 59 deletions
diff --git a/socketfuzzer/Makefile b/socketfuzzer/Makefile index 8cb8c7d8..14096678 100644 --- a/socketfuzzer/Makefile +++ b/socketfuzzer/Makefile @@ -1,5 +1,5 @@ all: vulnserver_cov -vulnserver_cov: +vulnserver_cov: vulnserver_cov.c unset HFUZZ_CC_ASAN ../hfuzz_cc/hfuzz-cc vulnserver_cov.c -o vulnserver_cov diff --git a/socketfuzzer/README.md b/socketfuzzer/README.md index eaa06c00..80062fe1 100644 --- a/socketfuzzer/README.md +++ b/socketfuzzer/README.md @@ -1,8 +1,10 @@ # Honggfuzz - SocketClient -Implement an external fuzzer to fuzz network servers or similar. +Use Honggfuzz as Code-Coverage tool, and implement an external fuzzer which +interacts with the target (usually a network server). The actual fuzzer and +honggfuzz communicate via a local socket. -Tested on Ubuntu 17.04. +Tested on Ubuntu 17.04, 18.04. ## Protocol @@ -16,6 +18,8 @@ HonggFuzz <-> FFW "New!" --> "Cras" --> <-- "bad!" +... + <-- "halt" ``` * "Fuzz": HongFuzz tells FFW to send its network messages to the target server @@ -23,6 +27,7 @@ HonggFuzz <-> FFW * "New!": HonggFuzz tells FFW that new basic blocks have been reached * "Cras": HonggFuzz tells FFW that the target has crashed * "bad!": FFW tells Honggfuzz that the server is crashed +* "halt": Fuzzing finished, shutdown HonggFuzz in an orderly manner. ## Overview @@ -89,38 +94,73 @@ Send to target: 5 Automatic test, successful run: ``` $ ./unittest.sh -Auto -connecting to /tmp/honggfuzz_socket +Auto Test +connecting to /tmp/honggfuzz_socket.24916 Test: 0 - initial +A SocketFuzzer client connected. Continuing. ok: Fuzz -Test: 1 - first new BB +Test: 1 - expecting first new BB +# vulnserver_cov: Listening on port: 5001 +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Auth success +# vulnserver_cov: Closing... ok: New! ok: Fuzz -Test: 2 - second new BB +Test: 2 - expecting second new BB +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Handledata1: BBBBBB +# vulnserver_cov: Closing... ok: New! ok: Fuzz -Test: 3 - repeat second msg, no new BB +Test: 3 - repeat second msg, expecting no new BB +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Handledata1: BBBBBB +# vulnserver_cov: Closing... ok: Fuzz -Test: 4 - crash stack +Test: 4 - crash stack, expect new BB, then crash notification +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 128 on state: 0 +# vulnserver_cov: Handledata1: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB� + ok: New! ok: Cras ok: Fuzz -Test: 5 - resend second, no new BB +Test: 5 - resend second, expecting no new BB +# vulnserver_cov: Listening on port: 5001 ok: Fuzz -Test: 6 - send three, new BB +Test: 6 - send three, expecting new BB +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Handledata2: CCCCCC +# vulnserver_cov: Closing... ok: New! ok: Fuzz Test: 7 - send four, new BB +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Handledata3: 6 +# vulnserver_cov: Closing... ok: New! ok: Fuzz -Test: 8 - send four again, no new BB +Test: 8 - fake unresponsive server + ok: Fuzz + +Test: 9 - send four again, no new BB +# vulnserver_cov: New client connected +# vulnserver_cov: Received data with len: 6 on state: 0 +# vulnserver_cov: Handledata3: 6 +# vulnserver_cov: Closing... +# vulnserver_cov: Listening on port: 5001 ok: Fuzz ``` diff --git a/socketfuzzer/honggfuzz_socketclient.py b/socketfuzzer/honggfuzz_socketclient.py index b129d6a6..29a90c76 100755 --- a/socketfuzzer/honggfuzz_socketclient.py +++ b/socketfuzzer/honggfuzz_socketclient.py @@ -107,12 +107,14 @@ class TargetSocket: if n == 7: # heap buffer overflow data = "C" * 128 + if n == 8: + # heap buffer overflow + data = "FFFFFF" #print " Send: " + str(data) return self.sendToSocket(data) - def sendResp(targetSocketRes, hfSocket): if not targetSocketRes: print " ! Server down. Send: bad!" @@ -121,16 +123,12 @@ def sendResp(targetSocketRes, hfSocket): hfSocket.send("okay") - def auto(pid): - print "Auto" - + print "Auto Test" hfSocket = HonggfuzzSocket(pid) targetSocket = TargetSocket() - hfSocket.connect() - print "" print "Test: 0 - initial" ret = hfSocket.recv() @@ -140,9 +138,8 @@ def auto(pid): print " nok: " + ret return - print "" - print "Test: 1 - first new BB" + print "Test: 1 - expecting first new BB" ret = targetSocket.sendFuzz(1) sendResp(ret, hfSocket) ret = hfSocket.recv() @@ -158,9 +155,8 @@ def auto(pid): print " nok: " + ret return - print "" - print "Test: 2 - second new BB" + print "Test: 2 - expecting second new BB" targetSocket.sendFuzz(2) sendResp(ret, hfSocket) ret = hfSocket.recv() @@ -176,9 +172,8 @@ def auto(pid): print " nok: " + ret return - print "" - print "Test: 3 - repeat second msg, no new BB" + print "Test: 3 - repeat second msg, expecting no new BB" targetSocket.sendFuzz(2) sendResp(ret, hfSocket) ret = hfSocket.recv() @@ -189,15 +184,25 @@ def auto(pid): return print "" - print "Test: 4 - crash stack" + print "Test: 4 - crash stack, expect new BB, then crash notification" targetSocket.sendFuzz(6) sendResp(ret, hfSocket) + # first, a new BB is detected + ret = hfSocket.recv() + if ret == "New!": + print " ok: " + ret + else: + print " nok: " + ret + return + # this leads to a crash ret = hfSocket.recv() if ret == "Cras": print " ok: " + ret else: print " nok: " + ret return + # after the crash, the target should have been restarted, and + # we are ready to fuzz again ret = hfSocket.recv() if ret == "Fuzz": print " ok: " + ret @@ -206,7 +211,7 @@ def auto(pid): return print "" - print "Test: 5 - resend second, no new BB" + print "Test: 5 - resend second, expecting no new BB" targetSocket.sendFuzz(2) sendResp(ret, hfSocket) ret = hfSocket.recv() @@ -217,22 +222,25 @@ def auto(pid): return print "" - print "Test: 6 - send three, new BB" + print "Test: 6 - send three, expecting new BB" targetSocket.sendFuzz(3) sendResp(ret, hfSocket) ret = hfSocket.recv() if ret == "New!": print " ok: " + ret - else: - print " nok: " + ret - return - ret = hfSocket.recv() - if ret == "Fuzz": - print " ok: " + ret + elif ret == "Fuzz": + print " okish: Should have been New!, but lets continue anyway" else: print " nok: " + ret return + if ret == "New!": + ret = hfSocket.recv() + if ret == "Fuzz": + print " ok: " + ret + else: + print " nok: " + ret + return print "" print "Test: 7 - send four, new BB" @@ -251,9 +259,20 @@ def auto(pid): print " nok: " + ret return + # lets simulate that the server has become unresponsive for some reason. + # as described in #253 + print "" + print "Test: 8 - fake unresponsive server" + hfSocket.send("bad!") + ret = hfSocket.recv() + if ret == "Fuzz": + print " ok: " + ret + else: + print " nok: " + ret + return print "" - print "Test: 8 - send four again, no new BB" + print "Test: 9 - send four again, no new BB" targetSocket.sendFuzz(4) sendResp(ret, hfSocket) ret = hfSocket.recv() @@ -263,6 +282,35 @@ def auto(pid): print " nok: " + ret return + # shut honggfuzz down + hfSocket.send("halt") + + # this does not really work yet in honggfuzz. + if (False): + # lets make the server unresponsive + print "" + print "Test: 10 - real unresponsive server" + targetSocket.sendFuzz(8) + sendResp(ret, hfSocket) + # we first have a new BB + ret = hfSocket.recv() + if ret == "New!": + print " ok: " + ret + else: + print " nok: " + ret + return + + print "" + print "Test: 11 - send four again, no new BB" + targetSocket.sendFuzz(4) + sendResp(ret, hfSocket) + ret = hfSocket.recv() + if ret == "Fuzz": + print " ok: " + ret + else: + print " nok: " + ret + return + def interactive(pid): hfSocket = HonggfuzzSocket(pid) @@ -306,7 +354,6 @@ def interactive(pid): print("Exception: " + str(e)) - def main(): mode = None pid = None diff --git a/socketfuzzer/unittest.sh b/socketfuzzer/unittest.sh index e1c3781e..e119c160 100644 --- a/socketfuzzer/unittest.sh +++ b/socketfuzzer/unittest.sh @@ -1,7 +1,6 @@ #!/bin/bash -rm -rf HONGGFUZZ.REPORT.TXT SIGABR* HF.san* +rm HONGGFUZZ.REPORT.TXT SIGABR* HF.san* SIGSEGV.*.fuzz ../honggfuzz --keep_output --debug --sanitizers --stdin_input --threads 1 --verbose --logfile log.txt --socket_fuzzer -- ./vulnserver_cov & - python ./honggfuzz_socketclient.py auto $! diff --git a/socketfuzzer/vulnserver_cov.c b/socketfuzzer/vulnserver_cov.c index d0926e33..a9d29cb1 100644 --- a/socketfuzzer/vulnserver_cov.c +++ b/socketfuzzer/vulnserver_cov.c @@ -10,7 +10,7 @@ /* Do nothing with first message */ void handleData0(char *data, int len) { - printf("Auth success\n"); + printf("# vulnserver_cov: Auth success\n"); } /* Second message is stack based buffer overflow */ @@ -18,30 +18,37 @@ void handleData1(char *data, int len) { char buff[8]; bzero(buff, 8); memcpy(buff, data, len); - printf("Handledata1: %s\n", buff); + printf("# vulnserver_cov: Handledata1: %s\n", buff); } /* Third message is heap overflow */ void handleData2(char *data, int len) { char *buff = malloc(8); + if (!buff) { + abort(); + } bzero(buff, 8); memcpy(buff, data, len); - printf("Handledata2: %s\n", buff); + printf("# vulnserver_cov: Handledata2: %s\n", buff); free(buff); } void handleData3(char *data, int len) { - printf("Meh: %i\n", len); + printf("# vulnserver_cov: Handledata3: %i\n", len); } void handleData4(char *data, int len) { - printf("Blah: %i\n", len); + printf("# vulnserver_cov: Handledata4: %i\n", len); +} + +void handleData5(char *data, int len) { + printf("# vulnserver_cov: Handledata5: %i\n", len); } -void doprocessing(int sock) { +void doprocessing(int sock, int serversock) { char data[1024]; - int n = 0; - int len = 0; + int n = 0; + int len = 0; while (1) { bzero(data, sizeof(data)); @@ -51,7 +58,7 @@ void doprocessing(int sock) { return; } - printf("Received data with len: %i on state: %i\n", len, n); + printf("# vulnserver_cov: Received data with len: %i on state: %i\n", len, n); switch (data[0]) { case 'A': handleData0(data, len); @@ -73,6 +80,12 @@ void doprocessing(int sock) { handleData4(data, len); write(sock, "ok", 2); break; + case 'F': + handleData5(data, len); + write(sock, "ok", 2); + // close the main server socket whoooops + close(serversock); + break; default: return; } @@ -82,10 +95,10 @@ void doprocessing(int sock) { } int main(int argc, char *argv[]) { - int sockfd, newsockfd, portno, clilen; - char buffer[256]; + int sockfd, newsockfd, portno, clilen; + char buffer[256]; struct sockaddr_in serv_addr, cli_addr; - int n, pid; + int n, pid; if (argc == 2) { portno = atoi(argv[1]); @@ -95,24 +108,24 @@ int main(int argc, char *argv[]) { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { - perror("ERROR opening socket"); + perror("# vulnserver_cov: ERROR opening socket"); exit(1); } int reuse = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char *)&reuse, sizeof(reuse)) < 0) - perror("setsockopt(SO_REUSEPORT) failed"); + perror("# vulnserver_cov: setsockopt(SO_REUSEPORT) failed"); bzero((char *)&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; + serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(portno); + serv_addr.sin_port = htons(portno); - printf("Listening on port: %i\n", portno); + printf("# vulnserver_cov: Listening on port: %i\n", portno); /* Now bind the host address using bind() call.*/ if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR on binding"); + perror("# vulnserver_cov: ERROR on binding"); exit(1); } @@ -122,12 +135,12 @@ int main(int argc, char *argv[]) { while (1) { newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); if (newsockfd < 0) { - perror("ERROR on accept"); + perror("# vulnserver_cov: ERROR on accept"); exit(1); } - printf("New client connected\n"); - doprocessing(newsockfd); - printf("Closing...\n"); + printf("# vulnserver_cov: New client connected\n"); + doprocessing(newsockfd, sockfd); + printf("# vulnserver_cov: Closing...\n"); shutdown(newsockfd, 2); close(newsockfd); } |