mirror of
https://github.com/clearml/dropbear
synced 2025-03-09 21:41:07 +00:00
Fix fuzz-sshpacketmutator to work
This commit is contained in:
parent
acd6a22a0c
commit
1260fbc5cd
@ -273,7 +273,8 @@ FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \
|
|||||||
fuzzer-client_mutator
|
fuzzer-client_mutator
|
||||||
|
|
||||||
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
|
FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
|
||||||
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS)))
|
FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
|
||||||
|
fuzz/fuzz-sshpacketmutator.o
|
||||||
|
|
||||||
list-fuzz-targets:
|
list-fuzz-targets:
|
||||||
@echo $(FUZZ_TARGETS)
|
@echo $(FUZZ_TARGETS)
|
||||||
@ -292,6 +293,8 @@ fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS)
|
|||||||
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
||||||
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) -lcrypt
|
$(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) -lcrypt
|
||||||
|
|
||||||
|
fuzzer-client_mutator: allobjs += fuzz/fuzz-sshpacketmutator.o
|
||||||
|
|
||||||
fuzzer-%.options: Makefile
|
fuzzer-%.options: Makefile
|
||||||
echo "[libfuzzer]" > $@
|
echo "[libfuzzer]" > $@
|
||||||
echo "max_len = 50000" >> $@
|
echo "max_len = 50000" >> $@
|
||||||
|
1
buffer.c
1
buffer.c
@ -188,6 +188,7 @@ unsigned char* buf_getptr(const buffer* buf, unsigned int len) {
|
|||||||
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) {
|
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len) {
|
||||||
|
|
||||||
if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
|
if (len > BUF_MAX_INCR || buf->pos + len > buf->size) {
|
||||||
|
abort();
|
||||||
dropbear_exit("Bad buf_getwriteptr");
|
dropbear_exit("Bad buf_getwriteptr");
|
||||||
}
|
}
|
||||||
return &buf->data[buf->pos];
|
return &buf->data[buf->pos];
|
||||||
|
@ -45,9 +45,9 @@ void fuzz_common_setup(void) {
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n");
|
// fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n");
|
||||||
fuzz.stderr = fopen("/dev/null", "w");
|
// fuzz.stderr = fopen("/dev/null", "w");
|
||||||
assert(fuzz.stderr);
|
// assert(fuzz.stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
|
#include "dbutil.h"
|
||||||
|
|
||||||
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ static void fuzz_get_packets(buffer *inp, buffer **out_packets, unsigned int *nu
|
|||||||
buf_incrpos(inp, version - inp->data);
|
buf_incrpos(inp, version - inp->data);
|
||||||
unsigned char* newline = memchr(&inp->data[inp->pos], '\n', inp->len - inp->pos);
|
unsigned char* newline = memchr(&inp->data[inp->pos], '\n', inp->len - inp->pos);
|
||||||
if (newline) {
|
if (newline) {
|
||||||
buf_incrpos(inp, newline - &inp->data[inp->pos]);
|
buf_incrpos(inp, newline - &inp->data[inp->pos]+1);
|
||||||
} else {
|
} else {
|
||||||
/* Give up on any version string */
|
/* Give up on any version string */
|
||||||
buf_setpos(inp, 0);
|
buf_setpos(inp, 0);
|
||||||
@ -32,8 +33,11 @@ static void fuzz_get_packets(buffer *inp, buffer **out_packets, unsigned int *nu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read packet */
|
/* Read packet */
|
||||||
|
//printf("at %d\n", inp->pos);
|
||||||
|
//printhex("lenget", buf_getptr(inp, 48), 48);
|
||||||
unsigned int packet_len = buf_getint(inp);
|
unsigned int packet_len = buf_getint(inp);
|
||||||
if (packet_len <= RECV_MAX_PACKET_LEN) {
|
// printf("len %u\n", packet_len);
|
||||||
|
if (packet_len > RECV_MAX_PACKET_LEN-4) {
|
||||||
/* Bad length, try skipping a single byte */
|
/* Bad length, try skipping a single byte */
|
||||||
buf_decrpos(inp, 3);
|
buf_decrpos(inp, 3);
|
||||||
continue;
|
continue;
|
||||||
@ -45,11 +49,11 @@ static void fuzz_get_packets(buffer *inp, buffer **out_packets, unsigned int *nu
|
|||||||
buf_putint(new_packet, packet_len);
|
buf_putint(new_packet, packet_len);
|
||||||
buf_putbytes(new_packet, buf_getptr(inp, packet_len), packet_len);
|
buf_putbytes(new_packet, buf_getptr(inp, packet_len), packet_len);
|
||||||
buf_incrpos(inp, packet_len);
|
buf_incrpos(inp, packet_len);
|
||||||
|
// printf("incr pos %d to %d\n", packet_len, inp->pos);
|
||||||
|
|
||||||
out_packets[*num_out_packets] = new_packet;
|
out_packets[*num_out_packets] = new_packet;
|
||||||
(*num_out_packets)++;
|
(*num_out_packets)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mutate in-place */
|
/* Mutate in-place */
|
||||||
@ -76,22 +80,51 @@ static const size_t MAX_OUT_SIZE = 50000;
|
|||||||
|
|
||||||
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
||||||
size_t MaxSize, unsigned int Seed) {
|
size_t MaxSize, unsigned int Seed) {
|
||||||
int i;
|
|
||||||
|
/* Avoid some allocations */
|
||||||
|
/* XXX perhaps this complication isn't worthwhile */
|
||||||
|
static buffer buf_oup, buf_alloc_packetA, buf_alloc_packetB;
|
||||||
|
static buffer *oup = &buf_oup;
|
||||||
|
static buffer *alloc_packetA = &buf_alloc_packetA;
|
||||||
|
static buffer *alloc_packetB = &buf_alloc_packetB;
|
||||||
|
static int once = 1;
|
||||||
|
if (once) {
|
||||||
|
once = 0;
|
||||||
|
// malloc doesn't get intercepted by epoch deallocator
|
||||||
|
oup->size = MAX_OUT_SIZE;
|
||||||
|
alloc_packetA->size = RECV_MAX_PACKET_LEN;
|
||||||
|
alloc_packetB->size = RECV_MAX_PACKET_LEN;
|
||||||
|
oup->data = malloc(oup->size);
|
||||||
|
alloc_packetA->data = malloc(alloc_packetA->size);
|
||||||
|
alloc_packetB->data = malloc(alloc_packetB->size);
|
||||||
|
}
|
||||||
|
alloc_packetA->pos = 0;
|
||||||
|
alloc_packetA->len = 0;
|
||||||
|
alloc_packetB->pos = 0;
|
||||||
|
alloc_packetB->len = 0;
|
||||||
|
oup->pos = 0;
|
||||||
|
oup->len = 0;
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
unsigned short randstate[3] = {0,0,0};
|
unsigned short randstate[3] = {0,0,0};
|
||||||
memcpy(randstate, &Seed, sizeof(Seed));
|
memcpy(randstate, &Seed, sizeof(Seed));
|
||||||
|
|
||||||
|
// printhex("mutator input", Data, Size);
|
||||||
|
#if 0
|
||||||
/* 1% chance straight llvm mutate */
|
/* 1% chance straight llvm mutate */
|
||||||
if (nrand48(randstate) % 100 == 0) {
|
if (nrand48(randstate) % 100 == 0) {
|
||||||
return LLVMFuzzerMutate(Data, Size, MaxSize);
|
return LLVMFuzzerMutate(Data, Size, MaxSize);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
buffer inp_buf = {.data = Data, .size = Size, .len = Size, .pos = 0};
|
buffer inp_buf = {.data = Data, .size = Size, .len = Size, .pos = 0};
|
||||||
buffer *inp = &inp_buf;
|
buffer *inp = &inp_buf;
|
||||||
|
|
||||||
/* Parse packets */
|
/* Parse packets */
|
||||||
buffer* packets[MAX_FUZZ_PACKETS] = {0};
|
buffer* packets[MAX_FUZZ_PACKETS];
|
||||||
unsigned int num_packets = MAX_FUZZ_PACKETS;
|
unsigned int num_packets = MAX_FUZZ_PACKETS;
|
||||||
fuzz_get_packets(inp, packets, &num_packets);
|
fuzz_get_packets(inp, packets, &num_packets);
|
||||||
|
// printf("%d packets\n", num_packets);
|
||||||
|
|
||||||
if (num_packets == 0) {
|
if (num_packets == 0) {
|
||||||
// gotta do something
|
// gotta do something
|
||||||
@ -100,7 +133,6 @@ size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Start output */
|
/* Start output */
|
||||||
buffer *oup = buf_new(MAX_OUT_SIZE);
|
|
||||||
/* Put a new banner to output */
|
/* Put a new banner to output */
|
||||||
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
|
buf_putbytes(oup, FIXED_VERSION, strlen(FIXED_VERSION));
|
||||||
|
|
||||||
@ -108,42 +140,46 @@ size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
|||||||
for (i = 0; i < num_packets+1; i++) {
|
for (i = 0; i < num_packets+1; i++) {
|
||||||
// These are pointers to output
|
// These are pointers to output
|
||||||
buffer *out_packetA = NULL, *out_packetB = NULL;
|
buffer *out_packetA = NULL, *out_packetB = NULL;
|
||||||
// These need to be freed
|
alloc_packetA->pos = 0;
|
||||||
buffer *alloc_packetA = NULL, *alloc_packetB = NULL;
|
alloc_packetA->len = 0;
|
||||||
|
alloc_packetB->pos = 0;
|
||||||
|
alloc_packetB->len = 0;
|
||||||
|
|
||||||
/* 5% chance each */
|
/* 5% chance each */
|
||||||
const int optA = nrand48(randstate) % 20;
|
const int optA = nrand48(randstate) % 20;
|
||||||
const int other = nrand48(randstate) % num_packets;
|
|
||||||
if (optA == 0) {
|
if (optA == 0) {
|
||||||
/* Copy another */
|
/* Copy another */
|
||||||
out_packetA = packets[nrand48(randstate) % num_packets];
|
unsigned int other = nrand48(randstate) % num_packets;
|
||||||
|
out_packetA = packets[other];
|
||||||
|
// printf("%d copy another %d\n", i, other);
|
||||||
}
|
}
|
||||||
if (optA == 1) {
|
if (optA == 1) {
|
||||||
/* Mutate another */
|
/* Mutate another */
|
||||||
alloc_packetA = buf_new(RECV_MAX_PACKET_LEN);
|
unsigned int other = nrand48(randstate) % num_packets;
|
||||||
buffer *from = packets[nrand48(randstate) % num_packets];
|
buffer *from = packets[other];
|
||||||
buf_putbytes(alloc_packetA, from->data, from->len);
|
buf_putbytes(alloc_packetA, from->data, from->len);
|
||||||
out_packetA = alloc_packetA;
|
out_packetA = alloc_packetA;
|
||||||
buf_llvm_mutate(out_packetA);
|
buf_llvm_mutate(out_packetA);
|
||||||
|
// printf("%d mutate another %d\n", i, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 10% chance each of mutate or drop */
|
|
||||||
if (i < num_packets) {
|
if (i < num_packets) {
|
||||||
int optB = nrand48(randstate) % 10;
|
int optB = nrand48(randstate) % 10;
|
||||||
if (optB == 0) {
|
|
||||||
/* Copy as-is */
|
|
||||||
out_packetB = packets[i];
|
|
||||||
}
|
|
||||||
if (optB == 1) {
|
if (optB == 1) {
|
||||||
|
/* 10% chance of drop */
|
||||||
/* Drop it */
|
/* Drop it */
|
||||||
}
|
// printf("%d drop\n", i);
|
||||||
if (optB == 2) {
|
} else if (optB <= 6) {
|
||||||
/* Mutate it */
|
/* Mutate it, 50% chance */
|
||||||
alloc_packetB = buf_new(RECV_MAX_PACKET_LEN);
|
// printf("%d mutate\n", i);
|
||||||
buffer *from = packets[nrand48(randstate) % num_packets];
|
buffer *from = packets[nrand48(randstate) % num_packets];
|
||||||
buf_putbytes(alloc_packetB, from->data, from->len);
|
buf_putbytes(alloc_packetB, from->data, from->len);
|
||||||
out_packetB = alloc_packetB;
|
out_packetB = alloc_packetB;
|
||||||
buf_llvm_mutate(out_packetB);
|
buf_llvm_mutate(out_packetB);
|
||||||
|
} else {
|
||||||
|
/* Copy as-is */
|
||||||
|
out_packetB = packets[i];
|
||||||
|
// printf("%d as-is\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,14 +189,6 @@ size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
|||||||
if (out_packetB && oup->len + out_packetB->len <= oup->size) {
|
if (out_packetB && oup->len + out_packetB->len <= oup->size) {
|
||||||
buf_putbytes(oup, out_packetB->data, out_packetB->len);
|
buf_putbytes(oup, out_packetB->data, out_packetB->len);
|
||||||
}
|
}
|
||||||
if (alloc_packetA) {
|
|
||||||
buf_free(alloc_packetA);
|
|
||||||
alloc_packetA = NULL;
|
|
||||||
}
|
|
||||||
if (alloc_packetB) {
|
|
||||||
buf_free(alloc_packetB);
|
|
||||||
alloc_packetB = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_packets; i++) {
|
for (i = 0; i < num_packets; i++) {
|
||||||
@ -169,7 +197,8 @@ size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
|||||||
|
|
||||||
size_t ret_len = MIN(MaxSize, oup->len);
|
size_t ret_len = MIN(MaxSize, oup->len);
|
||||||
memcpy(Data, oup->data, ret_len);
|
memcpy(Data, oup->data, ret_len);
|
||||||
buf_free(oup);
|
// printhex("mutator done", Data, ret_len);
|
||||||
return ret_len;
|
return ret_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
|
|
||||||
#include "fuzz-sshpacketmutator.c"
|
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
return fuzz_run_client(Data, Size, 0);
|
return fuzz_run_client(Data, Size, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user