Unify setting segment base

This commit is contained in:
momo5502
2025-03-29 08:04:56 +01:00
parent dec66f051d
commit af6492be6d
7 changed files with 102 additions and 30 deletions

View File

@@ -11,5 +11,8 @@ enum class x64_hookable_instructions
rdtscp,
};
using x64_emulator =
typed_emulator<uint64_t, x64_register, x64_register::rip, x64_register::rsp, x64_hookable_instructions>;
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;
};

View File

@@ -13,6 +13,7 @@ extern "C"
int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length);
size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length);
size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length);
void icicle_start(icicle_emulator*);
void icicle_destroy_emulator(icicle_emulator*);
}
@@ -57,12 +58,31 @@ namespace icicle
{
timeout = {};
}
icicle_start(this->emu_);
}
void stop() override
{
}
void set_segment_base(const x64_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);
break;
case x64_register::gs:
case x64_register::gs_base:
this->reg(x64_register::gs_base, value);
break;
default:
break;
}
}
size_t write_raw_register(const int reg, const void* value, const size_t size) override
{
return icicle_write_register(this->emu_, reg, value, size);

View File

@@ -46,6 +46,14 @@ impl IcicleEmulator {
return &mut self.vm.cpu.mem;
}
pub fn start(&mut self) {
self.vm.run();
}
pub fn stop(&mut self) {
//self.vm.stop();
}
pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP
| icicle_vm::cpu::mem::perm::INIT
@@ -608,8 +616,8 @@ struct X64RegisterNodes {
fptag: pcode::VarNode,
//msr: pcode::VarNode,
mxcsr: pcode::VarNode,
//fs_base: pcode::VarNode,
//gs_base: pcode::VarNode,
fs_base: pcode::VarNode,
gs_base: pcode::VarNode,
flags: pcode::VarNode,
rflags: pcode::VarNode,
fip: pcode::VarNode,
@@ -849,9 +857,9 @@ impl X64RegisterNodes {
fop: r("FPULastInstructionOpcode"),
/*fds: r("FDS"),
msr: r("MSR"),
fcs: r("FCS"),
fs_base: r("FSBASE"),
gs_base: r("GSBASE"),*/
fcs: r("FCS"),*/
fs_base: r("FS_OFFSET"),
gs_base: r("GS_OFFSET"),
}
}
@@ -1077,8 +1085,8 @@ impl X64RegisterNodes {
X64Register::Fptag => self.fptag,
//X64Register::Msr => self.msr,
X64Register::Mxcsr => self.mxcsr,
//X64Register::FsBase => self.fs_base,
//X64Register::GsBase => self.gs_base,
X64Register::FsBase => self.fs_base,
X64Register::GsBase => self.gs_base,
X64Register::Flags => self.flags,
X64Register::Rflags => self.rflags,
X64Register::Fip => self.fip,

View File

@@ -17,6 +17,14 @@ pub fn icicle_create_emulator() -> *mut c_void {
return Box::into_raw(emulator) as *mut c_void;
}
#[unsafe(no_mangle)]
pub fn icicle_start(ptr: *mut c_void) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
emulator.start();
}
}
#[unsafe(no_mangle)]
pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 {
unsafe {
@@ -45,7 +53,12 @@ pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permis
}
#[unsafe(no_mangle)]
pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, size: usize) -> i32 {
pub fn icicle_write_memory(
ptr: *mut c_void,
address: u64,
data: *const c_void,
size: usize,
) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
@@ -65,20 +78,30 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz
}
#[unsafe(no_mangle)]
pub fn icicle_read_register(ptr: *mut c_void, reg: X64Register, data: *mut c_void, size: usize) -> usize {
pub fn icicle_read_register(
ptr: *mut c_void,
reg: X64Register,
data: *mut c_void,
size: usize,
) -> usize {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size);
return emulator.read_register(reg, u8_slice);
return emulator.read_register(reg, u8_slice);
}
}
#[unsafe(no_mangle)]
pub fn icicle_write_register(ptr: *mut c_void, reg: X64Register, data: *const c_void, size: usize) -> usize {
pub fn icicle_write_register(
ptr: *mut c_void,
reg: X64Register,
data: *const c_void,
size: usize,
) -> usize {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
return emulator.write_register(reg, u8_slice);
return emulator.write_register(reg, u8_slice);
}
}

View File

@@ -302,6 +302,39 @@ namespace unicorn
uce(uc_emu_stop(*this));
}
void set_segment_base(const x64_register base, const pointer_type value) override
{
constexpr auto IA32_FS_BASE_MSR = 0xC0000100;
constexpr auto IA32_GS_BASE_MSR = 0xC0000101;
struct msr_value
{
uint32_t id;
uint64_t value;
};
msr_value msr_val{
.id = 0,
.value = value,
};
switch (base)
{
case x64_register::fs:
case x64_register::fs_base:
msr_val.id = IA32_FS_BASE_MSR;
break;
case x64_register::gs:
case x64_register::gs_base:
msr_val.id = IA32_GS_BASE_MSR;
break;
default:
return;
}
this->write_register(x64_register::msr, &msr_val, sizeof(msr_val));
}
size_t write_raw_register(const int reg, const void* value, const size_t size) override
{
auto result_size = size;

View File

@@ -28,19 +28,6 @@ namespace
emu.reg(x64_register::rsp, stack_end);
}
void setup_gs_segment(x64_emulator& emu, const emulator_allocator& allocator)
{
struct msr_value
{
uint32_t id;
uint64_t value;
};
const msr_value value{IA32_GS_BASE_MSR, allocator.get_base()};
emu.write_register(x64_register::msr, &value, sizeof(value));
}
bool is_object_signaled(process_context& c, const handle h, const uint32_t current_thread_id)
{
const auto type = h.value.type;
@@ -228,7 +215,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context&
}
setup_stack(emu, this->stack_base, this->stack_size);
setup_gs_segment(emu, *this->gs_segment);
emu.set_segment_base(x64_register::gs, this->gs_segment->get_base());
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;

View File

@@ -19,8 +19,6 @@
#define PEB_SEGMENT_SIZE (20 << 20) // 20 MB
#define GS_SEGMENT_SIZE (1 << 20) // 1 MB
#define IA32_GS_BASE_MSR 0xC0000101
#define STACK_SIZE 0x40000ULL
#define GDT_ADDR 0x30000