diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9f7a53c..6c27052 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] + target: [x86_64, aarch64] steps: - uses: actions/checkout@v3 with: @@ -48,7 +48,7 @@ jobs: runs-on: windows-latest strategy: matrix: - target: [x64, x86] + target: [x64] steps: - uses: actions/checkout@v3 with: diff --git a/Cargo.lock b/Cargo.lock index 767a0cd..447eaff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,12 +240,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "flate2" version = "1.0.26" @@ -356,7 +350,7 @@ dependencies = [ ] [[package]] -name = "icicle-unicorn" +name = "icicle-python" version = "0.1.0" dependencies = [ "icicle-cpu", @@ -541,16 +535,6 @@ dependencies = [ name = "pcode" version = "0.2.0" -[[package]] -name = "petgraph" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" -dependencies = [ - "fixedbitset", - "indexmap", -] - [[package]] name = "pin-project-lite" version = "0.2.9" @@ -738,7 +722,6 @@ name = "sleigh-compile" version = "0.3.0" dependencies = [ "pcode", - "petgraph", "sleigh-parse", "sleigh-runtime", ] diff --git a/Cargo.toml b/Cargo.toml index bff6094..5417341 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [package] -name = "icicle-unicorn" +name = "icicle-python" version = "0.1.0" edition = "2021" diff --git a/README.md b/README.md index 810c79c..1a97897 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# icicle-unicorn +# icicle-python -This project is an attempt to replace unicorn with a wrapper around [icicle-emu](https://github.com/icicle-emu/icicle-emu). +This project is an easy to use Python wrapper around [icicle-emu](https://github.com/icicle-emu/icicle-emu). ## Requirements @@ -9,6 +9,10 @@ This project is an attempt to replace unicorn with a wrapper around [icicle-emu] ## Building +TODO: talk about the submodule + +TODO: clone ghidra and set `GHIDRA_SRC` environment variable + Set up a virtual environment: ```shell diff --git a/icicle-emu b/icicle-emu index 094722e..dd99c88 160000 --- a/icicle-emu +++ b/icicle-emu @@ -1 +1 @@ -Subproject commit 094722e41f716303ff0ec6e4777f9e119aae21e2 +Subproject commit dd99c8805220113e4bfb0c209801ded6aa73f866 diff --git a/icicle.pyi b/icicle.pyi index 037fd2c..2446f4c 100644 --- a/icicle.pyi +++ b/icicle.pyi @@ -98,8 +98,12 @@ class Icicle: icount_limit: int + # TODO: API to get memory information? + def mem_map(self, address: int, size: int, protection: MemoryProtection): ... + def mem_unmap(self, address: int, size: int): ... + def mem_protect(self, address: int, size: int, protection: MemoryProtection): ... def mem_read(self, address: int, size: int) -> bytes: ... diff --git a/src/lib.rs b/src/lib.rs index 762f1bf..283a292 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ enum ExceptionCodePy { ExecViolation = 0x0401, SelfModifyingCode = 0x0402, + ExecUnaligned = 0x0404, OutOfMemory = 0x0501, AddressOverflow = 0x0502, @@ -166,6 +167,7 @@ impl From for ExceptionCodePy { ExceptionCode::WriteUnaligned => ExceptionCodePy::WriteUnaligned, ExceptionCode::ExecViolation => ExceptionCodePy::ExecViolation, ExceptionCode::SelfModifyingCode => ExceptionCodePy::SelfModifyingCode, + ExceptionCode::ExecUnaligned => ExceptionCodePy::ExecUnaligned, ExceptionCode::OutOfMemory => ExceptionCodePy::OutOfMemory, ExceptionCode::AddressOverflow => ExceptionCodePy::AddressOverflow, ExceptionCode::InvalidInstruction => ExceptionCodePy::InvalidInstruction, @@ -290,11 +292,13 @@ impl Icicle { ); } + // TODO: support instantiating this multiple times if tracing { - tracing_subscriber::fmt() + if tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .with_target(false) - .init(); + .try_init().is_err() { + } } // Setup the CPU state for the target triple @@ -362,6 +366,19 @@ impl Icicle { } } + fn mem_unmap(&mut self, address: u64, size: u64) -> PyResult<()> { + if self.vm.cpu.mem.unmap_memory_len(address, size) { + Ok(()) + } else { + Err( + raise_MemoryError( + format!("Failed to unmap memory {address:X}[{size:X}]"), + MemError::Unknown, + ) + ) + } + } + fn mem_protect(&mut self, address: u64, size: usize, protection: MemoryProtection) -> PyResult<()> { self.vm.cpu.mem.update_perm(address, size as u64, convert_protection(protection)) .map_err(|e| { diff --git a/src/main.rs b/src/main.rs index dcdf5d1..47b26c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,356 +1,379 @@ -use std::thread::sleep; -use icicle_vm::cpu::{Environment, ExceptionCode}; -use icicle_vm::cpu::mem::{AllocLayout, Mapping, perm}; +use std::borrow::Cow; +use std::collections::HashMap; +use icicle_cpu::mem::{Mapping, perm}; +use icicle_cpu::{VmExit}; +use icicle_vm; use icicle_vm::linux::LinuxCpu; -use icicle_vm::VmExit; -use crate::rawenv::RawEnvironment; +use target_lexicon; +use indexmap::IndexMap; +use sleigh_runtime::NamedRegister; -use std::time::{Duration, SystemTime}; - -mod rawenv; - -fn main() { - // Setup the CPU state for the target triple - let mut cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); - cpu_config.enable_jit = true; - cpu_config.enable_recompilation = false; - - let mut vm = icicle_vm::build(&cpu_config).unwrap(); - - let shellcode: [u8; 2780] = - [ - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, - 0x7C, 0x24, 0x18, 0x55, 0x48, 0x8B, 0xEC, 0x48, 0x83, 0xEC, 0x10, 0xB8, - 0x63, 0x72, 0x65, 0x61, 0xC7, 0x45, 0xF0, 0x37, 0x13, 0x00, 0x00, 0x41, - 0xBA, 0x62, 0x69, 0x6E, 0x67, 0xC7, 0x45, 0xF4, 0x69, 0x00, 0x00, 0x00, - 0xC7, 0x45, 0xF8, 0x20, 0x04, 0x00, 0x00, 0xBB, 0x80, 0x96, 0x98, 0x00, - 0xC7, 0x45, 0xFC, 0x66, 0x06, 0x00, 0x00, 0xBE, 0x40, 0x6E, 0xDE, 0x8D, - 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x33, 0xC9, 0x45, - 0x33, 0xC0, 0x45, 0x8D, 0x59, 0x04, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00, - 0x41, 0x83, 0xE0, 0x03, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x8B, 0xD0, 0xC1, - 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x03, 0xD0, 0x41, - 0x03, 0xC9, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x33, 0xD1, 0x45, - 0x8B, 0xC1, 0x44, 0x03, 0xD2, 0x41, 0x83, 0xE0, 0x03, 0x41, 0x8B, 0xCA, - 0x41, 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, - 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, - 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, - 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, - 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, - 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, - 0x41, 0x8B, 0xCA, 0x41, 0x83, 0xE0, 0x03, 0xC1, 0xE1, 0x04, 0x41, 0x8B, - 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, - 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, - 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, - 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, - 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, - 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, 0x41, 0x8B, - 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, - 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, - 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xD0, 0x8B, - 0xC8, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE0, 0x03, 0x33, - 0xD1, 0x03, 0xD0, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x41, - 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x33, 0xD1, 0x45, 0x8B, 0xC1, 0x44, - 0x03, 0xD2, 0x41, 0x83, 0xE0, 0x03, 0x41, 0x8B, 0xCA, 0x41, 0x8B, 0xD2, - 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, - 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, - 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, - 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, - 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, - 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, - 0x41, 0x83, 0xE0, 0x03, 0xC1, 0xE1, 0x04, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, - 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, - 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, - 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, - 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, - 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, - 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, 0x41, 0x8B, 0xD2, 0xC1, 0xE1, - 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, - 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, - 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xD0, 0x8B, 0xC8, 0xC1, 0xEA, - 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x03, 0xD0, 0x41, 0x83, 0xE0, 0x03, - 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x41, 0x81, 0xC1, 0xB9, - 0x79, 0x37, 0x9E, 0x33, 0xD1, 0x45, 0x8B, 0xC1, 0x44, 0x03, 0xD2, 0x41, - 0x83, 0xE0, 0x03, 0x41, 0x8B, 0xCA, 0x41, 0x8B, 0xD2, 0xC1, 0xE1, 0x04, - 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, - 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, - 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, - 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, - 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, - 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x83, 0xE0, 0x03, 0x41, 0x8B, - 0xCA, 0xC1, 0xE1, 0x04, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, - 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, - 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, - 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, - 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, - 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, - 0xC1, 0x41, 0x8B, 0xCA, 0x41, 0x83, 0xE0, 0x03, 0xC1, 0xE1, 0x04, 0x41, - 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, - 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, - 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xD0, 0x8B, 0xC8, 0xC1, - 0xEA, 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, - 0x03, 0xD0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, - 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x83, 0xE0, 0x03, - 0x41, 0x8B, 0xCA, 0xC1, 0xE1, 0x04, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, - 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, - 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, - 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, - 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, - 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, - 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, 0x41, 0x83, 0xE0, 0x03, 0xC1, 0xE1, - 0x04, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, - 0x48, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, - 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, - 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, 0x4C, - 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, - 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x8B, - 0xCA, 0x41, 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE0, 0x03, 0xC1, - 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, - 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, - 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xD0, 0x8B, 0xC8, 0xC1, 0xEA, 0x05, 0xC1, - 0xE1, 0x04, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, - 0x03, 0xD0, 0x33, 0xD1, 0x44, 0x03, 0xD2, 0x41, 0x81, 0xC1, 0xB9, 0x79, - 0x37, 0x9E, 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, 0xC1, 0xE1, 0x04, 0x41, - 0x83, 0xE0, 0x03, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, - 0x8B, 0xC9, 0x41, 0x03, 0xD2, 0x48, 0xC1, 0xE9, 0x0B, 0x83, 0xE1, 0x03, - 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, - 0xC8, 0x8B, 0xD0, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, - 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, - 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, - 0x41, 0x83, 0xE0, 0x03, 0x41, 0x8B, 0xCA, 0xC1, 0xE1, 0x04, 0x41, 0x8B, - 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x41, 0x03, 0xD2, - 0x48, 0xC1, 0xE9, 0x0B, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, - 0x03, 0xC9, 0x33, 0xD1, 0x03, 0xC2, 0x8B, 0xC8, 0x8B, 0xD0, 0xC1, 0xEA, - 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, - 0x03, 0xC9, 0x03, 0xD0, 0x33, 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, - 0x9E, 0x44, 0x03, 0xD2, 0x45, 0x8B, 0xC1, 0x41, 0x8B, 0xCA, 0x41, 0x83, - 0xE0, 0x03, 0xC1, 0xE1, 0x04, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, - 0xD1, 0x41, 0x8B, 0xC9, 0x41, 0x03, 0xD2, 0x48, 0xC1, 0xE9, 0x0B, 0x83, - 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, 0x33, 0xD1, 0x03, - 0xC2, 0x8B, 0xD0, 0x8B, 0xC8, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, 0x33, - 0xD1, 0x42, 0x8B, 0x4C, 0x85, 0xF0, 0x41, 0x03, 0xC9, 0x03, 0xD0, 0x33, - 0xD1, 0x41, 0x81, 0xC1, 0xB9, 0x79, 0x37, 0x9E, 0x44, 0x03, 0xD2, 0x45, - 0x8B, 0xC1, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x41, 0x8B, 0xCA, 0xC1, - 0xE1, 0x04, 0x33, 0xD1, 0x41, 0x8B, 0xC9, 0x48, 0xC1, 0xE9, 0x0B, 0x41, - 0x03, 0xD2, 0x83, 0xE1, 0x03, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xC9, - 0x33, 0xD1, 0x03, 0xC2, 0x49, 0x83, 0xEB, 0x01, 0x0F, 0x85, 0x06, 0xFB, - 0xFF, 0xFF, 0x44, 0x8B, 0xDE, 0x4C, 0x8B, 0xCE, 0xBF, 0x04, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x49, 0xC1, 0xE9, 0x0B, 0x41, 0x8B, 0xCA, 0xC1, 0xE1, 0x04, 0x41, 0x83, - 0xE1, 0x03, 0x41, 0x8B, 0xD2, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xD2, 0x41, 0x03, 0xCB, 0x41, 0x81, 0xC3, - 0x47, 0x86, 0xC8, 0x61, 0x33, 0xD1, 0x45, 0x8B, 0xCB, 0x2B, 0xC2, 0x49, - 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, 0x03, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x8B, - 0xC8, 0x44, 0x8B, 0xC0, 0xC1, 0xE1, 0x04, 0x41, 0xC1, 0xE8, 0x05, 0x44, - 0x33, 0xC1, 0x41, 0x8B, 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, - 0x54, 0x8D, 0xF0, 0x41, 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, - 0x41, 0x8B, 0xD2, 0x41, 0x8B, 0xCA, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, - 0x33, 0xD1, 0x49, 0xC1, 0xE9, 0x0B, 0x41, 0x03, 0xD2, 0x41, 0x83, 0xE1, - 0x03, 0x42, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x81, 0xC3, - 0x47, 0x86, 0xC8, 0x61, 0x33, 0xD1, 0x45, 0x8B, 0xCB, 0x2B, 0xC2, 0x49, - 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, 0x03, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x8B, - 0xC8, 0x44, 0x8B, 0xC0, 0xC1, 0xE1, 0x04, 0x41, 0xC1, 0xE8, 0x05, 0x44, - 0x33, 0xC1, 0x41, 0x8B, 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, - 0x54, 0x8D, 0xF0, 0x41, 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, - 0x41, 0x8B, 0xD2, 0x41, 0x8B, 0xCA, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, - 0x33, 0xD1, 0x41, 0x03, 0xD2, 0x49, 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, - 0x03, 0x42, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x81, 0xC3, - 0x47, 0x86, 0xC8, 0x61, 0x33, 0xD1, 0x45, 0x8B, 0xCB, 0x2B, 0xC2, 0x49, - 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, 0x03, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x8B, - 0xC8, 0x49, 0xC1, 0xE9, 0x0B, 0xC1, 0xE1, 0x04, 0x44, 0x8B, 0xC0, 0x41, - 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, 0xCB, 0x83, 0xE1, 0x03, - 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, 0x03, 0xD3, 0x44, 0x33, - 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xD2, 0x41, 0x8B, 0xCA, 0xC1, 0xEA, - 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x41, 0x03, 0xD2, 0x41, 0x83, 0xE1, - 0x03, 0x42, 0x8B, 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x81, 0xC3, - 0x47, 0x86, 0xC8, 0x61, 0x33, 0xD1, 0x45, 0x8B, 0xCB, 0x2B, 0xC2, 0x49, - 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, 0x03, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x8B, - 0xC8, 0x49, 0xC1, 0xE9, 0x0B, 0xC1, 0xE1, 0x04, 0x44, 0x8B, 0xC0, 0x41, - 0xC1, 0xE8, 0x05, 0x41, 0x83, 0xE1, 0x03, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xD2, 0x41, - 0x8B, 0xCA, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x2B, - 0xC2, 0x41, 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x8B, 0xC8, 0xC1, 0xE1, - 0x04, 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x45, - 0x8B, 0xCB, 0x44, 0x03, 0xC0, 0x49, 0xC1, 0xE9, 0x0B, 0x41, 0x83, 0xE1, - 0x03, 0x41, 0x8B, 0xCB, 0x83, 0xE1, 0x03, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xCA, 0x41, - 0x8B, 0xD2, 0xC1, 0xE1, 0x04, 0xC1, 0xEA, 0x05, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x41, - 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x2B, 0xC2, 0x45, 0x8B, 0xCB, 0x49, - 0xC1, 0xE9, 0x0B, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x41, 0x83, 0xE1, 0x03, - 0x44, 0x8B, 0xC0, 0x41, 0xC1, 0xE8, 0x05, 0x44, 0x33, 0xC1, 0x41, 0x8B, - 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, 0x54, 0x8D, 0xF0, 0x41, - 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, 0x41, 0x8B, 0xD2, 0x41, - 0x8B, 0xCA, 0xC1, 0xEA, 0x05, 0xC1, 0xE1, 0x04, 0x33, 0xD1, 0x42, 0x8B, - 0x4C, 0x8D, 0xF0, 0x41, 0x03, 0xCB, 0x41, 0x03, 0xD2, 0x33, 0xD1, 0x2B, - 0xC2, 0x41, 0x81, 0xC3, 0x47, 0x86, 0xC8, 0x61, 0x44, 0x8B, 0xC0, 0x45, - 0x8B, 0xCB, 0x41, 0xC1, 0xE8, 0x05, 0x8B, 0xC8, 0xC1, 0xE1, 0x04, 0x44, - 0x33, 0xC1, 0x41, 0x8B, 0xCB, 0x83, 0xE1, 0x03, 0x44, 0x03, 0xC0, 0x8B, - 0x54, 0x8D, 0xF0, 0x41, 0x03, 0xD3, 0x44, 0x33, 0xC2, 0x45, 0x2B, 0xD0, - 0x48, 0x83, 0xEF, 0x01, 0x0F, 0x85, 0xB6, 0xFA, 0xFF, 0xFF, 0x48, 0x83, - 0xEB, 0x01, 0x0F, 0x85, 0x8C, 0xF5, 0xFF, 0xFF, 0x48, 0x8B, 0x5C, 0x24, - 0x20, 0x41, 0x33, 0xC2, 0x48, 0x8B, 0x74, 0x24, 0x28, 0x48, 0x8B, 0x7C, - 0x24, 0x30, 0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 - ]; - - // &[0xFF, 0xC0, 0x90, 0x90, 0xC3] - - // Setup an environment to run inside of. - let mut renv = Box::new(RawEnvironment::new()); - - renv.load(&mut vm.cpu, &shellcode).unwrap(); - vm.env = renv; - - let stack_base = 0xF0000; - vm.cpu.mem.alloc_memory( - AllocLayout { - addr: Some(stack_base), - size: 0x2000, - align: 0x1000, - }, - Mapping { - perm: perm::READ | perm::WRITE, - value: 0xAA, - }, - ).unwrap(); - - // Set up the stack - let rsp_node = vm.cpu.sleigh().get_reg("RSP").unwrap().var; - vm.cpu.write_reg(rsp_node, stack_base + 0x2000 - 0x100); - - // Add instrumentation - let counter = vm.cpu.trace.register_store(vec![0_u64]); - //vm.add_injector(BlockCounter { counter }); - - // Run until the VM exits. - let limit = 1000000; - let mut start = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis(); - println!("start: {start}"); - sleep(Duration::from_millis(100)); - start = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis(); - println!("start: {start}"); - let mut count = 0; - let exit = loop { - vm.icount_limit = limit; - vm.cpu.icount = 0; - let exit = vm.run(); - let now = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis(); - let elapsed = now - start; - count += 1; - if count == 50 { - panic!("nein"); - } - let freq = (limit as f64) / ((elapsed as f64) / 1000.0); - println!("{limit} instructions in {elapsed}ms ({freq:.2}/s)"); - start = now; - match exit { - VmExit::InstructionLimit => { - println!("Instruction limit") - } - _ => break exit - } - }; - - println!("execution finished!"); - println!("{exit:?}"); - //println!("{}", icicle_vm::debug::current_disasm(&mut vm)); - - // Read instrumentation data. - let blocks_hit = vm.cpu.trace[counter] - .as_any() - .downcast_ref::>() - .unwrap()[0]; - let blocks_executed = blocks_hit.saturating_sub(1); - println!("{blocks_executed} blocks were executed"); - - let rax = vm.cpu.sleigh().get_reg("RAX").unwrap().var; - let rax_val = vm.cpu.read_reg(rax); - println!("rax: 0x{rax_val:X}"); +#[allow(dead_code)] +#[derive(Clone)] +enum MemoryProtection { + NoAccess, + ReadOnly, + ReadWrite, + ExecuteOnly, + ExecuteRead, + ExecuteReadWrite, } -struct BlockCounter { - counter: icicle_vm::cpu::StoreRef, +struct Icicle { + vm: icicle_vm::Vm, + regs: HashMap, } -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(), - ]; - - // Inject the instrumentation at the start of the block. - block.pcode.instructions.splice(..0, instrumentation); - } +fn convert_protection(protection: MemoryProtection) -> u8 { + match protection { + MemoryProtection::NoAccess => perm::NONE, + MemoryProtection::ReadOnly => perm::READ, + MemoryProtection::ReadWrite => perm::READ | perm::WRITE, + MemoryProtection::ExecuteOnly => perm::EXEC, + MemoryProtection::ExecuteRead => perm::EXEC | perm::READ, + MemoryProtection::ExecuteReadWrite => perm::EXEC | perm::READ | perm::WRITE, } } + +fn reg_find<'a>(i: &'a Icicle, name: &str) -> Result<&'a NamedRegister, String> { + let sleigh = i.vm.cpu.sleigh(); + match sleigh.get_reg(name) { + None => { + i.regs.get(name.to_lowercase().as_str()) + .ok_or( + format!("Register not found: {name}") + ) + } + Some(r) => Ok(r), + } +} + +impl Icicle { + #[allow(dead_code)] + fn get_icount_limit(&mut self) -> u64 { + self.vm.icount_limit + } + + #[allow(dead_code)] + fn set_icount_limit(&mut self, value: u64) { + self.vm.icount_limit = value; + } + + #[allow(dead_code)] + fn get_icount(&mut self) -> u64 { + return self.vm.cpu.icount; + } + + #[allow(dead_code)] + fn set_icount(&mut self, value: u64) { + self.vm.cpu.icount = value; + } + + fn new( + architecture: String, + jit: bool, + jit_mem: bool, + shadow_stack: bool, + recompilation: bool, + track_uninitialized: bool, + optimize_instructions: bool, + optimize_block: bool, + tracing: bool, + ) -> Result { + // Prevent mixing '_' and '-' + if architecture.split("-").count() != 1 { + return Err( + format!("Bad architecture format: {architecture}") + ); + } + + // TODO: support instantiating this multiple times + if tracing { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .with_target(false) + .init(); + } + + // Setup the CPU state for the target triple + let mut config = icicle_vm::cpu::Config::from_target_triple( + format!("{architecture}-none").as_str() + ); + if config.triple.architecture == target_lexicon::Architecture::Unknown { + return Err( + format!("Unknown architecture: {architecture}") + ); + } + + // Configuration + config.enable_jit = jit; + config.enable_jit_mem = jit_mem; + config.enable_shadow_stack = shadow_stack; + config.enable_recompilation = recompilation; + config.track_uninitialized = track_uninitialized; + config.optimize_instructions = optimize_instructions; + config.optimize_block = optimize_block; + + let vm = icicle_vm::build(&config) + .map_err(|e| { + format!("VM build error: {e}") + })?; + + // Populate the lowercase register map + let mut regs = HashMap::new(); + let sleigh = vm.cpu.sleigh(); + for reg in &sleigh.named_registers { + let name = sleigh.get_str(reg.name); + regs.insert(name.to_lowercase(), reg.clone()); + } + + Ok(Icicle { + vm, + regs, + }) + } + + fn __str__(&mut self) -> String { + let arch = &self.vm.cpu.arch; + let endianness = if arch.sleigh.big_endian { + "big endian" + } else { + "little endian" + }; + format!("Icicle VM for {0:?} ({endianness})", arch.triple.architecture) + } + + fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> Result<(), String> { + let mapping = Mapping { + perm: convert_protection(protection), + value: 0, + }; + if self.vm.cpu.mem.map_memory_len(address, size, mapping) { + Ok(()) + } else { + Err( + format!("Failed to map memory {address:X}[{size:X}]") + ) + } + } + + #[allow(dead_code)] + fn mem_unmap(&mut self, address: u64, size: u64) -> Result<(), String> { + if self.vm.cpu.mem.unmap_memory_len(address, size) { + Ok(()) + } else { + Err( + format!("Failed to unmap memory {address:X}[{size:X}]") + ) + } + } + + fn mem_protect(&mut self, address: u64, size: usize, protection: MemoryProtection) -> Result<(), String> { + self.vm.cpu.mem.update_perm(address, size as u64, convert_protection(protection)) + .map_err(|_| { + format!("Failed to protect memory {address:X}[{size:X}]") + })?; + Ok(()) + } + + #[allow(dead_code)] + fn mem_read(&mut self, address: u64, size: usize) -> Result, String> { + // Allocate a buffer + let mut buffer = Vec::with_capacity(size); + buffer.resize(size, 0); + + // Read the memory + match self.vm.cpu.mem.read_bytes(address, &mut buffer[..], perm::NONE) { + Ok(_) => Ok(Cow::Owned(buffer)), + Err(_) => Err(format!("Failed to read memory {address:X}[{size:X}]")) + } + } + + fn mem_write(&mut self, address: u64, data: Vec) -> Result<(), String> { + let size = data.len(); + match self.vm.cpu.mem.write_bytes(address, &data[..], perm::NONE) { + Ok(_) => Ok(()), + Err(_) => Err(format!("Failed to write memory {address:X}[{size:X}]")) + } + } + + #[allow(dead_code)] + fn reg_list(&self) -> IndexMap { + let mut result = IndexMap::new(); + let sleigh = self.vm.cpu.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 result; + } + + #[allow(dead_code)] + fn reg_offset(&self, name: &str) -> Result { + Ok(reg_find(self, name)?.offset) + } + + #[allow(dead_code)] + fn reg_size(&self, name: &str) -> Result { + Ok(reg_find(self, name)?.var.size) + } + + fn reg_read(&mut self, name: &str) -> Result { + Ok(self.vm.cpu.read_reg(reg_find(self, name)?.var)) + } + + fn reg_write(&mut self, name: &str, value: u64) -> Result<(), String> { + Ok(self.vm.cpu.write_reg(reg_find(self, name)?.var, value)) + } + + #[allow(dead_code)] + fn reset(&mut self) { + self.vm.reset(); + } + + fn run(&mut self) -> VmExit { + self.vm.run() + } + + #[allow(dead_code)] + fn run_until(&mut self, address: u64) -> VmExit { + let breakpoint_added = self.vm.add_breakpoint(address); + let status = self.run(); + if breakpoint_added { + self.vm.remove_breakpoint(address); + } + status + } + + #[allow(dead_code)] + fn step(&mut self, count: u64) -> VmExit { + let old_limit = self.vm.icount_limit; + self.vm.icount_limit = self.vm.cpu.icount.saturating_add(count); + let status = self.run(); + self.vm.icount_limit = old_limit; + status + } + + #[allow(dead_code)] + fn add_breakpoint(&mut self, address: u64) -> bool { + self.vm.add_breakpoint(address) + } + + #[allow(dead_code)] + fn remove_breakpoint(&mut self, address: u64) -> bool { + self.vm.remove_breakpoint(address) + } +} + +#[allow(dead_code)] +fn architectures() -> Result, String> { + Ok(vec![ + "i686", + "x86_64", + "aarch64", + ]) +} + +fn nx_start() { + let mut vm = Icicle::new( + "x86_64".to_string(), + false, + true, + true, + true, + false, + true, + true, + false, + ).unwrap(); + let page = 0x10000; + vm.mem_map(page, 0x1000, MemoryProtection::ReadOnly).unwrap(); + // inc eax; ret + vm.mem_write(page, b"\xFF\xC0\xC3".to_vec()).unwrap(); + vm.reg_write("rip", page).unwrap(); + let status = vm.run(); + println!("status: {:?}", status); + println!("rip: {:#x}", vm.reg_read("rip").unwrap()); +} + +fn nx_middle() { + let mut vm = Icicle::new( + "x86_64".to_string(), + false, + true, + true, + true, + false, + true, + true, + false, + ).unwrap(); + let page = 0x10000; + vm.mem_map(page, 0x2000, MemoryProtection::ExecuteRead).unwrap(); + vm.mem_protect(page + 0x1000, 0x1000, MemoryProtection::ReadOnly).unwrap(); + // inc eax; inc eax; ; ret + let rip = page + 0x1000 - 2; + vm.mem_write(rip, b"\xFF\xC0\xFF\xC0\xC3".to_vec()).unwrap(); + vm.reg_write("rip", rip).unwrap(); + let status = vm.run(); + println!("status: {:?}", status); + println!("rip: {:#x}", vm.reg_read("rip").unwrap()); + println!("rax: {:#x}", vm.reg_read("rax").unwrap()); +} + +fn inv_start() { + let mut vm = Icicle::new( + "x86_64".to_string(), + false, + true, + true, + true, + false, + true, + true, + false, + ).unwrap(); + let page = 0x10000; + vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead).unwrap(); + // ; ret + vm.mem_write(page, b"\xFF\xFF\xC3".to_vec()).unwrap(); + vm.reg_write("rip", page).unwrap(); + let status = vm.run(); + println!("status: {:?}", status); + println!("rip: {:#x}", vm.reg_read("rip").unwrap()); + println!("rax: {:#x}", vm.reg_read("rax").unwrap()); +} + +fn inv_middle() { + let mut vm = Icicle::new( + "x86_64".to_string(), + false, + true, + true, + true, + false, + true, + true, + false, + ).unwrap(); + let page = 0x10000; + vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead).unwrap(); + // inc eax; ; ret + vm.mem_write(page, b"\xFF\xC0\xFF\xFF\xC3".to_vec()).unwrap(); + vm.reg_write("rip", page).unwrap(); + let status = vm.run(); + println!("status: {:?}", status); + println!("rip: {:#x}", vm.reg_read("rip").unwrap()); + println!("rax: {:#x}", vm.reg_read("rax").unwrap()); +} + +fn main() { + println!("=== NX (block start) ==="); + nx_start(); + println!("=== NX (block middle) ==="); + nx_middle(); + println!("=== Invalid instruction (block start) ==="); + inv_start(); + println!("=== Invalid instruction (block middle) ==="); + inv_middle(); +} diff --git a/tests/example.py b/tests/example.py index 4c0ea9f..ee526a0 100644 --- a/tests/example.py +++ b/tests/example.py @@ -9,10 +9,13 @@ def assemble(code: str, addr: int = 0) -> bytes: raise keystone.KsError("no encoding") return bytes(encoding) -def disassemble(code: bytes, addr: int = 0) -> str: +def disassemble(code: bytes, addr: int = 0, max_count = 1000) -> str: result = "" cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) - while True: + count = 0 + while count < max_count: + count += 1 + # TODO: fix on invalid instruction for address, size, mnemonic, op_str in cs.disasm_lite(code, addr, 1): if len(result) > 0: result += "\n" @@ -25,6 +28,7 @@ def disassemble(code: bytes, addr: int = 0) -> str: if len(code) == 0: return result addr += size + return result def old_test(): buf = assemble("mov eax, ebx\nnop") diff --git a/tests/invalid.py b/tests/invalid.py new file mode 100644 index 0000000..a7c0320 --- /dev/null +++ b/tests/invalid.py @@ -0,0 +1,51 @@ +""" +Scenarios: +- Non-executable memory being executed + - What should happen when the memory doesn't exist at all? +- Invalid instruction at the start of the block +- Invalid instruction in the middle of a block +- IP alignment error (non-x86) +""" + +from icicle import * + +def nx(): + vm = Icicle("x86_64", jit=False) + page = 0x10000 + vm.mem_map(page, 0x1000, MemoryProtection.ReadOnly) + vm.mem_write(page, b"\x90\xC3") + vm.reg_write("rip", page) + status = vm.run() + print(status) + print(vm.exception_code, hex(vm.exception_value)) + +def inv_start(): + vm = Icicle("x86_64", jit=False) + page = 0x10000 + vm.mem_map(page, 0x1000, MemoryProtection.ExecuteRead) + vm.mem_write(page, b"\xFF\xFF\x90") + vm.reg_write("rip", page) + status = vm.run() + print(status) + print(vm.exception_code, hex(vm.exception_value)) + +def inv_middle(): + vm = Icicle("x86_64", jit=False) + page = 0x10000 + vm.mem_map(page, 0x1000, MemoryProtection.ExecuteRead) + vm.mem_write(page, b"\x90\x90\xFF\xFF\x90") + vm.reg_write("rip", page) + status = vm.run() + print(status) + print(vm.exception_code, hex(vm.exception_value)) + +def main(): + print("=== NX ===") + nx() + print("=== Invalid instruction (block start) ===") + inv_start() + print("=== Invalid instruction (block middle) ===") + inv_middle() + +if __name__ == "__main__": + main()