Skip to content

Commit

Permalink
fix arch_prctl a little and add info to PerErr
Browse files Browse the repository at this point in the history
  • Loading branch information
lenawanel committed Jul 19, 2023
1 parent 689183d commit 02f2a15
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/bin/test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ pub fn main() {
emu.print_stack::<u64, 8>(emu.stack_depth);
}
println!("exec result: {res:#x?}");
println!("cur_alc: {:#x?}", emu.memory.cur_alc);
}
82 changes: 71 additions & 11 deletions src/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ use crate::{
use std::{io::Write, ops::Range};

pub struct Emu {
memory: MMU,
pub memory: MMU,
registers: [u64; 18],
simd_registers: [u128; 16],
segment_registers: [u64; 2],
#[cfg(debug_assertions)]
pub stack_depth: usize,
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -79,6 +80,7 @@ impl Emu {
stack_depth: 0,
#[cfg(debug_assertions)]
exec_range: Range { start: 0, end: 0 },
segment_registers: [0; 2],
}
}

Expand Down Expand Up @@ -149,7 +151,7 @@ impl Emu {
let operand = instruction.op_kind(index);
match operand {
OpKind::Register => {
let reg: Register = reg_from_op_reg(instruction.op_register(index)).unwrap();
let reg: Register = reg_from_iced_reg(instruction.op_register(index)).unwrap();
Ok(self.get_reg(reg))
}
OpKind::NearBranch64 => Ok(instruction.near_branch64().try_into().unwrap()),
Expand All @@ -172,8 +174,7 @@ impl Emu {
Ok(self
.memory
.read_primitive(Virtaddr(address))
.map(T::from_ne_bytes)
.unwrap())
.map(T::from_ne_bytes)?)
}
x => todo!("{x:?}"),
}
Expand Down Expand Up @@ -233,6 +234,13 @@ impl Emu {
}
}

pub fn get_seg(&self, reg: SegReg) -> u64 {
self.segment_registers[reg as usize]
}
pub fn set_seg(&mut self, reg: SegReg, val: u64) {
self.segment_registers[reg as usize] = val;
}

pub fn run_emu(&mut self) -> Result<()> {
#[cfg(debug_assertions)]
let mut call_depth = 0;
Expand Down Expand Up @@ -986,6 +994,7 @@ impl Emu {
} else {
todo!()
}
self.set_reg(0u64, Register::RAX)
}
// brk
12 => {
Expand All @@ -1005,8 +1014,36 @@ impl Emu {
}
// arch_prctl (ignore this for now and see where it takes us)
158 => {
// we failed
self.set_reg(u64::MAX, Register::RAX)
match self.get_reg::<u64, 8>(Register::RDI) {
// ARCH_SET_GS
0x1001 => {
todo!("SET_GS")
}
// ARCH_SET_FS
0x1002 => {
self.set_seg(SegReg::Fs, self.get_reg(Register::RSI));
// we were succesful
self.set_reg(0u64, Register::RAX)
}
// ARCH_GET_GS
0x1003 => {
todo!("GET_GS")
}
// ARCH_GET_FS
0x1004 => {
todo!("GET_FS")
}
// ARCH_GET_CPUID
0x1011 => {
todo!("GET_CPUID")
}
// ARCH_SET_CPUID
0x1012 => {
todo!("GET_CPUID")
}
// EINVAL
_ => self.set_reg(u64::MAX, Register::RAX),
}
}
// exit
231 => {
Expand Down Expand Up @@ -1062,7 +1099,7 @@ impl Emu {
let opkind = instruction.op_kind(index);
match opkind {
OpKind::Register => {
let reg: Register = reg_from_op_reg(instruction.op_register(index)).unwrap();
let reg: Register = reg_from_iced_reg(instruction.op_register(index)).unwrap();
self.set_reg(val, reg);
Ok(())
}
Expand Down Expand Up @@ -1091,16 +1128,26 @@ impl Emu {
// if that is the case, then multiply the value stored in the register (r14 in the above)
// with its scale (8 in the above case)
// and add the resulting value to the displacement
if let Some(index_reg) = reg_from_op_reg(mem.memory_index()) {
if let Some(index_reg) = reg_from_iced_reg(mem.memory_index()) {
let scale = mem.memory_index_scale() as usize;
addr = addr.wrapping_add(scale * self.get_reg::<usize, 8>(index_reg));
}

// check if we are indexin a segment register
// if so, add it to the addres
// example:
// mov rbx,QWORD PTR fs:0x10
// here fs is the segment register
if let Some(seg_reg) = seg_from_iced_seg(mem.memory_segment()) {
addr = addr.wrapping_add(self.get_seg(seg_reg) as usize);
}

// check if there is a base register indexing the memory
// if that is the case, add the value stored in the register to the current address
// example:
// call QWORD PTR [r12+r14*8]
// here r12 is the base register
if let Some(base_reg) = reg_from_op_reg(mem.memory_base()) {
if let Some(base_reg) = reg_from_iced_reg(mem.memory_base()) {
// this can be wrapping, for example you can have
// cmp QWORD PTR [rdi-0x8],0x0
// substracting some displacement (i.e. doing a wrapping add (I could be wrong here))
Expand Down Expand Up @@ -1166,7 +1213,8 @@ impl Emu {
let val = self.get_reg::<u64, 8>(reg);
print!("\x1b[1;32m {:06?}:\x1b[0m {:#x}", reg, val);
}
println!()
println!();
println!("segment regs: {:#x?}", self.segment_registers);
}
}

Expand All @@ -1188,6 +1236,11 @@ impl From<AccessError> for ExecErr {
}
}

pub enum SegReg {
Fs,
Gs,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Register {
/// the intruction pointer
Expand Down Expand Up @@ -1298,7 +1351,7 @@ pub enum Bitness {
HundredTwentyEigth = 128,
}
#[inline]
fn reg_from_op_reg(reg: iced_x86::Register) -> Option<Register> {
fn reg_from_iced_reg(reg: iced_x86::Register) -> Option<Register> {
use self::Register::*;
use iced_x86::Register;
match reg {
Expand Down Expand Up @@ -1349,6 +1402,13 @@ fn reg_from_op_reg(reg: iced_x86::Register) -> Option<Register> {
}
}

fn seg_from_iced_seg(reg: iced_x86::Register) -> Option<SegReg> {
match reg {
iced_x86::Register::FS => Some(SegReg::Fs),
_ => None,
}
}

#[inline]
fn bitness(instr: Instruction) -> Bitness {
match instr.op0_kind() {
Expand Down
16 changes: 8 additions & 8 deletions src/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl MMU {
{
println!("expected permission: {:#b}", exp_perm.0);
println!("perm check failed");
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}
// dbg!("after checking permissions");

Expand Down Expand Up @@ -159,7 +159,7 @@ impl MMU {
.iter()
.all(|&x| (x & PERM_READ).0 != 0)
{
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}

// actually copy the memory
Expand All @@ -179,7 +179,7 @@ impl MMU {
.iter()
.all(|&x| x & exp_perms == exp_perms)
{
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}

// actually copy the memory
Expand All @@ -200,7 +200,7 @@ impl MMU {
.iter()
.all(|perm| (*perm & PERM_WRITE).0 != 0)
{
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}

// acutally write the requested memory
Expand Down Expand Up @@ -265,7 +265,7 @@ impl MMU {
.iter()
.all(|perm| (*perm & PERM_READ).0 != 0)
{
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}

// copy the requested memory
Expand All @@ -281,7 +281,7 @@ impl MMU {
.iter()
.all(|perm| (*perm & exp_perms).0 != 0)
{
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
}

Ok(&self.memory[addr.0..addr.0 + size])
Expand Down Expand Up @@ -410,7 +410,7 @@ impl MMU {
return Err(AccessError::AddrOverflow);
};
let Some(region) = self.permissions.get_mut(addr.0..end_addr) else {
return Err(AccessError::PermErr);
return Err(AccessError::PermErr(addr, self.permissions[addr.0]));
};
region.iter_mut().for_each(|x| *x = perms);

Expand Down Expand Up @@ -447,7 +447,7 @@ pub enum AccessError {
AddrOOB,
/// We tried to acces memory without the
/// needed permissions
PermErr,
PermErr(Virtaddr, Perm),
}

#[repr(transparent)]
Expand Down

0 comments on commit 02f2a15

Please sign in to comment.