Skip to content

Commit

Permalink
Fuzzing libpcap
Browse files Browse the repository at this point in the history
One target for a pcap file
One target for a bpf filter
One target for pcap_offline_filter
  • Loading branch information
catenacyber committed Oct 8, 2018
1 parent fdadf44 commit 98f0552
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 0 deletions.
2 changes: 2 additions & 0 deletions testprogs/CMakeLists.txt
Expand Up @@ -38,3 +38,5 @@ add_test_executable(threadsignaltest ${CMAKE_THREAD_LIBS_INIT})
if(NOT WIN32)
add_test_executable(valgrindtest)
endif()

add_subdirectory(fuzz)
8 changes: 8 additions & 0 deletions testprogs/fuzz/CMakeLists.txt
@@ -0,0 +1,8 @@
add_executable(fuzz_pcap onefile.c fuzz_pcap.c)
target_link_libraries(fuzz_pcap ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})

add_executable(fuzz_filter onefile.c fuzz_filter.c)
target_link_libraries(fuzz_filter ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})

add_executable(fuzz_both onefile.c fuzz_both.c)
target_link_libraries(fuzz_both ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
102 changes: 102 additions & 0 deletions testprogs/fuzz/fuzz_both.c
@@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#include <pcap/pcap.h>

FILE * outfile = NULL;

static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
FILE * fd;
if (remove(name) != 0) {
if (errno != ENOENT) {
printf("failed remove, errno=%d\n", errno);
return -1;
}
}
fd = fopen(name, "wb");
if (fd == NULL) {
printf("failed open, errno=%d\n", errno);
return -2;
}
if (fwrite (Data, 1, Size, fd) != Size) {
fclose(fd);
return -3;
}
fclose(fd);
return 0;
}

void fuzz_openFile(const char * name) {
if (outfile != NULL) {
fclose(outfile);
}
outfile = fopen(name, "w");
}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
char errbuf[PCAP_ERRBUF_SIZE];
const u_char *pkt;
struct pcap_pkthdr *header;
struct pcap_stat stats;
int r;
size_t filterSize;
char * filter;
struct bpf_program bpf;


//initialize output file
if (outfile == NULL) {
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
}

if (Size < 1) {
return 0;
}
filterSize = Data[0];
if (Size < 1+filterSize || filterSize == 0) {
return 0;
}

//rewrite buffer to a file as libpcap does not have buffer inputs
if (bufferToFile("/tmp/fuzz.pcap", Data+1+filterSize, Size-(1+filterSize)) < 0) {
return 0;
}

//initialize structure
pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
if (pkts == NULL) {
fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
return 0;
}

filter = malloc(filterSize);
memcpy(filter, Data+1, filterSize);
//null terminate string
filter[filterSize-1] = 0;

if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
//loop over packets
r = pcap_next_ex(pkts, &header, &pkt);
while (r > 0) {
//checks filter
fprintf(outfile, "packet length=%d/%d filter=%d\n",header->caplen, header->len, pcap_offline_filter(&bpf, header, pkt));
r = pcap_next_ex(pkts, &header, &pkt);
}
//close structure
pcap_close(pkts);
pcap_freecode(&bpf);
}
else {
pcap_close(pkts);
}
free(filter);

return 0;
}
2 changes: 2 additions & 0 deletions testprogs/fuzz/fuzz_both.options
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65535
43 changes: 43 additions & 0 deletions testprogs/fuzz/fuzz_filter.c
@@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <pcap/pcap.h>

void fuzz_openFile(const char * name){
//do nothing
}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
struct bpf_program bpf;
char * filter;

//we need at least 1 byte for linktype
if (Size < 1) {
return 0;
}

//initialize structure snaplen = 65535
pkts = pcap_open_dead(Data[Size-1], 0xFFFF);
if (pkts == NULL) {
printf("pcap_open_dead failed\n");
return 0;
}
filter = malloc(Size);
memcpy(filter, Data, Size);
//null terminate string
filter[Size-1] = 0;

if (pcap_compile(pkts, &bpf, filter, 1, PCAP_NETMASK_UNKNOWN) == 0) {
pcap_setfilter(pkts, &bpf);
pcap_close(pkts);
pcap_freecode(&bpf);
}
else {
pcap_close(pkts);
}
free(filter);

return 0;
}
2 changes: 2 additions & 0 deletions testprogs/fuzz/fuzz_filter.options
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 4096
80 changes: 80 additions & 0 deletions testprogs/fuzz/fuzz_pcap.c
@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

#include <pcap/pcap.h>

FILE * outfile = NULL;

static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) {
FILE * fd;
if (remove(name) != 0) {
if (errno != ENOENT) {
printf("failed remove, errno=%d\n", errno);
return -1;
}
}
fd = fopen(name, "wb");
if (fd == NULL) {
printf("failed open, errno=%d\n", errno);
return -2;
}
if (fwrite (Data, 1, Size, fd) != Size) {
fclose(fd);
return -3;
}
fclose(fd);
return 0;
}

void fuzz_openFile(const char * name) {
if (outfile != NULL) {
fclose(outfile);
}
outfile = fopen(name, "w");
}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
pcap_t * pkts;
char errbuf[PCAP_ERRBUF_SIZE];
const u_char *pkt;
struct pcap_pkthdr *header;
struct pcap_stat stats;
int r;

//initialize output file
if (outfile == NULL) {
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
}

//rewrite buffer to a file as libpcap does not have buffer inputs
if (bufferToFile("/tmp/fuzz.pcap", Data, Size) < 0) {
return 0;
}

//initialize structure
pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
if (pkts == NULL) {
fprintf(outfile, "Couldn't open pcap file %s\n", errbuf);
return 0;
}

//loop over packets
r = pcap_next_ex(pkts, &header, &pkt);
while (r > 0) {
//TODO pcap_offline_filter
fprintf(outfile, "packet length=%d/%d\n",header->caplen, header->len);
r = pcap_next_ex(pkts, &header, &pkt);
}
if (pcap_stats(pkts, &stats) == 0) {
fprintf(outfile, "number of packets=%d\n", stats.ps_recv);
}
//close structure
pcap_close(pkts);

return 0;
}
2 changes: 2 additions & 0 deletions testprogs/fuzz/fuzz_pcap.options
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65535
54 changes: 54 additions & 0 deletions testprogs/fuzz/onefile.c
@@ -0,0 +1,54 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
void fuzz_openFile(const char * name);

int main(int argc, char** argv)
{
FILE * fp;
uint8_t *Data;
size_t Size;

if (argc == 3) {
fuzz_openFile(argv[2]);
} else if (argc != 2) {
return 1;
}
//opens the file, get its size, and reads it into a buffer
fp = fopen(argv[1], "rb");
if (fp == NULL) {
return 2;
}
if (fseek(fp, 0L, SEEK_END) != 0) {
fclose(fp);
return 2;
}
Size = ftell(fp);
if (Size == (size_t) -1) {
fclose(fp);
return 2;
}
if (fseek(fp, 0L, SEEK_SET) != 0) {
fclose(fp);
return 2;
}
Data = malloc(Size);
if (Data == NULL) {
fclose(fp);
return 2;
}
if (fread(Data, Size, 1, fp) != 1) {
fclose(fp);
free(Data);
return 2;
}

//lauch fuzzer
LLVMFuzzerTestOneInput(Data, Size);
free(Data);
fclose(fp);
return 0;
}

0 comments on commit 98f0552

Please sign in to comment.