From ed5c76a0f8e92656539f305b9b7ea5e032517f36 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 10 Oct 2021 14:40:55 -0700 Subject: support endbr{32,64} --- CHANGELOG | 5 +++++ src/long_mode/display.rs | 4 ++++ src/long_mode/mod.rs | 36 ++++++++++++++++++++++++++++++++---- src/protected_mode/display.rs | 4 ++++ src/protected_mode/mod.rs | 33 +++++++++++++++++++++++++++++---- src/real_mode/display.rs | 4 ++++ src/real_mode/mod.rs | 33 +++++++++++++++++++++++++++++---- test/long_mode/mod.rs | 3 +++ test/protected_mode/mod.rs | 3 +++ test/real_mode/mod.rs | 3 +++ 10 files changed, 116 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a647897..f4b31e6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +## 1.1.1 +* support `endbr64` and `endbr32` + - these are interpretations of `nop` (`0f1e` wide nop), so the only issue + with for users <1.1.1 will be `yaxpeax-86` decoding `nop` instead. + ## 1.1.0 * implement `AnnotatingDecoder` from `yaxpeax-arch=0.2.6` and later. diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 7c344b7..35b9c1f 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -1405,6 +1405,8 @@ const MNEMONICS: &[&'static str] = &[ "setssbsy", "clrssbsy", "rstorssp", + "endbr64", + "endbr32", // TDX "tdcall", @@ -3220,6 +3222,8 @@ impl Colorize for Opcode { Opcode::SETSSBSY | Opcode::CLRSSBSY | Opcode::RSTORSSP | + Opcode::ENDBR64 | + Opcode::ENDBR32 | Opcode::AESDEC | Opcode::AESDECLAST | Opcode::AESENC | diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 3d6d977..866eb8f 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -2139,6 +2139,8 @@ pub enum Opcode { SETSSBSY, CLRSSBSY, RSTORSSP, + ENDBR64, + ENDBR32, // TDX TDCALL, @@ -4986,9 +4988,7 @@ enum OperandCode { ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(), ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), -// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(), + ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(), // ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(), // ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(), // ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(), @@ -6372,7 +6372,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { 0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e), 0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), @@ -8833,6 +8833,34 @@ fn unlikely_operands< instruction.operand_count = 3; } + OperandCode::ModRM_0xf30f1e => { + let modrm = read_modrm(words)?; + match modrm { + 0xfa => { + instruction.opcode = Opcode::ENDBR64; + instruction.operand_count = 0; + }, + 0xfb => { + instruction.opcode = Opcode::ENDBR32; + instruction.operand_count = 0; + }, + _ => { + let (sz, bank) = if instruction.prefixes.rex_unchecked().w() { + (8, RegisterBank::Q) + } else if !instruction.prefixes.operand_size() { + (4, RegisterBank::D) + } else { + (2, RegisterBank::W) + }; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank); + instruction.operand_count = 2; + + } + }; + } OperandCode::G_E_xmm_Ub => { let modrm = read_modrm(words)?; diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index 275a61d..f545111 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -1406,6 +1406,8 @@ const MNEMONICS: &[&'static str] = &[ "setssbsy", "clrssbsy", "rstorssp", + "endbr64", + "endbr32", // TDX "tdcall", @@ -3233,6 +3235,8 @@ impl Colorize for Opcode { Opcode::SETSSBSY | Opcode::CLRSSBSY | Opcode::RSTORSSP | + Opcode::ENDBR64 | + Opcode::ENDBR32 | Opcode::AESDEC | Opcode::AESDECLAST | Opcode::AESENC | diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index fef1807..232284d 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -2077,6 +2077,8 @@ pub enum Opcode { SETSSBSY, CLRSSBSY, RSTORSSP, + ENDBR64, + ENDBR32, // TDX TDCALL, @@ -4905,9 +4907,7 @@ enum OperandCode { ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(), ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), -// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(), + ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(), // ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(), // ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(), // ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(), @@ -6393,7 +6393,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { 0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e), 0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), @@ -8781,6 +8781,31 @@ fn unlikely_operands< instruction.operand_count = 3; } + OperandCode::ModRM_0xf30f1e => { + let modrm = read_modrm(words)?; + match modrm { + 0xfa => { + instruction.opcode = Opcode::ENDBR64; + instruction.operand_count = 0; + }, + 0xfb => { + instruction.opcode = Opcode::ENDBR32; + instruction.operand_count = 0; + }, + _ => { + let (sz, bank) = if !instruction.prefixes.operand_size() { + (4, RegisterBank::D) + } else { + (2, RegisterBank::W) + }; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + instruction.operand_count = 2; + } + }; + } OperandCode::G_E_xmm_Ub => { let modrm = read_modrm(words)?; diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index 10640a4..258f5d9 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -1406,6 +1406,8 @@ const MNEMONICS: &[&'static str] = &[ "setssbsy", "clrssbsy", "rstorssp", + "endbr64", + "endbr32", // TDX "tdcall", @@ -3233,6 +3235,8 @@ impl Colorize for Opcode { Opcode::SETSSBSY | Opcode::CLRSSBSY | Opcode::RSTORSSP | + Opcode::ENDBR64 | + Opcode::ENDBR32 | Opcode::AESDEC | Opcode::AESDECLAST | Opcode::AESENC | diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 45dd7a3..92c0592 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -2077,6 +2077,8 @@ pub enum Opcode { SETSSBSY, CLRSSBSY, RSTORSSP, + ENDBR64, + ENDBR32, // TDX TDCALL, @@ -4905,9 +4907,7 @@ enum OperandCode { ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(), ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), -// ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), -// ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(), + ModRM_0xf30f1e = OperandCodeBuilder::new().special_case(60).bits(), // ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(), // ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(), // ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(), @@ -6395,7 +6395,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { 0x1b => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::ModRM_0xf30f1e), 0x1f => OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), 0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), @@ -8785,6 +8785,31 @@ fn unlikely_operands< instruction.operand_count = 3; } + OperandCode::ModRM_0xf30f1e => { + let modrm = read_modrm(words)?; + match modrm { + 0xfa => { + instruction.opcode = Opcode::ENDBR64; + instruction.operand_count = 0; + }, + 0xfb => { + instruction.opcode = Opcode::ENDBR32; + instruction.operand_count = 0; + }, + _ => { + let (sz, bank) = if instruction.prefixes.operand_size() { + (4, RegisterBank::D) + } else { + (2, RegisterBank::W) + }; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + instruction.operand_count = 2; + } + }; + } OperandCode::G_E_xmm_Ub => { let modrm = read_modrm(words)?; diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index dab4e91..1efa74e 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -2677,6 +2677,9 @@ fn prefixed_f20f() { fn prefixed_f30f() { test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7"); test_display(&[0xf3, 0x4d, 0x0f, 0x16, 0xcf], "movshdup xmm9, xmm15"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop esp, edi"); } #[test] diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 41ecbb7..4b8ca8d 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -2361,6 +2361,9 @@ fn prefixed_f20f() { #[test] fn prefixed_f30f() { test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop esp, edi"); } #[test] diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs index dfbe4e8..6dcc3a2 100644 --- a/test/real_mode/mod.rs +++ b/test/real_mode/mod.rs @@ -17828,6 +17828,9 @@ fn test_real_mode() { test_display(&[0xf3, 0x0f, 0x16, 0x0f], "movshdup xmm1, xmmword [bx]"); test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7"); test_display(&[0xf3, 0x0f, 0x16, 0xcf], "movshdup xmm1, xmm7"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfa], "endbr64"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfb], "endbr32"); + test_display(&[0xf3, 0x0f, 0x1e, 0xfc], "nop sp, di"); test_display(&[0xf3, 0x0f, 0x21, 0xc8], "mov eax, dr1"); test_display(&[0xf3, 0x0f, 0x2a, 0x00], "cvtsi2ss xmm0, dword [bx + si]"); test_display(&[0xf3, 0x0f, 0x2a, 0x01], "cvtsi2ss xmm0, dword [bx + di]"); -- cgit v1.1