diff --git a/README-Realnetwork.md b/README-Realnetwork.md new file mode 100644 index 0000000..ea5704b --- /dev/null +++ b/README-Realnetwork.md @@ -0,0 +1,212 @@ +# Extending Nyx-Net for Fuzzing Libraries that hook Socket API Using Real Network Mode + + ## Introduction + + Nyx-Net is a powerful fuzzer for fuzzing TCP servers using memory snapshots. + However, its current implementation does not support fuzzing libraries that intercept Socket API calls. + Applying such a library to a target application will conflict with Nyx-Net's way of delivering fuzzed input. + In this document, an extended functionality that allows Nyx-Net to pass data to target applications + using a real network is introduced, enabling it to fuzz such libraries. + + ## Motivation + + Many libraries intercept Socket API calls. An example is [OpenOnload](https://github.com/Xilinx-CNS/onload), + a user-level network stack, which accelerates TCP and UDP network I/O for applications using the BSD sockets on Linux. + + The easiest way of fuzzing such libraries is to use them on some network application as usual and fuzz that application. + This way, the data passed to the app will eventually be captured by the desired library. We can collect coverage from it too + by compiling the library with afl-gcc/clang compiler or, even simpler, by using Intel PT. + + However, we cannot do it with native Nyx-Net since both Nyx-Net and the target library will intercept Socket API calls. + For example, Nyx-Net hooks the `recv` function in a way that the buffer is filled with fuzzed input, but the real function never invokes. + + ## Proposed Functionality + + To address these issues, we propose a mechanism that allows Nyx-Net to send data over a real network. + This mechanism involves implementing a TCP/UDP client directly inside the Nyx-Net agent embedded into the target application. + + It is worth noting that **it's possible to use real network mode to fuzz applications as usual, without such a library**. + However, one should better use native Nyx-Net, since its network emulation layer results in a significantly faster speed. + A general rule of thumb is switching to the real network **reduces speed by two orders of magnitude**. + + ## Review of Conventional Data Transferring + + Let's recall the mechanism of transferring data to an application during Nyx-Net operation using a TCP server as an example. + + By using LD_PRELOAD Nyx-Net embeds a so-called "Agent" into the application that will intercept Socket API functions. + Its job is to detect when the target application is ready to accept input, make a snapshot, and start transferring mutated data. + In the case of TCP, for example, the snapshot is made when sever invokes `recv` for the first time. + Note that the TCP handshake is already done, so we won't be performing it on each iteration. + + It's important to note that the actual recv function is never called. + The agent simply fills the appropriate buffer with data received from the fuzzer. + + ## Proposed Way of Transferring Data + + To transfer data to the target server via a real network we need some clients to do so. + + (FIXME: for now only TCP client is implemented) + + It is possible to interact with the target server via a loopback interface, however, it's better to put the client and server in different + network namespaces. This helps isolate the client from the rest of the system, plus, libraries like OpenOnload which + designed for real-world use simply do not support servers that run on a loopback interface, it has no real-world use cases. + However, with network namespaces, the client and server will use a pair of virtual ethernet devices (veth). + + ``` + ┌────────────────────────────────────────────┐ + │ │ + │ ┌──────────────────────┐ │ + │ │ │ │ + │ │ ┌─────┤ ┌─────┤ + │ │ │ │ │ │ + │ │ │veth1│◄───────────►│veth0│ + │ │ │ │ │ │ + │ │ └─────┤ └─────┤ + │ │ nspce │ │ + │ └──────────────────────┘ │ + │ │ + │ Host namespace│ + └────────────────────────────────────────────┘ + ``` + + (FIXME: For now "nspce" name is hardcoded as a namespace name) + + The LD_PRELOAD chain embeds the underlying library `target_lib.so` that intercepts Socket API calls + into the target application first, followed by the Agent `ld_preload_fuzz.so`. + + Note that the "underlying library" could be just a libc, i.e we can fuzz any network application as usual, + but transfer data to it via network instead of hooks. + + ### Data transfer workflow + + 1. The Nyx-Net agent replaces the listen function with the listen function from the underlying library and then creates a new thread. + 2. The thread is moved to a separate network namespace and acts as a client. Its job is to receive data from the fuzzer and transfer it. + 3. The thread connects to the server using the _real_ `connect` function and then idles, waiting for the fuzzer's notification to transfer data. + 4. Server calls _hooked_ `accept`, TCP handshake is established. + 5. Server calls _hooked_ `recv` function that does the following: + 1. Invokes memory snapshot, capturing the server and client after the TCP handshake. + 2. Gets data from the fuzzer as usual, using the `handle_next_packet()` function. + 3. Stores received data in a shared variable and notify the thread. + 3. Calls _real_ `recv`. + 6. When the thread receives a notification it sends the data stored in a shared variable using the _real_ `write` function and then terminates. + 7. Client will eventually get the data from its _hooked_ `recv` function invocation and starts processing it. + 8. After the data has been processed, the memory snapshot is restored and the process starts again. + + You can see this process clearly in the following scheme: + + - `read` --- real libc function + - `read*` --- `target_lib.so` hooked function + - `read**` --- Nyx-Net's Agent hooked function + + ``` + ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ │ + │ ┌──────────────────────────────────────┐ │ + │ │ │ │ + │ │ ┌───────────────────────┐ ┌───────┤ ┌───────┐ │ + │ │ │ │ │ │ Real network connection │ │ │ + │ │ │ Client │◄──►│ veth1 ◄────────────────────────────────────────────────────────────► veth0 │ │ + │ │ │ │ │ │ │ │ │ + │ │ │ ┌────────┐ │ └───────┤ └───┬───┘ │ + │ │ │ │socket │ │ │ │ │ + │ │ │ └──┬─────┘ │ │ │ │ + │ │ │ │ │ │ │ │ + │ │ │ ┌──┴─────┐ │ │ │ │ + │ │ │ │connect │ │ │ ┌─────────────────────────────────────────┐ │ │ + │ │ │ └──┬─────┘ │ │ │ Data transfer workflow │ │ │ + │ │ │ │ │ │ │ ┌────────┐ │ │ │ + │ │ │ ┌─────┴────────┐ │ │ │ │socket* │ │ │ │ + │ │ │ │ wait for the │ │ │ │ └──┬─────┘ │ │ │ + │ │ │ ┌─► notification │ │ │ │ │ │ │ │ + │ │ │ │ └─────┬────────┘ │ │ │ ┌───────────┐ hooks as ┌──┴─────┐ │ │ │ + │ │ │ │ │ │ │ │ │ bind* │◄──────────────┤bind** │ │ │ │ + │ │ │ │ ┌─────┴───────────┐ │ │ │ └───────────┘ └──┬─────┘ │ │ │ + │ │ │ │ │write(shared buf)│ │ │ │ │ │ │ │ + │ │ │ │ └─────────────────┘ │ │ │ ┌───────────────┐ ┌──┴─────┐ │ │ │ + │ │ │ │ │ │ │ │ listen* │◄──────────┤listen**│ │ │ │ + │ │ └─┼─────────────────────┘ │ │ │ │ └──┬─────┘ │ ┌────────────▼──────────┐ │ + │ │ │ │ │ │ Create thread │ │ │ │ │ │ + │ │ │ Separate network namespace │ │ └───────────────┘ │ │ │ Target Server │ │ + │ └───┼──────────────────────────────────┘ │ │ │ │ │ │ + │ │ │ ┌──────────────┐ ┌──┴─────┐ │ │ ┌───────────────────┐ │ │ + │ │ │ │ accept* │◄───────────┤accept**│ │ │ │ target_lib.so │ │ │ + │ │ │ └──────────────┘ └──┬─────┘ │ │ │ │ │ │ + │ │ │ │ ├────┤ │ ┌───────────────┐ │ │ │ + │ │ │ │ │ │ │ │ld_preload_fuzz│ │ │ │ + │ │ │ │ │ │ │ └───────────────┘ │ │ │ + │ │ │ │ │ │ │ │ │ │ + │ │ │ ┌───────────────────────┐ │ │ │ └───────────────────┘ │ │ + │ │ │ │ Create memory snapshot│ │ │ │ │ │ + │ │ │ │ │ │ │ └───────────────────────┘ │ + │ │ │ │ Fill shared buf with │ │ │ │ + │ │ │ │ data from fuzzer via │ ┌──┴─────┐ │ │ + │ │ │ │ `handle_next_packet` │◄─┤read** │ │ │ + │ │ │ │ │ └────────┘ │ │ + │ └───────────────────────────────────────┼──┼────Notify thread │ │ │ + │ │ │ │ │ │ + │ │ │ read* │ │ │ + │ │ │ │ │ │ + │ │ └───────────────────────┘ │ │ + │ │ │ │ + │ └─────────────────────────────────────────┘ │ + │ │ + └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + ``` + + ## Usage + + An example of fuzzing LightFTP using a real network without any Socket-API-intercepting-library: + + This guide uses a full-blown virtual machine as a base image for fuzzing, but the Nyx-Net's simple + rootfs implementation should also work if one adds the `net-tools` package here. + + 1. Set up regular distribution as a base image for fuzzing but stop before the `sudo ./loader` step. + Here's the guide for that: [guide](https://github.com/nyx-fuzz/Nyx/blob/main/docs/01-Nyx-VMs.md). + + 2. Invoke the following commands to create a "nspce" network namespace and a pair of + virtual ethernet devices connecting the main namespace with created one. + + ```bash + # create a network namespace + sudo ip netns add nspce + # Create a veth pair + sudo ip link add veth0 type veth peer name veth1 + # Move veth1 to the new namespace + sudo ip link set veth1 netns nspce + # Bring loopback interface up + sudo ip netns exec nscpe ip link set dev lo up + # Assign ip to interface in the new namespace + sudo ip netns exec nscpe ip addr add 10.0.0.2/24 dev veth1 + sudo ip netns exec nscpe ip link set dev veth1 up + # Assign ip to interface in the host namespace + sudo ip addr add 10.0.0.1/24 dev veth0 + sudo ip link set dev veth0 up + ``` + + 3. Call `sudo ./loader` and continue following the guide. + + 4. Change `127.0.0.1` to `10.0.0.1` in `targets/extra_folders/lightftp_extra_folder/fftp.conf`. + + 5. Pack LightFTP using conventional `targets/packer_scripts/pack_lightftp.sh` script with the following + modifications: + + ```diff + diff --git a/targets/packer_scripts/pack_lightftp.sh b/targets/packer_scripts/pack_lightftp.sh + --- a/targets/packer_scripts/pack_lightftp.sh + +++ b/targets/packer_scripts/pack_lightftp.sh + @@ -15,9 +15,13 @@ python3 $PACKER ../setup_scripts/build/lightftp/LightFTP-gcov/Source/Release/fft + --purge \ + --nyx_net \ + --nyx_net_port 2200 \ + +--nyx_net_ip 10.0.0.1 \ + +--nyx_net_real_network_mode \ + -spec ../specs/ftp \ + -args "fftp.conf 2200" \ + --setup_folder ../extra_folders/lightftp_extra_folder && \ + -python3 $CONFIG_GEN $SHAREDIR Kernel -s ../specs/ftp/lightftpd/ -d ../dicts/ftp.dict $DEFAULT_CONFIG + +python3 $CONFIG_GEN $SHAREDIR Snapshot -m 2048 -s ../specs/ftp/lightftpd/ -d ../dicts/ftp.dict $DEFAULT_CONFIG + ``` + + 6. Run the fuzzer as usual. + + Expect about **30-40 execs/sec** instead of **3000-4000 execs/sec**, but the fuzzer will use a real network to transfer data. diff --git a/modify_seq_ack.py b/modify_seq_ack.py new file mode 100644 index 0000000..cad03e7 --- /dev/null +++ b/modify_seq_ack.py @@ -0,0 +1,93 @@ +import glob +import socket +import time +import struct +import sys +import os + +def checksum(msg): + if len(msg) % 2 != 0: + msg += struct.pack('!B', 0) + + s = 0 + # loop taking 2 characters at a time + for i in range(0, len(msg), 2): + w = (msg[i] << 8) + msg[i+1] + s = s + w + + s = (s>>16) + (s & 0xffff); + #s = s + (s >> 16); + #complement and mask to 4 byte short + s = ~s & 0xffff + + return s + +def calculate_checksum(source_ip, dest_ip, tcp_header, tcp_data): + pseudo_header = struct.pack('!4s4sBBH', + socket.inet_aton(source_ip), + socket.inet_aton(dest_ip), + 0, + socket.IPPROTO_TCP, + len(tcp_header) + len(tcp_data)) + + return checksum(pseudo_header + tcp_header + tcp_data) + +def modify_seed(new_syn_seq_num, new_synack_seq_num, file_name, source_ip, dest_ip): + # Open the file and read its contents + with open(file_name, 'rb') as f: + file_data = f.read() + + # Extract old sequence numbers from the file + old_syn_seq_num, old_synack_seq_num = struct.unpack('!II', file_data[:8]) # '!II' means two unsigned integers in network byte order + + # Remove the first 8 bytes from the file data and split it by CRLF + packets = file_data[8:].split(b'\r\n') + + # Calculate relative sequence and acknowledgment numbers for each packet + for i in range(len(packets) - 1): # exclude last empty packet after final split + packet = packets[i] + # sequence and acknowledgment numbers are located at 4-8 and 8-12 bytes of TCP header + seq_num, ack_num = struct.unpack('!II', packet[4:12]) + relative_seq_num = seq_num - old_syn_seq_num + relative_ack_num = ack_num - old_synack_seq_num + print(relative_seq_num, relative_ack_num) + + # Calculate new sequence and acknowledgment numbers + new_seq_num = new_syn_seq_num + relative_seq_num + new_ack_num = new_synack_seq_num + relative_ack_num + + # Replace the sequence and acknowledgment numbers in the packet + packets[i] = packet[:4] + struct.pack('!II', new_seq_num, new_ack_num) + packet[12:] + + for i in range(len(packets) - 1): # exclude last empty packet after final split + # Recalculate the checksum + tcp_header = packets[i][:20] + tcp_data = packets[i][20:] + tcp_data += b'\r\n' + # Make checksum field in TCP header zero + tcp_header = tcp_header[:16] + struct.pack('!H', 0) + tcp_header[18:] + + checksum = calculate_checksum(source_ip, dest_ip, tcp_header, tcp_data) + + # Insert the new checksum into the TCP header + packets[i] = tcp_header[:16] + struct.pack('!H', checksum) + tcp_header[18:] + tcp_data + print("new checksum is ", checksum) + + # Join the packets back together and write the result to the file + with open(file_name, 'wb') as f: + for packet in packets: + f.write(packet) + +# Verify command line arguments +if len(sys.argv) != 5: + print("Usage: python script.py ") + sys.exit(1) + +client_ip = sys.argv[1] +server_ip = sys.argv[2] +syn_seq_num = int(sys.argv[3]) +synack_seq_num = int(sys.argv[4]) + +for path in glob.glob("lightftpd/*.raw"): + modify_seed(syn_seq_num, synack_seq_num, path, client_ip, server_ip) + diff --git a/packer/common/config.py b/packer/common/config.py index a669ec4..b8e4a81 100644 --- a/packer/common/config.py +++ b/packer/common/config.py @@ -306,6 +306,9 @@ def __load_arguments(self): nyx_net_group.add_argument('--nyx_net_port', metavar='', help='fuzz specified network port', default=0, type=int) nyx_net_group.add_argument('--nyx_net_udp', help='fuzz UDP port instead TCP', action='store_true', default=False) nyx_net_group.add_argument('--nyx_net_client_mode', help='fuzz target in client mode', action='store_true', default=False) + nyx_net_group.add_argument('--nyx_net_real_network_mode', help='Use real network to transfer data to target', action='store_true', default=False) + nyx_net_group.add_argument('--nyx_net_client_ip', metavar='', help='specify client ip (useful with real network mode)', default="127.0.0.1", type=str) + nyx_net_group.add_argument('--nyx_net_client_port', metavar='', help='specify client port (useful with real network mode)', default=0, type=int) nyx_net_group.add_argument('--nyx_net_stdin', help='use file as stdin input', action=FullPath, type=parse_is_file) nyx_net_group = parser.add_argument_group("Nyx-Net Extras") diff --git a/packer/linux_x86_64-userspace/compile_32.sh b/packer/linux_x86_64-userspace/compile_32.sh index b723c2b..e1104d8 100755 --- a/packer/linux_x86_64-userspace/compile_32.sh +++ b/packer/linux_x86_64-userspace/compile_32.sh @@ -17,7 +17,7 @@ else if [ "$NET_FUZZ" = "ON" ] then - MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}" + MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG} ${REAL_NETWORK_MODE}" 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 diff --git a/packer/linux_x86_64-userspace/compile_64.sh b/packer/linux_x86_64-userspace/compile_64.sh index cc12138..e39dbb6 100755 --- a/packer/linux_x86_64-userspace/compile_64.sh +++ b/packer/linux_x86_64-userspace/compile_64.sh @@ -17,10 +17,10 @@ else if [ "$NET_FUZZ" = "ON" ] then - MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG}" + MODE="${UDP_MODE} ${CLIENT_MODE} ${DEBUG_MODE} ${STDOUT_STDERR_DEBUG} ${REAL_NETWORK_MODE}" #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 + 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 -pthread + 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 -pthread else diff --git a/packer/linux_x86_64-userspace/src/loader.c b/packer/linux_x86_64-userspace/src/loader.c index 4dbae95..1a50418 100644 --- a/packer/linux_x86_64-userspace/src/loader.c +++ b/packer/linux_x86_64-userspace/src/loader.c @@ -155,4 +155,4 @@ int main(int argc, char** argv){ } printf("Usage: \n"); return 0; -} \ No newline at end of file +} diff --git a/packer/linux_x86_64-userspace/src/misc/harness_state.c b/packer/linux_x86_64-userspace/src/misc/harness_state.c index 03924e0..5974087 100644 --- a/packer/linux_x86_64-userspace/src/misc/harness_state.c +++ b/packer/linux_x86_64-userspace/src/misc/harness_state.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE #include +#include #include #include "misc/harness_state.h" #include "netfuzz/syscalls.h" @@ -34,6 +35,13 @@ static bool check_env(const char* env){ return ret; } +static bool validate_ip_addr(const char *ip_addr) +{ + struct in_addr ipv4_binary; + + return inet_pton(AF_INET, ip_addr, &ipv4_binary) == 1; +} + void set_harness_state(void){ harness_state_t* state = get_harness_state(); @@ -53,6 +61,29 @@ void set_harness_state(void){ state->nyx_net_port = 0; } + if(real_getenv("NYX_NET_CLIENT_IP_ADDR")){ + char *ip_addr = real_getenv("NYX_NET_CLIENT_IP_ADDR"); + + if (!validate_ip_addr(ip_addr)) + { + hprintf("Invalid IPv4 address in NYX_NET_CLIENT_IP_ADDR environment variable.\n"); + exit(EXIT_FAILURE); + } + + strncpy(state->nyx_net_client_ip_addr, ip_addr, INET_ADDRSTRLEN - 1); + state->nyx_net_client_ip_addr[INET_ADDRSTRLEN - 1] = '\0'; // Ensure null-termination + } + else{ + strcpy(state->nyx_net_client_ip_addr, "127.0.0.1"); + } + + if(real_getenv("NYX_NET_CLIENT_PORT")){ + state->nyx_net_client_port = (uint16_t)strtol(real_getenv("NYX_NET_CLIENT_PORT"), NULL, 10); + } + else{ + state->nyx_net_client_port = 0; + } + #ifdef DEBUG_HARNESS_STATE hprintf("fast_exit_mode: %d\n", state->fast_exit_mode); hprintf("asan_executable: %d\n", state->asan_executable); @@ -63,6 +94,7 @@ void set_harness_state(void){ hprintf("pt_auto_addr_range_a: %d\n", state->pt_auto_addr_range_a); hprintf("pt_auto_addr_range_b: %d\n", state->pt_auto_addr_range_b); hprintf("NYX_NET_PORT: %d\n", state->nyx_net_port); + hprintf("NYX_NET_CLIENT_IP_ADDR: %s\n", state->NYX_NET_CLIENT_IP_ADDR); #endif harness_state_ready = true; diff --git a/packer/linux_x86_64-userspace/src/misc/harness_state.h b/packer/linux_x86_64-userspace/src/misc/harness_state.h index 23af7eb..02d6e52 100644 --- a/packer/linux_x86_64-userspace/src/misc/harness_state.h +++ b/packer/linux_x86_64-userspace/src/misc/harness_state.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -14,6 +15,8 @@ typedef struct harness_state_s{ bool pt_auto_addr_range_a; bool pt_auto_addr_range_b; uint16_t nyx_net_port; + char nyx_net_client_ip_addr[INET_ADDRSTRLEN]; + uint16_t nyx_net_client_port; } harness_state_t; harness_state_t* get_harness_state(void); diff --git a/packer/linux_x86_64-userspace/src/netfuzz/inject.c b/packer/linux_x86_64-userspace/src/netfuzz/inject.c index 4408e3a..3d53db6 100644 --- a/packer/linux_x86_64-userspace/src/netfuzz/inject.c +++ b/packer/linux_x86_64-userspace/src/netfuzz/inject.c @@ -118,6 +118,9 @@ static inline void init_nyx(void){ static bool init_done = false; if(!init_done){ DEBUG("%s: init_done = false\n", __func__); +#if REAL_NETWORK_MODE + wait_for_client(); +#endif nyx_init_start(); init_done = true; } @@ -344,11 +347,23 @@ ssize_t recv(int sockfd, void *buf, size_t len, int flags){ //int client_socket = server_socket_to_client_socket(sockfd); //if(client_socket != -1){ DEBUG("%s --> %d\n", __func__, sockfd); +#ifdef REAL_NETWORK_MODE + char buff_for_send[8200] = {0}; +#endif if(server_socket_exists(sockfd)){ #ifndef NET_STANDALONE init_nyx(); +#ifdef REAL_NETWORK_MODE + size_t data_len = handle_next_packet(sockfd, buff_for_send, len, false); + + //notify client thread + send_malformed_data(buff_for_send, data_len); + + return real_recv(sockfd, buf, len, flags); +#else return handle_next_packet(sockfd, buf, len, false); +#endif #endif //hprintf("%s: not implemented\n", __func__); @@ -595,6 +610,7 @@ int close(int fd){ /* broken ? */ if(get_active_connections() == 0){ DEBUG("RELEASE!\n"); + real_close(fd); //while(1){} // //} @@ -660,9 +676,9 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout){ extern void foo(void); -int connect_to_server(const char* ip, int port){ +int connect_to_server(struct sockaddr_in *server){ int socket_desc; - struct sockaddr_in server; + uint16_t port = ntohs(server->sin_port); DEBUG("%s enter\n", __func__); @@ -700,13 +716,10 @@ int connect_to_server(const char* ip, int port){ exit(-1); } - server.sin_addr.s_addr = inet_addr(ip); //inet_addr(ip); //"74.125.235.20"); - server.sin_family = AF_INET; - server.sin_port = htons(port); //Connect to remote server //printf("%s: connect to socket...\n", __func__); - if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0) + if (connect(socket_desc , (struct sockaddr *)server , sizeof(*server)) < 0) { DEBUG("connect error %s", strerror(errno)); exit(-1); @@ -751,6 +764,17 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen){ return accept4(sockfd, addr, addrlen, 0); } +static void get_client_sockaddr(struct sockaddr_in *addr) +{ + addr->sin_family = AF_INET; + addr->sin_port = htons(get_harness_state()->nyx_net_client_port); + if (inet_pton(AF_INET, get_harness_state()->nyx_net_client_ip_addr, &addr->sin_addr) < 0) + { + hprintf("inet_pton failed: %s\n", strerror(errno)); + exit(-1); + } +} + #ifdef UDP_MODE #ifndef CLIENT_MODE int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){ @@ -782,7 +806,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){ add_connection(ntohs(((struct sockaddr_in*)addr)->sin_port)); - connect_to_server("127.0.0.1", ntohs(((struct sockaddr_in*)addr)->sin_port)); /* fix me */ + connect_to_server((struct sockaddr_in*)addr); //hprintf("%s %d %d\n", __func__, tmp_addr.sin_port, ret); assert(set_server_socket_to_connection(ntohs(((struct sockaddr_in*)addr)->sin_port), sockfd)); } @@ -824,30 +848,36 @@ int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen){ #ifndef CLIENT_MODE int listen(int sockfd, int backlog){ - struct sockaddr_in addr; + struct sockaddr_in server_addr; int len = sizeof(struct sockaddr); //hprintf("=== %s\n", __func__); int ret = -1; - if(getsockname(sockfd, (struct sockaddr *) &addr, (void*)&len) != -1){ + if(getsockname(sockfd, (struct sockaddr *) &server_addr, (void*)&len) != -1){ - bool exists = connection_exists(ntohs(addr.sin_port)); + bool exists = connection_exists(ntohs(server_addr.sin_port)); if(!exists){ - DEBUG("%s: port number %d\n", __func__, ntohs(addr.sin_port)); + DEBUG("%s: port number %d\n", __func__, ntohs(server_addr.sin_port)); } ret = real_listen(sockfd, backlog); if(!exists){ - if(is_target_port(ntohs(addr.sin_port))){ - add_connection(ntohs(addr.sin_port)); - connect_to_server("127.0.0.1", ntohs(addr.sin_port)); /* fix me */ - DEBUG("%s: DONE \n", __func__); + if(is_target_port(ntohs(server_addr.sin_port))){ + add_connection(ntohs(server_addr.sin_port)); - } +#ifdef REAL_NETWORK_MODE + struct sockaddr_in client_addr; + get_client_sockaddr(&client_addr); + create_client(&server_addr, &client_addr); +#else + connect_to_server(&server_addr); +#endif + DEBUG("%s: DONE \n", __func__); + } } } diff --git a/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.c b/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.c index cc8e3f9..1cd6b84 100644 --- a/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.c +++ b/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.c @@ -1,8 +1,23 @@ - +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include "socket_cache.h" #include "nyx.h" +#include "syscalls.h" #ifdef DEBUG_MODE #define DEBUG(f_, ...) hprintf((f_), ##__VA_ARGS__) @@ -10,12 +25,16 @@ #define DEBUG(f_, ...) #endif +//FIXME: use harness_state() to get namespace name +#define NNS_NAME "nspce" + typedef struct interfaces_s { int server_sockets[8]; uint8_t server_sockets_num; int client_sockets[8]; uint8_t client_sockets_num; + pthread_t client_thread; // TODO: add 8 thread support uint16_t port_server; uint16_t port_client; @@ -24,12 +43,24 @@ typedef struct interfaces_s { } interfaces_t; +typedef struct thread_args_s { + struct sockaddr_in client; + struct sockaddr_in server; +} thread_args_t; + #define MAX_CONNECTIONS 16 uint8_t active_connections = 0; interfaces_t connections[MAX_CONNECTIONS] = {0}; uint8_t active_con_num = 0; +pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //TODO: add 8 mutexes? +pthread_cond_t server_ready = PTHREAD_COND_INITIALIZER; +pthread_cond_t client_ready = PTHREAD_COND_INITIALIZER; +bool server_ready_flag = false; +bool client_ready_flag = false; +char *client_thread_data_to_send; +size_t client_thread_data_to_send_len; /* TODO: make this code thread safe */ @@ -112,6 +143,7 @@ static bool close_server_socket(interfaces_t* connection, int socket){ /* ok */ bool connection_exists(uint16_t port){ + pthread_mutex_lock(&lock); DEBUG("%s: %d\n", __func__, port); for(uint8_t i = 0; i < active_connections; i++){ @@ -119,15 +151,18 @@ bool connection_exists(uint16_t port){ continue; } if(connections[i].port == port){ + pthread_mutex_unlock(&lock); return true; } } + pthread_mutex_unlock(&lock); return false; } /* modify -> multi FDs */ bool server_socket_exists(int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d\n", __func__, socket); for(uint8_t i = 0; i < active_connections; i++){ @@ -136,15 +171,18 @@ bool server_socket_exists(int socket){ } if(check_server_socket(&connections[i], socket)){ + pthread_mutex_unlock(&lock); return true; } } + pthread_mutex_unlock(&lock); return false; } int server_socket_to_port(int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d\n", __func__, socket); for(uint8_t i = 0; i < active_connections; i++){ @@ -153,16 +191,19 @@ int server_socket_to_port(int socket){ } if(check_server_socket(&connections[i], socket)){ + pthread_mutex_unlock(&lock); return connections[i].port; } } + pthread_mutex_unlock(&lock); return -1; } /* unused ? */ bool client_socket_exists(int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d\n", __func__, socket); for(uint8_t i = 0; i < active_connections; i++){ @@ -171,16 +212,19 @@ bool client_socket_exists(int socket){ } if(check_client_socket(&connections[i], socket)){ + pthread_mutex_unlock(&lock); return true; } } + pthread_mutex_unlock(&lock); return false; } /* modify -> multi FDs */ bool set_server_socket_to_connection(uint16_t port, int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d %d\n", __func__, socket, port); for(uint8_t i = 0; i < active_connections; i++){ @@ -191,14 +235,17 @@ bool set_server_socket_to_connection(uint16_t port, int socket){ add_server_socket(&connections[i], socket); + pthread_mutex_unlock(&lock); return true; } } + pthread_mutex_unlock(&lock); return false; } /* modify -> multi FDs or keep it? */ bool set_client_socket_to_connection(uint16_t port, int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d %d\n", __func__, socket, port); for(uint8_t i = 0; i < active_connections; i++){ @@ -208,21 +255,299 @@ bool set_client_socket_to_connection(uint16_t port, int socket){ if(connections[i].port == port){ add_client_socket(&connections[i], socket); + pthread_mutex_unlock(&lock); return true; } } + pthread_mutex_unlock(&lock); return false; } +static pthread_t get_thread_id_from_connection(uint16_t port){ + pthread_mutex_lock(&lock); + pthread_t thread_id; + + for(uint8_t i = 0; i < active_connections; i++){ + if(connections[i].disabled == true){ + continue; + } + if(connections[i].port == port){ + thread_id = connections[i].client_thread; + pthread_mutex_unlock(&lock); + return thread_id; + } + } + pthread_mutex_unlock(&lock); + return -1; +} + +static void move_thread_to_netns() { + hprintf("%s: ", __func__); + const char *netns_path_fmt = "/var/run/netns/%s"; + char netns_path[272]; /* 15 for "/var/.." + 256 for netns name + 1 '\0' */ + int netns_fd; + + if (strlen(NNS_NAME) > 256) + hprintf("Network namespace name \"%s\" is too long\n", NNS_NAME); + + sprintf(netns_path, netns_path_fmt, NNS_NAME); + + netns_fd = open(netns_path, O_RDONLY); + if (netns_fd == -1) + hprintf("Unable to open %s\n", netns_path); + + if (setns(netns_fd, CLONE_NEWNET) == -1) + hprintf("setns failed: %s\n", strerror(errno)); + hprintf("done\n"); +} + +char *hexdump_representation(const char *rcvbuf, size_t len) { + if (rcvbuf == NULL) { + return NULL; + } + + size_t line_len = 76; // Line length without any shift + size_t hex_lines = (len + 15) / 16; // Calculate the number of lines needed + size_t hex_len = hex_lines * line_len + 1; // Total length of hex_dump string + char *hex_dump = (char *)malloc(hex_len * sizeof(char)); + + if (hex_dump == NULL) { + return NULL; + } + + size_t hex_dump_pos = 0; + for (size_t i = 0; i < len; i += 16) { + int line_offset = snprintf(hex_dump + hex_dump_pos, 11, "%08zX ", i); + hex_dump_pos += line_offset; + + for (size_t j = 0; j < 16; j++) { + if (i + j < len) { + line_offset = snprintf(hex_dump + hex_dump_pos, 5, "%02X ", + (unsigned char)rcvbuf[i + j]); + } else { + line_offset = snprintf(hex_dump + hex_dump_pos, 5, " "); + } + hex_dump_pos += line_offset; + if (j == 7) { + hex_dump[hex_dump_pos++] = ' '; + } + } + + hex_dump[hex_dump_pos++] = ' '; + hex_dump[hex_dump_pos++] = '|'; + + for (size_t j = 0; j < 16 && i + j < len; j++) { + hex_dump[hex_dump_pos++] = + (rcvbuf[i + j] >= 32 && rcvbuf[i + j] <= 126) ? rcvbuf[i + j] : '.'; + } + + hex_dump[hex_dump_pos++] = '|'; + hex_dump[hex_dump_pos++] = '\n'; + } + hex_dump[hex_dump_pos] = '\0'; // Null-terminate the hex_dump string + + return hex_dump; +} + +void wait_for_client() +{ + pthread_mutex_lock(&lock); + + while (!client_ready_flag) + pthread_cond_wait(&client_ready, &lock); + + pthread_mutex_unlock(&lock); +} + +void client_is_ready() +{ + pthread_mutex_lock(&lock); + client_ready_flag = true; + pthread_mutex_unlock(&lock); + + pthread_cond_signal(&client_ready); +} + +void find_tcp_seq_numbers_of_connection(int raw_socket, uint32_t *seq_num_client, uint32_t *seq_num_server) +{ + char buffer[80]; //sizeof(struct iphdr) + max size of a tcp handshake packet (60) + + DEBUG("%s: Reading SYNACK to get seq numbers.\n", __func__); + + while (1) { + ssize_t len = real_read(raw_socket, buffer, sizeof(buffer)); + if (len <= 0) { + hprintf("%s: read error: %s\n", __func__, strerror(errno)); + exit(-1); + } + + struct iphdr *iph = (struct iphdr *)buffer; + struct tcphdr *tcph = (struct tcphdr *)((uint8_t *)iph + iph->ihl * 4); + + if (tcph->syn == 1 && tcph->ack == 1) { + DEBUG("%s: found synack\n", __func__); + *seq_num_server = ntohl(tcph->seq); + *seq_num_client = ntohl(tcph->ack_seq) - 1; + break; + } + } + + DEBUG("%s: Got SEQ client: %u, SEQ server: %u\n", __func__, *seq_num_client, *seq_num_server); +} + +static void dump_payload(void* buffer, size_t len, const char* filename) +{ + static kafl_dump_file_t file_obj = {0}; + + file_obj.file_name_str_ptr = (uintptr_t)filename; + file_obj.append = 0; + file_obj.bytes = 0; + kAFL_hypercall(HYPERCALL_KAFL_DUMP_FILE, (uintptr_t) (&file_obj)); + + file_obj.append = 1; + file_obj.bytes = len; + file_obj.data_ptr = (uintptr_t)buffer; + kAFL_hypercall(HYPERCALL_KAFL_DUMP_FILE, (uintptr_t) (&file_obj)); +} + +static void send_tcp_numbers_to_main_fuzzer(uint32_t seq_num_client, uint32_t seq_num_server) +{ + uint32_t data[2] = {seq_num_client, seq_num_server}; + size_t size = sizeof(data); + + hprintf("%s: SEQ client: %u, SEQ server: %u\n", __func__, seq_num_client, seq_num_server); + + dump_payload(data, size, "tcp_sequence_numbers.bin"); +} + +void *client_thread_func(void *data) +{ + move_thread_to_netns(); + thread_args_t *args = (thread_args_t *)data; + struct sockaddr_in server = args->server; + struct sockaddr_in client = args->client; + int handshake_socket; + uint32_t seq_num_client = 0; + uint32_t seq_num_server = 0; + + hprintf("%s: create socket...\n", __func__); + + handshake_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (handshake_socket == -1) + { + hprintf("socket error: %s\n", strerror(errno)); + exit(-1); + } + + if (real_bind(handshake_socket, (struct sockaddr *)&client, sizeof(client)) < 0) + { + hprintf("bind error: %s\n", strerror(errno)); + exit(-1); + } + + int send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); + if (send_socket == -1) { + hprintf("socket error: %s\n", strerror(errno)); + exit(-1); + } + + if (real_bind(send_socket, (struct sockaddr *)&client, sizeof(client)) < 0) { + hprintf("bind error: %s\n", strerror(errno)); + exit(-1); + } + + //Connect to remote server + hprintf("%s: connect to socket...\n", __func__); + hprintf("%s: server port is %d\n", __func__, ntohs(server.sin_port)); + if (real_connect(handshake_socket, (struct sockaddr *)&server, sizeof(server)) < 0) + { + hprintf("connect error: %s\n", strerror(errno)); + exit(-1); + } + + hprintf("%s: Connected. Handshake is done\n", __func__); + + find_tcp_seq_numbers_of_connection(send_socket, &seq_num_client, &seq_num_server); + + send_tcp_numbers_to_main_fuzzer(seq_num_client, seq_num_server); + + assert(set_client_socket_to_connection(ntohs(server.sin_port), handshake_socket)); + + free(data); + + client_is_ready(); + + while (1) { + pthread_mutex_lock(&lock); + + while (!server_ready_flag) + pthread_cond_wait(&server_ready, &lock); + + real_sendto(send_socket, client_thread_data_to_send, + client_thread_data_to_send_len, 0, + (struct sockaddr *)&server, sizeof(server)); + +#define DEBUG_MODE 1 +#ifdef DEBUG_MODE + { + fflush(stdout); + char *hexdumped_data = hexdump_representation(client_thread_data_to_send, + client_thread_data_to_send_len); + hprintf("%s: Data that will be sended (%zu len):\n%s\n", __func__, + client_thread_data_to_send_len, hexdumped_data); + free(hexdumped_data); + } +#endif +#undef DEBUG_MODE + + server_ready_flag = false; + pthread_mutex_unlock(&lock); + } + + return NULL; +} + +void send_malformed_data(char *data, size_t len) +{ + pthread_mutex_lock(&lock); + client_thread_data_to_send = data; + client_thread_data_to_send_len = len; + server_ready_flag = true; + pthread_mutex_unlock(&lock); + + pthread_cond_signal(&server_ready); +} + +void create_client(struct sockaddr_in *server, struct sockaddr_in *client) +{ + DEBUG("%s: server ip: %s, server port: %d\n", __func__, + inet_ntoa(server->sin_addr), ntohs(server->sin_port)); + DEBUG("%s: client ip: %s, client port: %d\n", __func__, + inet_ntoa(client->sin_addr), ntohs(client->sin_port)); + + thread_args_t *args = malloc(sizeof(thread_args_t)); + + memcpy(&args->server, server, sizeof(struct sockaddr_in)); + memcpy(&args->client, client, sizeof(struct sockaddr_in)); + + pthread_t thread_id = + get_thread_id_from_connection(ntohs(server->sin_port)); + + pthread_create(&thread_id, NULL, client_thread_func, args); +} + /* ok */ bool add_connection(uint16_t port){ DEBUG("%s: %d\n", __func__, port); assert(!connection_exists(port)); + pthread_mutex_lock(&lock); + if(active_con_num >= MAX_CONNECTIONS){ /* TODO: replace with ABORT hypercall */ hprintf("%s -> release\n", __func__); + pthread_mutex_unlock(&lock); kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0); } //hprintf("%s -> port: %d\n", __func__, port); @@ -233,12 +558,14 @@ bool add_connection(uint16_t port){ connections[active_connections].server_sockets_num = 0; active_connections++; - active_con_num++; + active_con_num++; + pthread_mutex_unlock(&lock); return true; } /* modify -> multi FDs */ int set_select_fds(fd_set *set, fd_set *old_set){ + pthread_mutex_lock(&lock); //hprintf("%s -> %d\n", __func__, active_connections); int ret = 0; @@ -255,12 +582,14 @@ int set_select_fds(fd_set *set, fd_set *old_set){ } } + pthread_mutex_unlock(&lock); return ret; } /* modify -> multi FDs */ void disable_connection_by_server_socket(int socket){ + pthread_mutex_lock(&lock); DEBUG("%s: %d\n", __func__, socket); for(uint8_t i = 0; i < active_connections; i++){ @@ -271,10 +600,13 @@ void disable_connection_by_server_socket(int socket){ if(close_server_socket(&connections[i], socket) && connections[i].server_sockets_num == 0){ active_con_num--; connections[i].disabled = true; + //TODO pthread_join here?? + pthread_mutex_unlock(&lock); return; } } + pthread_mutex_unlock(&lock); } uint16_t get_active_connections(void){ diff --git a/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.h b/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.h index e25b6a4..c3fe952 100644 --- a/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.h +++ b/packer/linux_x86_64-userspace/src/netfuzz/socket_cache.h @@ -1,7 +1,8 @@ #pragma once -#include +#include #include +#include #include #include #include @@ -14,9 +15,11 @@ bool client_socket_exists(int socket); bool set_server_socket_to_connection(uint16_t port, int socket); bool set_client_socket_to_connection(uint16_t port, int socket); bool add_connection(uint16_t port); -//int server_socket_to_client_socket(int socket); int set_select_fds(fd_set *set, fd_set *old_set); void disable_connection_by_server_socket(int socket); ssize_t real_send(int sockfd, const void *buf, size_t len, int flags); +void send_malformed_data(char *data, size_t len); +void wait_for_client(); +void create_client(struct sockaddr_in *server, struct sockaddr_in *client); -int server_socket_to_port(int socket); \ No newline at end of file +int server_socket_to_port(int socket); diff --git a/packer/nyx_net_payload_executor.py b/packer/nyx_net_payload_executor.py index 8eaf620..e3949d2 100644 --- a/packer/nyx_net_payload_executor.py +++ b/packer/nyx_net_payload_executor.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 import sys import socket import select diff --git a/packer/nyx_packer.py b/packer/nyx_packer.py index 5ccb920..4376c35 100644 --- a/packer/nyx_packer.py +++ b/packer/nyx_packer.py @@ -185,6 +185,9 @@ def compile(config): SETUP_FOLDER = config.argument_values["setup_folder"] UDP_MODE = config.argument_values["nyx_net_udp"] CLIENT_MODE = config.argument_values["nyx_net_client_mode"] + REAL_NETWORK_MODE = config.argument_values["nyx_net_real_network_mode"] + NET_FUZZ_CLIENT_IP = config.argument_values["nyx_net_client_ip"] + NET_FUZZ_CLIENT_PORT = config.argument_values["nyx_net_client_port"] RECOMPILE_SPEC = config.argument_values["recompile_spec"] DEBUG_MODE = config.argument_values["nyx_net_debug_mode"] STDOUT_STDERR_DEBUG = config.argument_values["debug_stdin_stderr"] @@ -243,6 +246,8 @@ def compile(config): os.environ["CLIENT_MODE"] = "-DCLIENT_MODE " if DEBUG_MODE: os.environ["DEBUG_MODE"] = "-DDEBUG_MODE " + if REAL_NETWORK_MODE: + os.environ["REAL_NETWORK_MODE"] = "-DREAL_NETWORK_MODE " if STDOUT_STDERR_DEBUG: os.environ["STDOUT_STDERR_DEBUG"] = "-DSTDOUT_STDERR_DEBUG " if IGNORE_UDP_PORT: @@ -378,12 +383,15 @@ def compile(config): f.write(f_content) f.close() + download_script += "patchelf --add-needed /home/user/onload/build/gnu_x86_64/lib/transport/unix/libcitransport0.so target_executable\n" + download_script += "LD_LIBRARY_PATH=/tmp/:$LD_LIBRARY_PATH " if asan_lib: download_script += "LD_BIND_NOW=1 LD_PRELOAD=/tmp/%s:ld_preload_fuzz.so "%(asan_lib) else: download_script += "LD_BIND_NOW=1 LD_PRELOAD=/tmp/ld_preload_fuzz.so " + download_script += "ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:log_path=/tmp/data.log:abort_on_error=true " if DELAYED_INIT: @@ -396,6 +404,10 @@ def compile(config): download_script += "NYX_NET_FUZZ_MODE=ON " if NET_FUZZ_PORT: download_script += "NYX_NET_PORT=%s "%(NET_FUZZ_PORT) + if NET_FUZZ_CLIENT_IP: + download_script += "NYX_NET_CLIENT_IP_ADDR=%s "%(NET_FUZZ_CLIENT_IP) + if NET_FUZZ_CLIENT_PORT: + download_script += "NYX_NET_CLIENT_PORT=%s "%(NET_FUZZ_CLIENT_PORT) if LEGACY_FILE_MODE: download_script += "NYX_LEGACY_FILE_MODE=%s "%(config.argument_values["file"]) if not DISABLE_PT_RANGE_A: @@ -416,13 +428,13 @@ def compile(config): download_script += " " if STDOUT_STDERR_DEBUG: - download_script += " > stdout.txt 2> stderr.txt\n" + download_script += " | ./hcat\n" + # download_script += " > stdout.txt 2> stderr.txt\n" download_script += "cat stdout.txt | ./hcat\n" download_script += "cat stderr.txt | ./hcat\n" else: download_script += " > /dev/null 2> /dev/null\n" - download_script += "dmesg | grep segfault | ./hcat\n" download_script += "./habort\n" @@ -454,4 +466,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/qemu_tool.sh b/qemu_tool.sh index 056b9e5..b922b83 100755 --- a/qemu_tool.sh +++ b/qemu_tool.sh @@ -80,7 +80,7 @@ then error_install fi - NYX_DISABLE_DIRTY_RING=y NYX_DISABLE_BLOCK_COW=TRUE $QEMU_PT_BIN --enable-kvm -drive format=raw,file=$2 -cdrom $3 -k de -vnc :0 -m $MEMORY_SIZE + NYX_DISABLE_DIRTY_RING=y NYX_DISABLE_BLOCK_COW=TRUE $QEMU_PT_BIN --enable-kvm -drive format=raw,file=$2 -cdrom $3 -k de -vnc :8 -m $MEMORY_SIZE exit 0 fi @@ -91,7 +91,7 @@ then error_post_install fi - NYX_DISABLE_DIRTY_RING=y NYX_DISABLE_BLOCK_COW=TRUE $QEMU_PT_BIN --enable-kvm -drive format=raw,file=$2 -k de -vnc :0 -m $MEMORY_SIZE -net user,hostfwd=tcp::2222-:22 -net nic + NYX_DISABLE_DIRTY_RING=y NYX_DISABLE_BLOCK_COW=TRUE $QEMU_PT_BIN --enable-kvm -drive format=raw,file=$2 -k de -vnc :8 -m $MEMORY_SIZE -net user,hostfwd=tcp::2222-:22 -net nic exit 0 fi @@ -103,7 +103,7 @@ then fi mkdir $4 && \ - NYX_DISABLE_DIRTY_RING=y $QEMU_PT_BIN --enable-kvm -hda $2 -k de -vnc :0 -m $3 -net none -machine kAFL64-v1 -cpu kAFL64-Hypervisor-v1 -fast_vm_reload pre_path=$4,load=off + NYX_DISABLE_DIRTY_RING=y $QEMU_PT_BIN --enable-kvm -hda $2 -k de -vnc :8 -m $3 -net none -machine kAFL64-v1 -cpu kAFL64-Hypervisor-v1 -fast_vm_reload pre_path=$4,load=off exit 0 fi