Skip to content

Commit f491a22

Browse files
authored
Merge pull request #23 from icicle-emu/push-rewind
Delay updating RSP until after the memory write when executing 'push'
2 parents 210b64c + 37c0fc5 commit f491a22

File tree

2 files changed

+103
-33
lines changed

2 files changed

+103
-33
lines changed

python/icicle/Ghidra/Processors/x86/data/languages/ia.sinc

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,78 +1145,78 @@ macro ptr8(r,x) {
11451145

11461146
macro push22(x) {
11471147
mysave:2 = x;
1148-
SP = SP -2;
1149-
tmp:$(SIZE) = segment(SS,SP);
1148+
tmp:$(SIZE) = segment(SS,SP-2);
11501149
*:2 tmp = mysave;
1150+
SP = SP-2;
11511151
}
11521152

11531153
macro push24(x) {
11541154
mysave:4 = x;
1155-
SP = SP-4;
1156-
tmp:$(SIZE) = segment(SS,SP);
1155+
tmp:$(SIZE) = segment(SS,SP-4);
11571156
*:4 tmp = mysave;
1157+
SP = SP-4;
11581158
}
11591159

11601160
macro push28(x) {
11611161
mysave:8 = x;
1162-
SP = SP-8;
1163-
tmp:$(SIZE) = segment(SS,SP);
1162+
tmp:$(SIZE) = segment(SS,SP-8);
11641163
*:8 tmp = mysave;
1164+
SP = SP-8;
11651165
}
11661166

11671167
macro push42(x) {
11681168
mysave:2 = x;
1169-
$(STACKPTR) = $(STACKPTR) - 2;
1170-
*:2 $(STACKPTR) = mysave;
1169+
*:2 ($(STACKPTR)-2) = mysave;
1170+
$(STACKPTR) = $(STACKPTR)-2;
11711171
}
11721172

11731173
macro push44(x) {
11741174
mysave:4 = x;
1175-
$(STACKPTR) = $(STACKPTR) - 4;
1176-
*:4 $(STACKPTR) = mysave;
1175+
*:4 ($(STACKPTR)-4) = mysave;
1176+
$(STACKPTR) = $(STACKPTR)-4;
11771177
}
11781178

11791179
macro pushseg44(x) {
11801180
mysave:2 = x;
1181-
$(STACKPTR) = $(STACKPTR) - 4;
1182-
*:2 $(STACKPTR) = mysave;
1181+
*:2 ($(STACKPTR)-4) = mysave;
1182+
$(STACKPTR) = $(STACKPTR)-4;
11831183
}
11841184

11851185
macro push48(x) {
11861186
mysave:8 = x;
1187-
$(STACKPTR) = $(STACKPTR) - 8;
1188-
*:8 $(STACKPTR) = mysave;
1187+
*:8 ($(STACKPTR)-8) = mysave;
1188+
$(STACKPTR) = $(STACKPTR)-8;
11891189
}
11901190

11911191
@ifdef IA64
11921192
macro push82(x) {
11931193
mysave:2 = x;
1194-
$(STACKPTR) = $(STACKPTR) - 2;
1195-
*:2 $(STACKPTR) = mysave;
1194+
*:2 ($(STACKPTR)-2) = mysave;
1195+
$(STACKPTR) = $(STACKPTR)-2;
11961196
}
11971197

11981198
macro push84(x) {
11991199
mysave:4 = x;
1200-
$(STACKPTR) = $(STACKPTR) - 4;
1201-
*:4 $(STACKPTR) = mysave;
1200+
*:4 ($(STACKPTR)-4) = mysave;
1201+
$(STACKPTR) = $(STACKPTR)-4;
12021202
}
12031203

12041204
macro push88(x) {
12051205
mysave:8 = x;
1206-
$(STACKPTR) = $(STACKPTR) - 8;
1207-
*:8 $(STACKPTR) = mysave;
1206+
*:8 ($(STACKPTR)-8) = mysave;
1207+
$(STACKPTR) = $(STACKPTR)-8;
12081208
}
12091209

12101210
macro pushseg82(x) {
12111211
mysave:2 = x;
1212-
$(STACKPTR) = $(STACKPTR) - 2;
1213-
*:2 $(STACKPTR) = mysave;
1212+
*:2 ($(STACKPTR)-2) = mysave;
1213+
$(STACKPTR) = $(STACKPTR)-2;
12141214
}
12151215

12161216
macro pushseg88(x) {
12171217
mysave:2 = x;
1218-
$(STACKPTR) = $(STACKPTR) - 8;
1219-
*:2 $(STACKPTR) = mysave;
1218+
*:2 ($(STACKPTR)-8) = mysave;
1219+
$(STACKPTR) = $(STACKPTR)-8;
12201220
}
12211221
@endif
12221222

tests/tests.rs

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(unused)]
2+
13
use icicle::*;
24
use pyo3::PyResult;
35
use std::process::exit;
@@ -22,6 +24,20 @@ fn new_vm(jit: bool) -> PyResult<Icicle> {
2224
)
2325
}
2426

27+
fn new_trace_vm(jit: bool) -> PyResult<Icicle> {
28+
Icicle::new(
29+
"x86_64".to_string(),
30+
jit,
31+
true,
32+
false,
33+
true,
34+
false,
35+
true,
36+
false,
37+
true,
38+
)
39+
}
40+
2541
fn nx_start() -> PyResult<()> {
2642
let mut vm = new_vm(false)?;
2743
let page = 0x10000;
@@ -102,7 +118,7 @@ fn block_optimization() -> PyResult<()> {
102118
vm.mem_map(heap, 0x1000, MemoryProtection::ReadWrite)?;
103119
vm.mem_write(heap + 4, b"\x37\x13\x00\x00".to_vec())?;
104120
vm.mem_map(addr & !0xFFF, 0x1000, MemoryProtection::ExecuteRead)?;
105-
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())?;
121+
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())?;
106122

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

145-
vm.mem_write(0x100, b"\x55".to_vec())?; // push rbp
161+
vm.mem_write(0x100, b"\x55\xCC".to_vec())?; // push rbp
146162
vm.reg_write("rbp", 0xF00)?;
147163
vm.reg_write("rsp", 0x210)?;
148164
vm.reg_write("rip", 0x100)?;
@@ -155,16 +171,60 @@ fn rewind() -> PyResult<()> {
155171
Ok(())
156172
}
157173

174+
fn execute_uninitialized() -> PyResult<()> {
175+
let mut vm = Icicle::new(
176+
"x86_64".to_string(),
177+
false,
178+
true,
179+
false,
180+
true,
181+
true, // NOTE: setting this to true is not properly supported
182+
true,
183+
false,
184+
true,
185+
)?;
186+
187+
// \x48\x8d\x05\x01\x00\x00\x00\x90\x8a\x18\x90
188+
189+
vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteOnly)?;
190+
vm.mem_write(0x100, b"\xFF\xC0".to_vec())?; // inc eax
191+
vm.reg_write("rip", 0x100)?;
192+
let status = vm.step(1);
193+
// NOTE: the real reason is that INIT is not set
194+
println!("run status : {:?}", status);
195+
println!("exception code : {:?}", vm.get_exception_code());
196+
println!("exception value : {:#x}", vm.get_exception_value());
197+
println!("rax : {:#x}", vm.reg_read("rax")?);
198+
199+
// TODO: status is now UnhandledException, should be InstructionLimit
200+
// on the next stpe it should be UnhandledException -> ExecViolation
201+
202+
Ok(())
203+
}
204+
158205
fn execute_only() -> PyResult<()> {
159-
let mut vm = new_vm(true)?;
206+
let mut vm = new_vm(false)?;
160207

161208
vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteOnly)?;
162-
vm.mem_write(0x100, b"\x90".to_vec())?; // nop
209+
/*
210+
0x100: lea rax, [rip]
211+
0x107: nop
212+
0x108: mov bl, byte ptr [rax]
213+
0x10A: int3
214+
*/
215+
vm.mem_write(
216+
0x100,
217+
b"\x48\x8d\x05\x00\x00\x00\x00\x90\x8a\x18\xCC".to_vec(),
218+
)?; // nop
163219
vm.reg_write("rip", 0x100)?;
220+
vm.step(2);
164221
let status = vm.step(1);
222+
// NOTE: the real reason is that INIT is not set
165223
println!("run status : {:?}", status);
166224
println!("exception code : {:?}", vm.get_exception_code());
167225
println!("exception value : {:#x}", vm.get_exception_value());
226+
println!("bl: {:#x}", vm.reg_read("bl")?);
227+
println!("rip: {:#x}", vm.reg_read("rip")?);
168228

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

183246
vm.reg_write("rax", 0xF00)?;
184247
vm.reg_write("rbx", 0x210)?;
@@ -194,7 +257,7 @@ fn step_modify_rip() -> PyResult<()> {
194257
);
195258
vm.reg_write("rip", 0x100)?;
196259
//vm.write_pc(0x100);
197-
//println!("pc: {:#x}", vm.read_pc());
260+
//println!("pc: {:#x}", vm.read_pc());
198261
println!("rip rewritten {:#x}", vm.reg_read("rip")?);
199262
status = vm.step(1);
200263
println!(
@@ -210,7 +273,7 @@ fn eflags_reconstruction() -> PyResult<()> {
210273
let mut vm = new_vm(false)?;
211274
vm.mem_map(0x100, 0x20, MemoryProtection::ExecuteRead)?;
212275

213-
vm.mem_write(0x100, b"\x48\x01\xD8".to_vec())?;
276+
vm.mem_write(0x100, b"\x48\x01\xD8\xCC".to_vec())?;
214277
vm.reg_write("rax", 0x7FFFFFFFFFFFFFFF)?;
215278
vm.reg_write("rbx", 0x1)?;
216279

@@ -232,7 +295,10 @@ fn eflags_reconstruction() -> PyResult<()> {
232295
let rflags = vm.reg_read("rflags")?;
233296
let of = vm.reg_read("OF")?;
234297
let of_set = (eflags & of_mask) == of_mask;
235-
println!("[post] eflags: {:#x} == {:#x}, OF: {:#x} == {}", eflags, rflags, of, of_set);
298+
println!(
299+
"[post] eflags: {:#x} == {:#x}, OF: {:#x} == {}",
300+
eflags, rflags, of, of_set
301+
);
236302
}
237303

238304
{
@@ -249,7 +315,10 @@ fn eflags_reconstruction() -> PyResult<()> {
249315
vm.reg_write("rflags", eflags)?;
250316
let of = vm.reg_read("OF")?;
251317
let of_set = (eflags >> 11) & 1;
252-
println!("[rflags|={:#x}] eflags: {:#x}, OF: {:#x} == {}", of_mask, eflags, of, of_set);
318+
println!(
319+
"[rflags|={:#x}] eflags: {:#x}, OF: {:#x} == {}",
320+
of_mask, eflags, of, of_set
321+
);
253322
}
254323

255324
Ok(())
@@ -284,6 +353,7 @@ fn main() {
284353
("Block optimization bug", block_optimization),
285354
("Rewind", rewind),
286355
("Execute only", execute_only),
356+
("Execute uninitialized", execute_uninitialized),
287357
("Step modify rip", step_modify_rip),
288358
("EFlags reconstruction", eflags_reconstruction),
289359
];

0 commit comments

Comments
 (0)