Fix of libafl qemu runtime files (#1996)

* Change naming and fix LibAFLQEMU header file. Fix and document LibAFL QEMU Windows ASM file.

* fmt
This commit is contained in:
Romain Malmain 2024-04-03 11:57:48 +02:00 committed by GitHub
parent d90d232e7a
commit 50be2f4aaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 179 additions and 127 deletions

View File

@ -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

View File

@ -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 <stdint.h>
#include <stdint.h>
typedef uint64_t libafl_word;
#ifdef __x86_64__
typedef uint64_t libafl_word;
#define LIBAFL_CALLING_CONVENTION __attribute__(())
#endif
#ifdef __arm__
#include <stdint.h>
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,27 +188,27 @@ 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 === */

View File

@ -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

View File

@ -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<QT, S, E>