Skip to content

Commit

Permalink
[nyx] Move nyx patches to standalone files
Browse files Browse the repository at this point in the history
  • Loading branch information
pyoor committed Dec 19, 2024
1 parent 1c6481f commit 3c00953
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 94 deletions.
1 change: 1 addition & 0 deletions services/nyx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ COPY \
services/nyx/build_afl.sh \
services/nyx/clang.sh \
/srv/repos/setup/
COPY services/nyx/patches/ /srv/repos/setup/patches/
RUN /srv/repos/setup/build_afl.sh

FROM ubuntu:22.04
Expand Down
103 changes: 9 additions & 94 deletions services/nyx/build_afl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,66 +57,23 @@ mkdir -p /srv/repos
pushd /srv/repos >/dev/null
git-clone-rev https://github.com/AFLplusplus/AFLplusplus 78b7e14c73baacf1d88b3c03955e78f5080d17ba
pushd AFLplusplus >/dev/null
# WIP 2-byte chunked variant of honggfuzz custom mutator
retry-curl https://github.com/AFLplusplus/AFLplusplus/commit/1b611bb30c14724f0f2eb9330772d30723ba122c.diff | git apply
git apply << "EOF"
diff --git a/custom_mutators/honggfuzz/Makefile b/custom_mutators/honggfuzz/Makefile
index 5c2fcddb..2dde8ba1 100644
--- a/custom_mutators/honggfuzz/Makefile
+++ b/custom_mutators/honggfuzz/Makefile
@@ -1,5 +1,5 @@
-CFLAGS = -O3 -funroll-loops -fPIC -Wl,-Bsymbolic
+CFLAGS = -O3 -funroll-loops -fPIC -fblocks -lBlocksRuntime -Wl,-Bsymbolic
all: honggfuzz-mutator.so honggfuzz-2b-chunked-mutator.so
commit d606e18332b4f919780604b9daf9a3761602b7c5
Author: Jesse Schwartzentruber <[email protected]>
Date: Fri Jul 14 11:04:04 2023 -0400
Increase MAP_SIZE for Nyx

diff --git a/include/config.h b/include/config.h
index 8585041e..6e526717 100644
--- a/include/config.h
+++ b/include/config.h
@@ -442,7 +442,7 @@
problems with complex programs). You need to recompile the target binary
after changing this - otherwise, SEGVs may ensue. */
-#define MAP_SIZE_POW2 16
+#define MAP_SIZE_POW2 23
/* Do not change this unless you really know what you are doing. */
EOF
# WIP 2-byte chunked variant of honggfuzz custom mutator
git apply /srv/repos/setup/patches/hongfuzz-2b-chunked.diff
make -f GNUmakefile afl-fuzz afl-showmap CODE_COVERAGE=1
pushd custom_mutators/honggfuzz >/dev/null
make
popd >/dev/null

pushd nyx_mode >/dev/null
git submodule init

retry git submodule update --depth 1 --single-branch libnyx
pushd libnyx >/dev/null
git apply << "EOF"
diff --git a/fuzz_runner/src/nyx/qemu_process.rs b/fuzz_runner/src/nyx/qemu_process.rs
index d062d87..c4ebeea 100644
--- a/fuzz_runner/src/nyx/qemu_process.rs
+++ b/fuzz_runner/src/nyx/qemu_process.rs
@@ -97,9 +97,7 @@ impl QemuProcess {
pub fn new(params: QemuParams) -> Result<QemuProcess, String> {
Self::prepare_redqueen_workdir(&params.workdir, params.qemu_id);
- if params.qemu_id == 0{
- println!("[!] libnyx: spawning qemu with:\n {}", params.cmd.join(" "));
- }
+ println!("[!] libnyx: spawning qemu with:\n {}", params.cmd.join(" "));
let (shm_work_dir, file_lock) = Self::create_shm_work_dir();
let mut shm_work_dir_path = PathBuf::from(&shm_work_dir);
EOF
git ls-tree HEAD fuzz_runner/src/nyx/qemu_process.rs
git apply /srv/repos/setup/patches/libnyx.diff
popd >/dev/null

retry git submodule update --depth 1 --single-branch packer
retry git submodule update --depth 1 --single-branch QEMU-Nyx
pushd QEMU-Nyx >/dev/null
Expand All @@ -126,51 +83,9 @@ retry git submodule update --depth 1 --single-branch libxdc
export CAPSTONE_ROOT="$PWD/capstone_v4"
export LIBXDC_ROOT="$PWD/libxdc"
sed -i '/^LDFLAGS =$/d' libxdc/Makefile
git apply << "EOF"
diff --git a/nyx/hypercall/hypercall.c b/nyx/hypercall/hypercall.c
index fa06af3201..47053472ed 100644
--- a/nyx/hypercall/hypercall.c
+++ b/nyx/hypercall/hypercall.c
@@ -746,9 +746,34 @@ static void handle_hypercall_kafl_dump_file(struct kvm_run *run,
strncpy(filename, "tmp.XXXXXX", sizeof(filename) - 1);
}
- char *base_name = basename(filename); // clobbers the filename buffer!
- assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
- base_name) != -1);
+ char *slashmatch = strstr(filename, "/");
+ char *base_name = NULL;
+ if (slashmatch) {
+ char sub_dir[256];
+ memset(sub_dir, 0, sizeof(sub_dir));
+ memcpy(sub_dir, filename, slashmatch - filename);
+
+ // Safety check, avoid dots in the subdir as they might make us
+ // leave the dump directory.
+ if (strstr(sub_dir, ".") || !strlen(sub_dir)) {
+ nyx_error("Invalid filename in %s: %s. Skipping..\n",
+ __func__, filename);
+ goto err_out1;
+ }
+
+ assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
+ sub_dir) != -1);
+ mkdir(host_path, 0777); // TODO: Check for errors other than EEXIST
+
+ base_name = basename(filename); // clobbers the filename buffer!
+ assert(asprintf(&host_path, "%s/dump/%s/%s", GET_GLOBAL_STATE()->workdir_path,
+ sub_dir, base_name) != -1);
+
+ } else {
+ base_name = basename(filename); // clobbers the filename buffer!
+ assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
+ base_name) != -1);
+ }
// check if base_name is mkstemp() pattern, otherwise write/append to exact name
char *pattern = strstr(base_name, "XXXXXX");
EOF
git apply /srv/repos/setup/patches/nyx.diff
popd >/dev/null

NO_CHECKOUT=1 ./build_nyx_support.sh
popd >/dev/null
find . -name .git -type d -exec rm -rf '{}' +
Expand Down
190 changes: 190 additions & 0 deletions services/nyx/patches/hongfuzz-2b-chunked.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
diff --git a/custom_mutators/honggfuzz/Makefile b/custom_mutators/honggfuzz/Makefile
index 5c2fcddb..83ae5fc7 100644
--- a/custom_mutators/honggfuzz/Makefile
+++ b/custom_mutators/honggfuzz/Makefile
@@ -1,11 +1,14 @@

-CFLAGS = -O3 -funroll-loops -fPIC -Wl,-Bsymbolic
+CFLAGS = -O3 -funroll-loops -fPIC -fblocks -lBlocksRuntime -Wl,-Bsymbolic

-all: honggfuzz-mutator.so
+all: honggfuzz-mutator.so honggfuzz-2b-chunked-mutator.so

honggfuzz-mutator.so: honggfuzz.c input.h mangle.c ../../src/afl-performance.c
$(CC) $(CFLAGS) -I../../include -I. -shared -o honggfuzz-mutator.so honggfuzz.c mangle.c ../../src/afl-performance.c

+honggfuzz-2b-chunked-mutator.so: honggfuzz.c input.h mangle.c ../../src/afl-performance.c
+ $(CC) $(CFLAGS) -DHONGGFUZZ_2B_CHUNKED -I../../include -I. -shared -o honggfuzz-2b-chunked-mutator.so honggfuzz.c mangle.c ../../src/afl-performance.c
+
update:
@# seriously? --unlink is a dud option? sigh ...
rm -f mangle.c mangle.h honggfuzz.h
diff --git a/custom_mutators/honggfuzz/honggfuzz.c b/custom_mutators/honggfuzz/honggfuzz.c
index 0dd59aee..02e93575 100644
--- a/custom_mutators/honggfuzz/honggfuzz.c
+++ b/custom_mutators/honggfuzz/honggfuzz.c
@@ -112,6 +112,142 @@ uint8_t afl_custom_queue_get(void *data, const uint8_t *filename) {

/* here we run the honggfuzz mutator, which is really good */

+#ifdef HONGGFUZZ_2B_CHUNKED
+typedef uint16_t chunk_size;
+const chunk_size chunk_size_mask = 0x7ff;
+
+typedef struct fuzz_packet {
+ chunk_size size;
+ uint16_t mut;
+ uint8_t* buf;
+} fuzz_packet_t;
+
+void read_fuzz_packets(uint8_t *buf, size_t buf_size, fuzz_packet_t* out, size_t* out_size, size_t max_packets) {
+ size_t remain = buf_size;
+ uint8_t* cur = buf;
+ *out_size = 0;
+
+ while(1) {
+ if (remain < sizeof(chunk_size) + 1) {
+ // Minimum length required to proceed
+ return;
+ }
+
+ if (*out_size >= max_packets) {
+ return;
+ }
+
+ out[*out_size].mut = 0;
+ out[*out_size].size = *(chunk_size*)cur & chunk_size_mask; // Only interpret lower bits for size
+ cur += sizeof(chunk_size); remain -= sizeof(chunk_size);
+
+ if (remain < out[*out_size].size) {
+ // Truncate last input, if remaining data too small
+ out[*out_size].size = remain;
+ }
+
+ out[*out_size].buf = cur;
+ cur += out[*out_size].size; remain -= out[*out_size].size;
+
+ *out_size += 1;
+ }
+}
+
+size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
+ u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
+ size_t max_size) {
+
+ fuzz_packet_t packet_out[64];
+ size_t packet_size = 0;
+
+ fuzz_packet_t packet_out_add[64];
+ size_t packet_size_add = 0;
+
+ read_fuzz_packets(buf, buf_size, packet_out, &packet_size, 64);
+
+ if (!packet_size) {
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ if (add_buf) {
+ read_fuzz_packets(add_buf, add_buf_size, packet_out_add, &packet_size_add, 64);
+ }
+
+ int num_mutations = rand() % 5 + 1;
+
+
+ for (int i = 0; i < num_mutations; ++i) {
+ if (add_buf && packet_size_add > 0 && (rand() % 2)) {
+ // Splice one index
+ packet_out[rand() % packet_size].mut = 1;
+ } else {
+ // Mutate one index
+ packet_out[rand() % packet_size].mut = 2;
+ }
+ }
+
+ size_t written = 0;
+
+ *out_buf = data->mutator_buf;
+ uint8_t* cur = data->mutator_buf;
+
+ for (size_t idx = 0; idx < packet_size; ++idx) {
+ chunk_size* size_out = (chunk_size*)cur;
+
+ if (packet_out[idx].mut == 1) {
+ // Splice
+ size_t splice_idx = rand() % packet_size_add;
+
+ if (written + sizeof(chunk_size) + packet_out_add[splice_idx].size >= max_size) {
+ return written;
+ }
+
+ memcpy(cur + sizeof(chunk_size), packet_out_add[splice_idx].buf, packet_out_add[splice_idx].size);
+ *size_out = packet_out_add[splice_idx].size;
+ } else {
+ if (written + sizeof(chunk_size) + packet_out[idx].size >= max_size) {
+ return written;
+ }
+
+ memcpy(cur + sizeof(chunk_size), packet_out[idx].buf, packet_out[idx].size);
+ if (packet_out[idx].mut == 2) {
+ // Mutate
+ run.dynfile->data = data->mutator_buf + sizeof(chunk_size);
+ run.dynfile->size = packet_out[idx].size;
+
+ queue_input = run.dynfile->data;
+ queue_input_size = run.dynfile->size;
+
+ run.global->mutate.maxInputSz = MAX_FILE - written - sizeof(chunk_size);
+
+ mangle_mangleContent(&run, NUMBER_OF_MUTATIONS);
+
+ // Truncate output
+ if (run.dynfile->size > chunk_size_mask) {
+ run.dynfile->size = chunk_size_mask;
+ }
+
+ if (run.dynfile->data != data->mutator_buf + sizeof(chunk_size)) {
+ abort();
+ }
+
+ packet_out[idx].size = run.dynfile->size;
+ }
+
+ *size_out = packet_out[idx].size;
+ }
+
+ cur += *size_out + sizeof(chunk_size);
+ written += *size_out + sizeof(chunk_size);
+ }
+
+ /* return size of mutated data */
+ return written;
+}
+
+#else
+
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
size_t max_size) {
@@ -132,6 +268,8 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,

}

+#endif
+
/**
* Deinitialize everything
*
diff --git a/include/config.h b/include/config.h
index d8177a75..6a588810 100644
--- a/include/config.h
+++ b/include/config.h
@@ -459,7 +459,7 @@
problems with complex programs). You need to recompile the target binary
after changing this - otherwise, SEGVs may ensue. */

-#define MAP_SIZE_POW2 16
+#define MAP_SIZE_POW2 23

/* Do not change this unless you really know what you are doing. */

15 changes: 15 additions & 0 deletions services/nyx/patches/libnyx.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/fuzz_runner/src/nyx/qemu_process.rs b/fuzz_runner/src/nyx/qemu_process.rs
index d63cea7..de24fec 100644
--- a/fuzz_runner/src/nyx/qemu_process.rs
+++ b/fuzz_runner/src/nyx/qemu_process.rs
@@ -100,9 +100,7 @@ impl QemuProcess {
pub fn new(params: QemuParams) -> Result<QemuProcess, String> {
Self::prepare_redqueen_workdir(&params.workdir, params.qemu_id);

- if params.qemu_id == 0{
- println!("[!] libnyx: spawning qemu with:\n {}", params.cmd.join(" "));
- }
+ println!("[!] libnyx: spawning qemu with:\n {}", params.cmd.join(" "));

let (shm_work_dir, file_lock) = Self::create_shm_work_dir();
let mut shm_work_dir_path = PathBuf::from(&shm_work_dir);
42 changes: 42 additions & 0 deletions services/nyx/patches/nyx.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
diff --git a/nyx/hypercall/hypercall.c b/nyx/hypercall/hypercall.c
index 7ee3025..257cf2b 100644
--- a/nyx/hypercall/hypercall.c
+++ b/nyx/hypercall/hypercall.c
@@ -751,9 +751,34 @@ static void handle_hypercall_kafl_dump_file(struct kvm_run *run,
strncpy(filename, "tmp.XXXXXX", sizeof(filename) - 1);
}

- char *base_name = basename(filename); // clobbers the filename buffer!
- assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
- base_name) != -1);
+ char *slashmatch = strstr(filename, "/");
+ char *base_name = NULL;
+ if (slashmatch) {
+ char sub_dir[256];
+ memset(sub_dir, 0, sizeof(sub_dir));
+ memcpy(sub_dir, filename, slashmatch - filename);
+
+ // Safety check, avoid dots in the subdir as they might make us
+ // leave the dump directory.
+ if (strstr(sub_dir, ".") || !strlen(sub_dir)) {
+ nyx_error("Invalid filename in %s: %s. Skipping..\n",
+ __func__, filename);
+ goto err_out1;
+ }
+
+ assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
+ sub_dir) != -1);
+ mkdir(host_path, 0777); // TODO: Check for errors other than EEXIST
+
+ base_name = basename(filename); // clobbers the filename buffer!
+ assert(asprintf(&host_path, "%s/dump/%s/%s", GET_GLOBAL_STATE()->workdir_path,
+ sub_dir, base_name) != -1);
+
+ } else {
+ base_name = basename(filename); // clobbers the filename buffer!
+ assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
+ base_name) != -1);
+ }

// check if base_name is mkstemp() pattern, otherwise write/append to exact name
char *pattern = strstr(base_name, "XXXXXX");

0 comments on commit 3c00953

Please sign in to comment.