264 lines
16 KiB
C
264 lines
16 KiB
C
#ifndef LIBAFL_QEMU_H
|
|
#define LIBAFL_QEMU_H
|
|
|
|
/**
|
|
* LibAFL QEMU header file.
|
|
*
|
|
* This file is a portable header file used to build target harnesses more
|
|
* conveniently. Its main purpose is to generate ready-to-use calls to
|
|
* communicate with the fuzzer. The list of commands is available at the bottom
|
|
* of this file. The rest mostly consists of macros generating the code used by
|
|
* the commands.
|
|
*/
|
|
|
|
/* === The private part starts here === */
|
|
|
|
/* This part should not be useful for most people. Callable commands are
|
|
* available at the end of this file. */
|
|
|
|
#define STRINGIFY(s) #s
|
|
#define XSTRINGIFY(s) STRINGIFY(s)
|
|
|
|
// Target Specific imports / definitions
|
|
#ifdef _WIN32
|
|
#include <stdint.h>
|
|
#include <intsafe.h>
|
|
|
|
typedef UINT64 libafl_word;
|
|
#define LIBAFL_CALLING_CONVENTION __fastcall
|
|
|
|
#else
|
|
#include <stdint.h>
|
|
|
|
#if defined(__x86_64__) || defined(__aarch64__)
|
|
typedef uint64_t libafl_word;
|
|
#define LIBAFL_CALLING_CONVENTION __attribute__(())
|
|
#endif
|
|
|
|
#ifdef __arm__
|
|
typedef uint32_t libafl_word;
|
|
#define LIBAFL_CALLING_CONVENTION __attribute__(())
|
|
#endif
|
|
#endif
|
|
|
|
#define LIBAFL_SYNC_EXIT_OPCODE 0x66f23a0f
|
|
#define LIBAFL_BACKDOOR_OPCODE 0x44f23a0f
|
|
|
|
#define LIBAFL_QEMU_HDR_VERSION_NUMBER 0111 // TODO: find a nice way to set it.
|
|
|
|
typedef enum LibaflQemuCommand {
|
|
LIBAFL_QEMU_COMMAND_START_VIRT = 0,
|
|
LIBAFL_QEMU_COMMAND_START_PHYS = 1,
|
|
LIBAFL_QEMU_COMMAND_INPUT_VIRT = 2,
|
|
LIBAFL_QEMU_COMMAND_INPUT_PHYS = 3,
|
|
LIBAFL_QEMU_COMMAND_END = 4,
|
|
LIBAFL_QEMU_COMMAND_SAVE = 5,
|
|
LIBAFL_QEMU_COMMAND_LOAD = 6,
|
|
LIBAFL_QEMU_COMMAND_VERSION = 7,
|
|
LIBAFL_QEMU_COMMAND_VADDR_FILTER_ALLOW = 8,
|
|
} LibaflExit;
|
|
|
|
typedef enum LibaflQemuEndStatus {
|
|
LIBAFL_QEMU_END_UNKNOWN = 0,
|
|
LIBAFL_QEMU_END_OK = 1,
|
|
LIBAFL_QEMU_END_CRASH = 2,
|
|
} LibaflExitEndParams;
|
|
|
|
#ifdef _WIN32
|
|
#define LIBAFL_DEFINE_FUNCTIONS(name, _opcode) \
|
|
#ifdef __cplusplus \
|
|
extern "C" { \
|
|
#endif \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0(libafl_word action); \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1(libafl_word action, \
|
|
##name## libafl_word arg1); \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2(libafl_word action, \
|
|
libafl_word arg1, \
|
|
libafl_word arg2); \
|
|
#ifdef __cplusplus \
|
|
} \
|
|
#endif
|
|
#else
|
|
|
|
#if defined(__x86_64__)
|
|
#define LIBAFL_DEFINE_FUNCTIONS(name, opcode) \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0( \
|
|
libafl_word action) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov %1, %%rax\n" \
|
|
".4byte " XSTRINGIFY(opcode) "\n" \
|
|
"mov %%rax, %0\n" \
|
|
: "=g"(ret) \
|
|
: "g"(action) \
|
|
: "%rax" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1( \
|
|
libafl_word action, libafl_word arg1) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov %1, %%rax\n" \
|
|
"mov %2, %%rdi\n" \
|
|
".4byte " XSTRINGIFY(opcode) "\n" \
|
|
"mov %%rax, %0\n" \
|
|
: "=g"(ret) \
|
|
: "g"(action), "g"(arg1) \
|
|
: "%rax", "%rdi" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2( \
|
|
libafl_word action, libafl_word arg1, libafl_word arg2) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov %1, %%rax\n" \
|
|
"mov %2, %%rdi\n" \
|
|
"mov %3, %%rsi\n" \
|
|
".4byte " XSTRINGIFY(opcode) "\n" \
|
|
"mov %%rax, %0\n" \
|
|
: "=g"(ret) \
|
|
: "g"(action), "g"(arg1), "g"(arg2) \
|
|
: "%rax", "%rdi", "%rsi" \
|
|
); \
|
|
return ret; \
|
|
}
|
|
|
|
#elif defined(__arm__)
|
|
#define LIBAFL_DEFINE_FUNCTIONS(name, opcode) \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0( \
|
|
libafl_word action) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov r0, %1\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, r0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action) \
|
|
: "r0" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1( \
|
|
libafl_word action, libafl_word arg1) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov r0, %1\n" \
|
|
"mov r1, %2\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, r0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action), "r"(arg1) \
|
|
: "r0", "r1" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2( \
|
|
libafl_word action, libafl_word arg1, libafl_word arg2) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov r0, %1\n" \
|
|
"mov r1, %2\n" \
|
|
"mov r2, %3\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, r0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action), "r"(arg1), "r"(arg2) \
|
|
: "r0", "r1", "r2" \
|
|
); \
|
|
return ret; \
|
|
}
|
|
|
|
#elif defined(__aarch64__)
|
|
#define LIBAFL_DEFINE_FUNCTIONS(name, opcode) \
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0( \
|
|
libafl_word action) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov x0, %1\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, x0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action) \
|
|
: "x0" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1( \
|
|
libafl_word action, libafl_word arg1) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov x0, %1\n" \
|
|
"mov x1, %2\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, x0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action), "r"(arg1) \
|
|
: "x0", "x1" \
|
|
); \
|
|
return ret; \
|
|
} \
|
|
\
|
|
libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2( \
|
|
libafl_word action, libafl_word arg1, libafl_word arg2) { \
|
|
libafl_word ret; \
|
|
__asm__ volatile ( \
|
|
"mov x0, %1\n" \
|
|
"mov x1, %2\n" \
|
|
"mov x2, %3\n" \
|
|
".word " XSTRINGIFY(opcode) "\n" \
|
|
"mov %0, x0\n" \
|
|
: "=r"(ret) \
|
|
: "r"(action), "r"(arg1), "r"(arg2) \
|
|
: "x0", "x1", "x2" \
|
|
); \
|
|
return ret; \
|
|
}
|
|
#else
|
|
#warning "LibAFL QEMU Runtime does not support your architecture yet, please leave an issue."
|
|
#endif
|
|
|
|
#endif
|
|
|
|
// Generates sync exit functions
|
|
LIBAFL_DEFINE_FUNCTIONS(sync_exit, LIBAFL_SYNC_EXIT_OPCODE)
|
|
|
|
// Generates backdoor functions
|
|
LIBAFL_DEFINE_FUNCTIONS(backdoor, LIBAFL_BACKDOOR_OPCODE)
|
|
|
|
/* === The private part ends here === */
|
|
|
|
/* === The public part starts here === */
|
|
|
|
/* LibAFL QEMU Commands */
|
|
|
|
#define LIBAFL_QEMU_START_VIRT(buf_vaddr, max_len) \
|
|
_libafl_sync_exit_call2(LIBAFL_QEMU_COMMAND_START_VIRT, buf_vaddr, max_len)
|
|
|
|
#define LIBAFL_QEMU_START_PHYS(buf_paddr, max_len) \
|
|
_libafl_sync_exit_call2(LIBAFL_QEMU_COMMAND_START_PHYS, buf_paddr, max_len)
|
|
|
|
#define LIBAFL_QEMU_INPUT_VIRT(buf_vaddr, max_len) \
|
|
_libafl_sync_exit_call2(LIBAFL_QEMU_COMMAND_INPUT_VIRT, buf_vaddr, max_len)
|
|
|
|
#define LIBAFL_QEMU_INPUT_PHYS(buf_paddr, max_len) \
|
|
_libafl_exit_call2(LIBAFL_QEMU_COMMAND_INPUT_PHYS, buf_paddr, max_len)
|
|
|
|
#define LIBAFL_QEMU_END(status) _libafl_sync_exit_call1(LIBAFL_QEMU_COMMAND_END, status)
|
|
|
|
#define LIBAFL_QEMU_SAVE() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_SAVE)
|
|
|
|
#define LIBAFL_QEMU_LOAD() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_LOAD)
|
|
|
|
#define LIBAFL_QEMU_VERSION() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_VERSION)
|
|
|
|
/* === The public part ends here === */
|
|
|
|
#endif
|