Fuzzing related changes

This commit is contained in:
Joseph C. Lehner 2020-07-06 18:14:41 +02:00
parent 46c56b75e2
commit ec29ee610d
11 changed files with 149 additions and 36 deletions

View file

@ -10,6 +10,12 @@ ifeq ($(shell uname -s),Linux)
LIBS += $(shell pkg-config libnl-route-3.0 --libs) LIBS += $(shell pkg-config libnl-route-3.0 --libs)
endif 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 nmrpflash_OBJ = nmrp.o tftp.o ethsock.o main.o util.o
.PHONY: clean install release release/macos release/linux release/win32 .PHONY: clean install release release/macos release/linux release/win32
@ -23,17 +29,20 @@ tftptest:
%.o: %.c nmrpd.h %.o: %.c nmrpd.h
$(CC) -c $(CFLAGS) $< -o $@ $(CC) -c $(CFLAGS) $< -o $@
fuzz: clean fuzz_nmrp: tftp.c util.c nmrp.c fuzz.c
CC=afl-gcc CFLAGS=-DNMRPFLASH_FUZZ make nmrpflash $(AFL) $(CFLAGS) -DNMRPFLASH_FUZZ $^ -o $@
mv nmrpflash fuzz
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 core | sudo tee /proc/sys/kernel/core_pattern
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 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 echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
clean: clean:
rm -f $(nmrpflash_OBJ) nmrpflash rm -f $(nmrpflash_OBJ) nmrpflash fuzz_nmrp fuzz_tftp
install: nmrpflash install: nmrpflash
install -m 755 nmrpflash $(PREFIX)/bin install -m 755 nmrpflash $(PREFIX)/bin

View file

@ -80,14 +80,6 @@ struct ethsock_ip_undo
#endif #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) static int x_pcap_findalldevs(pcap_if_t **devs)
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
@ -631,26 +623,6 @@ cleanup:
return NULL; 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) ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len)
{ {
struct pcap_pkthdr* hdr; struct pcap_pkthdr* hdr;

23
fuzz.c Normal file
View file

@ -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 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
main.c
View file

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

65
mkfuzz.c Normal file
View file

@ -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
nmrp.c
View file

@ -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_add(a, b, c, d) (0)
#define ethsock_ip_del(a, b) (0) #define ethsock_ip_del(a, b) (0)
#define ethsock_close(a) (0) #define ethsock_close(a) (0)
#define ethsock_for_each_ip(a, b, c) (1)
#define tftp_put(a) (0) #define tftp_put(a) (0)
static uint8_t *ethsock_get_hwaddr_fake(struct ethsock* sock) static uint8_t *ethsock_get_hwaddr_fake(struct ethsock* sock)

16
tftp.c
View file

@ -193,12 +193,20 @@ static ssize_t tftp_recvfrom(int sock, char *pkt, uint16_t* port,
return 0; return 0;
} }
#ifndef NMRPFLASH_FUZZ
alen = sizeof(src); alen = sizeof(src);
len = recvfrom(sock, pkt, pktlen, 0, (struct sockaddr*)&src, &alen); len = recvfrom(sock, pkt, pktlen, 0, (struct sockaddr*)&src, &alen);
if (len < 0) { if (len < 0) {
sock_perror("recvfrom"); sock_perror("recvfrom");
return -1; return -1;
} }
#else
len = read(sock, pkt, pktlen);
if (len < 0) {
perror("read");
return -1;
}
#endif
*port = ntohs(src.sin_port); *port = ntohs(src.sin_port);
@ -263,10 +271,14 @@ static ssize_t tftp_sendto(int sock, char *pkt, size_t len,
printf("\n"); printf("\n");
} }
#ifndef NMRPFLASH_FUZZ
sent = sendto(sock, pkt, len, 0, (struct sockaddr*)dst, sizeof(*dst)); sent = sendto(sock, pkt, len, 0, (struct sockaddr*)dst, sizeof(*dst));
if (sent < 0) { if (sent < 0) {
sock_perror("sendto"); sock_perror("sendto");
} }
#else
sent = len;
#endif
return sent; 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); sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) { if (sock < 0) {
sock_perror("socket"); sock_perror("socket");
ret = sock; ret = sock;
goto cleanup; goto cleanup;
} }
#else
sock = STDIN_FILENO;
#endif
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));

29
util.c
View file

@ -28,6 +28,7 @@
#endif #endif
volatile sig_atomic_t g_interrupted = 0; volatile sig_atomic_t g_interrupted = 0;
int verbosity = 0;
time_t time_monotonic() time_t time_monotonic()
{ {
@ -58,6 +59,14 @@ char *lltostr(long long ll, int base)
return buf; 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 bitcount(uint32_t n)
{ {
uint32_t c; uint32_t c;
@ -72,6 +81,26 @@ uint32_t netmask(uint32_t count)
return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0); 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) void xperror(const char *msg)
{ {
if (errno != EINTR) { if (errno != EINTR) {