1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
#include "nyx.h"
#define TRACE_BUFFER_SIZE (64)
#define PAGE_SIZE 0x1000
#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE - 1)) + PAGE_SIZE)
int main(int argc, char **argv) {
/* if you want to debug code running in Nyx, hprintf() is the way to go.
* Long story short -- it's just a guest-to-hypervisor printf. Hence the name
* "hprintf"
*/
hprintf("Agent test\n");
/* Request information on available (host) capabilites (optional) */
host_config_t host_config;
kAFL_hypercall(HYPERCALL_KAFL_GET_HOST_CONFIG, (uintptr_t)&host_config);
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);
/* this is our "bitmap" that is later shared with the fuzzer (you can also
* pass the pointer of the bitmap used by compile-time instrumentations in
* your target) */
uint8_t *trace_buffer =
mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memset(trace_buffer, 0,
TRACE_BUFFER_SIZE); // makes sure that the bitmap buffer is already
// mapped into the guest's memory (alternatively
// you can use mlock) */
/* Submit agent configuration */
agent_config_t agent_config = {0};
agent_config.agent_magic = NYX_AGENT_MAGIC;
agent_config.agent_version = NYX_AGENT_VERSION;
agent_config.agent_timeout_detection =
0; /* timeout detection is implemented by the agent (currently not used)
*/
agent_config.agent_tracing =
1; /* set this flag to propagade that instrumentation-based fuzzing is
availabe */
agent_config.agent_ijon_tracing = 0; /* set this flag to propagade that IJON
extension is implmented agent-wise */
agent_config.trace_buffer_vaddr =
(uintptr_t)trace_buffer; /* trace "bitmap" pointer - required for
instrumentation-only fuzzing */
agent_config.ijon_trace_buffer_vaddr =
(uintptr_t)NULL; /* "IJON" buffer pointer */
agent_config.agent_non_reload_mode =
1; /* non-reload mode is supported (usually because the agent implements a
fork-server; currently not used) */
agent_config.coverage_bitmap_size = TRACE_BUFFER_SIZE;
kAFL_hypercall(HYPERCALL_KAFL_SET_AGENT_CONFIG, (uintptr_t)&agent_config);
/* Tell hypervisor the virtual address of the payload (input) buffer (call
* mlock to ensure that this buffer stays in the guest's memory)*/
kAFL_payload *payload_buffer =
mmap(NULL, host_config.payload_buffer_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
mlock(payload_buffer, (size_t)host_config.payload_buffer_size);
memset(payload_buffer, 0, host_config.payload_buffer_size);
kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (uintptr_t)payload_buffer);
hprintf("[init] payload buffer is mapped at %p\n", payload_buffer);
/* the main fuzzing loop */
while (1) {
/* Creates a root snapshot on first execution. Also we requested the next
* input with this hypercall */
kAFL_hypercall(HYPERCALL_KAFL_USER_FAST_ACQUIRE, 0); // root snapshot <--
#ifdef DEBUG
hprintf("Size: %ld Data: %x %x %x %x\n", payload_buffer->size,
payload_buffer->data[4], payload_buffer->data[5],
payload_buffer->data[6], payload_buffer->data[7]);
#endif
uint32_t len = payload_buffer->size;
/* set a byte to make AFL++ happy (otherwise the fuzzer might refuse to
* start fuzzing at all) */
((uint8_t *)trace_buffer)[0] = 0x1;
if (len >= 4) {
/* set a byte in the bitmap to guide your fuzzer */
((uint8_t *)trace_buffer)[0] = 0x1;
if (payload_buffer->data[0] == '!') {
((uint8_t *)trace_buffer)[1] = 0x1;
if (payload_buffer->data[1] == 'N') {
((uint8_t *)trace_buffer)[2] = 0x1;
if (payload_buffer->data[2] == 'Y') {
((uint8_t *)trace_buffer)[3] = 0x1;
if (payload_buffer->data[3] == 'X') {
((uint8_t *)trace_buffer)[4] = 0x1;
/* Notifiy the hypervisor and the fuzzer that a "crash" has
* occured. Also a string is passed by this hypercall (this is
* currently not supported by AFL++-Nyx) */
kAFL_hypercall(HYPERCALL_KAFL_PANIC_EXTENDED,
(uintptr_t) "Something went wrong\n");
}
}
}
}
}
/* this hypercall is used to notify the hypervisor and the fuzzer that a
* single fuzzing "execution" has finished. If the reload-mode is enabled,
* we will jump back to our root snapshot. Otherwise, the hypervisor passes
* control back to the guest once the bitmap buffer has been "processed" by
* the fuzzer.
*/
kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
/* This shouldn't happen if you have enabled the reload mode */
hprintf("This should never happen :)\n");
}
return 0;
}
|