|
|
|
@ -7,6 +7,18 @@ namespace vm
|
|
|
|
|
{
|
|
|
|
|
using instr_callback_t = bool(*)(const zydis_decoded_instr_t& instr);
|
|
|
|
|
|
|
|
|
|
enum VM_MNEMONIC
|
|
|
|
|
{
|
|
|
|
|
INVALID,
|
|
|
|
|
|
|
|
|
|
SREGQ,
|
|
|
|
|
SREGDW,
|
|
|
|
|
SREGW,
|
|
|
|
|
|
|
|
|
|
LREGQ,
|
|
|
|
|
LREGDW
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum extention_t
|
|
|
|
|
{
|
|
|
|
|
none,
|
|
|
|
@ -17,6 +29,7 @@ namespace vm
|
|
|
|
|
struct profile_t
|
|
|
|
|
{
|
|
|
|
|
const char* name;
|
|
|
|
|
VM_MNEMONIC mnemonic;
|
|
|
|
|
u8 imm_size;
|
|
|
|
|
std::vector<instr_callback_t> signature;
|
|
|
|
|
extention_t extention;
|
|
|
|
@ -24,12 +37,12 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
namespace profile
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RBP]
|
|
|
|
|
// ADD RBP, 8
|
|
|
|
|
// MOV [RAX+RDI], RDX
|
|
|
|
|
inline vm::handler::profile_t sregq =
|
|
|
|
|
{
|
|
|
|
|
"SREGQ", 8,
|
|
|
|
|
// MOV RDX, [RBP]
|
|
|
|
|
// ADD RBP, 8
|
|
|
|
|
// MOV [RAX+RDI], RDX
|
|
|
|
|
"SREGQ", SREGQ, 8,
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RBP]
|
|
|
|
@ -50,7 +63,7 @@ namespace vm
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
|
|
|
|
instr.operands[1].imm.value.u == 8;
|
|
|
|
|
},
|
|
|
|
|
// MOV [RAX+RDI], RDX
|
|
|
|
|
// MOV [RAX+RDI], RDX or MOV [RDI+RAX], RDX
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
@ -66,9 +79,179 @@ namespace vm
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline vm::handler::profile_t sregdw =
|
|
|
|
|
{
|
|
|
|
|
// MOV EDX, [RBP]
|
|
|
|
|
// ADD RBP, 0x4
|
|
|
|
|
// MOV [RAX+RDI], EDX
|
|
|
|
|
"SREGDW", SREGDW, 8,
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// MOV EDX, [RBP]
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_EDX &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
|
},
|
|
|
|
|
// ADD RBP, 0x4
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
|
|
|
|
instr.operands[1].imm.value.u == 0x4;
|
|
|
|
|
},
|
|
|
|
|
// MOV [RAX+RDI], EDX or MOV [RDI+RAX], EDX
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) &&
|
|
|
|
|
(instr.operands[0].mem.index == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[0].mem.index == ZYDIS_REGISTER_RDI) &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_EDX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline vm::handler::profile_t sregw =
|
|
|
|
|
{
|
|
|
|
|
// MOV DX, [RBP]
|
|
|
|
|
// ADD RBP, 0x2
|
|
|
|
|
// MOV [RAX+RDI], DX
|
|
|
|
|
"SREGW", SREGW, 8,
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// MOV DX, [RBP]
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_DX &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
|
},
|
|
|
|
|
// ADD RBP, 0x2
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
|
|
|
|
instr.operands[1].imm.value.u == 0x2;
|
|
|
|
|
},
|
|
|
|
|
// MOV [RAX+RDI], DX or MOV [RDI+RAX], DX
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) &&
|
|
|
|
|
(instr.operands[0].mem.index == ZYDIS_REGISTER_RDI ||
|
|
|
|
|
instr.operands[0].mem.index == ZYDIS_REGISTER_RAX) &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_DX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lregq =
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RAX+RDI]
|
|
|
|
|
// SUB RBP, 8
|
|
|
|
|
// MOV [RBP], RDX
|
|
|
|
|
"LREGQ", LREGQ, 8,
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RAX+RDI] or MOV RDX, [RDI+RAX]
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
(instr.operands[1].mem.base == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RDI) &&
|
|
|
|
|
(instr.operands[1].mem.index == ZYDIS_REGISTER_RDI ||
|
|
|
|
|
instr.operands[1].mem.index == ZYDIS_REGISTER_RAX);
|
|
|
|
|
},
|
|
|
|
|
// SUB RBP, 8
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
|
|
|
|
instr.operands[1].imm.value.u == 0x8;
|
|
|
|
|
},
|
|
|
|
|
// MOV [RBP], RDX
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lregdw =
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RAX + RDI]
|
|
|
|
|
// SUB RBP, 0x4
|
|
|
|
|
// MOV [RBP], EDX
|
|
|
|
|
"LREGDW", LREGDW, 8,
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// MOV RDX, [RAX + RDI] or MOV RDX, [RDI + RAX]
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_EDX &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
(instr.operands[1].mem.base == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RDI) &&
|
|
|
|
|
(instr.operands[1].mem.index == ZYDIS_REGISTER_RAX ||
|
|
|
|
|
instr.operands[1].mem.index == ZYDIS_REGISTER_RDI);
|
|
|
|
|
},
|
|
|
|
|
// SUB RBP, 0x4
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
|
|
|
|
instr.operands[1].imm.value.u == 0x4;
|
|
|
|
|
},
|
|
|
|
|
// MOV [RBP], EDX
|
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
|
{
|
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_EDX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline std::vector<vm::handler::profile_t*> all =
|
|
|
|
|
{
|
|
|
|
|
&sregq
|
|
|
|
|
&sregq, &sregdw, &sregw,
|
|
|
|
|
|
|
|
|
|
&lregq, &lregdw
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|