Browse Source

Fuzzing related changes

Joseph C. Lehner 3 years ago
parent
commit
ec29ee610d
11 changed files with 149 additions and 36 deletions
  1. 15 6
      Makefile
  2. 0 28
      ethsock.c
  3. 23 0
      fuzz.c
  4. BIN
      fuzzin/tftp.bin
  5. BIN
      fuzzin/tftp/fsize_4096_blksize_1k.bin
  6. BIN
      fuzzin/tftp/fsize_4096_default.bin
  7. 0 2
      main.c
  8. 65 0
      mkfuzz.c
  9. 1 0
      nmrp.c
  10. 16 0
      tftp.c
  11. 29 0
      util.c

+ 15 - 6
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

+ 0 - 28
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;

+ 23 - 0
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
+}

BIN
fuzzin/tftp.bin


BIN
fuzzin/tftp/fsize_4096_blksize_1k.bin


BIN
fuzzin/tftp/fsize_4096_default.bin


+ 0 - 2
main.c

@@ -23,8 +23,6 @@
 #include <stdio.h>
 #include "nmrpd.h"
 
-int verbosity = 0;
-
 void usage(FILE *fp)
 {
 	fprintf(fp,

+ 65 - 0
mkfuzz.c

@@ -0,0 +1,65 @@
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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);
+	}
+}

+ 1 - 0
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)

+ 16 - 0
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));
 

+ 29 - 0
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) {