Skip to content

Commit

Permalink
Fixed movdiri (APX) and compressed disp8 handling (#536)
Browse files Browse the repository at this point in the history
* Fixed `movdiri` (APX) and compressed disp8 handling

* Fixed VSIB encoding in 16-bit mode

* Workaround for `xsha1`/`xsha256`
  • Loading branch information
mappzor authored Nov 6, 2024
1 parent b8149e3 commit 35509e1
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 25 deletions.
21 changes: 17 additions & 4 deletions src/Encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,16 @@ static ZyanBool ZydisCheckVectorMemorySize(ZydisEncoderInstructionMatch *match,
ZyanU16 allowed_mem_size = def_op->size[eosz_index];
if (allowed_mem_size || (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX))
{
return user_op->mem.size == allowed_mem_size;
if (user_op->mem.size == allowed_mem_size)
{
return ZYAN_TRUE;
}
if (!match->eosz64_forbidden && (eosz_index == 2))
{
ZYAN_ASSERT(def_op->size[0] == def_op->size[1]);
return user_op->mem.size == def_op->size[1];
}
return ZYAN_FALSE;
}
ZYAN_ASSERT((match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
(match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX));
Expand Down Expand Up @@ -2123,7 +2132,7 @@ static ZyanBool ZydisIsMemoryOperandCompatible(ZydisEncoderInstructionMatch *mat
reg_index_class);
}
}
else if (disp_size != 8 || !match->cd8_scale)
else
{
const ZyanU8 addr_size = ZydisGetMaxAddressSize(match->request);
if (disp_size > addr_size)
Expand Down Expand Up @@ -2168,9 +2177,13 @@ static ZyanBool ZydisIsMemoryOperandCompatible(ZydisEncoderInstructionMatch *mat
return ZYAN_FALSE;
}
}
else
else if (candidate_easz == 16)
{
if (candidate_easz == 16 && !disp_only)
if (is_vsib)
{
candidate_easz = 32;
}
else if (!disp_only)
{
if (disp_size > 16)
{
Expand Down
1 change: 0 additions & 1 deletion src/Generated/EncoderTables.inc
Original file line number Diff line number Diff line change
Expand Up @@ -11746,4 +11746,3 @@ const ZydisEncodableInstruction encoder_instructions[] =
{ 0x07A3, 0x0000, 0x01, 0xE8, ZYDIS_INSTRUCTION_ENCODING_LEGACY, ZYDIS_OPCODE_MAP_0F, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_MANDATORY_PREFIX_F2, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYDIS_VECTOR_LENGTH_INVALID, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE },
{ 0x07A4, 0x0000, 0x01, 0xD6, ZYDIS_INSTRUCTION_ENCODING_LEGACY, ZYDIS_OPCODE_MAP_0F, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_WIDTH_16 | ZYDIS_WIDTH_32 | ZYDIS_WIDTH_64, ZYDIS_MANDATORY_PREFIX_NONE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYAN_FALSE, ZYDIS_VECTOR_LENGTH_INVALID, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE },
};

13 changes: 9 additions & 4 deletions tests/crash_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,16 @@ def get_combined_flags(flag_str, enum_class):
return functools.reduce(lambda x, y: x | y, [enum_class[v] for v in flag_str.split('|')])


def get_disasm(zydis_info, machine_mode, stack_width, payload):
def get_disasm(zydis_info, machine_mode, stack_width, payload, knc=False):
if not zydis_info:
return ''
arg_machine_mode = '-' + get_width_from_enum(machine_mode)
arg_stack_width = '-' + get_width_from_enum(stack_width)
proc = Popen([zydis_info, arg_machine_mode, arg_stack_width, payload[:30]], stdout=PIPE, stderr=PIPE)
args = [zydis_info, arg_machine_mode, arg_stack_width]
if knc:
args.append('-knc')
args.append(payload[:30])
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out = proc.communicate()[0].decode('utf-8')
if proc.returncode != 0:
return ''
Expand Down Expand Up @@ -176,13 +180,14 @@ def convert_re_enc_crash_to_json(crash, zydis_info, return_dict=False):
stack_width = ZydisStackWidth(reader.read_uint32())
decoder_mode = reader.read_uint32()
payload = reader.read_bytes().hex().upper()
is_knc = (decoder_mode & ZYDIS_DECODER_MODE_KNC) != 0
test_case = {
'machine_mode': machine_mode.name,
'stack_width': stack_width.name,
'payload': payload,
'description': get_disasm(zydis_info, machine_mode, stack_width, payload),
'description': get_disasm(zydis_info, machine_mode, stack_width, payload, is_knc),
}
if decoder_mode & ZYDIS_DECODER_MODE_KNC:
if is_knc:
test_case['knc'] = True
if return_dict:
return test_case
Expand Down
31 changes: 31 additions & 0 deletions tests/re_enc_test_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -913,5 +913,36 @@
"stack_width": "ZYDIS_STACK_WIDTH_64",
"payload": "D51087C02300",
"description": "xchg r16d, eax"
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_64",
"stack_width": "ZYDIS_STACK_WIDTH_64",
"payload": "676262794BBE0C6500FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00006F",
"description": "vfnmsub231ps zmm25 {k3}, zmm0, xmmword ptr ds:[0xFFFFFF00] {uint8}",
"knc": true
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_64",
"stack_width": "ZYDIS_STACK_WIDTH_64",
"payload": "62DC7C08F90500000002",
"description": "movdiri dword ptr ds:[0x000000000200000A], eax"
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_COMPAT_16",
"stack_width": "ZYDIS_STACK_WIDTH_16",
"payload": "C4C3F961E1C4",
"description": "vpcmpestri xmm4, xmm1, 0xC4"
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_64",
"stack_width": "ZYDIS_STACK_WIDTH_64",
"payload": "F3660FA7C86239F6",
"description": "rep xcrypt_ecb <- TODO: Remove 0x66 byte after fixing OSIZE handling for XCRYPT"
},
{
"machine_mode": "ZYDIS_MACHINE_MODE_LONG_COMPAT_16",
"stack_width": "ZYDIS_STACK_WIDTH_16",
"payload": "6762C27D2DA00C150000000000000000",
"description": "vpscatterdd dword ptr ds:[ymm2*1] {k5}, ymm1"
}
]
16 changes: 0 additions & 16 deletions tests/zydis_encoder_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2430,22 +2430,6 @@
'ZYDIS_REGISTER_BND3',
'ZYDIS_REGISTER_BNDCFG',
'ZYDIS_REGISTER_BNDSTATUS',
'ZYDIS_REGISTER_DFV0',
'ZYDIS_REGISTER_DFV1',
'ZYDIS_REGISTER_DFV2',
'ZYDIS_REGISTER_DFV3',
'ZYDIS_REGISTER_DFV4',
'ZYDIS_REGISTER_DFV5',
'ZYDIS_REGISTER_DFV6',
'ZYDIS_REGISTER_DFV7',
'ZYDIS_REGISTER_DFV8',
'ZYDIS_REGISTER_DFV9',
'ZYDIS_REGISTER_DFV10',
'ZYDIS_REGISTER_DFV11',
'ZYDIS_REGISTER_DFV12',
'ZYDIS_REGISTER_DFV13',
'ZYDIS_REGISTER_DFV14',
'ZYDIS_REGISTER_DFV15',
'ZYDIS_REGISTER_MXCSR',
'ZYDIS_REGISTER_PKRU',
'ZYDIS_REGISTER_XCR0',
Expand Down
8 changes: 8 additions & 0 deletions tools/ZydisFuzzReEncoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ int ZydisFuzzTarget(ZydisStreamRead read_fn, void *stream_ctx)
{
return EXIT_FAILURE;
}
// TODO: Temporary workaround for `xsha1` and `xsha256` with OSIZE prefix
if (insn1.mnemonic == ZYDIS_MNEMONIC_XSHA1 || insn1.mnemonic == ZYDIS_MNEMONIC_XSHA256)
{
if (insn1.attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
{
return EXIT_SUCCESS;
}
}

ZydisReEncodeInstruction(&decoder, &insn1, operands1, insn1.operand_count_visible, buffer);

Expand Down
4 changes: 4 additions & 0 deletions tools/ZydisFuzzShared.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ void ZydisPrintInstruction(const ZydisDecodedInstruction* instruction,
ZYAN_UNREACHABLE;
}
printf("-%u ", instruction->stack_width);
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
{
printf("-knc ");
}

for (ZyanU8 i = 0; i < instruction->length; ++i)
{
Expand Down

0 comments on commit 35509e1

Please sign in to comment.