mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-07 15:51:32 +00:00
142 lines
5.2 KiB
C
142 lines
5.2 KiB
C
#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;
|
|
|
|
}
|
|
|