From ec29ee610ded4b2d829b452c10d6bab7572f42c5 Mon Sep 17 00:00:00 2001 From: "Joseph C. Lehner" Date: Mon, 6 Jul 2020 18:14:41 +0200 Subject: [PATCH] Fuzzing related changes --- Makefile | 21 ++++++--- ethsock.c | 28 ----------- fuzz.c | 23 +++++++++ fuzzin/tftp.bin | Bin 0 -> 4096 bytes fuzzin/tftp/fsize_4096_blksize_1k.bin | Bin 0 -> 4608 bytes fuzzin/tftp/fsize_4096_default.bin | Bin 0 -> 4608 bytes main.c | 2 - mkfuzz.c | 65 ++++++++++++++++++++++++++ nmrp.c | 1 + tftp.c | 16 +++++++ util.c | 29 ++++++++++++ 11 files changed, 149 insertions(+), 36 deletions(-) create mode 100644 fuzz.c create mode 100644 fuzzin/tftp.bin create mode 100644 fuzzin/tftp/fsize_4096_blksize_1k.bin create mode 100644 fuzzin/tftp/fsize_4096_default.bin create mode 100644 mkfuzz.c diff --git a/Makefile b/Makefile index 797aaac..80793df 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,12 @@ ifeq ($(shell uname -s),Linux) LIBS += $(shell pkg-config libnl-route-3.0 --libs) endif +ifeq ($(shell uname -s),Darwin) + AFL=afl-clang +else + AFL=afl-gcc +endif + nmrpflash_OBJ = nmrp.o tftp.o ethsock.o main.o util.o .PHONY: clean install release release/macos release/linux release/win32 @@ -23,17 +29,20 @@ tftptest: %.o: %.c nmrpd.h $(CC) -c $(CFLAGS) $< -o $@ -fuzz: clean - CC=afl-gcc CFLAGS=-DNMRPFLASH_FUZZ make nmrpflash - mv nmrpflash fuzz +fuzz_nmrp: tftp.c util.c nmrp.c fuzz.c + $(AFL) $(CFLAGS) -DNMRPFLASH_FUZZ $^ -o $@ -dofuzz: fuzz +fuzz_tftp: tftp.c util.c nmrp.c fuzz.c + $(AFL) $(CFLAGS) -DNMRPFLASH_FUZZ -DNMRPFLASH_FUZZ_TFTP $^ -o $@ + +dofuzz_tftp: fuzz echo core | sudo tee /proc/sys/kernel/core_pattern echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - afl-fuzz -i fuzzin -o fuzzout -- ./fuzz + afl-fuzz -i fuzzin/nmrp -o fuzzout/nmrp -- ./fuzz_tftp echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor + clean: - rm -f $(nmrpflash_OBJ) nmrpflash + rm -f $(nmrpflash_OBJ) nmrpflash fuzz_nmrp fuzz_tftp install: nmrpflash install -m 755 nmrpflash $(PREFIX)/bin diff --git a/ethsock.c b/ethsock.c index 838f6bf..3c5572e 100644 --- a/ethsock.c +++ b/ethsock.c @@ -80,14 +80,6 @@ struct ethsock_ip_undo #endif }; -const char *mac_to_str(uint8_t *mac) -{ - static char buf[18]; - snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return buf; -} - static int x_pcap_findalldevs(pcap_if_t **devs) { char errbuf[PCAP_ERRBUF_SIZE]; @@ -631,26 +623,6 @@ cleanup: return NULL; } -int select_fd(int fd, unsigned timeout) -{ - struct timeval tv; - int status; - fd_set fds; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = 1000 * (timeout % 1000); - - status = select(fd + 1, &fds, NULL, NULL, &tv); - if (status < 0) { - sock_perror("select"); - } - - return status; -} - ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len) { struct pcap_pkthdr* hdr; diff --git a/fuzz.c b/fuzz.c new file mode 100644 index 0000000..0da2446 --- /dev/null +++ b/fuzz.c @@ -0,0 +1,23 @@ +#include "nmrpd.h" + +int main(int argc, char** argv) +{ + struct nmrpd_args args = { + .rx_timeout = 60, + .ul_timeout = 60, + .ipmask = "255.255.255.0", + .mac = "ff:ff:ff:ff:ff:ff", + .op = NMRP_UPLOAD_FW, + .port = 69, + }; +#ifdef NMRPFLASH_FUZZ_TFTP + if (argc != 2) { + return 1; + } + args.file_local = argv[1]; + + return tftp_put(&args); +#else + return nmrp_do(&args); +#endif +} diff --git a/fuzzin/tftp.bin b/fuzzin/tftp.bin new file mode 100644 index 0000000000000000000000000000000000000000..08e7df176454f3ee5eeda13efa0adaa54828dfd8 GIT binary patch literal 4096 ocmeIu0Sy2E0K%a6Pi+qe5hx58Fkrxd0RsjM7%*VKfPwdc0T2KH0RR91 literal 0 HcmV?d00001 diff --git a/fuzzin/tftp/fsize_4096_blksize_1k.bin b/fuzzin/tftp/fsize_4096_blksize_1k.bin new file mode 100644 index 0000000000000000000000000000000000000000..03b82dcbf98020ba3bea9bc4a50bd322d61dacf8 GIT binary patch literal 4608 zcmeIuu?>JQ00TioEao9mCW=IXl8%n)Y1qR58~o`QYd-gTsh+Ki(gdt6ZJA#L5cmbG Z9SZ~y2o #include "nmrpd.h" -int verbosity = 0; - void usage(FILE *fp) { fprintf(fp, diff --git a/mkfuzz.c b/mkfuzz.c new file mode 100644 index 0000000..a7e3031 --- /dev/null +++ b/mkfuzz.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +enum tftp_opcode { + RRQ = 1, + WRQ = 2, + DATA = 3, + ACK = 4, + ERR = 5, + OACK = 6 +}; + +static inline char *pkt_mknum(char *pkt, uint16_t n) +{ + *(uint16_t*)pkt = htons(n); + return pkt + 2; +} + +static char *pkt_mkopt(char *pkt, const char *opt, const char* val) +{ + strcpy(pkt, opt); + pkt += strlen(opt) + 1; + strcpy(pkt, val); + pkt += strlen(val) + 1; + return pkt; +} + +int main(int argc, char** argv) +{ + if (argc != 2) { + return 1; + } + + const size_t fsize = 4096; + + char pkt[1024]; + char* p; + size_t len = 512; + + memset(pkt, 0, sizeof(pkt)); + + if (argc == 2 && argv[1][0] == 'k') { + len = 1024; + + p = pkt_mknum(pkt, OACK); + pkt_mkopt(p, "blksize", "1024"); + } else { + p = pkt_mknum(pkt, ACK); + pkt_mknum(p, 0); + } + + write(STDOUT_FILENO, pkt, 512); + + size_t i = 0; + + for (; i < fsize/len; ++i) { + memset(pkt, 0, len); + p = pkt_mknum(pkt, ACK); + pkt_mknum(p, i + 1); + write(STDOUT_FILENO, pkt, len); + } +} diff --git a/nmrp.c b/nmrp.c index e4fcbf1..41cc07d 100644 --- a/nmrp.c +++ b/nmrp.c @@ -240,6 +240,7 @@ static void msg_mkconfack(struct nmrp_msg *msg, uint32_t ipaddr, uint32_t ipmask #define ethsock_ip_add(a, b, c, d) (0) #define ethsock_ip_del(a, b) (0) #define ethsock_close(a) (0) +#define ethsock_for_each_ip(a, b, c) (1) #define tftp_put(a) (0) static uint8_t *ethsock_get_hwaddr_fake(struct ethsock* sock) diff --git a/tftp.c b/tftp.c index 27ca320..3cbf7c6 100644 --- a/tftp.c +++ b/tftp.c @@ -193,12 +193,20 @@ static ssize_t tftp_recvfrom(int sock, char *pkt, uint16_t* port, return 0; } +#ifndef NMRPFLASH_FUZZ alen = sizeof(src); len = recvfrom(sock, pkt, pktlen, 0, (struct sockaddr*)&src, &alen); if (len < 0) { sock_perror("recvfrom"); return -1; } +#else + len = read(sock, pkt, pktlen); + if (len < 0) { + perror("read"); + return -1; + } +#endif *port = ntohs(src.sin_port); @@ -263,10 +271,14 @@ static ssize_t tftp_sendto(int sock, char *pkt, size_t len, printf("\n"); } +#ifndef NMRPFLASH_FUZZ sent = sendto(sock, pkt, len, 0, (struct sockaddr*)dst, sizeof(*dst)); if (sent < 0) { sock_perror("sendto"); } +#else + sent = len; +#endif return sent; } @@ -340,12 +352,16 @@ int tftp_put(struct nmrpd_args *args) } } +#ifndef NMRPFLASH_FUZZ_TFTP sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { sock_perror("socket"); ret = sock; goto cleanup; } +#else + sock = STDIN_FILENO; +#endif memset(&addr, 0, sizeof(addr)); diff --git a/util.c b/util.c index 0d2aab9..c115ad1 100644 --- a/util.c +++ b/util.c @@ -28,6 +28,7 @@ #endif volatile sig_atomic_t g_interrupted = 0; +int verbosity = 0; time_t time_monotonic() { @@ -58,6 +59,14 @@ char *lltostr(long long ll, int base) return buf; } +const char *mac_to_str(uint8_t *mac) +{ + static char buf[18]; + snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return buf; +} + uint32_t bitcount(uint32_t n) { uint32_t c; @@ -72,6 +81,26 @@ uint32_t netmask(uint32_t count) return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0); } +int select_fd(int fd, unsigned timeout) +{ + struct timeval tv; + int status; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = 1000 * (timeout % 1000); + + status = select(fd + 1, &fds, NULL, NULL, &tv); + if (status < 0) { + sock_perror("select"); + } + + return status; +} + void xperror(const char *msg) { if (errno != EINTR) {