mirror of https://github.com/x64dbg/zydis
Added error-condition for illegal LOCK-prefixes
This commit is contained in:
parent
7ba6ea0596
commit
6ce34bd141
|
@ -1,17 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""Process script copy & paste template."""
|
||||
|
||||
import json
|
||||
import collections
|
||||
import re
|
||||
|
||||
with open('instructions.json') as fi:
|
||||
fi = fi.read()
|
||||
|
||||
data = json.loads(fi, object_pairs_hook=collections.OrderedDict)
|
||||
defs = data['definitions']
|
||||
|
||||
# ... processing code here ...
|
||||
|
||||
with open('instructions.json', 'w') as of:
|
||||
json.dump(data, of)
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* @brief Defines the basic @c ZydisInstructionInfo and @c ZydisOperandInfo struct.
|
||||
* @brief Defines the basic @c ZydisDecodedInstruction and @c ZydisDecodedOperand structs.
|
||||
*/
|
||||
|
||||
#ifndef ZYDIS_INSTRUCTIONINFO_H
|
||||
|
@ -964,7 +964,7 @@ typedef struct ZydisDecodedInstruction_
|
|||
* @brief Signals, if the broadcast is a static broadcast.
|
||||
*
|
||||
* This is the case for instructions with inbuild broadcast functionality, that is
|
||||
* always active and not controlled by a flag in the EVEX/MVEX-prefix.
|
||||
* always active and not be controlled by a flag in the XOP/VEX/EVEX/MVEX-prefix.
|
||||
*/
|
||||
ZydisBool isStatic;
|
||||
/**
|
||||
|
|
326
src/Decoder.c
326
src/Decoder.c
|
@ -195,6 +195,8 @@ enum ZydisRegisterEncodings
|
|||
ZYDIS_REG_ENCODING_MASK
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal functions */
|
||||
/* ============================================================================================== */
|
||||
|
@ -3979,13 +3981,189 @@ static ZydisStatus ZydisNodeHandlerMvexE(ZydisDecodedInstruction* instruction, u
|
|||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Checks for certain post-decode error-conditions.
|
||||
*
|
||||
* @param context A pointer to the @c ZydisDecoderContext instance.
|
||||
* @param instruction A pointer to the @c ZydisDecodedInstruction struct.
|
||||
* @param definition A pointer to the @c ZydisInstructionDefinition struct.
|
||||
*
|
||||
* @return A zydis status code.
|
||||
*
|
||||
* This function is called directly after a valid instruction-definition was found.
|
||||
*/
|
||||
static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
|
||||
ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
|
||||
{
|
||||
ZydisBool acceptsLock = ZYDIS_FALSE;
|
||||
ZydisBool hasNDSNDDOperand = ZYDIS_FALSE;
|
||||
ZydisBool hasVSIB = ZYDIS_FALSE;
|
||||
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
|
||||
switch (instruction->encoding)
|
||||
{
|
||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||
{
|
||||
const ZydisInstructionDefinitionDEFAULT* def =
|
||||
(const ZydisInstructionDefinitionDEFAULT*)definition;
|
||||
acceptsLock = def->acceptsLock;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||
{
|
||||
const ZydisInstructionDefinitionXOP* def =
|
||||
(const ZydisInstructionDefinitionXOP*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionVEX* def =
|
||||
(const ZydisInstructionDefinitionVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionEVEX* def =
|
||||
(const ZydisInstructionDefinitionEVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
hasVSIB = def->hasVSIB;
|
||||
maskPolicy = def->maskPolicy;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionMVEX* def =
|
||||
(const ZydisInstructionDefinitionMVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
hasVSIB = def->hasVSIB;
|
||||
maskPolicy = def->maskPolicy;
|
||||
|
||||
// Check for invalid MVEX.SSS values
|
||||
static const uint8_t lookup[26][8] =
|
||||
{
|
||||
// ZYDIS_MVEX_FUNC_IGNORED
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_INVALID
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_RC
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SAE
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_F_32
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_I_32
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_F_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_I_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SWIZZLE_32
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SWIZZLE_64
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32_BCST
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16
|
||||
{ 1, 0, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SF_64
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32
|
||||
{ 1, 1, 1, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32_BCST
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16
|
||||
{ 1, 0, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_64
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_UF_32
|
||||
{ 1, 0, 0, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_UF_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_UI_32
|
||||
{ 1, 0, 0, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_UI_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_DF_32
|
||||
{ 1, 0, 0, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_DF_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_DI_32
|
||||
{ 1, 0, 0, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_DI_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
ZYDIS_ASSERT(def->functionality < ZYDIS_ARRAY_SIZE(lookup));
|
||||
ZYDIS_ASSERT(instruction->details.mvex.SSS < 8);
|
||||
if (!lookup[def->functionality][instruction->details.mvex.SSS])
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
||||
// Check for illegal LOCK-prefix
|
||||
if (instruction->details.prefixes.hasF0 && !acceptsLock)
|
||||
{
|
||||
return ZYDIS_STATUS_ILLEGAL_LOCK;
|
||||
}
|
||||
|
||||
// Check for invalid `XOP/VEX/EVEX/MVEX.vvvv` value
|
||||
if (!hasNDSNDDOperand && (context->cache.v_vvvv & 0x0F))
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
|
||||
// Check for invalid `EVEX/MVEX.v'` value
|
||||
if (!hasNDSNDDOperand && !hasVSIB && context->cache.V2)
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
|
||||
// Check for invalid MASK registers
|
||||
switch (maskPolicy)
|
||||
{
|
||||
case ZYDIS_MASK_POLICY_INVALID:
|
||||
case ZYDIS_MASK_POLICY_ALLOWED:
|
||||
// Nothing to do here
|
||||
break;
|
||||
case ZYDIS_MASK_POLICY_REQUIRED:
|
||||
if (!context->cache.mask)
|
||||
{
|
||||
return ZYDIS_STATUS_INVALID_MASK;
|
||||
}
|
||||
break;
|
||||
case ZYDIS_MASK_POLICY_FORBIDDEN:
|
||||
if (context->cache.mask)
|
||||
{
|
||||
return ZYDIS_STATUS_INVALID_MASK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Uses the instruction-tree to decode the current instruction.
|
||||
*
|
||||
* @param context A pointer to the @c ZydisDecoderContext instance.
|
||||
* @param instruction A pointer to the @c ZydisDecodedInstruction struct.
|
||||
*
|
||||
* @return A zydis decoder status code.
|
||||
* @return A zydis status code.
|
||||
*/
|
||||
static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
|
||||
ZydisDecodedInstruction* instruction)
|
||||
|
@ -4088,16 +4266,10 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
|
|||
|
||||
const ZydisInstructionParts* optionalParts;
|
||||
ZydisGetOptionalInstructionParts(node, &optionalParts);
|
||||
ZYDIS_CHECK(ZydisDecodeOptionalInstructionParts(context, instruction, optionalParts));
|
||||
ZYDIS_CHECK(
|
||||
ZydisDecodeOptionalInstructionParts(context, instruction, optionalParts));
|
||||
|
||||
ZydisBool hasNDSNDDOperand = ZYDIS_FALSE;
|
||||
ZydisBool hasVSIB = ZYDIS_FALSE;
|
||||
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
|
||||
switch (instruction->encoding)
|
||||
{
|
||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||
break;
|
||||
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
||||
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
|
||||
{
|
||||
// Get actual 3dnow opcode and definition
|
||||
ZYDIS_CHECK(ZydisInputNext(context, instruction, &instruction->opcode));
|
||||
|
@ -4113,141 +4285,9 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
|
|||
node = ZydisInstructionTreeGetChildNode(
|
||||
node, (instruction->details.modrm.mod == 0x3) ? 0 : 1);
|
||||
ZydisGetInstructionDefinition(node, &definition);
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||
{
|
||||
const ZydisInstructionDefinitionXOP* def =
|
||||
(const ZydisInstructionDefinitionXOP*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionVEX* def =
|
||||
(const ZydisInstructionDefinitionVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionEVEX* def =
|
||||
(const ZydisInstructionDefinitionEVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
hasVSIB = def->hasVSIB;
|
||||
maskPolicy = def->maskPolicy;
|
||||
break;
|
||||
}
|
||||
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
|
||||
{
|
||||
const ZydisInstructionDefinitionMVEX* def =
|
||||
(const ZydisInstructionDefinitionMVEX*)definition;
|
||||
hasNDSNDDOperand = def->hasNDSNDDOperand;
|
||||
hasVSIB = def->hasVSIB;
|
||||
maskPolicy = def->maskPolicy;
|
||||
|
||||
// Check for invalid MVEX.SSS values
|
||||
static const uint8_t lookup[26][8] =
|
||||
{
|
||||
// ZYDIS_MVEX_FUNC_IGNORED
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_INVALID
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_RC
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SAE
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_F_32
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_I_32
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_F_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_I_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SWIZZLE_32
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SWIZZLE_64
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32_BCST
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16
|
||||
{ 1, 0, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SF_64
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32
|
||||
{ 1, 1, 1, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32_BCST
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16
|
||||
{ 1, 0, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_SI_64
|
||||
{ 1, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_UF_32
|
||||
{ 1, 0, 0, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_UF_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_UI_32
|
||||
{ 1, 0, 0, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_UI_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_DF_32
|
||||
{ 1, 0, 0, 1, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_DF_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 },
|
||||
// ZYDIS_MVEX_FUNC_DI_32
|
||||
{ 1, 0, 0, 0, 1, 1, 1, 1 },
|
||||
// ZYDIS_MVEX_FUNC_DI_64
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
ZYDIS_ASSERT(def->functionality < ZYDIS_ARRAY_SIZE(lookup));
|
||||
ZYDIS_ASSERT(instruction->details.mvex.SSS < 8);
|
||||
if (!lookup[def->functionality][instruction->details.mvex.SSS])
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ZYDIS_UNREACHABLE;
|
||||
}
|
||||
|
||||
// Check for invalid `XOP/VEX/EVEX/MVEX.vvvv` value
|
||||
if (!hasNDSNDDOperand && (context->cache.v_vvvv & 0x0F))
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
|
||||
// Check for invalid `EVEX/MVEX.v'` value
|
||||
if (!hasNDSNDDOperand && !hasVSIB && context->cache.V2)
|
||||
{
|
||||
return ZYDIS_STATUS_DECODING_ERROR;
|
||||
}
|
||||
|
||||
// Check for invalid MASK registers
|
||||
switch (maskPolicy)
|
||||
{
|
||||
case ZYDIS_MASK_POLICY_INVALID:
|
||||
case ZYDIS_MASK_POLICY_ALLOWED:
|
||||
// Nothing to do here
|
||||
break;
|
||||
case ZYDIS_MASK_POLICY_REQUIRED:
|
||||
if (!context->cache.mask)
|
||||
{
|
||||
return ZYDIS_STATUS_INVALID_MASK;
|
||||
}
|
||||
break;
|
||||
case ZYDIS_MASK_POLICY_FORBIDDEN:
|
||||
if (context->cache.mask)
|
||||
{
|
||||
return ZYDIS_STATUS_INVALID_MASK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ZYDIS_UNREACHABLE;
|
||||
}
|
||||
ZYDIS_CHECK(ZydisCheckErrorConditions(context, instruction, definition));
|
||||
|
||||
instruction->mnemonic = definition->mnemonic;
|
||||
|
||||
|
|
Loading…
Reference in New Issue