Skip to content

Commit

Permalink
Merge pull request #23 from icicle-emu/push-rewind
Browse files Browse the repository at this point in the history
Delay updating RSP until after the memory write when executing 'push'
  • Loading branch information
mrexodia authored Dec 28, 2024
2 parents 210b64c + 37c0fc5 commit f491a22
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 33 deletions.
48 changes: 24 additions & 24 deletions python/icicle/Ghidra/Processors/x86/data/languages/ia.sinc
Original file line number Diff line number Diff line change
Expand Up @@ -1145,78 +1145,78 @@ macro ptr8(r,x) {

macro push22(x) {
mysave:2 = x;
SP = SP -2;
tmp:$(SIZE) = segment(SS,SP);
tmp:$(SIZE) = segment(SS,SP-2);
*:2 tmp = mysave;
SP = SP-2;
}

macro push24(x) {
mysave:4 = x;
SP = SP-4;
tmp:$(SIZE) = segment(SS,SP);
tmp:$(SIZE) = segment(SS,SP-4);
*:4 tmp = mysave;
SP = SP-4;
}

macro push28(x) {
mysave:8 = x;
SP = SP-8;
tmp:$(SIZE) = segment(SS,SP);
tmp:$(SIZE) = segment(SS,SP-8);
*:8 tmp = mysave;
SP = SP-8;
}

macro push42(x) {
mysave:2 = x;
$(STACKPTR) = $(STACKPTR) - 2;
*:2 $(STACKPTR) = mysave;
*:2 ($(STACKPTR)-2) = mysave;
$(STACKPTR) = $(STACKPTR)-2;
}

macro push44(x) {
mysave:4 = x;
$(STACKPTR) = $(STACKPTR) - 4;
*:4 $(STACKPTR) = mysave;
*:4 ($(STACKPTR)-4) = mysave;
$(STACKPTR) = $(STACKPTR)-4;
}

macro pushseg44(x) {
mysave:2 = x;
$(STACKPTR) = $(STACKPTR) - 4;
*:2 $(STACKPTR) = mysave;
*:2 ($(STACKPTR)-4) = mysave;
$(STACKPTR) = $(STACKPTR)-4;
}

macro push48(x) {
mysave:8 = x;
$(STACKPTR) = $(STACKPTR) - 8;
*:8 $(STACKPTR) = mysave;
*:8 ($(STACKPTR)-8) = mysave;
$(STACKPTR) = $(STACKPTR)-8;
}

@ifdef IA64
macro push82(x) {
mysave:2 = x;
$(STACKPTR) = $(STACKPTR) - 2;
*:2 $(STACKPTR) = mysave;
*:2 ($(STACKPTR)-2) = mysave;
$(STACKPTR) = $(STACKPTR)-2;
}

macro push84(x) {
mysave:4 = x;
$(STACKPTR) = $(STACKPTR) - 4;
*:4 $(STACKPTR) = mysave;
*:4 ($(STACKPTR)-4) = mysave;
$(STACKPTR) = $(STACKPTR)-4;
}

macro push88(x) {
mysave:8 = x;
$(STACKPTR) = $(STACKPTR) - 8;
*:8 $(STACKPTR) = mysave;
*:8 ($(STACKPTR)-8) = mysave;
$(STACKPTR) = $(STACKPTR)-8;
}

macro pushseg82(x) {
mysave:2 = x;
$(STACKPTR) = $(STACKPTR) - 2;
*:2 $(STACKPTR) = mysave;
*:2 ($(STACKPTR)-2) = mysave;
$(STACKPTR) = $(STACKPTR)-2;
}

macro pushseg88(x) {
mysave:2 = x;
$(STACKPTR) = $(STACKPTR) - 8;
*:2 $(STACKPTR) = mysave;
*:2 ($(STACKPTR)-8) = mysave;
$(STACKPTR) = $(STACKPTR)-8;
}
@endif

Expand Down
88 changes: 79 additions & 9 deletions tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(unused)]

use icicle::*;
use pyo3::PyResult;
use std::process::exit;
Expand All @@ -22,6 +24,20 @@ fn new_vm(jit: bool) -> PyResult<Icicle> {
)
}

fn new_trace_vm(jit: bool) -> PyResult<Icicle> {
Icicle::new(
"x86_64".to_string(),
jit,
true,
false,
true,
false,
true,
false,
true,
)
}

fn nx_start() -> PyResult<()> {
let mut vm = new_vm(false)?;
let page = 0x10000;
Expand Down Expand Up @@ -102,7 +118,7 @@ fn block_optimization() -> PyResult<()> {
vm.mem_map(heap, 0x1000, MemoryProtection::ReadWrite)?;
vm.mem_write(heap + 4, b"\x37\x13\x00\x00".to_vec())?;
vm.mem_map(addr & !0xFFF, 0x1000, MemoryProtection::ExecuteRead)?;
vm.mem_write(addr, b"\x41\xc1\xea\x07\x41\x83\xe2\x1f\x74\x08\x44\x89\xd0\x48\x89\x54\xc6\x08\x49\x83\xc1\x04\x4c\x89\x0e\x4c\x89\xc9\x44\x8b\x11\x44\x89\xd0\xf7\xd0\x49\x89\xc9\xa8\x03\x0f\x84\x88\xf6\xff\xff\xeb\x4c".to_vec())?;
vm.mem_write(addr, b"\x41\xc1\xea\x07\x41\x83\xe2\x1f\x74\x08\x44\x89\xd0\x48\x89\x54\xc6\x08\x49\x83\xc1\x04\x4c\x89\x0e\x4c\x89\xc9\x44\x8b\x11\x44\x89\xd0\xf7\xd0\x49\x89\xc9\xa8\x03\x0f\x84\x88\xf6\xff\xff\xeb\x4c\xcc".to_vec())?;

// Register setup
vm.reg_write("r9", heap)?;
Expand Down Expand Up @@ -142,7 +158,7 @@ fn rewind() -> PyResult<()> {
vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteRead)?;
vm.mem_map(0x200, 0x20, MemoryProtection::ReadOnly)?;

vm.mem_write(0x100, b"\x55".to_vec())?; // push rbp
vm.mem_write(0x100, b"\x55\xCC".to_vec())?; // push rbp
vm.reg_write("rbp", 0xF00)?;
vm.reg_write("rsp", 0x210)?;
vm.reg_write("rip", 0x100)?;
Expand All @@ -155,16 +171,60 @@ fn rewind() -> PyResult<()> {
Ok(())
}

fn execute_uninitialized() -> PyResult<()> {
let mut vm = Icicle::new(
"x86_64".to_string(),
false,
true,
false,
true,
true, // NOTE: setting this to true is not properly supported
true,
false,
true,
)?;

// \x48\x8d\x05\x01\x00\x00\x00\x90\x8a\x18\x90

vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteOnly)?;
vm.mem_write(0x100, b"\xFF\xC0".to_vec())?; // inc eax
vm.reg_write("rip", 0x100)?;
let status = vm.step(1);
// NOTE: the real reason is that INIT is not set
println!("run status : {:?}", status);
println!("exception code : {:?}", vm.get_exception_code());
println!("exception value : {:#x}", vm.get_exception_value());
println!("rax : {:#x}", vm.reg_read("rax")?);

// TODO: status is now UnhandledException, should be InstructionLimit
// on the next stpe it should be UnhandledException -> ExecViolation

Ok(())
}

fn execute_only() -> PyResult<()> {
let mut vm = new_vm(true)?;
let mut vm = new_vm(false)?;

vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteOnly)?;
vm.mem_write(0x100, b"\x90".to_vec())?; // nop
/*
0x100: lea rax, [rip]
0x107: nop
0x108: mov bl, byte ptr [rax]
0x10A: int3
*/
vm.mem_write(
0x100,
b"\x48\x8d\x05\x00\x00\x00\x00\x90\x8a\x18\xCC".to_vec(),
)?; // nop
vm.reg_write("rip", 0x100)?;
vm.step(2);
let status = vm.step(1);
// NOTE: the real reason is that INIT is not set
println!("run status : {:?}", status);
println!("exception code : {:?}", vm.get_exception_code());
println!("exception value : {:#x}", vm.get_exception_value());
println!("bl: {:#x}", vm.reg_read("bl")?);
println!("rip: {:#x}", vm.reg_read("rip")?);

Ok(())
}
Expand All @@ -178,7 +238,10 @@ fn step_modify_rip() -> PyResult<()> {
// 0x107: 48 89 d9 mov rcx,rbx
// 0x10a: 90 nop
// 0x10b: 90 nop
vm.mem_write(0x100, b"\x48\x01\xD8\x48\x83\xE9\x05\x48\x89\xD9\x90\x90".to_vec())?;
vm.mem_write(
0x100,
b"\x48\x01\xD8\x48\x83\xE9\x05\x48\x89\xD9\x90\x90\xCC".to_vec(),
)?;

vm.reg_write("rax", 0xF00)?;
vm.reg_write("rbx", 0x210)?;
Expand All @@ -194,7 +257,7 @@ fn step_modify_rip() -> PyResult<()> {
);
vm.reg_write("rip", 0x100)?;
//vm.write_pc(0x100);
//println!("pc: {:#x}", vm.read_pc());
//println!("pc: {:#x}", vm.read_pc());
println!("rip rewritten {:#x}", vm.reg_read("rip")?);
status = vm.step(1);
println!(
Expand All @@ -210,7 +273,7 @@ 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.mem_write(0x100, b"\x48\x01\xD8\xCC".to_vec())?;
vm.reg_write("rax", 0x7FFFFFFFFFFFFFFF)?;
vm.reg_write("rbx", 0x1)?;

Expand All @@ -232,7 +295,10 @@ fn eflags_reconstruction() -> PyResult<()> {
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);
println!(
"[post] eflags: {:#x} == {:#x}, OF: {:#x} == {}",
eflags, rflags, of, of_set
);
}

{
Expand All @@ -249,7 +315,10 @@ fn eflags_reconstruction() -> PyResult<()> {
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);
println!(
"[rflags|={:#x}] eflags: {:#x}, OF: {:#x} == {}",
of_mask, eflags, of, of_set
);
}

Ok(())
Expand Down Expand Up @@ -284,6 +353,7 @@ fn main() {
("Block optimization bug", block_optimization),
("Rewind", rewind),
("Execute only", execute_only),
("Execute uninitialized", execute_uninitialized),
("Step modify rip", step_modify_rip),
("EFlags reconstruction", eflags_reconstruction),
];
Expand Down

0 comments on commit f491a22

Please sign in to comment.