|
|
|
#pragma once
|
|
|
|
#include <transform.hpp>
|
|
|
|
|
|
|
|
namespace vm
|
|
|
|
{
|
|
|
|
namespace handler
|
|
|
|
{
|
|
|
|
using instr_callback_t = bool(*)(const zydis_decoded_instr_t& instr);
|
|
|
|
|
|
|
|
enum mnemonic_t
|
|
|
|
{
|
|
|
|
INVALID,
|
|
|
|
|
|
|
|
SREGQ,
|
|
|
|
SREGDW,
|
|
|
|
SREGW,
|
|
|
|
|
|
|
|
LREGQ,
|
|
|
|
LREGDW,
|
|
|
|
|
|
|
|
LCONSTQ,
|
|
|
|
LCONSTBZXW,
|
|
|
|
LCONSTBSXDW,
|
|
|
|
LCONSTDWSXQ,
|
|
|
|
LCONSTWSXQ,
|
|
|
|
LCONSTDW,
|
|
|
|
|
|
|
|
READQ,
|
|
|
|
READDW,
|
|
|
|
READW,
|
|
|
|
|
|
|
|
WRITEQ,
|
|
|
|
WRITEDW,
|
|
|
|
WRITEW,
|
|
|
|
|
|
|
|
READQ,
|
|
|
|
READDW,
|
|
|
|
READW,
|
|
|
|
|
|
|
|
PUSHVSP,
|
|
|
|
|
|
|
|
ADDQ,
|
|
|
|
ADDDW,
|
|
|
|
|
|
|
|
MULQ,
|
|
|
|
|
|
|
|
DIVQ,
|
|
|
|
|
|
|
|
NANDQ,
|
|
|
|
|
|
|
|
JMP,
|
|
|
|
|
|
|
|
VMEXIT
|
|
|
|
};
|
|
|
|
|
|
|
|
enum extention_t
|
|
|
|
{
|
|
|
|
none,
|
|
|
|
sign_extend,
|
|
|
|
zero_extend
|
|
|
|
};
|
|
|
|
|
|
|
|
struct profile_t
|
|
|
|
{
|
|
|
|
const char* name;
|
|
|
|
mnemonic_t mnemonic;
|
|
|
|
u8 imm_size;
|
|
|
|
std::vector<instr_callback_t> signature;
|
|
|
|
extention_t extention;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace profile
|
|
|
|
{
|
|
|
|
inline vm::handler::profile_t sregq =
|
|
|
|
{
|
|
|
|
// MOV RDX, [RBP]
|
|
|
|
// ADD RBP, 8
|
|
|
|
// MOV [RAX+RDI], RDX
|
|
|
|
"SREGQ", SREGQ, 8,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RDX, [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_RDX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// ADD RBP, 8
|
|
|
|
[](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 == 8;
|
|
|
|
},
|
|
|
|
// MOV [RAX+RDI], RDX or MOV [RDI+RAX], 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_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_RDX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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 =
|
|
|
|
{
|
|
|
|
// MOVZX AL, [RSI]
|
|
|
|
// 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 vm::handler::profile_t lconstq =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RSI]
|
|
|
|
// SUB RBP, 8
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
"LCONSTQ", LCONSTQ, 64,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 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], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lconstbzxw =
|
|
|
|
{
|
|
|
|
// MOV AL, [RSI]
|
|
|
|
// SUB RBP, 2
|
|
|
|
// MOV [RBP], AX
|
|
|
|
"LCONSTBZXW", LCONSTBZXW, 8,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// SUB RBP, 2
|
|
|
|
[](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 == 0x2;
|
|
|
|
},
|
|
|
|
// MOV [RBP], AX
|
|
|
|
[](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_AX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lconstbsxdw =
|
|
|
|
{
|
|
|
|
// CWDE
|
|
|
|
// SUB RBP, 4
|
|
|
|
// MOV [RBP], EAX
|
|
|
|
"LCONSTBSXDW", LCONSTBSXDW, 8,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// CWDE
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_CWDE;
|
|
|
|
},
|
|
|
|
// SUB RBP, 4
|
|
|
|
[](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], EAX
|
|
|
|
[](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_EAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
vm::handler::extention_t::sign_extend
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lconstdwsxq =
|
|
|
|
{
|
|
|
|
// CDQE
|
|
|
|
// SUB RBP, 8
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
"LCONSTDWSXQ", LCONSTDWSXQ, 32,
|
|
|
|
{
|
|
|
|
// CDQE
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_CDQE;
|
|
|
|
},
|
|
|
|
// 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], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
vm::handler::extention_t::sign_extend
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lconstwsxq =
|
|
|
|
{
|
|
|
|
// CDQE
|
|
|
|
// SUB RBP, 8
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
"LCONSTWSXQ", LCONSTWSXQ, 16,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// CDQE
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_CDQE;
|
|
|
|
},
|
|
|
|
// 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], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
vm::handler::extention_t::sign_extend
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t lconstdw =
|
|
|
|
{
|
|
|
|
// SUB RBP, 4
|
|
|
|
// MOV [RBP], EAX
|
|
|
|
"LCONSTDW", LCONSTDW, 32,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// SUB RBP, 4
|
|
|
|
[](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], EAX
|
|
|
|
[](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_EAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t pushvsp =
|
|
|
|
{
|
|
|
|
// MOV RAX, RBP
|
|
|
|
// SUB RBP, 8
|
|
|
|
"PUSHVSP", PUSHVSP, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, 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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// 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], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t addq =
|
|
|
|
{
|
|
|
|
// ADD [RBP+8], RAX
|
|
|
|
// PUSHFQ
|
|
|
|
// POP [RBP]
|
|
|
|
"ADDQ", ADDQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// ADD [RBP+8], RAX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// PUSHFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
|
|
|
|
},
|
|
|
|
// POP [RBP]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t adddw =
|
|
|
|
{
|
|
|
|
// ADD [RBP+8], EAX
|
|
|
|
// PUSHFQ
|
|
|
|
// POP [RBP]
|
|
|
|
"ADDDW", ADDDW, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// ADD [RBP+8], EAX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_EAX;
|
|
|
|
},
|
|
|
|
// PUSHFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
|
|
|
|
},
|
|
|
|
// POP [RBP]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t mulq =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP+0x8]
|
|
|
|
// SUB RBP, 0x8
|
|
|
|
// MUL RDX
|
|
|
|
// MOV [RBP+0x8], RDX
|
|
|
|
// MOV [RBP+0x10], RAX
|
|
|
|
// PUSHFQ
|
|
|
|
// POP [RBP]
|
|
|
|
"MULQ", MULQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP+0x8]
|
|
|
|
[](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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
instr.operands[1].mem.index == 0x8;
|
|
|
|
},
|
|
|
|
// SUB RBP, 0x8
|
|
|
|
[](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;
|
|
|
|
},
|
|
|
|
// MUL RDX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_MUL &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
},
|
|
|
|
// MOV [RBP+0x8], 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[0].mem.index == 0x8 &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
},
|
|
|
|
// MOV [RBP+0x10], RAX
|
|
|
|
[](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[0].mem.index == 0x10 &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// PUSHFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
|
|
|
|
},
|
|
|
|
// POP [RBP]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t divq =
|
|
|
|
{
|
|
|
|
// MOV RDX, [RBP]
|
|
|
|
// MOV RAX, [RBP+0x8]
|
|
|
|
// DIV [RBP+0x10]
|
|
|
|
// MOV [RBP+0x8], RDX
|
|
|
|
// MOV [RBP+0x10], RAX
|
|
|
|
// PUSHFQ
|
|
|
|
// POP [RBP]
|
|
|
|
"DIVQ", DIVQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RDX, [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_RDX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// MOV RAX, [RBP+0x8]
|
|
|
|
[](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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
instr.operands[1].mem.index == 0x8;
|
|
|
|
},
|
|
|
|
// DIV [RBP+0x10]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_DIV &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP &&
|
|
|
|
instr.operands[0].mem.index == 0x10;
|
|
|
|
},
|
|
|
|
// MOV [RBP+0x8], 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[0].mem.index == 0x8 &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
},
|
|
|
|
// MOV [RBP+0x10], RAX
|
|
|
|
[](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[0].mem.index == 0x10 &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// PUSHFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
|
|
|
|
},
|
|
|
|
// POP [RBP]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t nandq =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP]
|
|
|
|
// MOV RDX, [RBP+8]
|
|
|
|
// NOT RAX
|
|
|
|
// NOT RDX
|
|
|
|
// AND RAX, RDX
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
// PUSHFQ
|
|
|
|
// POP [RBP]
|
|
|
|
"NANDQ", NANDQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, [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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// MOV RDX, [RBP+8]
|
|
|
|
[](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_RBP &&
|
|
|
|
instr.operands[1].mem.index == 0x8;
|
|
|
|
},
|
|
|
|
// NOT RAX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// NOT RDX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
},
|
|
|
|
// AND RAX, RDX
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_AND &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
},
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
},
|
|
|
|
// PUSHFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
|
|
|
|
},
|
|
|
|
// POP [RBP]
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{
|
|
|
|
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
|
|
|
|
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t jmp =
|
|
|
|
{
|
|
|
|
// MOV ESI, [RBP]
|
|
|
|
// ADD RSI, RAX
|
|
|
|
// MOV RBX, RSI
|
|
|
|
// ADD RSI, [RBP]
|
|
|
|
"JMP", JMP, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV ESI, [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_ESI &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// ADD RSI, RAX
|
|
|
|
[](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_RSI &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// MOV RBX, RSI
|
|
|
|
[](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_RBX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RSI;
|
|
|
|
},
|
|
|
|
// ADD RSI, [RBP]
|
|
|
|
[](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_RSI &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t writeq =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP]
|
|
|
|
// MOV RDX, [RBP+0x8]
|
|
|
|
// ADD RBP, 0x10
|
|
|
|
// MOV [RAX], RDX
|
|
|
|
"WRITEQ", WRITEQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, [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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// MOV RDX, [RBP+0x8]
|
|
|
|
[](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_RBP &&
|
|
|
|
instr.operands[1].mem.index == 0x8;
|
|
|
|
},
|
|
|
|
// ADD RBP, 0x10
|
|
|
|
[](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 == 0x10;
|
|
|
|
},
|
|
|
|
// MOV [RAX], 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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t writedw =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP]
|
|
|
|
// MOV EDX, [RBP+0x8]
|
|
|
|
// ADD RBP, 0xC
|
|
|
|
// MOV [RAX], EDX
|
|
|
|
"WRITEDW", WRITEDW, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, [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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// MOV EDX, [RBP+0x8]
|
|
|
|
[](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 &&
|
|
|
|
instr.operands[1].mem.index == 0x8;
|
|
|
|
},
|
|
|
|
// ADD RBP, 0xC
|
|
|
|
[](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 == 0xC;
|
|
|
|
},
|
|
|
|
// MOV [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[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_EDX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t readq =
|
|
|
|
{
|
|
|
|
// MOV RAX, [RBP]
|
|
|
|
// MOV RAX, [RAX]
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
"READQ", READQ, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, [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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// MOV RAX, [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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr.operands[1].mem.base == ZYDIS_REGISTER_RAX;
|
|
|
|
},
|
|
|
|
// MOV [RBP], RAX
|
|
|
|
[](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_RAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline vm::handler::profile_t vmexit =
|
|
|
|
{
|
|
|
|
// MOV RAX, RBP
|
|
|
|
// POPFQ
|
|
|
|
// RET
|
|
|
|
"VMEXIT", VMEXIT, NULL,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// MOV RAX, 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_RAX &&
|
|
|
|
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
|
|
instr.operands[1].reg.value == ZYDIS_REGISTER_RBP;
|
|
|
|
},
|
|
|
|
// POPFQ
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{ return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; },
|
|
|
|
// RET
|
|
|
|
[](const zydis_decoded_instr_t& instr) -> bool
|
|
|
|
{ return instr.mnemonic == ZYDIS_MNEMONIC_RET; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
inline std::vector<vm::handler::profile_t*> all =
|
|
|
|
{
|
|
|
|
&sregq, &sregdw, &sregw,
|
|
|
|
|
|
|
|
&lregq, &lregdw,
|
|
|
|
|
|
|
|
&lconstq, &lconstbzxw, &lconstbsxdw, &lconstdwsxq, &lconstwsxq, &lconstdw,
|
|
|
|
|
|
|
|
&pushvsp,
|
|
|
|
|
|
|
|
&addq, &adddw,
|
|
|
|
|
|
|
|
&mulq,
|
|
|
|
|
|
|
|
&divq,
|
|
|
|
|
|
|
|
&writeq, &writedw,
|
|
|
|
|
|
|
|
&readq,
|
|
|
|
|
|
|
|
&nandq,
|
|
|
|
|
|
|
|
&jmp,
|
|
|
|
|
|
|
|
&vmexit
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|