Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nyx-net fuzzing for afl++ without specs #29

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
linux_initramfs/init.cpio.gz
linux_initramfs/init_debug_shell.cpio.gz
linux_initramfs/init
packer/linux_x86_64-userspace/src/proto/input.pb.cc
packer/linux_x86_64-userspace/src/proto/input.pb.h
packer/pack_test.sh
5 changes: 3 additions & 2 deletions packer/interpreter/build/data_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ typedef struct {size_t count; d_char* vals; } d_vec_path_string;
typedef uint8_t d_foo_bla;
typedef uint32_t d_foo_fuu;

#pragma pack(1)
#pragma pack(push, 1)
typedef struct {
d_foo_bla bla;
d_flags flags;
d_foo_fuu fuu;
} d_foo;
} d_foo;
#pragma pack(pop)
2 changes: 1 addition & 1 deletion packer/interpreter/build/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ typedef struct {
size_t ops_i;

uint8_t* data;
size_t* data_len;
uint32_t* data_len;
size_t data_i;
uint32_t* instruction_counter;

Expand Down
4 changes: 2 additions & 2 deletions packer/interpreter/spec_lib/templates/interpreter.jinja.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ typedef struct {
size_t ops_i;

uint8_t* data;
size_t* data_len;
uint32_t* data_len;
size_t data_i;
uint32_t* instruction_counter;

Expand Down Expand Up @@ -116,7 +116,7 @@ interpreter_t* new_interpreter(){
return vm;
}

void init_interpreter(interpreter_t* vm, uint16_t* ops, size_t* ops_len, uint8_t* data, size_t* data_len, uint32_t* instruction_counter){
void init_interpreter(interpreter_t* vm, uint16_t* ops, size_t* ops_len, uint8_t* data, uint32_t* data_len, uint32_t* instruction_counter){
vm->ops=ops;
vm->ops_len=ops_len;
vm->ops_i = 0;
Expand Down
6 changes: 3 additions & 3 deletions packer/linux_x86_64-userspace/compile_32.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ else

if [ "$NET_FUZZ" = "ON" ]
then
MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}"
MODE="${SPEC_MODE} ${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}"
echo "MODES => $MODE"
clang -shared -g -O0 -m32 -Werror $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -DNET_FUZZ -I$NYX_SPEC_FOLDER -o bin32/ld_preload_fuzz.so -ldl -Isrc
clang -shared -g -O0 -m32 -Werror -DNO_PT_NYX $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -DNET_FUZZ -I$NYX_SPEC_FOLDER -o bin32/ld_preload_fuzz_no_pt.so -ldl -Isrc
clang -shared -g -O0 -m32 -Werror -DNET_FUZZ $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -o bin32/ld_preload_fuzz.so -ldl -Isrc
clang -shared -g -O0 -m32 -Werror -DNET_FUZZ -DNO_PT_NYX $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -o bin32/ld_preload_fuzz_no_pt.so -ldl -Isrc

else

Expand Down
9 changes: 5 additions & 4 deletions packer/linux_x86_64-userspace/compile_64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ else

if [ "$NET_FUZZ" = "ON" ]
then
MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}"
#echo "MODES => $MODE"
clang -shared -g -O0 -m64 -Werror $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -DNET_FUZZ -I$NYX_SPEC_FOLDER -o bin64/ld_preload_fuzz.so -ldl -Isrc
clang -shared -g -O0 -m64 -Werror -DNO_PT_NYX $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -DNET_FUZZ -I$NYX_SPEC_FOLDER -o bin64/ld_preload_fuzz_no_pt.so -ldl -Isrc
MODE="${SPEC_MODE} ${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}"
echo "MODES => $MODE"

clang -shared -g -O0 -m64 -Werror -DNET_FUZZ $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -o bin64/ld_preload_fuzz.so -ldl -Isrc
clang -shared -g -O0 -m64 -Werror -DNET_FUZZ -DNO_PT_NYX $EXTRA $MODE -fPIC src/ld_preload_fuzz.c src/misc/crash_handler.c src/misc/harness_state.c src/netfuzz/inject.c src/netfuzz/syscalls.c src/netfuzz/socket_cache.c -I../../ -o bin64/ld_preload_fuzz_no_pt.so -ldl -Isrc

else

Expand Down
147 changes: 101 additions & 46 deletions packer/linux_x86_64-userspace/src/ld_preload_fuzz.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#define _GNU_SOURCE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <sys/mman.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -52,17 +54,34 @@ bool payload_mode = false;
#include "netfuzz/syscalls.h"
//#endif

#ifdef SPEC_MODE

#ifndef LEGACY_MODE
/* Spec mode uses the interpreter */
#include "interpreter.h"

#else

extern void __assert(const char *func, const char *file, int line, const char *failedexpr);
#define INTERPRETER_ASSERT(x) do { if (x){}else{ __assert(__func__, __FILE__, __LINE__, #x);} } while (0)
#define ASSERT(x) INTERPRETER_ASSERT(x)

/* Nyx-net mode uses the vm data structure */
#ifndef LEGACY_MODE
typedef struct {
uint16_t* ops;
size_t* ops_len;
size_t ops_i;

uint8_t* data;
uint32_t* data_len;
size_t data_i;
uint32_t* instruction_counter;
} interpreter_t;
#endif

#include "ijon_extension.h"
#endif

#include "ijon_extension.h"

#define ASAN_EXIT_CODE 101
//#define REDIRECT_STDERR_TO_HPRINTF
Expand All @@ -75,14 +94,7 @@ bool fuzzer_ready = false;



#ifndef LEGACY_MODE
interpreter_t* vm;
#ifdef NET_FUZZ
socket_state_t vm_state;
#else
fd_state_t vm_state;
#endif
#endif

ssize_t (*fptr_read)(int fd, void *data, size_t size);
ssize_t (*fptr_getline)(char **lineptr, size_t *n, FILE *stream);
Expand Down Expand Up @@ -192,7 +204,63 @@ void hprintf_payload(char* data, size_t len){
/* TODO: check via env var */
//#define COPY_PAYLOAD_MODE

#ifndef SPEC_MODE
ssize_t call_vm(void *data, size_t max_size, bool return_pkt_size, bool disable_dump_mode) {

#ifdef EARLY_EXIT_NODES
static int count = 0;

if (count++ > EARLY_EXIT_NODES){
//hprintf("EARLY EXIT\n");
return -1;
}
#endif

static size_t available_data = 0;
static size_t offset = 0;

if (available_data <= 0) {

/* Parse new data from vm buffer */

if (!vm->data_len || *vm->data_len == 0){
DEBUG("%s: out of data\n", __func__);
return -1;
}

available_data = *vm->data_len;
offset = 0;

vm->data_len = NULL; /* This assumes vm->data can only be written to once per execution */

}

/* Copy requested data from vm buffer */

size_t num_copied = min_size_t(available_data, max_size);
memcpy(data, vm->data+offset, num_copied);

DEBUG("%s: requested %d -> wrote %d bytes\n", __func__, max_size, num_copied);

#ifdef COPY_PAYLOAD_MODE
if(payload_mode && !disable_dump_mode){
hprintf_payload(data, num_copied);
}
#endif

#ifdef UDP_MODE
if (return_pkt_size) num_copied = available_data; /* MSG_TRUNC behaves differently with TCP, but is not implemented */
available_data = 0;
offset = 0;
#else
available_data -= num_copied;
offset += num_copied;
#endif

return num_copied;

}
#else
ssize_t call_vm(void *data, size_t max_size, bool return_pkt_size, bool disable_dump_mode){

#ifdef EARLY_EXIT_NODES
Expand Down Expand Up @@ -295,6 +363,7 @@ ssize_t call_vm(void *data, size_t max_size, bool return_pkt_size, bool disable_
return num_copied;
#endif
}
#endif

#ifndef NET_FUZZ
ssize_t read(int fd, void *data, size_t size) {
Expand Down Expand Up @@ -332,29 +401,13 @@ ssize_t getline(char **lineptr, size_t *n, FILE *stream){
#endif

static void setup_interpreter(void* payload_buffer) {
uint64_t* offsets = (uint64_t*)payload_buffer;
//hprintf("checksum: %lx, %lx\n",offsets[0], INTERPRETER_CHECKSUM);
ASSERT(offsets[0] == INTERPRETER_CHECKSUM);
ASSERT(offsets[1] < 0xffffff);
ASSERT(offsets[2] < 0xffffff);
ASSERT(offsets[3] < 0xffffff);
ASSERT(offsets[4] < 0xffffff);
uint64_t* graph_size = &offsets[1];
uint64_t* data_size = &offsets[2];

//printf("graph_size: %d\n", graph_size);
//printf("data_size: %d\n", graph_size);
//printf("graph_offset: %d\n", offsets[3]);
//printf("data_offset: %d\n", offsets[4]);

uint16_t* graph_ptr = (uint16_t*)(payload_buffer+offsets[3]);
uint8_t* data_ptr = (uint8_t*)(payload_buffer+offsets[4]);
ASSERT(input_buffer_size != 0);
ASSERT(offsets[3]+(*graph_size)*sizeof(uint16_t) <= input_buffer_size);
ASSERT(offsets[4]+*data_size <= input_buffer_size);
init_interpreter(vm, graph_ptr, (size_t*)graph_size, data_ptr, (size_t*)data_size, (void*)&ijon_trace_buffer->interpreter_data.executed_opcode_num);
interpreter_user_init(vm);
vm->user_data = &vm_state;
uint32_t* offsets = (uint32_t*)payload_buffer;

vm->data_len = offsets;
vm->data = (uint8_t*)&offsets[1];

// This should just be "INIT"
DEBUG("input length %zu, %hhx ...\n", *vm->data_len, vm->data[0]);
}
#endif

Expand Down Expand Up @@ -549,9 +602,9 @@ void capabilites_configuration(bool timeout_detection, bool agent_tracing, bool
habort("Error: NYX_HOST_VERSION not found in host configuration - You are probably using an outdated version of QEMU-Nyx...");
}

hprintf("[capablities] host_config.bitmap_size: 0x%"PRIx64"\n", host_config.bitmap_size);
hprintf("[capablities] host_config.ijon_bitmap_size: 0x%"PRIx64"\n", host_config.ijon_bitmap_size);
hprintf("[capablities] host_config.payload_buffer_size: 0x%"PRIx64"x\n", host_config.payload_buffer_size);
hprintf("[capablities] host_config.bitmap_size: 0x%" PRIx64 "\n", host_config.bitmap_size);
hprintf("[capablities] host_config.ijon_bitmap_size: 0x%" PRIx64 "\n", host_config.ijon_bitmap_size);
hprintf("[capablities] host_config.payload_buffer_size: 0x%" PRIx64 "x\n", host_config.payload_buffer_size);

input_buffer_size = host_config.payload_buffer_size;

Expand All @@ -574,7 +627,7 @@ void capabilites_configuration(bool timeout_detection, bool agent_tracing, bool
/* AFL++ LTO support */
if (get_harness_state()->afl_mode && __afl_final_loc_ptr){
unsigned int map_size = __afl_final_loc == 0 ? 65536 : __afl_final_loc;
hprintf("[capablities] overwriting bitmap_size: 0x%"PRIx64"\n", map_size);
hprintf("[capablities] overwriting bitmap_size: 0x%" PRIx64 "\n", map_size);
agent_config.coverage_bitmap_size = map_size;
}

Expand All @@ -589,11 +642,11 @@ void capabilites_configuration(bool timeout_detection, bool agent_tracing, bool

/* read debug flag */

if(agent_config.dump_payloads){
// if(agent_config.dump_payloads){
hprintf("[capablities] payload mode enabled\n");
payload_mode = true;
//abort();
}
// }


done = true;
Expand Down Expand Up @@ -858,7 +911,7 @@ void nyx_init_start(void){

for(i = 0; i < 4; i++){
if (range_buffer->enabled[i]){
hprintf("[init] Intel PT range %d is enabled\t -> (0x"PRIx64"-0x"PRIx64")\n", i, range_buffer->ip[i], range_buffer->ip[i]+range_buffer->size[i]);
hprintf("[init] Intel PT range %d is enabled\t -> (0x" PRIx64 "-0x" PRIx64 ")\n", i, range_buffer->ip[i], range_buffer->ip[i]+range_buffer->size[i]);
}
}

Expand Down Expand Up @@ -929,12 +982,14 @@ void nyx_init_start(void){
free(ar);
free(ranges);

#ifndef LEGACY_MODE
#ifdef SPEC_MODE
vm = new_interpreter();
vm->user_data = &vm_state;
vm->user_data->len = 0;
vm->user_data->data = 0;
vm->user_data->closed = false;
#else
#ifndef LEGACY_MODE
vm = malloc(sizeof(interpreter_t));
memset(vm, 0, sizeof(interpreter_t));
#endif
hprintf("interpreter: %p\n", vm);
#endif

uint8_t mlock_enabled = 1;
Expand Down Expand Up @@ -962,7 +1017,6 @@ void nyx_init_start(void){
//hprintf("========================================================\n");

while(1){

/* fixme */
#ifndef NET_FUZZ
pid = _fork();
Expand Down Expand Up @@ -1123,6 +1177,7 @@ int __main(int argc, char** argv, char** envp){
#ifdef LEGACY_MODE
nyx_init();
#endif

return original_main(argc, argv, envp);
}

Expand Down
2 changes: 1 addition & 1 deletion packer/linux_x86_64-userspace/src/misc/crash_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ void handle_asan(void){
}
}

void __assert(const char *func, const char *file, int line, const char *failedexpr){
void _assert(const char *func, const char *file, int line, const char *failedexpr){
sprintf(log_content, "HYPERCALL_KAFL_PANIC_EXTENDED: assert: %s %s %d: %s\n", func, file, line, failedexpr);
kAFL_hypercall(HYPERCALL_KAFL_PANIC_EXTENDED, (uintptr_t)log_content);
}
Expand Down
17 changes: 17 additions & 0 deletions packer/linux_x86_64-userspace/src/netfuzz/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,23 @@ ssize_t recv(int sockfd, void *buf, size_t len, int flags){
return ret;
}

int printf(const char* format, ...)
{
va_list arg;

va_start(arg, format);
DEBUG(format, va_arg(arg, int));
va_end(arg);

return 0;
}

int puts(const char* s)
{
DEBUG(s);
return 0;
}

static bool data_avaliable(int fd){
fd_set set;
struct timeval timeout;
Expand Down
Loading