mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
prepare 32bit support with name and class inheritance modifications
This commit is contained in:
@@ -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];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
66
src/emulator/arch_emulator.hpp
Normal file
66
src/emulator/arch_emulator.hpp
Normal 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>;
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum class x64_register
|
||||
// x86_64 and x86_32 register definitions
|
||||
enum class x86_register
|
||||
{
|
||||
invalid = 0,
|
||||
ah,
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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, {});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "std_include.hpp"
|
||||
#include <serialization.hpp>
|
||||
|
||||
#include "x64_emulator.hpp"
|
||||
#include "arch_emulator.hpp"
|
||||
|
||||
#include <utils/time.hpp>
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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_{};
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user