From 11524fe292cfd4f40d9c7127c0e82ff1ef3e9793 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sat, 30 Mar 2019 15:27:43 -0700 Subject: starting to get into some system instructions now --- src/display.rs | 19 ++++++ src/lib.rs | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.rs | 17 +++++ 3 files changed, 248 insertions(+) diff --git a/src/display.rs b/src/display.rs index 6846174..d11c7c5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -174,6 +174,15 @@ impl Colorize for Operand { impl fmt::Display for Opcode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + &Opcode::CPUID => write!(f, "{}", "cpuid"), + &Opcode::UD2 => write!(f, "{}", "ud2"), + &Opcode::WBINVD => write!(f, "{}", "wbinvd"), + &Opcode::INVD => write!(f, "{}", "invd"), + &Opcode::SYSRET => write!(f, "{}", "sysret"), + &Opcode::CLTS => write!(f, "{}", "clts"), + &Opcode::SYSCALL => write!(f, "{}", "syscall"), + &Opcode::LSL => write!(f, "{}", "lsl"), + &Opcode::LAR => write!(f, "{}", "lar"), &Opcode::INC => write!(f, "{}", "inc"), &Opcode::DEC => write!(f, "{}", "dec"), &Opcode::HLT => write!(f, "{}", "hlt"), @@ -406,6 +415,16 @@ impl Colorize for Opcode { Opcode::CMP | Opcode::CMPXCHG => { write!(out, "{}", colors.comparison_op(self)) } + Opcode::CPUID | + Opcode::WBINVD | + Opcode::INVD | + Opcode::SYSRET | + Opcode::CLTS | + Opcode::SYSCALL | + Opcode::LSL | + Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } + + Opcode::UD2 | Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } } } diff --git a/src/lib.rs b/src/lib.rs index f2e19c7..556ed8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,16 @@ impl RegSpec { } #[inline] + pub fn fs() -> RegSpec { + RegSpec { bank: RegisterBank::S, num: 3 } + } + + #[inline] + pub fn gs() -> RegSpec { + RegSpec { bank: RegisterBank::S, num: 4 } + } + + #[inline] pub fn rax() -> RegSpec { RegSpec { bank: RegisterBank::Q, num: 0 } } @@ -268,6 +278,15 @@ pub enum Opcode { SETGE, SETLE, SETG, + CPUID, + UD2, + WBINVD, + INVD, + SYSRET, + CLTS, + SYSCALL, + LSL, + LAR, Invalid } #[derive(Debug)] @@ -427,6 +446,14 @@ impl PrefixRex { #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] pub enum OperandCode { + ModRM_0x0f00, + ModRM_0x0f01, + Rq_Cq_0, + Rq_Dq_0, + Cq_Rq_0, + Dq_Rq_0, + FS, + GS, Eb_R0, ModRM_0xf6, ModRM_0xf7, @@ -521,11 +548,79 @@ fn read_opcode_0f_map>(bytes_iter: &mut T, instruction: &mu Some(b) => { *length += 1; match b { + 0x00 => { + instruction.prefixes = prefixes; + Ok(OperandCode::ModRM_0x0f00) + } + 0x01 => { + instruction.prefixes = prefixes; + Ok(OperandCode::ModRM_0x0f00) + } + 0x02 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::LAR; + Ok(OperandCode::Gv_M) + } + 0x03 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::LSL; + Ok(OperandCode::Gv_M) + } + 0x05 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::SYSCALL; + Ok(OperandCode::Nothing) + } + 0x06 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CLTS; + Ok(OperandCode::Nothing) + } + 0x07 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::SYSRET; + Ok(OperandCode::Nothing) + } + 0x08 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::INVD; + Ok(OperandCode::Nothing) + } + 0x09 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::WBINVD; + Ok(OperandCode::Nothing) + } + 0x0b => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::UD2; + Ok(OperandCode::Nothing) + } 0x1f => { instruction.prefixes = prefixes; instruction.opcode = Opcode::NOP; Ok(OperandCode::Ev) }, + 0x20 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOV; + Ok(OperandCode::Rq_Cq_0) + }, + 0x21 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOV; + Ok(OperandCode::Rq_Dq_0) + }, + 0x22 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOV; + Ok(OperandCode::Cq_Rq_0) + }, + 0x23 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::MOV; + Ok(OperandCode::Dq_Rq_0) + }, 0x40 => { instruction.prefixes = prefixes; instruction.opcode = Opcode::CMOVO; @@ -708,6 +803,36 @@ fn read_opcode_0f_map>(bytes_iter: &mut T, instruction: &mu ][(x & 0xf) as usize]; Ok(OperandCode::Eb_R0) } + 0xa0 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::PUSH; + Ok(OperandCode::FS) + } + 0xa1 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::POP; + Ok(OperandCode::GS) + } + 0xa2 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::CPUID; + Ok(OperandCode::Nothing) + } + 0xa8 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::PUSH; + Ok(OperandCode::Nothing) + } + 0xa9 => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::PUSH; + Ok(OperandCode::GS) + } + 0xae => { + instruction.prefixes = prefixes; + instruction.opcode = Opcode::PUSH; + Ok(OperandCode::GS) + } 0xb0 => { instruction.prefixes = prefixes; instruction.opcode = Opcode::CMPXCHG; @@ -2097,6 +2222,93 @@ fn read_operands>( instruction.operands = [Operand::ImmediateI32(offset as i32), Operand::Nothing]; Ok(()) } + OperandCode::Rq_Cq_0 => { + let opwidth = 8; + let modrm = match bytes_iter.next() { + Some(b) => b, + None => return Err("Out of bytes".to_string()) + }; + *length += 1; + let (_, mut r, mut m) = octets_of(modrm); + if instruction.prefixes.rex().r() { + r += 0b1000; + } + if instruction.prefixes.rex().b() { + m += 0b1000; + } + instruction.operands = [ + Operand::Register(RegSpec { bank: RegisterBank::Q, num: m }), + Operand::Register(RegSpec { bank: RegisterBank::CR, num: r }) + ]; + Ok(()) + } + OperandCode::Rq_Dq_0 => { + let opwidth = 8; + let modrm = match bytes_iter.next() { + Some(b) => b, + None => return Err("Out of bytes".to_string()) + }; + let (_, mut r, mut m) = octets_of(modrm); + if instruction.prefixes.rex().r() { + r += 0b1000; + } + if instruction.prefixes.rex().b() { + m += 0b1000; + } + instruction.operands = [ + Operand::Register(RegSpec { bank: RegisterBank::Q, num: m }), + Operand::Register(RegSpec { bank: RegisterBank::DR, num: r }) + ]; + Ok(()) + } + OperandCode::Cq_Rq_0 => { + let opwidth = 8; + let modrm = match bytes_iter.next() { + Some(b) => b, + None => return Err("Out of bytes".to_string()) + }; + *length += 1; + let (_, mut r, mut m) = octets_of(modrm); + if instruction.prefixes.rex().r() { + r += 0b1000; + } + if instruction.prefixes.rex().b() { + m += 0b1000; + } + instruction.operands = [ + Operand::Register(RegSpec { bank: RegisterBank::CR, num: r }), + Operand::Register(RegSpec { bank: RegisterBank::Q, num: m }) + ]; + Ok(()) + } + OperandCode::Dq_Rq_0 => { + let opwidth = 8; + let modrm = match bytes_iter.next() { + Some(b) => b, + None => return Err("Out of bytes".to_string()) + }; + *length += 1; + let (_, mut r, mut m) = octets_of(modrm); + if instruction.prefixes.rex().r() { + r += 0b1000; + } + if instruction.prefixes.rex().b() { + m += 0b1000; + } + instruction.operands = [ + Operand::Register(RegSpec { bank: RegisterBank::DR, num: r }), + Operand::Register(RegSpec { bank: RegisterBank::Q, num: m }) + ]; + Ok(()) + } + OperandCode::FS => { + instruction.operands = [Operand::Register(RegSpec::fs()), Operand::Nothing]; + Ok(()) + } + OperandCode::GS => { + instruction.operands = [Operand::Register(RegSpec::fs()), Operand::Nothing]; + Ok(()) + } OperandCode::Nothing => { instruction.operands = [Operand::Nothing, Operand::Nothing]; Ok(()) diff --git a/test/test.rs b/test/test.rs index df94aeb..1e73a2e 100644 --- a/test/test.rs +++ b/test/test.rs @@ -38,6 +38,23 @@ fn test_display(data: &[u8], expected: &'static str) { } #[test] +fn test_system() { + test_display(&[0x45, 0x0f, 0x22, 0xc8], "mov cr9, r8"); + test_display(&[0x45, 0x0f, 0x20, 0xc8], "mov r8, cr9"); + test_display(&[0x40, 0x0f, 0x22, 0xc8], "mov cr1, rax"); + test_display(&[0x0f, 0x22, 0xc8], "mov cr1, rax"); + test_display(&[0x44, 0x0f, 0x22, 0xcf], "mov cr9, rdi"); + test_display(&[0x0f, 0x22, 0xcf], "mov cr1, rdi"); + test_display(&[0x0f, 0x20, 0xc8], "mov rax, cr1"); + + test_display(&[0x45, 0x0f, 0x23, 0xc8], "mov dr9, r8"); + test_display(&[0x45, 0x0f, 0x21, 0xc8], "mov r8, dr9"); + test_display(&[0x40, 0x0f, 0x23, 0xc8], "mov dr1, rax"); + test_display(&[0x0f, 0x23, 0xc8], "mov dr1, rax"); + test_display(&[0x0f, 0x21, 0xc8], "mov rax, dr1"); +} + +#[test] fn test_arithmetic() { test_display(&[0x81, 0xec, 0x10, 0x03, 0x00, 0x00], "sub esp, 0x310"); } -- cgit v1.1