Icicle progress

This commit is contained in:
Maurice Heumann
2025-03-27 15:50:33 +01:00
committed by momo5502
parent 985dd49059
commit 63f54df78c
4 changed files with 286 additions and 56 deletions

65
src/icicle/src/icicle.rs Normal file
View File

@@ -0,0 +1,65 @@
fn create_x64_vm() -> icicle_vm::Vm {
let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none");
let vm = icicle_vm::build(&cpu_config).unwrap();
return vm;
}
fn map_permissions(foreign_permissions: u8) -> u8 {
const FOREIGN_READ: u8 = 1 << 0;
const FOREIGN_WRITE: u8 = 1 << 1;
const FOREIGN_EXEC: u8 = 1 << 2;
let mut permissions: u8 = 0;
if (foreign_permissions & FOREIGN_READ) != 0 {
permissions |= icicle_vm::cpu::mem::perm::READ;
}
if (foreign_permissions & FOREIGN_WRITE) != 0 {
permissions |= icicle_vm::cpu::mem::perm::WRITE;
}
if (foreign_permissions & FOREIGN_EXEC) != 0 {
permissions |= icicle_vm::cpu::mem::perm::EXEC;
}
return permissions;
}
pub struct IcicleEmulator {
vm: icicle_vm::Vm,
}
impl IcicleEmulator {
pub fn new() -> Self {
Self {
vm: create_x64_vm(),
}
}
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
| icicle_vm::cpu::mem::perm::IN_CODE_CACHE;
let native_permissions = map_permissions(permissions);
let mapping = icicle_vm::cpu::mem::Mapping {
perm: native_permissions | MAPPING_PERMISSIONS,
value: 0x0,
};
let layout = icicle_vm::cpu::mem::AllocLayout {
addr: Some(address),
size: length,
align: 0x1000,
};
let res = self.vm.cpu.mem.alloc_memory(layout, mapping);
return res.is_ok();
}
pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool {
return self.vm.cpu.mem.unmap_memory_len(address, length);
}
}

View File

@@ -1,58 +1,54 @@
mod icicle;
use icicle::IcicleEmulator;
use std::os::raw::c_void;
#[unsafe(no_mangle)]
pub fn test_rust() {
// Setup the CPU state for the target triple
let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none");
let mut vm = icicle_vm::build(&cpu_config).unwrap();
// Setup an environment to run inside of.
//let mut env = icicle_vm::env::build_auto(&mut vm).unwrap();
// Load a binary into the environment.
//env.load(&mut vm.cpu, b"./test.elf").unwrap();
//vm.env = env;
let mapping = icicle_vm::cpu::mem::Mapping { perm: icicle_vm::cpu::mem::perm::ALL, value: 0x0 };
let alloc1 =
vm.cpu.mem.alloc_memory(icicle_vm::cpu::mem::AllocLayout { addr: Some(0x10000), size: 0x100, align: 0x100 }, mapping).unwrap();
// Add instrumentation
let counter = vm.cpu.trace.register_store(vec![0_u64]);
vm.add_injector(BlockCounter { counter });
// Run until the VM exits.
let exit = vm.run();
println!("{exit:?}\n{}", icicle_vm::debug::current_disasm(&mut vm));
// Read instrumentation data.
let blocks_hit = vm.cpu.trace[counter].as_any().downcast_ref::<Vec<u64>>().unwrap()[0];
let blocks_executed = blocks_hit.saturating_sub(1);
println!("{blocks_executed} blocks were executed");
pub fn icicle_create_emulator() -> *mut c_void {
let emulator = Box::new(IcicleEmulator::new());
return Box::into_raw(emulator) as *mut c_void;
}
struct BlockCounter {
counter: icicle_vm::cpu::StoreRef,
#[unsafe(no_mangle)]
pub fn icicle_map_memory(
ptr: *mut c_void,
address: u64,
length: u64,
permissions: u8,
) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let res = emulator.map_memory(address, length, permissions);
if res {
return 1;
}
return 0;
}
}
impl icicle_vm::CodeInjector for BlockCounter {
fn inject(
&mut self,
_cpu: &mut icicle_vm::cpu::Cpu,
group: &icicle_vm::cpu::BlockGroup,
code: &mut icicle_vm::BlockTable,
) {
let store_id = self.counter.get_store_id();
for block in &mut code.blocks[group.range()] {
// counter += 1
let counter = block.pcode.alloc_tmp(8);
let instrumentation = [
(counter, pcode::Op::Load(store_id), 0_u64).into(),
(counter, pcode::Op::IntAdd, (counter, 1_u64)).into(),
(pcode::Op::Store(store_id), (0_u64, counter)).into(),
];
#[unsafe(no_mangle)]
pub fn icicle_unmap_memory(ptr: *mut c_void, address: u64, length: u64) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let res = emulator.unmap_memory(address, length);
// Inject the instrumentation at the start of the block.
block.pcode.instructions.splice(..0, instrumentation);
}
}
}
if res {
return 1;
}
return 0;
}
}
#[unsafe(no_mangle)]
pub fn icicle_destroy_emulator(ptr: *mut c_void) {
if ptr.is_null() {
return;
}
unsafe {
let _ = Box::from_raw(ptr as *mut IcicleEmulator);
}
}