From 50be2f4aaf7369c1ae8a0faee29ad6c6af86944d Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Wed, 3 Apr 2024 11:57:48 +0200 Subject: [PATCH] Fix of libafl qemu runtime files (#1996) * Change naming and fix LibAFLQEMU header file. Fix and document LibAFL QEMU Windows ASM file. * fmt --- libafl_qemu/runtime/libafl_qemu.asm | 63 ----------- libafl_qemu/runtime/libafl_qemu.h | 101 +++++++++-------- libafl_qemu/runtime/libafl_qemu_windows.asm | 115 ++++++++++++++++++++ libafl_qemu/src/command.rs | 27 ++--- 4 files changed, 179 insertions(+), 127 deletions(-) delete mode 100755 libafl_qemu/runtime/libafl_qemu.asm create mode 100755 libafl_qemu/runtime/libafl_qemu_windows.asm diff --git a/libafl_qemu/runtime/libafl_qemu.asm b/libafl_qemu/runtime/libafl_qemu.asm deleted file mode 100755 index 39be791fc9..0000000000 --- a/libafl_qemu/runtime/libafl_qemu.asm +++ /dev/null @@ -1,63 +0,0 @@ -PUBLIC _libafl_exit_call0, _libafl_exit_call1, _libafl_exit_call2 - -LIBAFL_EXIT_OPCODE MACRO - dd 66f23a0fh -ENDM - -.code - -; Execute LibAFL backdoor (no argument) -; Parameters: -; [RAX, OUT] Hook return value -; [RCX, IN] LibAFL Backdorr operation -_libafl_exit_call0: - mov rax, rcx - -IFNDEF _DEBUG - LIBAFL_EXIT_OPCODE -ENDIF - - ret - -; Execute LibAFL backdoor (one argument) -; Parameters: -; [RAX, OUT] Hook return value -; [RCX, IN] LibAFL Backdorr operation -; [RDX, IN] Arg1 -_libafl_exit_call1: - push rdi - - mov rax, rcx - mov rdi, rdx - -IFNDEF _DEBUG - LIBAFL_EXIT_OPCODE -ENDIF - - pop rdi - - ret - -; Execute LibAFL backdoor (two arguments) -; Parameters: -; [RAX, OUT] Hook return value -; [RCX, IN] LibAFL Backdorr operation -; [RDX, IN] Arg1 -; [R8, IN] Arg2 -_libafl_exit_call2: - push rdi - push rsi - - mov rax, rcx - mov rdi, rdx - mov rsi, r8 - -IFNDEF _DEBUG - LIBAFL_EXIT_OPCODE -ENDIF - pop rsi - pop rdi - - ret - -END \ No newline at end of file diff --git a/libafl_qemu/runtime/libafl_qemu.h b/libafl_qemu/runtime/libafl_qemu.h index 0ef008e8f6..0337fd9873 100644 --- a/libafl_qemu/runtime/libafl_qemu.h +++ b/libafl_qemu/runtime/libafl_qemu.h @@ -1,5 +1,5 @@ -#ifndef LIBAFL_EXIT_H -#define LIBAFL_EXIT_H +#ifndef LIBAFL_QEMU_H +#define LIBAFL_QEMU_H /** * LibAFL QEMU header file. @@ -28,57 +28,56 @@ typedef UINT64 libafl_word; #define LIBAFL_CALLING_CONVENTION __fastcall #else - #ifdef __x86_64__ - #include + #include -typedef uint64_t libafl_word; + #ifdef __x86_64__ + typedef uint64_t libafl_word; #define LIBAFL_CALLING_CONVENTION __attribute__(()) #endif #ifdef __arm__ - #include - -typedef uint32_t libafl_word; + typedef uint32_t libafl_word; #define LIBAFL_CALLING_CONVENTION __attribute__(()) #endif #endif -#define LIBAFL_EXIT_OPCODE 0x66f23a0f +#define LIBAFL_SYNC_EXIT_OPCODE 0x66f23a0f #define LIBAFL_BACKDOOR_OPCODE 0x44f23a0f -#define LIBAFL_EXIT_VERSION_NUMBER 0111 // TODO: find a nice way to set it. +#define LIBAFL_QEMU_HDR_VERSION_NUMBER 0111 // TODO: find a nice way to set it. -typedef enum LibaflExit { - LIBAFL_EXIT_START_VIRT = 0, - LIBAFL_EXIT_START_PHYS = 1, - LIBAFL_EXIT_INPUT_VIRT = 2, - LIBAFL_EXIT_INPUT_PHYS = 3, - LIBAFL_EXIT_END = 4, - LIBAFL_EXIT_SAVE = 5, - LIBAFL_EXIT_LOAD = 6, - LIBAFL_EXIT_VERSION = 7, - LIBAFL_EXIT_VADDR_FILTER_ALLOW = 8, +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 LibaflExitEndStatus { - LIBAFL_EXIT_END_UNKNOWN = 0, - LIBAFL_EXIT_END_OK = 1, - LIBAFL_EXIT_END_CRASH = 2, +typedef enum LibaflQemuEndStatus { + LIBAFL_QEMU_END_UNKNOWN = 0, + LIBAFL_QEMU_END_OK = 1, + LIBAFL_QEMU_END_CRASH = 2, } LibaflExitEndParams; #ifdef _WIN32 - #ifdef __cplusplus -extern "C" { - #endif -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call0(libafl_word action); -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call1(libafl_word action, - libafl_word arg1); -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, - libafl_word arg1, - libafl_word arg2); - #ifdef __cplusplus -} - #endif + #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 #ifdef __x86_64__ @@ -180,7 +179,7 @@ libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, #endif // Generates sync exit functions -LIBAFL_DEFINE_FUNCTIONS(exit, LIBAFL_EXIT_OPCODE) +LIBAFL_DEFINE_FUNCTIONS(sync_exit, LIBAFL_SYNC_EXIT_OPCODE) // Generates backdoor functions LIBAFL_DEFINE_FUNCTIONS(backdoor, LIBAFL_BACKDOOR_OPCODE) @@ -189,28 +188,28 @@ LIBAFL_DEFINE_FUNCTIONS(backdoor, LIBAFL_BACKDOOR_OPCODE) /* === The public part starts here === */ -/* Commands */ +/* LibAFL QEMU Commands */ -#define LIBAFL_EXIT_START_VIRT(buf_vaddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_START_VIRT, buf_vaddr, max_len) +#define LIBAFL_QEMU_START_VIRT(buf_vaddr, max_len) \ + _libafl_sync_exit_call2(LIBAFL_QEMU_COMMAND_START_VIRT, buf_vaddr, max_len) -#define LIBAFL_EXIT_START_PHYS(buf_paddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_START_PHYS, buf_paddr, 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_EXIT_INPUT_VIRT(buf_vaddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_INPUT_VIRT, buf_vaddr, 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_EXIT_INPUT_PHYS(buf_paddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_INPUT_PHYS, buf_paddr, 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_EXIT_END(status) _libafl_exit_call1(LIBAFL_EXIT_END, status) +#define LIBAFL_QEMU_END(status) _libafl_sync_exit_call1(LIBAFL_QEMU_COMMAND_END, status) -#define LIBAFL_EXIT_SAVE() _libafl_exit_call0(LIBAFL_EXIT_SAVE) +#define LIBAFL_QEMU_SAVE() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_SAVE) -#define LIBAFL_EXIT_LOAD() _libafl_exit_call0(LIBAFL_EXIT_LOAD) +#define LIBAFL_QEMU_LOAD() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_LOAD) -#define LIBAFL_EXIT_VERSION() _libafl_exit_call0(LIBAFL_EXIT_VERSION_NUMBER) +#define LIBAFL_QEMU_VERSION() _libafl_sync_exit_call0(LIBAFL_QEMU_COMMAND_VERSION) /* === The public part ends here === */ -#endif \ No newline at end of file +#endif diff --git a/libafl_qemu/runtime/libafl_qemu_windows.asm b/libafl_qemu/runtime/libafl_qemu_windows.asm new file mode 100755 index 0000000000..1b8163e887 --- /dev/null +++ b/libafl_qemu/runtime/libafl_qemu_windows.asm @@ -0,0 +1,115 @@ +; LibAFL QEMU Windows ASM companion file. It should be used together with libafl_qemu.h +; Since Windows does not support extended inline assembly, it is more convenient to use asm files directly. + +PUBLIC _libafl_sync_exit_call0, _libafl_sync_exit_call1, _libafl_sync_exit_call2 +PUBLIC _libafl_backdoor_call0, _libafl_backdoor_call1, _libafl_backdoor_call2 + +LIBAFL_SYNC_EXIT_OPCODE MACRO + dd 66f23a0fh +ENDM + +LIBAFL_BACKDOOR_OPCODE MACRO + dd 44f23a0fh +ENDM + +.code + +; Execute LibAFL sync exit (no argument) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +_libafl_sync_exit_call0: + mov rax, rcx + + LIBAFL_SYNC_EXIT_OPCODE + + ret + +; Execute LibAFL sync exit (one argument) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +; [RDX, IN] Arg1 +_libafl_sync_exit_call1: + push rdi + + mov rax, rcx + mov rdi, rdx + + LIBAFL_SYNC_EXIT_OPCODE + + pop rdi + + ret + +; Execute LibAFL sync exit (two arguments) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +; [RDX, IN] Arg1 +; [R8, IN] Arg2 +_libafl_sync_exit_call2: + push rdi + push rsi + + mov rax, rcx + mov rdi, rdx + mov rsi, r8 + + LIBAFL_SYNC_EXIT_OPCODE + + pop rsi + pop rdi + + ret + +; Execute LibAFL backdoor (no argument) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +_libafl_backdoor_call0: + mov rax, rcx + + LIBAFL_BACKDOOR_OPCODE + + ret + +; Execute LibAFL backdoor (one argument) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +; [RDX, IN] Arg1 +_libafl_backdoor_call1: + push rdi + + mov rax, rcx + mov rdi, rdx + + LIBAFL_BACKDOOR_OPCODE + + pop rdi + + ret + +; Execute LibAFL backdoor (two arguments) +; Parameters: +; [RAX, OUT] Hook return value +; [RCX, IN] LibAFL QEMU Command +; [RDX, IN] Arg1 +; [R8, IN] Arg2 +_libafl_backdoor_call2: + push rdi + push rsi + + mov rax, rcx + mov rdi, rdx + mov rsi, r8 + + LIBAFL_BACKDOOR_OPCODE + + pop rsi + pop rdi + + ret + +END diff --git a/libafl_qemu/src/command.rs b/libafl_qemu/src/command.rs index 9e70c0a46e..c3b4e46a82 100644 --- a/libafl_qemu/src/command.rs +++ b/libafl_qemu/src/command.rs @@ -21,7 +21,7 @@ use crate::{ StdEmuExitHandler, StdInstrumentationFilter, CPU, }; -pub const VERSION: u64 = bindings::LIBAFL_EXIT_VERSION_NUMBER as u64; +pub const VERSION: u64 = bindings::LIBAFL_QEMU_HDR_VERSION_NUMBER as u64; mod bindings { #![allow(non_upper_case_globals)] @@ -40,23 +40,24 @@ mod bindings { #[derive(Debug, Clone, TryFromPrimitive)] #[repr(u64)] pub enum NativeBackdoorCommand { - StartVirt = bindings::LibaflExit_LIBAFL_EXIT_START_VIRT.0 as u64, // Shortcut for Save + InputVirt - StartPhys = bindings::LibaflExit_LIBAFL_EXIT_START_PHYS.0 as u64, // Shortcut for Save + InputPhys - InputVirt = bindings::LibaflExit_LIBAFL_EXIT_INPUT_VIRT.0 as u64, // The address is a virtual address using the paging currently running in the VM. - InputPhys = bindings::LibaflExit_LIBAFL_EXIT_INPUT_PHYS.0 as u64, // The address is a physical address - End = bindings::LibaflExit_LIBAFL_EXIT_END.0 as u64, // Implies reloading of the target. The first argument gives the exit status. - Save = bindings::LibaflExit_LIBAFL_EXIT_SAVE.0 as u64, // Save the VM - Load = bindings::LibaflExit_LIBAFL_EXIT_LOAD.0 as u64, // Reload the target without ending the run? - Version = bindings::LibaflExit_LIBAFL_EXIT_VERSION.0 as u64, // Version of the bindings used in the target - VaddrFilterAllowRange = bindings::LibaflExit_LIBAFL_EXIT_VADDR_FILTER_ALLOW.0 as u64, // Allow given address range + StartVirt = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_START_VIRT.0 as u64, // Shortcut for Save + InputVirt + StartPhys = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_START_PHYS.0 as u64, // Shortcut for Save + InputPhys + InputVirt = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_INPUT_VIRT.0 as u64, // The address is a virtual address using the paging currently running in the VM. + InputPhys = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_INPUT_PHYS.0 as u64, // The address is a physical address + End = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_END.0 as u64, // Implies reloading of the target. The first argument gives the exit status. + Save = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_SAVE.0 as u64, // Save the VM + Load = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_LOAD.0 as u64, // Reload the target without ending the run? + Version = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_VERSION.0 as u64, // Version of the bindings used in the target + VaddrFilterAllowRange = + bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_VADDR_FILTER_ALLOW.0 as u64, // Allow given address range } #[derive(Debug, Clone, Enum, TryFromPrimitive)] #[repr(u64)] pub enum NativeExitKind { - Unknown = bindings::LibaflExitEndStatus_LIBAFL_EXIT_END_UNKNOWN.0 as u64, // Should not be used - Ok = bindings::LibaflExitEndStatus_LIBAFL_EXIT_END_OK.0 as u64, // Normal exit - Crash = bindings::LibaflExitEndStatus_LIBAFL_EXIT_END_CRASH.0 as u64, // Crash reported in the VM + Unknown = bindings::LibaflQemuEndStatus_LIBAFL_QEMU_END_UNKNOWN.0 as u64, // Should not be used + Ok = bindings::LibaflQemuEndStatus_LIBAFL_QEMU_END_OK.0 as u64, // Normal exit + Crash = bindings::LibaflQemuEndStatus_LIBAFL_QEMU_END_CRASH.0 as u64, // Crash reported in the VM } pub trait IsCommand