7 Commits

Author SHA1 Message Date
Duncan Ogilvie 0fc786f5f1 Merge pull request #22 from icicle-emu/uninitialized-memory
Map memory as initialized unless `track_uninitialized` is enabled
2024-12-28 10:28:04 +01:00
Duncan Ogilvie 583932dd33 Map memory as initialized unless track_uninitialized is enabled
Related to #9
2024-12-28 10:21:28 +01:00
Duncan Ogilvie ad481a2124 Minor code simplifications 2024-12-28 10:20:22 +01:00
Duncan Ogilvie aef686faa6 Merge pull request #20 from icicle-emu/x86-eflags-hook
X86 eflags hook
2024-12-27 17:15:26 +01:00
Duncan Ogilvie 556eb71fe7 Add custom register handler for eflags on x86
Closes #19
2024-12-27 16:24:51 +01:00
Duncan Ogilvie de16238d15 Add rust test for #19 2024-12-27 16:23:50 +01:00
Duncan Ogilvie 7a095640b4 Downgrade softprops/action-gh-release to v2.0.9
https://github.com/softprops/action-gh-release/issues/555
2024-12-27 15:49:20 +01:00
3 changed files with 89 additions and 12 deletions
+1 -1
View File
@@ -156,7 +156,7 @@ jobs:
packages-dir: dist/
- name: Release
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
with:
generate_release_notes: true
files: dist/*
+38 -11
View File
@@ -1,19 +1,35 @@
use std::borrow::Cow;
use std::collections::HashMap;
use icicle_cpu::mem::{Mapping, MemError, perm};
use icicle_cpu::{ExceptionCode, VmExit};
use icicle_cpu::{Cpu, ExceptionCode, ValueSource, VmExit};
use pyo3::prelude::*;
use icicle_vm;
use icicle_vm::linux::LinuxCpu;
use pyo3::exceptions::*;
use target_lexicon;
use indexmap::IndexMap;
use target_lexicon::Architecture;
use sleigh_runtime::NamedRegister;
// References:
// - https://pyo3.rs/main/conversions/tables
// - https://pyo3.rs/main/class
struct X86FlagsRegHandler {
pub eflags: pcode::VarNode,
}
impl icicle_cpu::RegHandler for X86FlagsRegHandler {
fn read(&mut self, cpu: &mut Cpu) {
let eflags = icicle_vm::x86::eflags(cpu);
cpu.write_var::<u32>(self.eflags, eflags);
}
fn write(&mut self, cpu: &mut Cpu) {
let eflags = cpu.read_var::<u32>(self.eflags);
icicle_vm::x86::set_eflags(cpu, eflags);
}
}
#[pyclass(eq, eq_int, module = "icicle")]
#[derive(Clone, Debug, PartialEq)]
pub enum MemoryProtection {
@@ -227,7 +243,7 @@ pub struct Icicle {
}
fn reg_find<'a>(i: &'a Icicle, name: &str) -> PyResult<&'a NamedRegister> {
let sleigh = i.vm.cpu.sleigh();
let sleigh = &i.vm.cpu.arch.sleigh;
match sleigh.get_reg(name) {
None => {
i.regs.get(name.to_lowercase().as_str())
@@ -253,7 +269,7 @@ impl Icicle {
#[getter]
pub fn get_icount(&mut self) -> u64 {
return self.vm.cpu.icount;
self.vm.cpu.icount
}
#[setter]
@@ -335,7 +351,7 @@ impl Icicle {
}
}
// Setup the CPU state for the target triple
// Set up the CPU state for the target triple
let mut config = icicle_vm::cpu::Config::from_target_triple(
format!("{architecture}-none").as_str()
);
@@ -354,19 +370,29 @@ impl Icicle {
config.optimize_instructions = optimize_instructions;
config.optimize_block = optimize_block;
let vm = icicle_vm::build(&config)
let mut vm = icicle_vm::build(&config)
.map_err(|e| {
PyException::new_err(format!("VM build error: {e}"))
})?;
// Populate the lowercase register map
let mut regs = HashMap::new();
let sleigh = vm.cpu.sleigh();
let sleigh = &vm.cpu.arch.sleigh;
for reg in &sleigh.named_registers {
let name = sleigh.get_str(reg.name);
regs.insert(name.to_lowercase(), reg.clone());
}
// Special handling for x86 flags
match config.triple.architecture {
Architecture::X86_32(_) | Architecture::X86_64 | Architecture::X86_64h => {
let eflags = sleigh.get_reg("eflags").unwrap().var;
let reg_handler = X86FlagsRegHandler { eflags };
vm.cpu.add_reg_handler(eflags.id, Box::new(reg_handler));
}
_ => {}
}
Ok(Icicle {
architecture,
vm,
@@ -385,8 +411,9 @@ impl Icicle {
}
pub fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> PyResult<()> {
let init_perm = if self.vm.cpu.mem.track_uninitialized { perm::NONE } else { perm::INIT };
let mapping = Mapping {
perm: convert_protection(protection),
perm: convert_protection(protection) | init_perm,
value: 0,
};
if self.vm.cpu.mem.map_memory_len(address, size, mapping) {
@@ -438,7 +465,7 @@ impl Icicle {
e,
)
})?;
return Ok(Cow::Owned(buffer));
Ok(Cow::Owned(buffer))
}
pub fn mem_write(&mut self, address: u64, data: Vec<u8>) -> PyResult<()> {
@@ -454,12 +481,12 @@ impl Icicle {
pub fn reg_list(&self) -> PyResult<IndexMap<String, (u32, u8)>> {
let mut result = IndexMap::new();
let sleigh = self.vm.cpu.sleigh();
let sleigh = &self.vm.cpu.arch.sleigh;
for reg in &sleigh.named_registers {
let name = sleigh.get_str(reg.name);
result.insert(name.to_string(), (reg.offset, reg.var.size));
}
return Ok(result);
Ok(result)
}
pub fn reg_offset(&self, name: &str) -> PyResult<u32> {
+50
View File
@@ -206,6 +206,55 @@ fn step_modify_rip() -> PyResult<()> {
Ok(())
}
fn eflags_reconstruction() -> PyResult<()> {
let mut vm = new_vm(false)?;
vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteRead)?;
vm.mem_write(0x100, b"\x48\x01\xD8".to_vec())?;
vm.reg_write("rax", 0x7FFFFFFFFFFFFFFF)?;
vm.reg_write("rbx", 0x1)?;
let of_mask = (1 << 11) as u64;
{
let eflags = vm.reg_read("eflags")?;
let of = vm.reg_read("OF")?;
let of_set = (eflags & of_mask) == of_mask;
println!("[pre] eflags: {:#x}, OF: {:#x} == {}", eflags, of, of_set);
}
vm.set_pc(0x100);
let status = vm.step(1);
println!("run status: {:?}", status);
{
let eflags = vm.reg_read("eflags")?;
let rflags = vm.reg_read("rflags")?;
let of = vm.reg_read("OF")?;
let of_set = (eflags & of_mask) == of_mask;
println!("[post] eflags: {:#x} == {:#x}, OF: {:#x} == {}", eflags, rflags, of, of_set);
}
{
vm.reg_write("OF", 0)?;
let eflags = vm.reg_read("eflags")?;
let of = vm.reg_read("OF")?;
let of_set = (eflags >> 11) & 1;
println!("[OF=0] eflags: {:#x}, OF: {:#x} == {}", eflags, of, of_set);
}
{
let mut eflags = vm.reg_read("eflags")?;
eflags |= of_mask;
vm.reg_write("rflags", eflags)?;
let of = vm.reg_read("OF")?;
let of_set = (eflags >> 11) & 1;
println!("[rflags|={:#x}] eflags: {:#x}, OF: {:#x} == {}", of_mask, eflags, of, of_set);
}
Ok(())
}
fn main() {
// Make sure the GHIDRA_SRC environment variable is valid
match std::env::var("GHIDRA_SRC") {
@@ -236,6 +285,7 @@ fn main() {
("Rewind", rewind),
("Execute only", execute_only),
("Step modify rip", step_modify_rip),
("EFlags reconstruction", eflags_reconstruction),
];
let mut success = 0;