prepare 32bit support with name and class inheritance modifications (#224)

an early merge of some initial preparations for 32bit emulation support.

some refactor of emulationlib and backends

* switch naming convention: arch_bitness (x86_xx / arm_xx)
* new arch_emulator.hpp header to easily create more explicit named
emulator types
This commit is contained in:
Maurice Heumann
2025-04-22 12:25:11 +02:00
committed by GitHub
31 changed files with 623 additions and 575 deletions

View File

@@ -204,7 +204,7 @@ impl ExecutionHooks {
pub struct IcicleEmulator {
executing_thread: std::thread::ThreadId,
vm: icicle_vm::Vm,
reg: registers::X64RegisterNodes,
reg: registers::X86RegisterNodes,
syscall_hooks: HookContainer<dyn Fn()>,
interrupt_hooks: HookContainer<dyn Fn(i32)>,
violation_hooks: HookContainer<dyn Fn(u64, u8, bool) -> bool>,
@@ -275,7 +275,7 @@ impl IcicleEmulator {
Self {
stop: stop_value,
executing_thread: std::thread::current().id(),
reg: registers::X64RegisterNodes::new(&virtual_machine.cpu.arch),
reg: registers::X86RegisterNodes::new(&virtual_machine.cpu.arch),
vm: virtual_machine,
syscall_hooks: HookContainer::new(),
interrupt_hooks: HookContainer::new(),
@@ -555,7 +555,7 @@ impl IcicleEmulator {
};
}
fn read_generic_register(&mut self, reg: registers::X64Register, buffer: &mut [u8]) -> usize {
fn read_generic_register(&mut self, reg: registers::X86Register, buffer: &mut [u8]) -> usize {
let reg_node = self.reg.get_node(reg);
let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node));
@@ -580,11 +580,11 @@ impl IcicleEmulator {
return limit;
}
pub fn read_register(&mut self, reg: registers::X64Register, data: &mut [u8]) -> usize {
pub fn read_register(&mut self, reg: registers::X86Register, data: &mut [u8]) -> usize {
match reg {
registers::X64Register::Rflags => self.read_flags::<u64>(data),
registers::X64Register::Eflags => self.read_flags::<u32>(data),
registers::X64Register::Flags => self.read_flags::<u16>(data),
registers::X86Register::Rflags => self.read_flags::<u64>(data),
registers::X86Register::Eflags => self.read_flags::<u32>(data),
registers::X86Register::Flags => self.read_flags::<u16>(data),
_ => self.read_generic_register(reg, data),
}
}
@@ -606,16 +606,16 @@ impl IcicleEmulator {
return limit;
}
pub fn write_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize {
pub fn write_register(&mut self, reg: registers::X86Register, data: &[u8]) -> usize {
match reg {
registers::X64Register::Rflags => self.write_flags::<u64>(data),
registers::X64Register::Eflags => self.write_flags::<u32>(data),
registers::X64Register::Flags => self.write_flags::<u16>(data),
registers::X86Register::Rflags => self.write_flags::<u64>(data),
registers::X86Register::Eflags => self.write_flags::<u32>(data),
registers::X86Register::Flags => self.write_flags::<u16>(data),
_ => self.write_generic_register(reg, data),
}
}
fn write_generic_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize {
fn write_generic_register(&mut self, reg: registers::X86Register, data: &[u8]) -> usize {
let reg_node = self.reg.get_node(reg);
let mut buffer = [0u8; 32];

View File

@@ -2,7 +2,7 @@ mod icicle;
mod registers;
use icicle::IcicleEmulator;
use registers::X64Register;
use registers::X86Register;
use std::os::raw::c_void;
fn to_cbool(value: bool) -> i32 {
@@ -252,7 +252,7 @@ pub fn icicle_remove_hook(ptr: *mut c_void, id: u32) {
#[unsafe(no_mangle)]
pub fn icicle_read_register(
ptr: *mut c_void,
reg: X64Register,
reg: X86Register,
data: *mut c_void,
size: usize,
) -> usize {
@@ -274,7 +274,7 @@ pub fn icicle_read_register(
#[unsafe(no_mangle)]
pub fn icicle_write_register(
ptr: *mut c_void,
reg: X64Register,
reg: X86Register,
data: *const c_void,
size: usize,
) -> usize {

View File

@@ -1,6 +1,6 @@
#[repr(i32)]
#[derive(PartialEq)]
pub enum X64Register {
pub enum X86Register {
Invalid = 0,
Ah,
Al,
@@ -244,7 +244,7 @@ pub enum X64Register {
}
#[derive(Clone)]
pub(crate) struct X64RegisterNodes {
pub(crate) struct X86RegisterNodes {
rax: pcode::VarNode,
rbx: pcode::VarNode,
rcx: pcode::VarNode,
@@ -474,7 +474,7 @@ pub(crate) struct X64RegisterNodes {
flags: Vec<pcode::VarNode>,
}
impl X64RegisterNodes {
impl X86RegisterNodes {
pub fn new(arch: &icicle_cpu::Arch) -> Self {
let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var;
let nodes = [
@@ -731,234 +731,234 @@ impl X64RegisterNodes {
}
}
pub fn get_node(&self, reg: X64Register) -> pcode::VarNode {
pub fn get_node(&self, reg: X86Register) -> pcode::VarNode {
match reg {
X64Register::Rax => self.rax,
X64Register::Rbx => self.rbx,
X64Register::Rcx => self.rcx,
X64Register::Rdx => self.rdx,
X64Register::Rsi => self.rsi,
X64Register::Rdi => self.rdi,
X64Register::Rbp => self.rbp,
X64Register::Rsp => self.rsp,
X64Register::R8 => self.r8,
X64Register::R9 => self.r9,
X64Register::R10 => self.r10,
X64Register::R11 => self.r11,
X64Register::R12 => self.r12,
X64Register::R13 => self.r13,
X64Register::R14 => self.r14,
X64Register::R15 => self.r15,
X64Register::Rip => self.rip,
X64Register::Cs => self.cs,
X64Register::Ds => self.ds,
X64Register::Es => self.es,
X64Register::Fs => self.fs,
X64Register::Gs => self.gs,
X64Register::Ss => self.ss,
X64Register::Ah => self.ah,
X64Register::Al => self.al,
X64Register::Ax => self.ax,
X64Register::Bh => self.bh,
X64Register::Bl => self.bl,
X64Register::Bpl => self.bpl,
X64Register::Ch => self.ch,
X64Register::Cl => self.cl,
X64Register::Cx => self.cx,
X64Register::Dh => self.dh,
X64Register::Dil => self.dil,
X64Register::Dl => self.dl,
X64Register::Dx => self.dx,
X64Register::Eax => self.eax,
X64Register::Ebp => self.ebp,
X64Register::Ebx => self.ebx,
X64Register::Ecx => self.ecx,
X64Register::Edi => self.edi,
X64Register::Edx => self.edx,
X64Register::Esi => self.esi,
X64Register::Esp => self.esp,
X64Register::Fpsw => self.fpsw,
X64Register::Gdtr => self.gdtr,
X64Register::Idtr => self.idtr,
X64Register::Ldtr => self.ldtr,
X64Register::Tr => self.tr,
X64Register::Cr0 => self.cr0,
X64Register::Cr1 => self.cr1,
X64Register::Cr2 => self.cr2,
X64Register::Cr3 => self.cr3,
X64Register::Cr4 => self.cr4,
X64Register::Cr8 => self.cr8,
X64Register::Dr0 => self.dr0,
X64Register::Dr1 => self.dr1,
X64Register::Dr2 => self.dr2,
X64Register::Dr3 => self.dr3,
X64Register::Dr4 => self.dr4,
X64Register::Dr5 => self.dr5,
X64Register::Dr6 => self.dr6,
X64Register::Dr7 => self.dr7,
X64Register::Fp0 => self.fp0,
X64Register::Fp1 => self.fp1,
X64Register::Fp2 => self.fp2,
X64Register::Fp3 => self.fp3,
X64Register::Fp4 => self.fp4,
X64Register::Fp5 => self.fp5,
X64Register::Fp6 => self.fp6,
X64Register::Fp7 => self.fp7,
/*X64Register::K0 => self.k0,
X64Register::K1 => self.k1,
X64Register::K2 => self.k2,
X64Register::K3 => self.k3,
X64Register::K4 => self.k4,
X64Register::K5 => self.k5,
X64Register::K6 => self.k6,
X64Register::K7 => self.k7,*/
X64Register::Mm0 => self.mm0,
X64Register::Mm1 => self.mm1,
X64Register::Mm2 => self.mm2,
X64Register::Mm3 => self.mm3,
X64Register::Mm4 => self.mm4,
X64Register::Mm5 => self.mm5,
X64Register::Mm6 => self.mm6,
X64Register::Mm7 => self.mm7,
X64Register::St0 => self.st0,
X64Register::St1 => self.st1,
X64Register::St2 => self.st2,
X64Register::St3 => self.st3,
X64Register::St4 => self.st4,
X64Register::St5 => self.st5,
X64Register::St6 => self.st6,
X64Register::St7 => self.st7,
X64Register::Xmm0 => self.xmm0,
X64Register::Xmm1 => self.xmm1,
X64Register::Xmm2 => self.xmm2,
X64Register::Xmm3 => self.xmm3,
X64Register::Xmm4 => self.xmm4,
X64Register::Xmm5 => self.xmm5,
X64Register::Xmm6 => self.xmm6,
X64Register::Xmm7 => self.xmm7,
X64Register::Xmm8 => self.xmm8,
X64Register::Xmm9 => self.xmm9,
X64Register::Xmm10 => self.xmm10,
X64Register::Xmm11 => self.xmm11,
X64Register::Xmm12 => self.xmm12,
X64Register::Xmm13 => self.xmm13,
X64Register::Xmm14 => self.xmm14,
X64Register::Xmm15 => self.xmm15,
/*X64Register::Xmm16 => self.xmm16,
X64Register::Xmm17 => self.xmm17,
X64Register::Xmm18 => self.xmm18,
X64Register::Xmm19 => self.xmm19,
X64Register::Xmm20 => self.xmm20,
X64Register::Xmm21 => self.xmm21,
X64Register::Xmm22 => self.xmm22,
X64Register::Xmm23 => self.xmm23,
X64Register::Xmm24 => self.xmm24,
X64Register::Xmm25 => self.xmm25,
X64Register::Xmm26 => self.xmm26,
X64Register::Xmm27 => self.xmm27,
X64Register::Xmm28 => self.xmm28,
X64Register::Xmm29 => self.xmm29,
X64Register::Xmm30 => self.xmm30,
X64Register::Xmm31 => self.xmm31,*/
X64Register::Ymm0 => self.ymm0,
X64Register::Ymm1 => self.ymm1,
X64Register::Ymm2 => self.ymm2,
X64Register::Ymm3 => self.ymm3,
X64Register::Ymm4 => self.ymm4,
X64Register::Ymm5 => self.ymm5,
X64Register::Ymm6 => self.ymm6,
X64Register::Ymm7 => self.ymm7,
X64Register::Ymm8 => self.ymm8,
X64Register::Ymm9 => self.ymm9,
X64Register::Ymm10 => self.ymm10,
X64Register::Ymm11 => self.ymm11,
X64Register::Ymm12 => self.ymm12,
X64Register::Ymm13 => self.ymm13,
X64Register::Ymm14 => self.ymm14,
X64Register::Ymm15 => self.ymm15,
/*X64Register::Ymm16 => self.ymm16,
X64Register::Ymm17 => self.ymm17,
X64Register::Ymm18 => self.ymm18,
X64Register::Ymm19 => self.ymm19,
X64Register::Ymm20 => self.ymm20,
X64Register::Ymm21 => self.ymm21,
X64Register::Ymm22 => self.ymm22,
X64Register::Ymm23 => self.ymm23,
X64Register::Ymm24 => self.ymm24,
X64Register::Ymm25 => self.ymm25,
X64Register::Ymm26 => self.ymm26,
X64Register::Ymm27 => self.ymm27,
X64Register::Ymm28 => self.ymm28,
X64Register::Ymm29 => self.ymm29,
X64Register::Ymm30 => self.ymm30,
X64Register::Ymm31 => self.ymm31,*/
/*X64Register::Zmm0 => self.zmm0,
X64Register::Zmm1 => self.zmm1,
X64Register::Zmm2 => self.zmm2,
X64Register::Zmm3 => self.zmm3,
X64Register::Zmm4 => self.zmm4,
X64Register::Zmm5 => self.zmm5,
X64Register::Zmm6 => self.zmm6,
X64Register::Zmm7 => self.zmm7,
X64Register::Zmm8 => self.zmm8,
X64Register::Zmm9 => self.zmm9,
X64Register::Zmm10 => self.zmm10,
X64Register::Zmm11 => self.zmm11,
X64Register::Zmm12 => self.zmm12,
X64Register::Zmm13 => self.zmm13,
X64Register::Zmm14 => self.zmm14,
X64Register::Zmm15 => self.zmm15,
X64Register::Zmm16 => self.zmm16,
X64Register::Zmm17 => self.zmm17,
X64Register::Zmm18 => self.zmm18,
X64Register::Zmm19 => self.zmm19,
X64Register::Zmm20 => self.zmm20,
X64Register::Zmm21 => self.zmm21,
X64Register::Zmm22 => self.zmm22,
X64Register::Zmm23 => self.zmm23,
X64Register::Zmm24 => self.zmm24,
X64Register::Zmm25 => self.zmm25,
X64Register::Zmm26 => self.zmm26,
X64Register::Zmm27 => self.zmm27,
X64Register::Zmm28 => self.zmm28,
X64Register::Zmm29 => self.zmm29,
X64Register::Zmm30 => self.zmm30,
X64Register::Zmm31 => self.zmm31,*/
X64Register::R8b => self.r8b,
X64Register::R9b => self.r9b,
X64Register::R10b => self.r10b,
X64Register::R11b => self.r11b,
X64Register::R12b => self.r12b,
X64Register::R13b => self.r13b,
X64Register::R14b => self.r14b,
X64Register::R15b => self.r15b,
X64Register::R8d => self.r8d,
X64Register::R9d => self.r9d,
X64Register::R10d => self.r10d,
X64Register::R11d => self.r11d,
X64Register::R12d => self.r12d,
X64Register::R13d => self.r13d,
X64Register::R14d => self.r14d,
X64Register::R15d => self.r15d,
X64Register::R8w => self.r8w,
X64Register::R9w => self.r9w,
X64Register::R10w => self.r10w,
X64Register::R11w => self.r11w,
X64Register::R12w => self.r12w,
X64Register::R13w => self.r13w,
X64Register::R14w => self.r14w,
X64Register::R15w => self.r15w,
X64Register::Fpcw => self.fpcw,
X64Register::Fptag => self.fptag,
//X64Register::Msr => self.msr,
X64Register::Mxcsr => self.mxcsr,
X64Register::FsBase => self.fs_base,
X64Register::GsBase => self.gs_base,
X64Register::Fip => self.fip,
X64Register::Fcs => self.fcs,
X64Register::Fdp => self.fdp,
X64Register::Fds => self.fds,
X64Register::Fop => self.fop,
X86Register::Rax => self.rax,
X86Register::Rbx => self.rbx,
X86Register::Rcx => self.rcx,
X86Register::Rdx => self.rdx,
X86Register::Rsi => self.rsi,
X86Register::Rdi => self.rdi,
X86Register::Rbp => self.rbp,
X86Register::Rsp => self.rsp,
X86Register::R8 => self.r8,
X86Register::R9 => self.r9,
X86Register::R10 => self.r10,
X86Register::R11 => self.r11,
X86Register::R12 => self.r12,
X86Register::R13 => self.r13,
X86Register::R14 => self.r14,
X86Register::R15 => self.r15,
X86Register::Rip => self.rip,
X86Register::Cs => self.cs,
X86Register::Ds => self.ds,
X86Register::Es => self.es,
X86Register::Fs => self.fs,
X86Register::Gs => self.gs,
X86Register::Ss => self.ss,
X86Register::Ah => self.ah,
X86Register::Al => self.al,
X86Register::Ax => self.ax,
X86Register::Bh => self.bh,
X86Register::Bl => self.bl,
X86Register::Bpl => self.bpl,
X86Register::Ch => self.ch,
X86Register::Cl => self.cl,
X86Register::Cx => self.cx,
X86Register::Dh => self.dh,
X86Register::Dil => self.dil,
X86Register::Dl => self.dl,
X86Register::Dx => self.dx,
X86Register::Eax => self.eax,
X86Register::Ebp => self.ebp,
X86Register::Ebx => self.ebx,
X86Register::Ecx => self.ecx,
X86Register::Edi => self.edi,
X86Register::Edx => self.edx,
X86Register::Esi => self.esi,
X86Register::Esp => self.esp,
X86Register::Fpsw => self.fpsw,
X86Register::Gdtr => self.gdtr,
X86Register::Idtr => self.idtr,
X86Register::Ldtr => self.ldtr,
X86Register::Tr => self.tr,
X86Register::Cr0 => self.cr0,
X86Register::Cr1 => self.cr1,
X86Register::Cr2 => self.cr2,
X86Register::Cr3 => self.cr3,
X86Register::Cr4 => self.cr4,
X86Register::Cr8 => self.cr8,
X86Register::Dr0 => self.dr0,
X86Register::Dr1 => self.dr1,
X86Register::Dr2 => self.dr2,
X86Register::Dr3 => self.dr3,
X86Register::Dr4 => self.dr4,
X86Register::Dr5 => self.dr5,
X86Register::Dr6 => self.dr6,
X86Register::Dr7 => self.dr7,
X86Register::Fp0 => self.fp0,
X86Register::Fp1 => self.fp1,
X86Register::Fp2 => self.fp2,
X86Register::Fp3 => self.fp3,
X86Register::Fp4 => self.fp4,
X86Register::Fp5 => self.fp5,
X86Register::Fp6 => self.fp6,
X86Register::Fp7 => self.fp7,
/*X86Register::K0 => self.k0,
X86Register::K1 => self.k1,
X86Register::K2 => self.k2,
X86Register::K3 => self.k3,
X86Register::K4 => self.k4,
X86Register::K5 => self.k5,
X86Register::K6 => self.k6,
X86Register::K7 => self.k7,*/
X86Register::Mm0 => self.mm0,
X86Register::Mm1 => self.mm1,
X86Register::Mm2 => self.mm2,
X86Register::Mm3 => self.mm3,
X86Register::Mm4 => self.mm4,
X86Register::Mm5 => self.mm5,
X86Register::Mm6 => self.mm6,
X86Register::Mm7 => self.mm7,
X86Register::St0 => self.st0,
X86Register::St1 => self.st1,
X86Register::St2 => self.st2,
X86Register::St3 => self.st3,
X86Register::St4 => self.st4,
X86Register::St5 => self.st5,
X86Register::St6 => self.st6,
X86Register::St7 => self.st7,
X86Register::Xmm0 => self.xmm0,
X86Register::Xmm1 => self.xmm1,
X86Register::Xmm2 => self.xmm2,
X86Register::Xmm3 => self.xmm3,
X86Register::Xmm4 => self.xmm4,
X86Register::Xmm5 => self.xmm5,
X86Register::Xmm6 => self.xmm6,
X86Register::Xmm7 => self.xmm7,
X86Register::Xmm8 => self.xmm8,
X86Register::Xmm9 => self.xmm9,
X86Register::Xmm10 => self.xmm10,
X86Register::Xmm11 => self.xmm11,
X86Register::Xmm12 => self.xmm12,
X86Register::Xmm13 => self.xmm13,
X86Register::Xmm14 => self.xmm14,
X86Register::Xmm15 => self.xmm15,
/*X86Register::Xmm16 => self.xmm16,
X86Register::Xmm17 => self.xmm17,
X86Register::Xmm18 => self.xmm18,
X86Register::Xmm19 => self.xmm19,
X86Register::Xmm20 => self.xmm20,
X86Register::Xmm21 => self.xmm21,
X86Register::Xmm22 => self.xmm22,
X86Register::Xmm23 => self.xmm23,
X86Register::Xmm24 => self.xmm24,
X86Register::Xmm25 => self.xmm25,
X86Register::Xmm26 => self.xmm26,
X86Register::Xmm27 => self.xmm27,
X86Register::Xmm28 => self.xmm28,
X86Register::Xmm29 => self.xmm29,
X86Register::Xmm30 => self.xmm30,
X86Register::Xmm31 => self.xmm31,*/
X86Register::Ymm0 => self.ymm0,
X86Register::Ymm1 => self.ymm1,
X86Register::Ymm2 => self.ymm2,
X86Register::Ymm3 => self.ymm3,
X86Register::Ymm4 => self.ymm4,
X86Register::Ymm5 => self.ymm5,
X86Register::Ymm6 => self.ymm6,
X86Register::Ymm7 => self.ymm7,
X86Register::Ymm8 => self.ymm8,
X86Register::Ymm9 => self.ymm9,
X86Register::Ymm10 => self.ymm10,
X86Register::Ymm11 => self.ymm11,
X86Register::Ymm12 => self.ymm12,
X86Register::Ymm13 => self.ymm13,
X86Register::Ymm14 => self.ymm14,
X86Register::Ymm15 => self.ymm15,
/*X86Register::Ymm16 => self.ymm16,
X86Register::Ymm17 => self.ymm17,
X86Register::Ymm18 => self.ymm18,
X86Register::Ymm19 => self.ymm19,
X86Register::Ymm20 => self.ymm20,
X86Register::Ymm21 => self.ymm21,
X86Register::Ymm22 => self.ymm22,
X86Register::Ymm23 => self.ymm23,
X86Register::Ymm24 => self.ymm24,
X86Register::Ymm25 => self.ymm25,
X86Register::Ymm26 => self.ymm26,
X86Register::Ymm27 => self.ymm27,
X86Register::Ymm28 => self.ymm28,
X86Register::Ymm29 => self.ymm29,
X86Register::Ymm30 => self.ymm30,
X86Register::Ymm31 => self.ymm31,*/
/*X86Register::Zmm0 => self.zmm0,
X86Register::Zmm1 => self.zmm1,
X86Register::Zmm2 => self.zmm2,
X86Register::Zmm3 => self.zmm3,
X86Register::Zmm4 => self.zmm4,
X86Register::Zmm5 => self.zmm5,
X86Register::Zmm6 => self.zmm6,
X86Register::Zmm7 => self.zmm7,
X86Register::Zmm8 => self.zmm8,
X86Register::Zmm9 => self.zmm9,
X86Register::Zmm10 => self.zmm10,
X86Register::Zmm11 => self.zmm11,
X86Register::Zmm12 => self.zmm12,
X86Register::Zmm13 => self.zmm13,
X86Register::Zmm14 => self.zmm14,
X86Register::Zmm15 => self.zmm15,
X86Register::Zmm16 => self.zmm16,
X86Register::Zmm17 => self.zmm17,
X86Register::Zmm18 => self.zmm18,
X86Register::Zmm19 => self.zmm19,
X86Register::Zmm20 => self.zmm20,
X86Register::Zmm21 => self.zmm21,
X86Register::Zmm22 => self.zmm22,
X86Register::Zmm23 => self.zmm23,
X86Register::Zmm24 => self.zmm24,
X86Register::Zmm25 => self.zmm25,
X86Register::Zmm26 => self.zmm26,
X86Register::Zmm27 => self.zmm27,
X86Register::Zmm28 => self.zmm28,
X86Register::Zmm29 => self.zmm29,
X86Register::Zmm30 => self.zmm30,
X86Register::Zmm31 => self.zmm31,*/
X86Register::R8b => self.r8b,
X86Register::R9b => self.r9b,
X86Register::R10b => self.r10b,
X86Register::R11b => self.r11b,
X86Register::R12b => self.r12b,
X86Register::R13b => self.r13b,
X86Register::R14b => self.r14b,
X86Register::R15b => self.r15b,
X86Register::R8d => self.r8d,
X86Register::R9d => self.r9d,
X86Register::R10d => self.r10d,
X86Register::R11d => self.r11d,
X86Register::R12d => self.r12d,
X86Register::R13d => self.r13d,
X86Register::R14d => self.r14d,
X86Register::R15d => self.r15d,
X86Register::R8w => self.r8w,
X86Register::R9w => self.r9w,
X86Register::R10w => self.r10w,
X86Register::R11w => self.r11w,
X86Register::R12w => self.r12w,
X86Register::R13w => self.r13w,
X86Register::R14w => self.r14w,
X86Register::R15w => self.r15w,
X86Register::Fpcw => self.fpcw,
X86Register::Fptag => self.fptag,
//X86Register::Msr => self.msr,
X86Register::Mxcsr => self.mxcsr,
X86Register::FsBase => self.fs_base,
X86Register::GsBase => self.gs_base,
X86Register::Fip => self.fip,
X86Register::Fcs => self.fcs,
X86Register::Fdp => self.fdp,
X86Register::Fds => self.fds,
X86Register::Fop => self.fop,
_ => panic!("Unsupported register"),
}
}

View File

@@ -1,5 +1,5 @@
#define ICICLE_EMULATOR_IMPL
#include "icicle_x64_emulator.hpp"
#include "icicle_x86_64_emulator.hpp"
#include <utils/object.hpp>
@@ -85,10 +85,10 @@ namespace icicle
}
}
class icicle_x64_emulator : public x64_emulator
class icicle_x86_64_emulator : public x86_64_emulator
{
public:
icicle_x64_emulator()
icicle_x86_64_emulator()
: emu_(icicle_create_emulator())
{
if (!this->emu_)
@@ -97,7 +97,7 @@ namespace icicle
}
}
~icicle_x64_emulator() override
~icicle_x86_64_emulator() override
{
if (this->emu_)
{
@@ -128,20 +128,20 @@ namespace icicle
const gdtr entry{.limit = limit, .address = address};
static_assert(sizeof(gdtr) - offsetof(gdtr, limit) == 12);
this->write_register(x64_register::gdtr, &entry.limit, 12);
this->write_register(x86_register::gdtr, &entry.limit, 12);
}
void set_segment_base(const x64_register base, const pointer_type value) override
void set_segment_base(const x86_register base, const pointer_type value) override
{
switch (base)
{
case x64_register::fs:
case x64_register::fs_base:
this->reg(x64_register::fs_base, value);
case x86_register::fs:
case x86_register::fs_base:
this->reg(x86_register::fs_base, value);
break;
case x64_register::gs:
case x64_register::gs_base:
this->reg(x64_register::gs_base, value);
case x86_register::gs:
case x86_register::gs_base:
this->reg(x86_register::gs_base, value);
break;
default:
break;
@@ -226,7 +226,7 @@ namespace icicle
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override
{
if (static_cast<x64_hookable_instructions>(instruction_type) != x64_hookable_instructions::syscall)
if (static_cast<x86_hookable_instructions>(instruction_type) != x86_hookable_instructions::syscall)
{
// TODO
return nullptr;
@@ -427,8 +427,8 @@ namespace icicle
icicle_emulator* emu_{};
};
std::unique_ptr<x64_emulator> create_x64_emulator()
std::unique_ptr<x86_64_emulator> create_x86_64_emulator()
{
return std::make_unique<icicle_x64_emulator>();
return std::make_unique<icicle_x86_64_emulator>();
}
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "platform/platform.hpp"
#ifdef ICICLE_EMULATOR_IMPL
@@ -15,5 +15,5 @@ namespace icicle
#if !MOMO_BUILD_AS_LIBRARY
ICICLE_EMULATOR_DLL_STORAGE
#endif
std::unique_ptr<x64_emulator> create_x64_emulator();
std::unique_ptr<x86_64_emulator> create_x86_64_emulator();
}

View File

@@ -1,5 +1,5 @@
#define UNICORN_EMULATOR_IMPL
#include "unicorn_x64_emulator.hpp"
#include "unicorn_x86_64_emulator.hpp"
#include <array>
@@ -18,19 +18,19 @@ namespace unicorn
static_assert(static_cast<uint32_t>(memory_permission::exec) == UC_PROT_EXEC);
static_assert(static_cast<uint32_t>(memory_permission::all) == UC_PROT_ALL);
static_assert(static_cast<uint32_t>(x64_register::end) == UC_X86_REG_ENDING);
static_assert(static_cast<uint32_t>(x86_register::end) == UC_X86_REG_ENDING);
uc_x86_insn map_hookable_instruction(const x64_hookable_instructions instruction)
uc_x86_insn map_hookable_instruction(const x86_hookable_instructions instruction)
{
switch (instruction)
{
case x64_hookable_instructions::syscall:
case x86_hookable_instructions::syscall:
return UC_X86_INS_SYSCALL;
case x64_hookable_instructions::cpuid:
case x86_hookable_instructions::cpuid:
return UC_X86_INS_CPUID;
case x64_hookable_instructions::rdtsc:
case x86_hookable_instructions::rdtsc:
return UC_X86_INS_RDTSC;
case x64_hookable_instructions::rdtscp:
case x86_hookable_instructions::rdtscp:
return UC_X86_INS_RDTSCP;
default:
throw std::runtime_error("Bad instruction for mapping");
@@ -195,10 +195,10 @@ namespace unicorn
}
}
class unicorn_x64_emulator : public x64_emulator
class unicorn_x86_64_emulator : public x86_64_emulator
{
public:
unicorn_x64_emulator()
unicorn_x86_64_emulator()
{
uce(uc_open(UC_ARCH_X86, UC_MODE_64, &this->uc_));
uce(uc_ctl_set_cpu_model(this->uc_, UC_CPU_X86_EPYC_ROME));
@@ -215,7 +215,7 @@ namespace unicorn
#endif
}
~unicorn_x64_emulator() override
~unicorn_x86_64_emulator() override
{
this->hooks_.clear();
uc_close(this->uc_);
@@ -254,10 +254,10 @@ namespace unicorn
void load_gdt(const pointer_type address, const uint32_t limit) override
{
const std::array<uint64_t, 4> gdtr = {0, address, limit, 0};
this->write_register(x64_register::gdtr, gdtr.data(), gdtr.size() * sizeof(uint64_t));
this->write_register(x86_register::gdtr, gdtr.data(), gdtr.size() * sizeof(uint64_t));
}
void set_segment_base(const x64_register base, const pointer_type value) override
void set_segment_base(const x86_register base, const pointer_type value) override
{
constexpr auto IA32_FS_BASE_MSR = 0xC0000100;
constexpr auto IA32_GS_BASE_MSR = 0xC0000101;
@@ -275,19 +275,19 @@ namespace unicorn
switch (base)
{
case x64_register::fs:
case x64_register::fs_base:
case x86_register::fs:
case x86_register::fs_base:
msr_val.id = IA32_FS_BASE_MSR;
break;
case x64_register::gs:
case x64_register::gs_base:
case x86_register::gs:
case x86_register::gs_base:
msr_val.id = IA32_GS_BASE_MSR;
break;
default:
return;
}
this->write_register(x64_register::msr, &msr_val, sizeof(msr_val));
this->write_register(x86_register::msr, &msr_val, sizeof(msr_val));
}
size_t write_raw_register(const int reg, const void* value, const size_t size) override
@@ -388,9 +388,9 @@ namespace unicorn
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
const auto inst_type = static_cast<x64_hookable_instructions>(instruction_type);
const auto inst_type = static_cast<x86_hookable_instructions>(instruction_type);
if (inst_type == x64_hookable_instructions::invalid)
if (inst_type == x86_hookable_instructions::invalid)
{
function_wrapper<int, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) {
return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0;
@@ -400,7 +400,7 @@ namespace unicorn
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
}
else if (inst_type == x64_hookable_instructions::syscall)
else if (inst_type == x86_hookable_instructions::syscall)
{
function_wrapper<void, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) { c(); });
@@ -708,8 +708,8 @@ namespace unicorn
};
}
std::unique_ptr<x64_emulator> create_x64_emulator()
std::unique_ptr<x86_64_emulator> create_x86_64_emulator()
{
return std::make_unique<unicorn_x64_emulator>();
return std::make_unique<unicorn_x86_64_emulator>();
}
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "platform/platform.hpp"
#ifdef UNICORN_EMULATOR_IMPL
@@ -15,5 +15,5 @@ namespace unicorn
#if !MOMO_BUILD_AS_LIBRARY
UNICORN_EMULATOR_DLL_STORAGE
#endif
std::unique_ptr<x64_emulator> create_x64_emulator();
std::unique_ptr<x86_64_emulator> create_x86_64_emulator();
}

View File

@@ -0,0 +1,66 @@
/*
Design notes:
1. emulator: the root interface (provides CPU, memory, and hook interfaces).
2. typed_emulator<Traits>: a template that adapts to architecture/bitness via the Traits struct.
3. arch_emulator<Traits>: a thin layer for architecture-specific logic, things that are shared by all x86 (32/64), or
all ARM (32/64), etc.
X. x86_emulator<Traits>: x86_emulator<Traits> are specialisations for
x86 and ARM, parameterised by their respective traits (e.g., x86_64_traits) and stuff :)
1. emulator (cpu_interface, memory_interface, hook_interface)
2. └── typed_emulator<address_t, register_t, ...>
3. └── arch_emulator<arch_traits>
├── x86_emulator<x86_32_traits>
├── x86_emulator<x86_64_traits>
├── arm_emulator<arm_32_traits>
└── arm_emulator<arm_64_traits>
*/
#pragma once
#include "typed_emulator.hpp"
#include "x86_register.hpp"
// --[Core]--------------------------------------------------------------------------
template <typename Traits>
struct arch_emulator : typed_emulator<Traits>
{
};
template <typename Traits>
struct x86_emulator : arch_emulator<Traits>
{
using register_type = typename Traits::register_type;
using pointer_type = typename Traits::pointer_type;
virtual void set_segment_base(register_type base, pointer_type value) = 0;
virtual void load_gdt(pointer_type address, uint32_t limit) = 0;
};
template <typename Traits>
struct arm_emulator : arch_emulator<Traits>
{
};
enum class x86_hookable_instructions
{
invalid,
syscall,
cpuid,
rdtsc,
rdtscp,
};
// --[x86_64]-------------------------------------------------------------------------
struct x86_64_traits
{
using pointer_type = uint64_t;
using register_type = x86_register;
static constexpr register_type instruction_pointer = x86_register::rip;
static constexpr register_type stack_pointer = x86_register::rsp;
using hookable_instructions = x86_hookable_instructions;
};
using x86_64_emulator = x86_emulator<x86_64_traits>;

View File

@@ -2,18 +2,17 @@
#include "emulator.hpp"
template <typename PointerType, typename Register, Register InstructionPointer, Register StackPointer,
typename HookableInstructions>
template <typename Traits>
class typed_emulator : public emulator
{
public:
using registers = Register;
using pointer_type = PointerType;
using hookable_instructions = HookableInstructions;
using registers = typename Traits::register_type;
using pointer_type = typename Traits::pointer_type;
using hookable_instructions = typename Traits::hookable_instructions;
static constexpr size_t pointer_size = sizeof(pointer_type);
static constexpr registers stack_pointer = StackPointer;
static constexpr registers instruction_pointer = InstructionPointer;
static constexpr registers stack_pointer = Traits::stack_pointer;
static constexpr registers instruction_pointer = Traits::instruction_pointer;
size_t write_register(registers reg, const void* value, const size_t size)
{

View File

@@ -1,19 +0,0 @@
#pragma once
#include "typed_emulator.hpp"
#include "x64_register.hpp"
enum class x64_hookable_instructions
{
invalid,
syscall,
cpuid,
rdtsc,
rdtscp,
};
struct x64_emulator
: typed_emulator<uint64_t, x64_register, x64_register::rip, x64_register::rsp, x64_hookable_instructions>
{
virtual void set_segment_base(x64_register base, pointer_type value) = 0;
virtual void load_gdt(pointer_type address, uint32_t limit) = 0;
};

View File

@@ -1,6 +1,7 @@
#pragma once
enum class x64_register
// x86_64 and x86_32 register definitions
enum class x86_register
{
invalid = 0,
ah,

View File

@@ -89,8 +89,8 @@ namespace
memory_permission::read_write);
emu.emu().write_memory(memory, data.data(), data.size());
emu.emu().reg(x64_register::rcx, memory);
emu.emu().reg<uint64_t>(x64_register::rdx, data.size());
emu.emu().reg(x86_register::rcx, memory);
emu.emu().reg<uint64_t>(x86_register::rdx, data.size());
try
{

View File

@@ -5,7 +5,7 @@
#include "../emulator_utils.hpp"
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <utils/io.hpp>
#include <utils/compression.hpp>
@@ -14,7 +14,7 @@ namespace apiset
{
namespace
{
uint64_t copy_string(x64_emulator& emu, emulator_allocator& allocator, const void* base_ptr,
uint64_t copy_string(x86_64_emulator& emu, emulator_allocator& allocator, const void* base_ptr,
const uint64_t offset, const size_t length)
{
if (!length)
@@ -29,7 +29,7 @@ namespace apiset
return str_obj;
}
ULONG copy_string_as_relative(x64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
ULONG copy_string_as_relative(x86_64_emulator& emu, emulator_allocator& allocator, const uint64_t result_base,
const void* base_ptr, const uint64_t offset, const size_t length)
{
const auto address = copy_string(emu, allocator, base_ptr, offset, length);
@@ -115,13 +115,13 @@ namespace apiset
return obtain(apiset_loc, root);
}
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const container& container)
{
return clone(emu, allocator, container.get());
}
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const API_SET_NAMESPACE& orig_api_set_map)
{
const auto api_set_map_obj = allocator.reserve<API_SET_NAMESPACE>();

View File

@@ -29,9 +29,9 @@ namespace apiset
container obtain(location location, const std::filesystem::path& root);
container obtain(const std::filesystem::path& root);
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const API_SET_NAMESPACE& orig_api_set_map);
emulator_object<API_SET_NAMESPACE> clone(x64_emulator& emu, emulator_allocator& allocator,
emulator_object<API_SET_NAMESPACE> clone(x86_64_emulator& emu, emulator_allocator& allocator,
const container& container);
}

View File

@@ -3,147 +3,147 @@
namespace cpu_context
{
void restore(x64_emulator& emu, const CONTEXT64& context)
void restore(x86_64_emulator& emu, const CONTEXT64& context)
{
if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) == CONTEXT_DEBUG_REGISTERS_64)
{
emu.reg(x64_register::dr0, context.Dr0);
emu.reg(x64_register::dr1, context.Dr1);
emu.reg(x64_register::dr2, context.Dr2);
emu.reg(x64_register::dr3, context.Dr3);
emu.reg(x64_register::dr6, context.Dr6);
emu.reg(x64_register::dr7, context.Dr7);
emu.reg(x86_register::dr0, context.Dr0);
emu.reg(x86_register::dr1, context.Dr1);
emu.reg(x86_register::dr2, context.Dr2);
emu.reg(x86_register::dr3, context.Dr3);
emu.reg(x86_register::dr6, context.Dr6);
emu.reg(x86_register::dr7, context.Dr7);
}
if ((context.ContextFlags & CONTEXT_CONTROL_64) == CONTEXT_CONTROL_64)
{
emu.reg<uint16_t>(x64_register::ss, context.SegSs);
emu.reg<uint16_t>(x64_register::cs, context.SegCs);
emu.reg<uint16_t>(x86_register::ss, context.SegSs);
emu.reg<uint16_t>(x86_register::cs, context.SegCs);
emu.reg(x64_register::rip, context.Rip);
emu.reg(x64_register::rsp, context.Rsp);
emu.reg(x86_register::rip, context.Rip);
emu.reg(x86_register::rsp, context.Rsp);
emu.reg<uint32_t>(x64_register::eflags, context.EFlags);
emu.reg<uint32_t>(x86_register::eflags, context.EFlags);
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
emu.reg(x64_register::rax, context.Rax);
emu.reg(x64_register::rbx, context.Rbx);
emu.reg(x64_register::rcx, context.Rcx);
emu.reg(x64_register::rdx, context.Rdx);
emu.reg(x64_register::rbp, context.Rbp);
emu.reg(x64_register::rsi, context.Rsi);
emu.reg(x64_register::rdi, context.Rdi);
emu.reg(x64_register::r8, context.R8);
emu.reg(x64_register::r9, context.R9);
emu.reg(x64_register::r10, context.R10);
emu.reg(x64_register::r11, context.R11);
emu.reg(x64_register::r12, context.R12);
emu.reg(x64_register::r13, context.R13);
emu.reg(x64_register::r14, context.R14);
emu.reg(x64_register::r15, context.R15);
emu.reg(x86_register::rax, context.Rax);
emu.reg(x86_register::rbx, context.Rbx);
emu.reg(x86_register::rcx, context.Rcx);
emu.reg(x86_register::rdx, context.Rdx);
emu.reg(x86_register::rbp, context.Rbp);
emu.reg(x86_register::rsi, context.Rsi);
emu.reg(x86_register::rdi, context.Rdi);
emu.reg(x86_register::r8, context.R8);
emu.reg(x86_register::r9, context.R9);
emu.reg(x86_register::r10, context.R10);
emu.reg(x86_register::r11, context.R11);
emu.reg(x86_register::r12, context.R12);
emu.reg(x86_register::r13, context.R13);
emu.reg(x86_register::r14, context.R14);
emu.reg(x86_register::r15, context.R15);
}
/*if ((context.ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
emu.reg<uint16_t>(x64_register::ds, context.SegDs);
emu.reg<uint16_t>(x64_register::es, context.SegEs);
emu.reg<uint16_t>(x64_register::fs, context.SegFs);
emu.reg<uint16_t>(x64_register::gs, context.SegGs);
emu.reg<uint16_t>(x86_register::ds, context.SegDs);
emu.reg<uint16_t>(x86_register::es, context.SegEs);
emu.reg<uint16_t>(x86_register::fs, context.SegFs);
emu.reg<uint16_t>(x86_register::gs, context.SegGs);
}*/
if ((context.ContextFlags & CONTEXT_FLOATING_POINT_64) == CONTEXT_FLOATING_POINT_64)
{
emu.reg<uint16_t>(x64_register::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x64_register::fpsw, context.FltSave.StatusWord);
emu.reg<uint16_t>(x64_register::fptag, context.FltSave.TagWord);
emu.reg<uint16_t>(x86_register::fpcw, context.FltSave.ControlWord);
emu.reg<uint16_t>(x86_register::fpsw, context.FltSave.StatusWord);
emu.reg<uint16_t>(x86_register::fptag, context.FltSave.TagWord);
for (int i = 0; i < 8; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::st0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::st0) + i);
emu.reg<M128A>(reg, context.FltSave.FloatRegisters[i]);
}
}
if ((context.ContextFlags & CONTEXT_XSTATE_64) == CONTEXT_XSTATE_64)
{
emu.reg<uint32_t>(x64_register::mxcsr, context.MxCsr);
emu.reg<uint32_t>(x86_register::mxcsr, context.MxCsr);
for (int i = 0; i < 16; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::xmm0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::xmm0) + i);
emu.reg<M128A>(reg, (&context.Xmm0)[i]);
}
}
}
void save(x64_emulator& emu, CONTEXT64& context)
void save(x86_64_emulator& emu, CONTEXT64& context)
{
if ((context.ContextFlags & CONTEXT_DEBUG_REGISTERS_64) == CONTEXT_DEBUG_REGISTERS_64)
{
context.Dr0 = emu.reg(x64_register::dr0);
context.Dr1 = emu.reg(x64_register::dr1);
context.Dr2 = emu.reg(x64_register::dr2);
context.Dr3 = emu.reg(x64_register::dr3);
context.Dr6 = emu.reg(x64_register::dr6);
context.Dr7 = emu.reg(x64_register::dr7);
context.Dr0 = emu.reg(x86_register::dr0);
context.Dr1 = emu.reg(x86_register::dr1);
context.Dr2 = emu.reg(x86_register::dr2);
context.Dr3 = emu.reg(x86_register::dr3);
context.Dr6 = emu.reg(x86_register::dr6);
context.Dr7 = emu.reg(x86_register::dr7);
}
if ((context.ContextFlags & CONTEXT_CONTROL_64) == CONTEXT_CONTROL_64)
{
context.SegSs = emu.reg<uint16_t>(x64_register::ss);
context.SegCs = emu.reg<uint16_t>(x64_register::cs);
context.Rip = emu.reg(x64_register::rip);
context.Rsp = emu.reg(x64_register::rsp);
context.EFlags = emu.reg<uint32_t>(x64_register::eflags);
context.SegSs = emu.reg<uint16_t>(x86_register::ss);
context.SegCs = emu.reg<uint16_t>(x86_register::cs);
context.Rip = emu.reg(x86_register::rip);
context.Rsp = emu.reg(x86_register::rsp);
context.EFlags = emu.reg<uint32_t>(x86_register::eflags);
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
context.Rax = emu.reg(x64_register::rax);
context.Rbx = emu.reg(x64_register::rbx);
context.Rcx = emu.reg(x64_register::rcx);
context.Rdx = emu.reg(x64_register::rdx);
context.Rbp = emu.reg(x64_register::rbp);
context.Rsi = emu.reg(x64_register::rsi);
context.Rdi = emu.reg(x64_register::rdi);
context.R8 = emu.reg(x64_register::r8);
context.R9 = emu.reg(x64_register::r9);
context.R10 = emu.reg(x64_register::r10);
context.R11 = emu.reg(x64_register::r11);
context.R12 = emu.reg(x64_register::r12);
context.R13 = emu.reg(x64_register::r13);
context.R14 = emu.reg(x64_register::r14);
context.R15 = emu.reg(x64_register::r15);
context.Rax = emu.reg(x86_register::rax);
context.Rbx = emu.reg(x86_register::rbx);
context.Rcx = emu.reg(x86_register::rcx);
context.Rdx = emu.reg(x86_register::rdx);
context.Rbp = emu.reg(x86_register::rbp);
context.Rsi = emu.reg(x86_register::rsi);
context.Rdi = emu.reg(x86_register::rdi);
context.R8 = emu.reg(x86_register::r8);
context.R9 = emu.reg(x86_register::r9);
context.R10 = emu.reg(x86_register::r10);
context.R11 = emu.reg(x86_register::r11);
context.R12 = emu.reg(x86_register::r12);
context.R13 = emu.reg(x86_register::r13);
context.R14 = emu.reg(x86_register::r14);
context.R15 = emu.reg(x86_register::r15);
}
if ((context.ContextFlags & CONTEXT_SEGMENTS_64) == CONTEXT_SEGMENTS_64)
{
context.SegDs = emu.reg<uint16_t>(x64_register::ds);
context.SegEs = emu.reg<uint16_t>(x64_register::es);
context.SegFs = emu.reg<uint16_t>(x64_register::fs);
context.SegGs = emu.reg<uint16_t>(x64_register::gs);
context.SegDs = emu.reg<uint16_t>(x86_register::ds);
context.SegEs = emu.reg<uint16_t>(x86_register::es);
context.SegFs = emu.reg<uint16_t>(x86_register::fs);
context.SegGs = emu.reg<uint16_t>(x86_register::gs);
}
if ((context.ContextFlags & CONTEXT_FLOATING_POINT_64) == CONTEXT_FLOATING_POINT_64)
{
context.FltSave.ControlWord = emu.reg<uint16_t>(x64_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x64_register::fpsw);
context.FltSave.TagWord = static_cast<BYTE>(emu.reg<uint16_t>(x64_register::fptag));
context.FltSave.ControlWord = emu.reg<uint16_t>(x86_register::fpcw);
context.FltSave.StatusWord = emu.reg<uint16_t>(x86_register::fpsw);
context.FltSave.TagWord = static_cast<BYTE>(emu.reg<uint16_t>(x86_register::fptag));
for (int i = 0; i < 8; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::st0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::st0) + i);
context.FltSave.FloatRegisters[i] = emu.reg<M128A>(reg);
}
}
if ((context.ContextFlags & CONTEXT_INTEGER_64) == CONTEXT_INTEGER_64)
{
context.MxCsr = emu.reg<uint32_t>(x64_register::mxcsr);
context.MxCsr = emu.reg<uint32_t>(x86_register::mxcsr);
for (int i = 0; i < 16; i++)
{
const auto reg = static_cast<x64_register>(static_cast<int>(x64_register::xmm0) + i);
const auto reg = static_cast<x86_register>(static_cast<int>(x86_register::xmm0) + i);
(&context.Xmm0)[i] = emu.reg<M128A>(reg);
}
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "x64_emulator.hpp"
#include "arch_emulator.hpp"
namespace cpu_context
{
void save(x64_emulator& emu, CONTEXT64& context);
void restore(x64_emulator& emu, const CONTEXT64& context);
void save(x86_64_emulator& emu, CONTEXT64& context);
void restore(x86_64_emulator& emu, const CONTEXT64& context);
}

View File

@@ -7,25 +7,26 @@
namespace
{
template <typename T>
emulator_object<T> allocate_object_on_stack(x64_emulator& emu)
emulator_object<T> allocate_object_on_stack(x86_64_emulator& emu)
{
const auto old_sp = emu.reg(x64_register::rsp);
const auto new_sp = align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x64_emulator::pointer_type)));
emu.reg(x64_register::rsp, new_sp);
const auto old_sp = emu.reg(x86_register::rsp);
const auto new_sp =
align_down(old_sp - sizeof(T), std::max(alignof(T), alignof(x86_64_emulator::pointer_type)));
emu.reg(x86_register::rsp, new_sp);
return {emu, new_sp};
}
void unalign_stack(x64_emulator& emu)
void unalign_stack(x86_64_emulator& emu)
{
auto sp = emu.reg(x64_register::rsp);
auto sp = emu.reg(x86_register::rsp);
sp = align_down(sp - 0x10, 0x10) + 8;
emu.reg(x64_register::rsp, sp);
emu.reg(x86_register::rsp, sp);
}
void setup_stack(x64_emulator& emu, const uint64_t stack_base, const size_t stack_size)
void setup_stack(x86_64_emulator& emu, const uint64_t stack_base, const size_t stack_size)
{
const uint64_t stack_end = stack_base + stack_size;
emu.reg(x64_register::rsp, stack_end);
emu.reg(x86_register::rsp, stack_end);
}
bool is_object_signaled(process_context& c, const handle h, const uint32_t current_thread_id)
@@ -207,7 +208,7 @@ bool emulator_thread::is_thread_ready(process_context& process, utils::clock& cl
return true;
}
void emulator_thread::setup_registers(x64_emulator& emu, const process_context& context) const
void emulator_thread::setup_registers(x86_64_emulator& emu, const process_context& context) const
{
if (!this->gs_segment)
{
@@ -215,7 +216,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
}
setup_stack(emu, this->stack_base, static_cast<size_t>(this->stack_size));
emu.set_segment_base(x64_register::gs, this->gs_segment->get_base());
emu.set_segment_base(x86_register::gs, this->gs_segment->get_base());
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
@@ -232,7 +233,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
unalign_stack(emu);
emu.reg(x64_register::rcx, ctx_obj.value());
emu.reg(x64_register::rdx, context.ntdll_image_base);
emu.reg(x64_register::rip, context.ldr_initialize_thunk);
emu.reg(x86_register::rcx, ctx_obj.value());
emu.reg(x86_register::rdx, context.ntdll_image_base);
emu.reg(x86_register::rip, context.ldr_initialize_thunk);
}

View File

@@ -105,17 +105,17 @@ class emulator_thread : public ref_counted_object
bool is_thread_ready(process_context& process, utils::clock& clock);
void save(x64_emulator& emu)
void save(x86_64_emulator& emu)
{
this->last_registers = emu.save_registers();
}
void restore(x64_emulator& emu) const
void restore(x86_64_emulator& emu) const
{
emu.restore_registers(this->last_registers);
}
void setup_if_necessary(x64_emulator& emu, const process_context& context)
void setup_if_necessary(x86_64_emulator& emu, const process_context& context)
{
if (!this->executed_instructions)
{
@@ -127,7 +127,7 @@ class emulator_thread : public ref_counted_object
const auto status = *this->pending_status;
this->pending_status = {};
emu.reg<uint64_t>(x64_register::rax, static_cast<uint64_t>(status));
emu.reg<uint64_t>(x86_register::rax, static_cast<uint64_t>(status));
}
}
@@ -211,7 +211,7 @@ class emulator_thread : public ref_counted_object
}
private:
void setup_registers(x64_emulator& emu, const process_context& context) const;
void setup_registers(x86_64_emulator& emu, const process_context& context) const;
void release()
{

View File

@@ -1,6 +1,6 @@
#pragma once
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "memory_manager.hpp"
#include "memory_utils.hpp"
@@ -51,7 +51,7 @@ class module_manager;
struct process_context;
using clock_wrapper = object_wrapper<utils::clock>;
using x64_emulator_wrapper = object_wrapper<x64_emulator>;
using x64_emulator_wrapper = object_wrapper<x86_64_emulator>;
using memory_manager_wrapper = object_wrapper<memory_manager>;
using module_manager_wrapper = object_wrapper<module_manager>;
using process_context_wrapper = object_wrapper<process_context>;

View File

@@ -89,7 +89,7 @@ namespace
uint64_t ss;
};
void dispatch_exception_pointers(x64_emulator& emu, const uint64_t dispatcher,
void dispatch_exception_pointers(x86_64_emulator& emu, const uint64_t dispatcher,
const EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers)
{
constexpr auto mach_frame_size = 0x40;
@@ -102,7 +102,7 @@ namespace
const auto allocation_size = combined_size + mach_frame_size;
const auto initial_sp = emu.reg(x64_register::rsp);
const auto initial_sp = emu.reg(x86_register::rsp);
const auto new_sp = align_down(initial_sp - allocation_size, 0x100);
const auto total_size = initial_sp - new_sp;
@@ -113,8 +113,8 @@ namespace
emu.write_memory(new_sp, zero_memory.data(), zero_memory.size());
emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, dispatcher);
emu.reg(x86_register::rsp, new_sp);
emu.reg(x86_register::rip, dispatcher);
const emulator_object<CONTEXT64> context_record_obj{emu, new_sp};
context_record_obj.write(*reinterpret_cast<CONTEXT64*>(pointers.ContextRecord));
@@ -140,7 +140,7 @@ namespace
}
}
void dispatch_exception(x64_emulator& emu, const process_context& proc, const DWORD status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const DWORD status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
CONTEXT64 ctx{};
@@ -172,7 +172,7 @@ void dispatch_exception(x64_emulator& emu, const process_context& proc, const DW
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
}
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, const uint64_t address,
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, const uint64_t address,
const memory_operation operation)
{
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
@@ -182,22 +182,22 @@ void dispatch_access_violation(x64_emulator& emu, const process_context& proc, c
});
}
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc)
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
}
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc)
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {});
}
void dispatch_single_step(x64_emulator& emu, const process_context& proc)
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_SINGLE_STEP, {});
}
void dispatch_breakpoint(x64_emulator& emu, const process_context& proc)
void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_BREAKPOINT, {});
}

View File

@@ -1,25 +1,25 @@
#pragma once
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <platform/traits.hpp>
#include <platform/primitives.hpp>
struct process_context;
void dispatch_exception(x64_emulator& emu, const process_context& proc, DWORD status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, DWORD status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters);
template <typename T>
requires(std::is_integral_v<T> && !std::is_same_v<T, DWORD>)
void dispatch_exception(x64_emulator& emu, const process_context& proc, const T status,
void dispatch_exception(x86_64_emulator& emu, const process_context& proc, const T status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
dispatch_exception(emu, proc, static_cast<DWORD>(status), parameters);
}
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, uint64_t address,
void dispatch_access_violation(x86_64_emulator& emu, const process_context& proc, uint64_t address,
memory_operation operation);
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc);
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc);
void dispatch_single_step(x64_emulator& emu, const process_context& proc);
void dispatch_breakpoint(x64_emulator& emu, const process_context& proc);
void dispatch_illegal_instruction_violation(x86_64_emulator& emu, const process_context& proc);
void dispatch_integer_division_by_zero(x86_64_emulator& emu, const process_context& proc);
void dispatch_single_step(x86_64_emulator& emu, const process_context& proc);
void dispatch_breakpoint(x86_64_emulator& emu, const process_context& proc);

View File

@@ -1,7 +1,7 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <serialization.hpp>
#include "emulator_utils.hpp"
@@ -22,7 +22,7 @@ struct io_device_context
emulator_pointer output_buffer{};
ULONG output_buffer_length{};
io_device_context(x64_emulator& emu)
io_device_context(x86_64_emulator& emu)
: io_status_block(emu)
{
}

View File

@@ -3,7 +3,7 @@
#include "std_include.hpp"
#include <serialization.hpp>
#include "x64_emulator.hpp"
#include "arch_emulator.hpp"
#include <utils/time.hpp>

View File

@@ -14,20 +14,20 @@ namespace
return emulator_allocator{memory, base, size};
}
void setup_gdt(x64_emulator& emu, memory_manager& memory)
void setup_gdt(x86_64_emulator& emu, memory_manager& memory)
{
memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read);
emu.load_gdt(GDT_ADDR, GDT_LIMIT);
emu.write_memory<uint64_t>(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF);
emu.reg<uint16_t>(x64_register::cs, 0x33);
emu.reg<uint16_t>(x86_register::cs, 0x33);
emu.write_memory<uint64_t>(GDT_ADDR + 5 * (sizeof(uint64_t)), 0xEFF6000000FFFF);
emu.reg<uint16_t>(x64_register::ss, 0x2B);
emu.reg<uint16_t>(x86_register::ss, 0x2B);
}
}
void process_context::setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
void process_context::setup(x86_64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
const mapped_module& executable, const mapped_module& ntdll,
const apiset::container& apiset_container)
{

View File

@@ -7,7 +7,7 @@
#include "module/module_manager.hpp"
#include <utils/nt_handle.hpp>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include "io_device.hpp"
#include "kusd_mmio.hpp"
@@ -50,7 +50,7 @@ struct process_context
atom_entry() = default;
};
process_context(x64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
process_context(x86_64_emulator& emu, memory_manager& memory, utils::clock& clock, callbacks& cb)
: callbacks_(&cb),
base_allocator(emu),
peb(emu),
@@ -59,7 +59,7 @@ struct process_context
{
}
void setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
void setup(x86_64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container);
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,

View File

@@ -65,7 +65,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
auto& context = win_emu.process;
const auto address = emu.read_instruction_pointer();
const auto syscall_id = emu.reg<uint32_t>(x64_register::eax);
const auto syscall_id = emu.reg<uint32_t>(x86_register::eax);
const syscall_context c{
.win_emu = win_emu,
@@ -82,7 +82,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
if (entry == this->handlers_.end())
{
win_emu.log.error("Unknown syscall: 0x%X\n", syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.reg<uint64_t>(x86_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
}
@@ -97,7 +97,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
if (!entry->second.handler)
{
win_emu.log.error("Unimplemented syscall: %s - 0x%X\n", entry->second.name.c_str(), syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.reg<uint64_t>(x86_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
}
@@ -139,13 +139,13 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
catch (std::exception& e)
{
win_emu.log.error("Syscall threw an exception: %X (0x%" PRIx64 ") - %s\n", syscall_id, address, e.what());
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.reg<uint64_t>(x86_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}
catch (...)
{
win_emu.log.error("Syscall threw an unknown exception: %X (0x%" PRIx64 ")\n", syscall_id, address);
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.reg<uint64_t>(x86_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}
}

View File

@@ -7,24 +7,24 @@
struct syscall_context
{
windows_emulator& win_emu;
x64_emulator& emu;
x86_64_emulator& emu;
process_context& proc;
mutable bool write_status{true};
mutable bool retrigger_syscall{false};
};
inline uint64_t get_syscall_argument(x64_emulator& emu, const size_t index)
inline uint64_t get_syscall_argument(x86_64_emulator& emu, const size_t index)
{
switch (index)
{
case 0:
return emu.reg(x64_register::r10);
return emu.reg(x86_register::r10);
case 1:
return emu.reg(x64_register::rdx);
return emu.reg(x86_register::rdx);
case 2:
return emu.reg(x64_register::r8);
return emu.reg(x86_register::r8);
case 3:
return emu.reg(x64_register::r9);
return emu.reg(x86_register::r9);
default:
return emu.read_stack(index + 1);
}
@@ -110,7 +110,7 @@ inline void map_syscalls(std::map<uint64_t, syscall_handler_entry>& handlers, st
template <typename T>
requires(std::is_integral_v<T> || std::is_enum_v<T>)
T resolve_argument(x64_emulator& emu, const size_t index)
T resolve_argument(x86_64_emulator& emu, const size_t index)
{
const auto arg = get_syscall_argument(emu, index);
return static_cast<T>(arg);
@@ -118,7 +118,7 @@ T resolve_argument(x64_emulator& emu, const size_t index)
template <typename T>
requires(std::is_same_v<std::remove_cvref_t<T>, handle>)
handle resolve_argument(x64_emulator& emu, const size_t index)
handle resolve_argument(x86_64_emulator& emu, const size_t index)
{
handle h{};
h.bits = resolve_argument<uint64_t>(emu, index);
@@ -127,14 +127,14 @@ handle resolve_argument(x64_emulator& emu, const size_t index)
template <typename T>
requires(std::is_same_v<T, emulator_object<typename T::value_type>>)
T resolve_argument(x64_emulator& emu, const size_t index)
T resolve_argument(x86_64_emulator& emu, const size_t index)
{
const auto arg = get_syscall_argument(emu, index);
return T(emu, arg);
}
template <typename T>
T resolve_indexed_argument(x64_emulator& emu, size_t& index)
T resolve_indexed_argument(x86_64_emulator& emu, size_t& index)
{
return resolve_argument<T>(emu, index++);
}
@@ -143,13 +143,13 @@ inline void write_syscall_status(const syscall_context& c, const NTSTATUS status
{
if (c.write_status && !c.retrigger_syscall)
{
c.emu.reg<uint64_t>(x64_register::rax, static_cast<uint64_t>(status));
c.emu.reg<uint64_t>(x86_register::rax, static_cast<uint64_t>(status));
}
const auto new_ip = c.emu.read_instruction_pointer();
if (initial_ip != new_ip || c.retrigger_syscall)
{
c.emu.reg(x64_register::rip, new_ip - 2);
c.emu.reg(x86_register::rip, new_ip - 2);
}
}
@@ -197,7 +197,7 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE<Traits>& attribute, const
}
template <typename ResponseType, typename Action, typename ReturnLengthSetter>
NTSTATUS handle_query_internal(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const ReturnLengthSetter& return_length_setter, const Action& action)
{
constexpr auto required_size = sizeof(ResponseType);
@@ -217,7 +217,7 @@ NTSTATUS handle_query_internal(x64_emulator& emu, const uint64_t buffer, const u
}
template <typename ResponseType, typename Action>
NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const emulator_object<uint32_t> return_length, const Action& action)
{
const auto length_setter = [&](const uint32_t required_size) {
@@ -231,7 +231,7 @@ NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t l
}
template <typename ResponseType, typename Action>
NTSTATUS handle_query(x64_emulator& emu, const uint64_t buffer, const uint32_t length,
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
const Action& action)
{

View File

@@ -3,10 +3,10 @@
#include "cpu_context.hpp"
#include <unicorn_x64_emulator.hpp>
#include <unicorn_x86_64_emulator.hpp>
#if MOMO_ENABLE_RUST_CODE
#include <icicle_x64_emulator.hpp>
#include <icicle_x86_64_emulator.hpp>
#endif
#include <utils/io.hpp>
@@ -117,13 +117,13 @@ namespace
ctx.ContextFlags = CONTEXT64_ALL;
cpu_context::save(emu, ctx);
const auto initial_sp = emu.reg(x64_register::rsp);
const auto initial_sp = emu.reg(x86_register::rsp);
const auto new_sp = align_down(initial_sp - sizeof(stack_layout), 0x100);
emu.write_memory(new_sp, stack_layout);
emu.reg(x64_register::rsp, new_sp);
emu.reg(x64_register::rip, win_emu.process.ki_user_apc_dispatcher);
emu.reg(x86_register::rsp, new_sp);
emu.reg(x86_register::rip, win_emu.process.ki_user_apc_dispatcher);
}
bool switch_to_thread(windows_emulator& win_emu, emulator_thread& thread, const bool force = false)
@@ -267,22 +267,22 @@ namespace
}
}
std::unique_ptr<x64_emulator> create_default_x64_emulator()
std::unique_ptr<x86_64_emulator> create_default_x86_64_emulator()
{
#if MOMO_ENABLE_RUST_CODE
const auto* env = getenv("EMULATOR_ICICLE");
if (env && (env == "1"sv || env == "true"sv))
{
return icicle::create_x64_emulator();
return icicle::create_x86_64_emulator();
}
#endif
return unicorn::create_x64_emulator();
return unicorn::create_x86_64_emulator();
}
windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings,
emulator_callbacks callbacks, emulator_interfaces interfaces,
std::unique_ptr<x64_emulator> emu)
std::unique_ptr<x86_64_emulator> emu)
: windows_emulator(settings, std::move(callbacks), std::move(interfaces), std::move(emu))
{
fixup_application_settings(app_settings);
@@ -290,7 +290,7 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul
}
windows_emulator::windows_emulator(const emulator_settings& settings, emulator_callbacks callbacks,
emulator_interfaces interfaces, std::unique_ptr<x64_emulator> emu)
emulator_interfaces interfaces, std::unique_ptr<x86_64_emulator> emu)
: emu_(std::move(emu)),
clock_(get_clock(interfaces, this->executed_instructions_, settings.use_relative_time)),
socket_factory_(get_socket_factory(interfaces)),
@@ -485,26 +485,26 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
log.print(color::gray,
"Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64
" - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n",
address, emu.reg(x64_register::rax), emu.reg(x64_register::rbx), emu.reg(x64_register::rcx),
emu.reg(x64_register::rdx), emu.reg(x64_register::r8), emu.reg(x64_register::r9),
emu.reg(x64_register::rdi), emu.reg(x64_register::rsi), binary ? binary->name.c_str() : "<N/A>");
address, emu.reg(x86_register::rax), emu.reg(x86_register::rbx), emu.reg(x86_register::rcx),
emu.reg(x86_register::rdx), emu.reg(x86_register::r8), emu.reg(x86_register::r9),
emu.reg(x86_register::rdi), emu.reg(x86_register::rsi), binary ? binary->name.c_str() : "<N/A>");
}
void windows_emulator::setup_hooks()
{
this->emu().hook_instruction(x64_hookable_instructions::syscall, [&] {
this->emu().hook_instruction(x86_hookable_instructions::syscall, [&] {
this->dispatcher.dispatch(*this);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] {
this->emu().hook_instruction(x86_hookable_instructions::rdtsc, [&] {
const auto ticks = this->clock_->timestamp_counter();
this->emu().reg(x64_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x64_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&] {
this->emu().hook_instruction(x86_hookable_instructions::invalid, [&] {
const auto ip = this->emu().read_instruction_pointer();
this->log.print(color::gray, "Invalid instruction at: 0x%" PRIx64 " (via 0x%" PRIx64 ")\n", ip,

View File

@@ -1,7 +1,7 @@
#pragma once
#include "std_include.hpp"
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <utils/function.hpp>
@@ -13,11 +13,11 @@
#include "module/module_manager.hpp"
#include "network/socket_factory.hpp"
std::unique_ptr<x64_emulator> create_default_x64_emulator();
std::unique_ptr<x86_64_emulator> create_default_x86_64_emulator();
struct emulator_callbacks : module_manager::callbacks, process_context::callbacks
{
utils::optional_function<instruction_hook_continuation(uint32_t syscall_id, x64_emulator::pointer_type address,
utils::optional_function<instruction_hook_continuation(uint32_t syscall_id, x86_64_emulator::pointer_type address,
std::string_view mod_name, std::string_view syscall_name)>
on_syscall{};
@@ -57,7 +57,7 @@ class windows_emulator
{
uint64_t executed_instructions_{0};
std::unique_ptr<x64_emulator> emu_{};
std::unique_ptr<x86_64_emulator> emu_{};
std::unique_ptr<utils::clock> clock_{};
std::unique_ptr<network::socket_factory> socket_factory_{};
@@ -74,10 +74,10 @@ class windows_emulator
windows_emulator(const emulator_settings& settings = {}, emulator_callbacks callbacks = {},
emulator_interfaces interfaces = {},
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
std::unique_ptr<x86_64_emulator> emu = create_default_x86_64_emulator());
windows_emulator(application_settings app_settings, const emulator_settings& settings = {},
emulator_callbacks callbacks = {}, emulator_interfaces interfaces = {},
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
std::unique_ptr<x86_64_emulator> emu = create_default_x86_64_emulator());
windows_emulator(windows_emulator&&) = delete;
windows_emulator(const windows_emulator&) = delete;
@@ -86,12 +86,12 @@ class windows_emulator
~windows_emulator();
x64_emulator& emu()
x86_64_emulator& emu()
{
return *this->emu_;
}
const x64_emulator& emu() const
const x86_64_emulator& emu() const
{
return *this->emu_;
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <gdb_stub.hpp>
#include <scoped_hook.hpp>
#include <x64_emulator.hpp>
#include <arch_emulator.hpp>
#include <utils/concurrency.hpp>
@@ -33,7 +33,7 @@ struct std::hash<breakpoint_key>
class x64_gdb_stub_handler : public gdb_stub::debugging_handler
{
public:
x64_gdb_stub_handler(x64_emulator& emu)
x64_gdb_stub_handler(x86_64_emulator& emu)
: emu_(&emu)
{
}
@@ -238,7 +238,7 @@ class x64_gdb_stub_handler : public gdb_stub::debugging_handler
}
private:
x64_emulator* emu_{};
x86_64_emulator* emu_{};
using hook_map = std::unordered_map<breakpoint_key, scoped_hook>;
utils::concurrency::container<hook_map> hooks_{};

View File

@@ -1,15 +1,15 @@
#pragma once
#include <cstddef>
#include <optional>
#include <x64_register.hpp>
#include <x86_register.hpp>
struct register_entry
{
x64_register reg;
x86_register reg;
std::optional<size_t> expected_size;
std::optional<size_t> offset;
register_entry(const x64_register reg = x64_register::invalid,
register_entry(const x86_register reg = x86_register::invalid,
const std::optional<size_t> expected_size = std::nullopt,
const std::optional<size_t> offset = std::nullopt)
: reg(reg),
@@ -20,83 +20,83 @@ struct register_entry
};
inline std::vector<register_entry> gdb_registers{
x64_register::rax,
x64_register::rbx,
x64_register::rcx,
x64_register::rdx,
x64_register::rsi,
x64_register::rdi,
x64_register::rbp,
x64_register::rsp,
x64_register::r8,
x64_register::r9,
x64_register::r10,
x64_register::r11,
x64_register::r12,
x64_register::r13,
x64_register::r14,
x64_register::r15,
x64_register::rip,
x64_register::eflags,
x86_register::rax,
x86_register::rbx,
x86_register::rcx,
x86_register::rdx,
x86_register::rsi,
x86_register::rdi,
x86_register::rbp,
x86_register::rsp,
x86_register::r8,
x86_register::r9,
x86_register::r10,
x86_register::r11,
x86_register::r12,
x86_register::r13,
x86_register::r14,
x86_register::r15,
x86_register::rip,
x86_register::eflags,
{x64_register::cs, 4},
{x64_register::ss, 4},
{x64_register::ds, 4},
{x64_register::es, 4},
{x64_register::fs, 4},
{x64_register::gs, 4},
{x86_register::cs, 4},
{x86_register::ss, 4},
{x86_register::ds, 4},
{x86_register::es, 4},
{x86_register::fs, 4},
{x86_register::gs, 4},
x64_register::st0,
x64_register::st1,
x64_register::st2,
x64_register::st3,
x64_register::st4,
x64_register::st5,
x64_register::st6,
x64_register::st7,
x86_register::st0,
x86_register::st1,
x86_register::st2,
x86_register::st3,
x86_register::st4,
x86_register::st5,
x86_register::st6,
x86_register::st7,
{x64_register::fpcw, 4}, // fctrl
{x64_register::fpsw, 4}, // fstat
{x64_register::fptag, 4}, // ftag
{x64_register::fcs, 4}, // fiseg
{x64_register::fip, 4}, // fioff
{x64_register::fds, 4}, // foseg
{x64_register::fdp, 4}, // fooff
{x64_register::fop, 4}, // fop
{x86_register::fpcw, 4}, // fctrl
{x86_register::fpsw, 4}, // fstat
{x86_register::fptag, 4}, // ftag
{x86_register::fcs, 4}, // fiseg
{x86_register::fip, 4}, // fioff
{x86_register::fds, 4}, // foseg
{x86_register::fdp, 4}, // fooff
{x86_register::fop, 4}, // fop
x64_register::xmm0,
x64_register::xmm1,
x64_register::xmm2,
x64_register::xmm3,
x64_register::xmm4,
x64_register::xmm5,
x64_register::xmm6,
x64_register::xmm7,
x64_register::xmm8,
x64_register::xmm9,
x64_register::xmm10,
x64_register::xmm11,
x64_register::xmm12,
x64_register::xmm13,
x64_register::xmm14,
x64_register::xmm15,
x64_register::mxcsr,
x64_register::fs_base,
x64_register::gs_base,
{x64_register::ymm0, 16, 16},
{x64_register::ymm1, 16, 16},
{x64_register::ymm2, 16, 16},
{x64_register::ymm3, 16, 16},
{x64_register::ymm4, 16, 16},
{x64_register::ymm5, 16, 16},
{x64_register::ymm6, 16, 16},
{x64_register::ymm7, 16, 16},
{x64_register::ymm8, 16, 16},
{x64_register::ymm9, 16, 16},
{x64_register::ymm10, 16, 16},
{x64_register::ymm11, 16, 16},
{x64_register::ymm12, 16, 16},
{x64_register::ymm13, 16, 16},
{x64_register::ymm14, 16, 16},
{x64_register::ymm15, 16, 16},
x86_register::xmm0,
x86_register::xmm1,
x86_register::xmm2,
x86_register::xmm3,
x86_register::xmm4,
x86_register::xmm5,
x86_register::xmm6,
x86_register::xmm7,
x86_register::xmm8,
x86_register::xmm9,
x86_register::xmm10,
x86_register::xmm11,
x86_register::xmm12,
x86_register::xmm13,
x86_register::xmm14,
x86_register::xmm15,
x86_register::mxcsr,
x86_register::fs_base,
x86_register::gs_base,
{x86_register::ymm0, 16, 16},
{x86_register::ymm1, 16, 16},
{x86_register::ymm2, 16, 16},
{x86_register::ymm3, 16, 16},
{x86_register::ymm4, 16, 16},
{x86_register::ymm5, 16, 16},
{x86_register::ymm6, 16, 16},
{x86_register::ymm7, 16, 16},
{x86_register::ymm8, 16, 16},
{x86_register::ymm9, 16, 16},
{x86_register::ymm10, 16, 16},
{x86_register::ymm11, 16, 16},
{x86_register::ymm12, 16, 16},
{x86_register::ymm13, 16, 16},
{x86_register::ymm14, 16, 16},
{x86_register::ymm15, 16, 16},
};