added clang format, its 90% ok

merge-requests/2/head
_xeroxz 4 years ago
parent fc46c63445
commit 4832530dfb

@ -0,0 +1,18 @@
---
BasedOnStyle: Microsoft
AlignAfterOpenBracket: Align
AllowAllArgumentsOnNextLine: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortIfStatementsOnASingleLine: Never
BreakBeforeBraces: Allman
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
SpacesInAngles: 'true'
SpacesInCStyleCastParentheses: 'true'
SpacesInContainerLiterals: 'true'
SpacesInParentheses: 'true'
SpacesInSquareBrackets: 'true'
UseTab: Never
...

@ -1,238 +1,213 @@
#pragma once #pragma once
#include <map>
#include <Zydis/Zydis.h> #include <Zydis/Zydis.h>
#include <stdexcept>
#include <functional> #include <functional>
#include <map>
#include <stdexcept>
#include <vmutils.h> #include <vmutils.h>
namespace vm namespace vm
{ {
namespace transform namespace transform
{ {
// taken from ida... // taken from ida...
template<class T> inline T __ROL__(T value, int count) template < class T > inline T __ROL__( T value, int count )
{ {
const unsigned int nbits = sizeof(T) * 8; const unsigned int nbits = sizeof( T ) * 8;
if (count > 0) if ( count > 0 )
{ {
count %= nbits; count %= nbits;
T high = value >> (nbits - count); T high = value >> ( nbits - count );
if (T(-1) < 0) // signed value if ( T( -1 ) < 0 ) // signed value
high &= ~((T(-1) << count)); high &= ~( ( T( -1 ) << count ) );
value <<= count; value <<= count;
value |= high; value |= high;
} }
else else
{ {
count = -count % nbits; count = -count % nbits;
T low = value << (nbits - count); T low = value << ( nbits - count );
value >>= count; value >>= count;
value |= low; value |= low;
} }
return value; return value;
} }
// taken from ida... // taken from ida...
inline u8 __ROL1__(u8 value, int count) { return __ROL__((u8)value, count); } inline u8 __ROL1__( u8 value, int count )
inline u16 __ROL2__(u16 value, int count) { return __ROL__((u16)value, count); } {
inline u32 __ROL4__(u32 value, int count) { return __ROL__((u32)value, count); } return __ROL__( ( u8 )value, count );
inline u64 __ROL8__(u64 value, int count) { return __ROL__((u64)value, count); } }
inline u8 __ROR1__(u8 value, int count) { return __ROL__((u8)value, -count); } inline u16 __ROL2__( u16 value, int count )
inline u16 __ROR2__(u16 value, int count) { return __ROL__((u16)value, -count); } {
inline u32 __ROR4__(u32 value, int count) { return __ROL__((u32)value, -count); } return __ROL__( ( u16 )value, count );
inline u64 __ROR8__(u64 value, int count) { return __ROL__((u64)value, -count); } }
inline u32 __ROL4__( u32 value, int count )
template <typename T> {
using transform_t = std::function<T(T, T)>; return __ROL__( ( u32 )value, count );
}
enum class type inline u64 __ROL8__( u64 value, int count )
{ {
generic0, return __ROL__( ( u64 )value, count );
rolling_key, }
generic1, inline u8 __ROR1__( u8 value, int count )
generic2, {
generic3, return __ROL__( ( u8 )value, -count );
update_key }
}; inline u16 __ROR2__( u16 value, int count )
{
using map_t = std::map<transform::type, zydis_decoded_instr_t>; return __ROL__( ( u16 )value, -count );
}
template <class T> inline u32 __ROR4__( u32 value, int count )
inline const auto _bswap = [](T a, T b) -> T {
{ return __ROL__( ( u32 )value, -count );
if constexpr (std::is_same_v<T, std::uint64_t>) }
return _byteswap_uint64(a); inline u64 __ROR8__( u64 value, int count )
if constexpr (std::is_same_v<T, std::uint32_t>) {
return _byteswap_ulong(a); return __ROL__( ( u64 )value, -count );
if constexpr (std::is_same_v<T, std::uint16_t>) }
return _byteswap_ushort(a);
template < typename T > using transform_t = std::function< T( T, T ) >;
throw std::invalid_argument("invalid type size...");
}; enum class type
{
template <class T> generic0,
inline const auto _add = [](T a, T b) -> T rolling_key,
{ generic1,
return a + b; generic2,
}; generic3,
update_key
template <class T> };
inline const auto _xor = [](T a, T b) -> T
{ using map_t = std::map< transform::type, zydis_decoded_instr_t >;
return a ^ b;
}; template < class T >
inline const auto _bswap = []( T a, T b ) -> T {
template <class T> if constexpr ( std::is_same_v< T, std::uint64_t > )
inline const auto _sub = [](T a, T b) -> T return _byteswap_uint64( a );
{ if constexpr ( std::is_same_v< T, std::uint32_t > )
return a - b; return _byteswap_ulong( a );
}; if constexpr ( std::is_same_v< T, std::uint16_t > )
return _byteswap_ushort( a );
template <class T>
inline const auto _neg = [](T a, T b) -> T throw std::invalid_argument( "invalid type size..." );
{ };
return a * -1;
}; template < class T > inline const auto _add = []( T a, T b ) -> T { return a + b; };
template <class T> template < class T > inline const auto _xor = []( T a, T b ) -> T { return a ^ b; };
inline const auto _not = [](T a, T b) -> T
{ template < class T > inline const auto _sub = []( T a, T b ) -> T { return a - b; };
return ~a;
}; template < class T > inline const auto _neg = []( T a, T b ) -> T { return a * -1; };
template <class T> template < class T > inline const auto _not = []( T a, T b ) -> T { return ~a; };
inline const auto _ror = [](T a, T b) -> T
{ template < class T >
if constexpr (std::is_same_v<T, std::uint64_t>) inline const auto _ror = []( T a, T b ) -> T {
return __ROR8__(a, b); if constexpr ( std::is_same_v< T, std::uint64_t > )
if constexpr (std::is_same_v<T, std::uint32_t>) return __ROR8__( a, b );
return __ROR4__(a, b); if constexpr ( std::is_same_v< T, std::uint32_t > )
if constexpr (std::is_same_v<T, std::uint16_t>) return __ROR4__( a, b );
return __ROR2__(a, b); if constexpr ( std::is_same_v< T, std::uint16_t > )
if constexpr (std::is_same_v <T, std::uint8_t>) return __ROR2__( a, b );
return __ROR1__(a, b); if constexpr ( std::is_same_v< T, std::uint8_t > )
return __ROR1__( a, b );
throw std::invalid_argument("invalid type size...");
}; throw std::invalid_argument( "invalid type size..." );
};
template <class T>
inline const auto _rol = [](T a, T b) -> T template < class T >
{ inline const auto _rol = []( T a, T b ) -> T {
if constexpr (std::is_same_v<T, std::uint64_t>) if constexpr ( std::is_same_v< T, std::uint64_t > )
return __ROL8__(a, b); return __ROL8__( a, b );
if constexpr (std::is_same_v<T, std::uint32_t>) if constexpr ( std::is_same_v< T, std::uint32_t > )
return __ROL4__(a, b); return __ROL4__( a, b );
if constexpr (std::is_same_v<T, std::uint16_t>) if constexpr ( std::is_same_v< T, std::uint16_t > )
return __ROL2__(a, b); return __ROL2__( a, b );
if constexpr (std::is_same_v <T, std::uint8_t>) if constexpr ( std::is_same_v< T, std::uint8_t > )
return __ROL1__(a, b); return __ROL1__( a, b );
throw std::invalid_argument("invalid type size..."); throw std::invalid_argument( "invalid type size..." );
}; };
template <class T> template < class T > inline const auto _inc = []( T a, T b ) -> T { return a + 1; };
inline const auto _inc = [](T a, T b) -> T
{ template < class T > inline const auto _dec = []( T a, T b ) -> T { return a - 1; };
return a + 1;
}; template < class T >
inline std::map< ZydisMnemonic, transform_t< T > > transforms = {
template <class T> { ZYDIS_MNEMONIC_ADD, _add< T > }, { ZYDIS_MNEMONIC_XOR, _xor< T > }, { ZYDIS_MNEMONIC_BSWAP, _bswap< T > },
inline const auto _dec = [](T a, T b) -> T { ZYDIS_MNEMONIC_SUB, _sub< T > }, { ZYDIS_MNEMONIC_NEG, _neg< T > }, { ZYDIS_MNEMONIC_NOT, _not< T > },
{ { ZYDIS_MNEMONIC_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > },
return a - 1; { ZYDIS_MNEMONIC_DEC, _dec< T > } };
};
inline std::map< ZydisMnemonic, ZydisMnemonic > inverse = {
template <class T> { ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR },
inline std::map<ZydisMnemonic, transform_t<T>> transforms = { ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD },
{ { ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT },
{ ZYDIS_MNEMONIC_ADD, _add<T> }, { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR },
{ ZYDIS_MNEMONIC_XOR, _xor<T> }, { ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } };
{ ZYDIS_MNEMONIC_BSWAP, _bswap<T> },
{ ZYDIS_MNEMONIC_SUB, _sub<T>}, inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse )
{ ZYDIS_MNEMONIC_NEG, _neg<T>}, {
{ ZYDIS_MNEMONIC_NOT, _not<T>}, inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ];
{ ZYDIS_MNEMONIC_ROR, _ror<T>}, inverse[ transform::type::generic0 ].mnemonic =
{ ZYDIS_MNEMONIC_ROL, _rol<T>}, transform::inverse[ transforms[ transform::type::generic0 ].mnemonic ];
{ ZYDIS_MNEMONIC_INC, _inc<T>},
{ ZYDIS_MNEMONIC_DEC, _dec<T>} inverse[ transform::type::rolling_key ] = transforms[ transform::type::rolling_key ];
}; inverse[ transform::type::rolling_key ].mnemonic =
transform::inverse[ transforms[ transform::type::rolling_key ].mnemonic ];
inline std::map<ZydisMnemonic, ZydisMnemonic> inverse =
{ inverse[ transform::type::generic1 ] = transforms[ transform::type::generic1 ];
{ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB}, inverse[ transform::type::generic1 ].mnemonic =
{ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR}, transform::inverse[ transforms[ transform::type::generic1 ].mnemonic ];
{ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP},
{ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD}, inverse[ transform::type::generic2 ] = transforms[ transform::type::generic2 ];
{ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG}, inverse[ transform::type::generic2 ].mnemonic =
{ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT}, transform::inverse[ transforms[ transform::type::generic2 ].mnemonic ];
{ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL},
{ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR}, inverse[ transform::type::generic3 ] = transforms[ transform::type::generic3 ];
{ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC}, inverse[ transform::type::generic3 ].mnemonic =
{ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC} transform::inverse[ transforms[ transform::type::generic3 ].mnemonic ];
};
inverse[ transform::type::update_key ] = transforms[ transform::type::update_key ];
inline void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse) inverse[ transform::type::update_key ].mnemonic =
{ transform::inverse[ transforms[ transform::type::update_key ].mnemonic ];
inverse[transform::type::generic0] = transforms[transform::type::generic0]; }
inverse[transform::type::generic0].mnemonic =
transform::inverse[transforms[transform::type::generic0].mnemonic]; inline auto inverse_transform( std::vector< zydis_decoded_instr_t > &instrs ) -> bool
{
inverse[transform::type::rolling_key] = transforms[transform::type::rolling_key]; for ( auto idx = 0u; idx < instrs.size() - 1; ++idx )
inverse[transform::type::rolling_key].mnemonic = if ( !( instrs[ idx ].mnemonic = inverse[ instrs[ idx ].mnemonic ] ) )
transform::inverse[transforms[transform::type::rolling_key].mnemonic]; return false;
inverse[transform::type::generic1] = transforms[transform::type::generic1]; return true;
inverse[transform::type::generic1].mnemonic = }
transform::inverse[transforms[transform::type::generic1].mnemonic];
// max size of a and b is 64 bits, a and b is then converted to
inverse[transform::type::generic2] = transforms[transform::type::generic2]; // the number of bits in bitsize, the transformation is applied,
inverse[transform::type::generic2].mnemonic = // finally the result is converted back to 64bits... zero extended...
transform::inverse[transforms[transform::type::generic2].mnemonic]; inline auto apply( std::uint8_t bitsize, ZydisMnemonic op, std::uint64_t a, std::uint64_t b ) -> std::uint64_t
{
inverse[transform::type::generic3] = transforms[transform::type::generic3]; switch ( bitsize )
inverse[transform::type::generic3].mnemonic = {
transform::inverse[transforms[transform::type::generic3].mnemonic]; case 8:
return transforms< std::uint8_t >[ op ]( a, b );
inverse[transform::type::update_key] = transforms[transform::type::update_key]; case 16:
inverse[transform::type::update_key].mnemonic = return transforms< std::uint16_t >[ op ]( a, b );
transform::inverse[transforms[transform::type::update_key].mnemonic]; case 32:
} return transforms< std::uint32_t >[ op ]( a, b );
case 64:
inline auto inverse_transform(std::vector<zydis_decoded_instr_t>& instrs) -> bool return transforms< std::uint64_t >[ op ]( a, b );
{ default:
for (auto idx = 0u; idx < instrs.size() - 1; ++idx) throw std::invalid_argument( "invalid bit size..." );
if (!(instrs[idx].mnemonic = inverse[instrs[idx].mnemonic])) }
return false; }
return true; inline bool has_imm( zydis_decoded_instr_t *instr )
} {
return instr->operand_count > 1 && ( instr->operands[ 1 ].type & ZYDIS_OPERAND_TYPE_IMMEDIATE );
// max size of a and b is 64 bits, a and b is then converted to }
// the number of bits in bitsize, the transformation is applied, } // namespace transform
// finally the result is converted back to 64bits... zero extended... } // namespace vm
inline auto apply(std::uint8_t bitsize, ZydisMnemonic op,
std::uint64_t a, std::uint64_t b) -> std::uint64_t
{
switch (bitsize)
{
case 8:
return transforms<std::uint8_t>[op](a, b);
case 16:
return transforms<std::uint16_t>[op](a, b);
case 32:
return transforms<std::uint32_t>[op](a, b);
case 64:
return transforms<std::uint64_t>[op](a, b);
default:
throw std::invalid_argument("invalid bit size...");
}
}
inline bool has_imm(zydis_decoded_instr_t* instr)
{
return instr->operand_count > 1 &&
(instr->operands[1].type & ZYDIS_OPERAND_TYPE_IMMEDIATE);
}
}
}

@ -3,70 +3,70 @@
namespace vmp2 namespace vmp2
{ {
enum class exec_type_t enum class exec_type_t
{ {
forward, forward,
backward backward
}; };
enum class version_t enum class version_t
{ {
invalid, invalid,
v1 = 0x101 v1 = 0x101
}; };
struct file_header struct file_header
{ {
u32 magic; // VMP2 u32 magic; // VMP2
u64 epoch_time; u64 epoch_time;
u64 module_base; u64 module_base;
exec_type_t advancement; exec_type_t advancement;
version_t version; version_t version;
u32 entry_count; u32 entry_count;
u32 entry_offset; u32 entry_offset;
}; };
struct entry_t struct entry_t
{ {
u8 handler_idx; u8 handler_idx;
u64 decrypt_key; u64 decrypt_key;
u64 vip; u64 vip;
union union
{ {
struct struct
{ {
u64 r15; u64 r15;
u64 r14; u64 r14;
u64 r13; u64 r13;
u64 r12; u64 r12;
u64 r11; u64 r11;
u64 r10; u64 r10;
u64 r9; u64 r9;
u64 r8; u64 r8;
u64 rbp; u64 rbp;
u64 rdi; u64 rdi;
u64 rsi; u64 rsi;
u64 rdx; u64 rdx;
u64 rcx; u64 rcx;
u64 rbx; u64 rbx;
u64 rax; u64 rax;
u64 rflags; u64 rflags;
}; };
u64 raw[16]; u64 raw[ 16 ];
} regs; } regs;
union union
{ {
u64 qword[0x28]; u64 qword[ 0x28 ];
u8 raw[0x140]; u8 raw[ 0x140 ];
} vregs; } vregs;
union union
{ {
u64 qword[0x20]; u64 qword[ 0x20 ];
u8 raw[0x100]; u8 raw[ 0x100 ];
} vsp; } vsp;
}; };
} } // namespace vmp2

@ -3,69 +3,68 @@
namespace vm namespace vm
{ {
namespace calc_jmp namespace calc_jmp
{ {
bool get(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp); bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp );
} }
namespace instrs namespace instrs
{ {
// decrypt transformations for encrypted virtual instruction rva... // decrypt transformations for encrypted virtual instruction rva...
bool get_rva_decrypt(const zydis_routine_t& vm_entry, bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs );
std::vector<zydis_decoded_instr_t>& transform_instrs);
std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms, std::uint64_t rolling_key );
std::uint64_t operand, std::uint64_t rolling_key);
std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand,
std::pair<std::uint64_t, std::uint64_t> encrypt_operand(transform::map_t& transforms, std::uint64_t rolling_key );
std::uint64_t operand, std::uint64_t rolling_key); } // namespace instrs
}
namespace handler
namespace handler {
{ using instr_callback_t = bool ( * )( const zydis_decoded_instr_t &instr );
using instr_callback_t = bool(*)(const zydis_decoded_instr_t& instr);
enum mnemonic_t
enum mnemonic_t {
{ INVALID,
INVALID, PUSHVSP,
PUSHVSP, SHRQ,
SHRQ, MULQ,
MULQ, DIVQ,
DIVQ, JMP,
JMP, VMEXIT,
VMEXIT,
SREGQ,
SREGQ, SREGDW,
SREGDW, SREGW,
SREGW,
LREGQ,
LREGQ, LREGDW,
LREGDW,
LCONSTQ,
LCONSTQ, LCONSTBZXW,
LCONSTBZXW, LCONSTBSXDW,
LCONSTBSXDW, LCONSTDWSXQ,
LCONSTDWSXQ, LCONSTWSXQ,
LCONSTWSXQ, LCONSTDW,
LCONSTDW,
READQ,
READQ, READDW,
READDW, READW,
READW,
WRITEQ,
WRITEQ, WRITEDW,
WRITEDW, WRITEW,
WRITEW,
ADDQ,
ADDQ, ADDDW,
ADDDW,
SHLQ,
SHLQ, SHLDW,
SHLDW,
NANDQ,
NANDQ, NANDDW
NANDDW };
};
enum extention_t enum extention_t
{ {
@ -76,97 +75,85 @@ namespace vm
struct profile_t struct profile_t
{ {
const char* name; const char *name;
mnemonic_t mnemonic; mnemonic_t mnemonic;
u8 imm_size; u8 imm_size;
std::vector<instr_callback_t> signature; std::vector< instr_callback_t > signature;
extention_t extention; extention_t extention;
}; };
struct handler_t struct handler_t
{ {
u8 imm_size; // size in bits... u8 imm_size; // size in bits...
vm::transform::map_t transforms; vm::transform::map_t transforms;
vm::handler::profile_t* profile; vm::handler::profile_t *profile;
zydis_routine_t instrs; zydis_routine_t instrs;
std::uintptr_t address; std::uintptr_t address;
}; };
bool has_imm(const zydis_routine_t& vm_handler); bool has_imm( const zydis_routine_t &vm_handler );
std::uint8_t imm_size(const zydis_routine_t& vm_handler); std::uint8_t imm_size( const zydis_routine_t &vm_handler );
bool get(zydis_routine_t& vm_entry, zydis_routine_t& vm_handler, std::uintptr_t handler_addr); bool get( zydis_routine_t &vm_entry, zydis_routine_t &vm_handler, std::uintptr_t handler_addr );
// may throw an exception... // may throw an exception...
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base, bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry,
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<handler_t>& vm_handlers); std::uintptr_t *vm_handler_table, std::vector< handler_t > &vm_handlers );
// can be used on calc_jmp... // can be used on calc_jmp...
bool get_operand_transforms(const zydis_routine_t& vm_handler, transform::map_t& transforms); bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms );
vm::handler::profile_t* get_profile(handler_t& vm_handler); vm::handler::profile_t *get_profile( handler_t &vm_handler );
namespace table namespace table
{ {
std::uintptr_t* get(const zydis_routine_t& vm_entry); std::uintptr_t *get( const zydis_routine_t &vm_entry );
bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr); bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr );
std::uint64_t encrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val); std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val );
std::uint64_t decrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val); std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val );
} } // namespace table
namespace profile namespace profile
{ {
extern vm::handler::profile_t sregq; extern vm::handler::profile_t sregq;
extern vm::handler::profile_t sregdw; extern vm::handler::profile_t sregdw;
extern vm::handler::profile_t sregw; extern vm::handler::profile_t sregw;
extern vm::handler::profile_t lregq; extern vm::handler::profile_t lregq;
extern vm::handler::profile_t lregdw; extern vm::handler::profile_t lregdw;
extern vm::handler::profile_t lconstq; extern vm::handler::profile_t lconstq;
extern vm::handler::profile_t lconstbzxw; extern vm::handler::profile_t lconstbzxw;
extern vm::handler::profile_t lconstbsxdw; extern vm::handler::profile_t lconstbsxdw;
extern vm::handler::profile_t lconstdwsxq; extern vm::handler::profile_t lconstdwsxq;
extern vm::handler::profile_t lconstwsxq; extern vm::handler::profile_t lconstwsxq;
extern vm::handler::profile_t lconstdw; extern vm::handler::profile_t lconstdw;
extern vm::handler::profile_t addq; extern vm::handler::profile_t addq;
extern vm::handler::profile_t adddw; extern vm::handler::profile_t adddw;
extern vm::handler::profile_t shlq; extern vm::handler::profile_t shlq;
extern vm::handler::profile_t shldw; extern vm::handler::profile_t shldw;
extern vm::handler::profile_t nandq; extern vm::handler::profile_t nandq;
extern vm::handler::profile_t nanddw; extern vm::handler::profile_t nanddw;
extern vm::handler::profile_t writeq; extern vm::handler::profile_t writeq;
extern vm::handler::profile_t writedw; extern vm::handler::profile_t writedw;
extern vm::handler::profile_t shrq; extern vm::handler::profile_t shrq;
extern vm::handler::profile_t pushvsp; extern vm::handler::profile_t pushvsp;
extern vm::handler::profile_t mulq; extern vm::handler::profile_t mulq;
extern vm::handler::profile_t divq; extern vm::handler::profile_t divq;
extern vm::handler::profile_t jmp; extern vm::handler::profile_t jmp;
extern vm::handler::profile_t readq; extern vm::handler::profile_t readq;
extern vm::handler::profile_t vmexit; extern vm::handler::profile_t vmexit;
inline std::vector<vm::handler::profile_t*> all = inline std::vector< vm::handler::profile_t * > all = {
{ &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw,
&sregq, &sregdw, &sregw, &lconstbsxdw, &lconstdwsxq, &lconstwsxq, &lconstdw, &addq, &adddw, &shlq,
&lregq, &lregdw, &shldw, &writeq, &writedw, &nandq, &nanddw,
&lconstq, &lconstbzxw, &lconstbsxdw, &lconstdwsxq, &lconstwsxq, &lconstdw,
&addq, &adddw, &shrq, &readq, &mulq, &pushvsp, &divq, &jmp, &vmexit };
&shlq, &shldw, } // namespace profile
&writeq, &writedw, } // namespace handler
&nandq, &nanddw, } // namespace vm
&shrq,
&readq,
&mulq,
&pushvsp,
&divq,
&jmp,
&vmexit
};
}
}
}

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector>
#include <Zydis/Zydis.h>
#include <Zydis/Utils.h> #include <Zydis/Utils.h>
#include <Zydis/Zydis.h>
#include <vector>
#include <xmmintrin.h> #include <xmmintrin.h>
using u8 = unsigned char; using u8 = unsigned char;
@ -15,29 +15,29 @@ using zydis_register_t = ZydisRegister;
struct zydis_instr_t struct zydis_instr_t
{ {
zydis_decoded_instr_t instr; zydis_decoded_instr_t instr;
std::vector<u8> raw; std::vector< u8 > raw;
std::uintptr_t addr; std::uintptr_t addr;
}; };
using zydis_routine_t = std::vector<zydis_instr_t>; using zydis_routine_t = std::vector< zydis_instr_t >;
namespace vm namespace vm
{ {
namespace util namespace util
{ {
namespace reg namespace reg
{ {
// converts say... AL to RAX... // converts say... AL to RAX...
zydis_register_t to64(zydis_register_t reg); zydis_register_t to64( zydis_register_t reg );
bool compare(zydis_register_t a, zydis_register_t b); bool compare( zydis_register_t a, zydis_register_t b );
} } // namespace reg
void print(zydis_routine_t& routine); void print( zydis_routine_t &routine );
void print(const zydis_decoded_instr_t& instr); void print( const zydis_decoded_instr_t &instr );
bool is_jmp(const zydis_decoded_instr_t& instr); bool is_jmp( const zydis_decoded_instr_t &instr );
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps = false); bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps = false );
void deobfuscate(zydis_routine_t& routine); void deobfuscate( zydis_routine_t &routine );
} } // namespace util
} } // namespace vm

@ -2,32 +2,30 @@
namespace vm namespace vm
{ {
namespace calc_jmp namespace calc_jmp
{ {
bool get(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp) bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp )
{ {
auto result = std::find_if(vm_entry.begin(), vm_entry.end(), auto result =
[](const zydis_instr_t& instr_data) -> bool std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
{ // mov/movsx/movzx rax/eax/ax/al, [rsi]
// mov/movsx/movzx rax/eax/ax/al, [rsi] if ( instr_data.instr.operand_count > 1 &&
if (instr_data.instr.operand_count > 1 && ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX && instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI) return true;
return true; return false;
return false; } );
}
);
if (result == vm_entry.end()) if ( result == vm_entry.end() )
return false; return false;
calc_jmp.insert(calc_jmp.end(), result, vm_entry.end()); calc_jmp.insert( calc_jmp.end(), result, vm_entry.end() );
return true; return true;
} }
} } // namespace calc_jmp
} } // namespace vm

@ -2,398 +2,349 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
bool get(zydis_routine_t& calc_jmp, zydis_routine_t& vm_handler, std::uintptr_t handler_addr) bool get( zydis_routine_t &calc_jmp, zydis_routine_t &vm_handler, std::uintptr_t handler_addr )
{ {
if (!vm::util::flatten(vm_handler, handler_addr)) if ( !vm::util::flatten( vm_handler, handler_addr ) )
return false; return false;
vm::util::deobfuscate(vm_handler); vm::util::deobfuscate( vm_handler );
static const auto calc_jmp_check = static const auto calc_jmp_check = [ & ]( std::uintptr_t addr ) -> bool {
[&](std::uintptr_t addr) -> bool for ( const auto &[ instr, instr_raw, instr_addr ] : calc_jmp )
{ if ( instr_addr == addr )
for (const auto& [instr, instr_raw, instr_addr] : calc_jmp) return true;
if (instr_addr == addr)
return true; return false;
};
return false;
}; auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr ) -> bool {
if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
auto result = std::find_if( instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
vm_handler.begin(), vm_handler.end(), instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI &&
[](const zydis_instr_t& instr) -> bool instr.instr.operands[ 1 ].mem.disp.value == 0xE0 )
{ return true;
if (instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
instr.instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && return calc_jmp_check( instr.addr );
instr.instr.operands[1].mem.base == ZYDIS_REGISTER_RDI && } );
instr.instr.operands[1].mem.disp.value == 0xE0)
return true; // remove calc_jmp from the vm handler vector...
if ( result != vm_handler.end() )
return calc_jmp_check(instr.addr); vm_handler.erase( result, vm_handler.end() );
} else // locate the last mov al, [rsi],
); // then remove all instructions after that...
{
// remove calc_jmp from the vm handler vector... zydis_routine_t::iterator last = vm_handler.end();
if (result != vm_handler.end()) result = vm_handler.begin();
vm_handler.erase(result, vm_handler.end());
else // locate the last mov al, [rsi], while ( result != vm_handler.end() )
// then remove all instructions after that... {
{ result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
zydis_routine_t::iterator last = vm_handler.end(); // mov/movsx/movzx rax/eax/ax/al, [rsi]
result = vm_handler.begin(); if ( instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
while (result != vm_handler.end()) instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
{ instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
result = std::find_if( instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
++result, vm_handler.end(), util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
[](const zydis_instr_t& instr_data) -> bool instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
// mov/movsx/movzx rax/eax/ax/al, [rsi] return true;
if (instr_data.instr.operand_count > 1 && return false;
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || } );
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && if ( result != vm_handler.end() )
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && last = result;
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX && }
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI) if ( last != vm_handler.end() )
return true; vm_handler.erase( last, vm_handler.end() );
return false; }
} return true;
); }
if (result != vm_handler.end()) bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry,
last = result; std::uintptr_t *vm_handler_table, std::vector< vm::handler::handler_t > &vm_handlers )
} {
zydis_decoded_instr_t instr;
if (last != vm_handler.end()) if ( !vm::handler::table::get_transform( vm_entry, &instr ) )
vm_handler.erase(last, vm_handler.end()); return false;
}
return true; zydis_routine_t calc_jmp;
} if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) )
return false;
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base,
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<vm::handler::handler_t>& vm_handlers) for ( auto idx = 0u; idx < 256; ++idx )
{ {
zydis_decoded_instr_t instr; const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] );
if (!vm::handler::table::get_transform(vm_entry, &instr))
return false; handler_t vm_handler;
vm::transform::map_t transforms;
zydis_routine_t calc_jmp; zydis_routine_t vm_handler_instrs;
if (!vm::calc_jmp::get(vm_entry, calc_jmp))
return false; if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) )
return false;
for (auto idx = 0u; idx < 256; ++idx)
{ const auto has_imm = vm::handler::has_imm( vm_handler_instrs );
const auto decrypt_val =
vm::handler::table::decrypt( const auto imm_size = vm::handler::imm_size( vm_handler_instrs );
instr, vm_handler_table[idx]);
if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) )
handler_t vm_handler; return false;
vm::transform::map_t transforms;
zydis_routine_t vm_handler_instrs; vm_handler.address = ( decrypt_val - image_base ) + module_base;
vm_handler.instrs = vm_handler_instrs;
if (!vm::handler::get(calc_jmp, vm_handler_instrs, (decrypt_val - image_base) + module_base)) vm_handler.imm_size = imm_size;
return false; vm_handler.transforms = transforms;
vm_handler.profile = vm::handler::get_profile( vm_handler );
const auto has_imm = vm_handlers.push_back( vm_handler );
vm::handler::has_imm(vm_handler_instrs); }
const auto imm_size = return true;
vm::handler::imm_size(vm_handler_instrs); }
if (has_imm && !vm::handler::get_operand_transforms(vm_handler_instrs, transforms)) bool has_imm( const zydis_routine_t &vm_handler )
return false; {
const auto result =
vm_handler.address = (decrypt_val - image_base) + module_base; std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
vm_handler.instrs = vm_handler_instrs; // mov/movsx/movzx rax/eax/ax/al, [rsi]
vm_handler.imm_size = imm_size; if ( instr_data.instr.operand_count > 1 &&
vm_handler.transforms = transforms; ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
vm_handler.profile = vm::handler::get_profile(vm_handler); instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
vm_handlers.push_back(vm_handler); instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
} instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
return true; instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
} instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
return true;
bool has_imm(const zydis_routine_t& vm_handler) return false;
{ } );
const auto result = std::find_if(
vm_handler.begin(), vm_handler.end(), return result != vm_handler.end();
[](const zydis_instr_t& instr_data) -> bool }
{
// mov/movsx/movzx rax/eax/ax/al, [rsi] std::uint8_t imm_size( const zydis_routine_t &vm_handler )
if (instr_data.instr.operand_count > 1 && {
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || const auto result =
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && // mov/movsx/movzx rax/eax/ax/al, [rsi]
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && if ( instr_data.instr.operand_count > 1 &&
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX && ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI) instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
return true; instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return false; util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
} instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
); instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
return true;
return result != vm_handler.end(); return false;
} } );
std::uint8_t imm_size(const zydis_routine_t& vm_handler) if ( result == vm_handler.end() )
{ return 0u;
const auto result = std::find_if(
vm_handler.begin(), vm_handler.end(), return result->instr.operands[ 1 ].size;
[](const zydis_instr_t& instr_data) -> bool }
{
// mov/movsx/movzx rax/eax/ax/al, [rsi] bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms )
if (instr_data.instr.operand_count > 1 && {
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || auto imm_fetch =
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && // mov/movsx/movzx rax/eax/ax/al, [rsi]
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && if ( instr_data.instr.operand_count > 1 &&
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX && ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI) instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
return true; instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return false; util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
} instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
); instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
return true;
if (result == vm_handler.end()) return false;
return 0u; } );
return result->instr.operands[1].size; if ( imm_fetch == vm_handler.end() )
} return false;
bool get_operand_transforms(const zydis_routine_t& vm_handler, transform::map_t& transforms) // this finds the first transformation which looks like:
{ // transform rax, rbx <--- note these registers can be smaller so we to64 them...
auto imm_fetch = std::find_if( auto key_transform =
vm_handler.begin(), vm_handler.end(), std::find_if( imm_fetch, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
[](const zydis_instr_t& instr_data) -> bool if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
{ util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) )
// mov/movsx/movzx rax/eax/ax/al, [rsi] return true;
if (instr_data.instr.operand_count > 1 && return false;
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || } );
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) && if ( key_transform == vm_handler.end() )
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && return false;
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && // look for a primer/instruction that alters RAX prior to the 5 transformations...
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI) auto generic0 = std::find_if( imm_fetch + 1, key_transform, []( const zydis_instr_t &instr_data ) -> bool {
return true; return util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
return false; !util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX );
} } );
);
zydis_decoded_instr_t nogeneric0;
if (imm_fetch == vm_handler.end()) nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
return false;
transforms[ transform::type::generic0 ] = generic0 != key_transform ? generic0->instr : nogeneric0;
// this finds the first transformation which looks like:
// transform rax, rbx <--- note these registers can be smaller so we to64 them... // last transformation is the same as the first except src and dest are swwapped...
auto key_transform = std::find_if(imm_fetch, vm_handler.end(), transforms[ transform::type::rolling_key ] = key_transform->instr;
[](const zydis_instr_t& instr_data) -> bool auto instr_copy = key_transform->instr;
{ instr_copy.operands[ 0 ].reg.value = key_transform->instr.operands[ 1 ].reg.value;
if (util::reg::compare(instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX) && instr_copy.operands[ 1 ].reg.value = key_transform->instr.operands[ 0 ].reg.value;
util::reg::compare(instr_data.instr.operands[1].reg.value, ZYDIS_REGISTER_RBX)) transforms[ transform::type::update_key ] = instr_copy;
return true;
return false; // three generic transformations...
} auto generic_transform = key_transform;
);
for ( auto idx = 2u; idx < 5; ++idx )
if (key_transform == vm_handler.end()) {
return false; generic_transform =
std::find_if( ++generic_transform, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// look for a primer/instruction that alters RAX prior to the 5 transformations... if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) )
auto generic0 = std::find_if(imm_fetch + 1, key_transform, return true;
[](const zydis_instr_t& instr_data) -> bool
{ return false;
return util::reg::compare( } );
instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX) &&
!util::reg::compare(instr_data.instr.operands[1].reg.value, ZYDIS_REGISTER_RBX); if ( generic_transform == vm_handler.end() )
} return false;
);
transforms[ ( transform::type )( idx ) ] = generic_transform->instr;
zydis_decoded_instr_t nogeneric0; }
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
return true;
transforms[transform::type::generic0] = }
generic0 != key_transform ? generic0->instr : nogeneric0;
vm::handler::profile_t *get_profile( handler_t &vm_handler )
// last transformation is the same as the first except src and dest are swwapped... {
transforms[transform::type::rolling_key] = key_transform->instr; static const auto vcontains = []( vm::handler::profile_t *vprofile, handler_t *vm_handler ) -> bool {
auto instr_copy = key_transform->instr; if ( vprofile->imm_size != vm_handler->imm_size )
instr_copy.operands[0].reg.value = key_transform->instr.operands[1].reg.value; return false;
instr_copy.operands[1].reg.value = key_transform->instr.operands[0].reg.value;
transforms[transform::type::update_key] = instr_copy; for ( auto &instr : vprofile->signature )
{
// three generic transformations... const auto contains = std::find_if(
auto generic_transform = key_transform; vm_handler->instrs.begin(), vm_handler->instrs.end(),
for (auto idx = 2u; idx < 5; ++idx) [ & ]( zydis_instr_t &instr_data ) -> bool { return instr( instr_data.instr ); } );
{
generic_transform = std::find_if(++generic_transform, vm_handler.end(), if ( contains == vm_handler->instrs.end() )
[](const zydis_instr_t& instr_data) -> bool return false;
{ }
if (util::reg::compare(instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX))
return true; return true;
};
return false;
} for ( auto profile : vm::handler::profile::all )
); if ( vcontains( profile, &vm_handler ) )
return profile;
if (generic_transform == vm_handler.end())
return false; return nullptr;
}
transforms[(transform::type)(idx)] = generic_transform->instr;
} namespace table
{
return true; std::uintptr_t *get( const zydis_routine_t &vm_entry )
} {
const auto result =
vm::handler::profile_t* get_profile(handler_t& vm_handler) std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
{ const auto instr = &instr_data.instr;
static const auto vcontains = // lea r12, vm_handlers... (always r12)...
[](vm::handler::profile_t* vprofile, handler_t* vm_handler) -> bool if ( instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
{ instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
if (vprofile->imm_size != vm_handler->imm_size) instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 &&
return false; !instr->raw.sib.base ) // no register used for the sib base...
return true;
for (auto& instr : vprofile->signature)
{ return false;
const auto contains = std::find_if } );
(
vm_handler->instrs.begin(), if ( result == vm_entry.end() )
vm_handler->instrs.end(), return nullptr;
[&](zydis_instr_t& instr_data) -> bool std::uintptr_t ptr = 0u;
{ return instr(instr_data.instr); } ZydisCalcAbsoluteAddress( &result->instr, &result->instr.operands[ 1 ], result->addr, &ptr );
);
return reinterpret_cast< std::uintptr_t * >( ptr );
if (contains == vm_handler->instrs.end()) }
return false;
} bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr )
{
return true; zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
};
auto handler_fetch =
for (auto profile : vm::handler::profile::all) std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
if (vcontains(profile, &vm_handler)) const auto instr = &instr_data.instr;
return profile; if ( instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 &&
instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return nullptr; instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 &&
} instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX &&
instr->operands[ 1 ].mem.scale == 8 &&
namespace table instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX ||
std::uintptr_t* get(const zydis_routine_t& vm_entry) instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ) )
{ {
const auto result = std::find_if( rcx_or_rdx = instr->operands[ 0 ].reg.value;
vm_entry.begin(), vm_entry.end(), return true;
[](const zydis_instr_t& instr_data) -> bool }
{
const auto instr = &instr_data.instr; return false;
// lea r12, vm_handlers... (always r12)... } );
if (instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
instr->operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // check to see if we found the fetch instruction and if the next instruction
instr->operands[0].reg.value == ZYDIS_REGISTER_R12 && // is not the end of the vector...
!instr->raw.sib.base) // no register used for the sib base... if ( handler_fetch == vm_entry.end() || ++handler_fetch == vm_entry.end() ||
return true; // must be RCX or RDX... else something went wrong...
( rcx_or_rdx != ZYDIS_REGISTER_RCX && rcx_or_rdx != ZYDIS_REGISTER_RDX ) )
return false; return false;
}
); // find the next instruction that writes to RCX or RDX...
// the register is determined by the vm handler fetch above...
if (result == vm_entry.end()) auto handler_transform =
return nullptr; std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx &&
std::uintptr_t ptr = 0u; instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE )
ZydisCalcAbsoluteAddress(&result->instr, return true;
&result->instr.operands[1], result->addr, &ptr); return false;
} );
return reinterpret_cast<std::uintptr_t*>(ptr);
} if ( handler_transform == vm_entry.end() )
return false;
bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr)
{ *transform_instr = handler_transform->instr;
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE; return true;
}
auto handler_fetch = std::find_if(
vm_entry.begin(), vm_entry.end(), std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val )
[&](const zydis_instr_t& instr_data) -> bool {
{ assert( transform_instr.operands[ 0 ].size == 64,
const auto instr = &instr_data.instr; "invalid transformation for vm handler table entries..." );
if (instr->mnemonic == ZYDIS_MNEMONIC_MOV &&
instr->operand_count == 2 && const auto operation = vm::transform::inverse[ transform_instr.mnemonic ];
instr->operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && const auto bitsize = transform_instr.operands[ 0 ].size;
instr->operands[1].mem.base == ZYDIS_REGISTER_R12 && const auto imm =
instr->operands[1].mem.index == ZYDIS_REGISTER_RAX && vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u;
instr->operands[1].mem.scale == 8 &&
instr->operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && return vm::transform::apply( bitsize, operation, val, imm );
(instr->operands[0].reg.value == ZYDIS_REGISTER_RDX || }
instr->operands[0].reg.value == ZYDIS_REGISTER_RCX))
{ std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val )
rcx_or_rdx = instr->operands[0].reg.value; {
return true; assert( transform_instr.operands[ 0 ].size == 64,
} "invalid transformation for vm handler table entries..." );
return false; const auto operation = transform_instr.mnemonic;
} const auto bitsize = transform_instr.operands[ 0 ].size;
); const auto imm =
vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u;
// check to see if we found the fetch instruction and if the next instruction
// is not the end of the vector... return vm::transform::apply( bitsize, operation, val, imm );
if (handler_fetch == vm_entry.end() || ++handler_fetch == vm_entry.end() || }
// must be RCX or RDX... else something went wrong... } // namespace table
(rcx_or_rdx != ZYDIS_REGISTER_RCX && rcx_or_rdx != ZYDIS_REGISTER_RDX)) } // namespace handler
return false; } // namespace vm
// find the next instruction that writes to RCX or RDX...
// the register is determined by the vm handler fetch above...
auto handler_transform = std::find_if(
handler_fetch, vm_entry.end(),
[&](const zydis_instr_t& instr_data) -> bool
{
if (instr_data.instr.operands[0].reg.value == rcx_or_rdx &&
instr_data.instr.operands[0].actions & ZYDIS_OPERAND_ACTION_WRITE)
return true;
return false;
}
);
if (handler_transform == vm_entry.end())
return false;
*transform_instr = handler_transform->instr;
return true;
}
std::uint64_t encrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val)
{
assert(transform_instr.operands[0].size == 64,
"invalid transformation for vm handler table entries...");
const auto operation = vm::transform::inverse[transform_instr.mnemonic];
const auto bitsize = transform_instr.operands[0].size;
const auto imm = vm::transform::has_imm(&transform_instr) ?
transform_instr.operands[1].imm.value.u : 0u;
return vm::transform::apply(bitsize, operation, val, imm);
}
std::uint64_t decrypt(zydis_decoded_instr_t& transform_instr, std::uint64_t val)
{
assert(transform_instr.operands[0].size == 64,
"invalid transformation for vm handler table entries...");
const auto operation = transform_instr.mnemonic;
const auto bitsize = transform_instr.operands[0].size;
const auto imm = vm::transform::has_imm(&transform_instr) ?
transform_instr.operands[1].imm.value.u : 0u;
return vm::transform::apply(bitsize, operation, val, imm);
}
}
}
}

@ -2,190 +2,165 @@
namespace vm namespace vm
{ {
namespace instrs namespace instrs
{ {
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms, std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
std::uint64_t operand, std::uint64_t rolling_key) std::uint64_t rolling_key )
{ {
const auto generic_decrypt_0 = &transforms[transform::type::generic0]; const auto generic_decrypt_0 = &transforms[ transform::type::generic0 ];
const auto key_decrypt = &transforms[transform::type::rolling_key]; const auto key_decrypt = &transforms[ transform::type::rolling_key ];
const auto generic_decrypt_1 = &transforms[transform::type::generic1]; const auto generic_decrypt_1 = &transforms[ transform::type::generic1 ];
const auto generic_decrypt_2 = &transforms[transform::type::generic2]; const auto generic_decrypt_2 = &transforms[ transform::type::generic2 ];
const auto generic_decrypt_3 = &transforms[transform::type::generic3]; const auto generic_decrypt_3 = &transforms[ transform::type::generic3 ];
const auto update_key = &transforms[transform::type::update_key]; const auto update_key = &transforms[ transform::type::update_key ];
if (generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID) if ( generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID )
{ {
operand = transform::apply( operand = transform::apply(
generic_decrypt_0->operands[0].size, generic_decrypt_0->operands[ 0 ].size, generic_decrypt_0->mnemonic, operand,
generic_decrypt_0->mnemonic, operand, // check to see if this instruction has an IMM...
// check to see if this instruction has an IMM... transform::has_imm( generic_decrypt_0 ) ? generic_decrypt_0->operands[ 1 ].imm.value.u : 0 );
transform::has_imm(generic_decrypt_0) ? }
generic_decrypt_0->operands[1].imm.value.u : 0);
} // apply transformation with rolling decrypt key...
operand = transform::apply( key_decrypt->operands[ 0 ].size, key_decrypt->mnemonic, operand, rolling_key );
// apply transformation with rolling decrypt key...
operand = transform::apply(key_decrypt->operands[0].size, // apply three generic transformations...
key_decrypt->mnemonic, operand, rolling_key); {
operand = transform::apply(
// apply three generic transformations... generic_decrypt_1->operands[ 0 ].size, generic_decrypt_1->mnemonic, operand,
{ // check to see if this instruction has an IMM...
operand = transform::apply( transform::has_imm( generic_decrypt_1 ) ? generic_decrypt_1->operands[ 1 ].imm.value.u : 0 );
generic_decrypt_1->operands[0].size,
generic_decrypt_1->mnemonic, operand, operand = transform::apply(
// check to see if this instruction has an IMM... generic_decrypt_2->operands[ 0 ].size, generic_decrypt_2->mnemonic, operand,
transform::has_imm(generic_decrypt_1) ? // check to see if this instruction has an IMM...
generic_decrypt_1->operands[1].imm.value.u : 0); transform::has_imm( generic_decrypt_2 ) ? generic_decrypt_2->operands[ 1 ].imm.value.u : 0 );
operand = transform::apply( operand = transform::apply(
generic_decrypt_2->operands[0].size, generic_decrypt_3->operands[ 0 ].size, generic_decrypt_3->mnemonic, operand,
generic_decrypt_2->mnemonic, operand, // check to see if this instruction has an IMM...
// check to see if this instruction has an IMM... transform::has_imm( generic_decrypt_3 ) ? generic_decrypt_3->operands[ 1 ].imm.value.u : 0 );
transform::has_imm(generic_decrypt_2) ? }
generic_decrypt_2->operands[1].imm.value.u : 0);
// update rolling key...
operand = transform::apply( auto result =
generic_decrypt_3->operands[0].size, transform::apply( update_key->operands[ 0 ].size, update_key->mnemonic, rolling_key, operand );
generic_decrypt_3->mnemonic, operand,
// check to see if this instruction has an IMM... // update decryption key correctly...
transform::has_imm(generic_decrypt_3) ? switch ( update_key->operands[ 0 ].size )
generic_decrypt_3->operands[1].imm.value.u : 0); {
} case 8:
rolling_key = ( rolling_key & ~0xFFull ) + result;
// update rolling key... break;
auto result = transform::apply(update_key->operands[0].size, case 16:
update_key->mnemonic, rolling_key, operand); rolling_key = ( rolling_key & ~0xFFFFull ) + result;
break;
// update decryption key correctly... default:
switch (update_key->operands[0].size) rolling_key = result;
{ break;
case 8: }
rolling_key = (rolling_key & ~0xFFull) + result;
break; return { operand, rolling_key };
case 16: }
rolling_key = (rolling_key & ~0xFFFFull) + result;
break; std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand,
default: std::uint64_t rolling_key )
rolling_key = result; {
break; transform::map_t inverse;
} inverse_transforms( transforms, inverse );
return { operand, rolling_key }; const auto generic_decrypt_0 = &inverse[ transform::type::generic0 ];
} const auto key_decrypt = &inverse[ transform::type::rolling_key ];
const auto generic_decrypt_1 = &inverse[ transform::type::generic1 ];
std::pair<std::uint64_t, std::uint64_t> encrypt_operand(transform::map_t& transforms, const auto generic_decrypt_2 = &inverse[ transform::type::generic2 ];
std::uint64_t operand, std::uint64_t rolling_key) const auto generic_decrypt_3 = &inverse[ transform::type::generic3 ];
{ const auto update_key = &inverse[ transform::type::update_key ];
transform::map_t inverse;
inverse_transforms(transforms, inverse); auto result =
transform::apply( update_key->operands[ 0 ].size, update_key->mnemonic, rolling_key, operand );
const auto generic_decrypt_0 = &inverse[transform::type::generic0];
const auto key_decrypt = &inverse[transform::type::rolling_key]; // make sure we update the rolling decryption key correctly...
const auto generic_decrypt_1 = &inverse[transform::type::generic1]; switch ( update_key->operands[ 0 ].size )
const auto generic_decrypt_2 = &inverse[transform::type::generic2]; {
const auto generic_decrypt_3 = &inverse[transform::type::generic3]; case 8:
const auto update_key = &inverse[transform::type::update_key]; rolling_key = ( rolling_key & ~0xFFull ) + result;
break;
auto result = transform::apply(update_key->operands[0].size, case 16:
update_key->mnemonic, rolling_key, operand); rolling_key = ( rolling_key & ~0xFFFFull ) + result;
break;
// make sure we update the rolling decryption key correctly... default:
switch (update_key->operands[0].size) rolling_key = result;
{ break;
case 8: }
rolling_key = (rolling_key & ~0xFFull) + result;
break; {
case 16: operand = transform::apply(
rolling_key = (rolling_key & ~0xFFFFull) + result; generic_decrypt_3->operands[ 0 ].size, generic_decrypt_3->mnemonic, operand,
break; // check to see if this instruction has an IMM...
default: transform::has_imm( generic_decrypt_3 ) ? generic_decrypt_3->operands[ 1 ].imm.value.u : 0 );
rolling_key = result;
break; operand = transform::apply(
} generic_decrypt_2->operands[ 0 ].size, generic_decrypt_2->mnemonic, operand,
// check to see if this instruction has an IMM...
{ transform::has_imm( generic_decrypt_2 ) ? generic_decrypt_2->operands[ 1 ].imm.value.u : 0 );
operand = transform::apply(
generic_decrypt_3->operands[0].size, operand = transform::apply(
generic_decrypt_3->mnemonic, operand, generic_decrypt_1->operands[ 0 ].size, generic_decrypt_1->mnemonic, operand,
// check to see if this instruction has an IMM... // check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_3) ? transform::has_imm( generic_decrypt_1 ) ? generic_decrypt_1->operands[ 1 ].imm.value.u : 0 );
generic_decrypt_3->operands[1].imm.value.u : 0); }
operand = transform::apply( operand = transform::apply( key_decrypt->operands[ 0 ].size, key_decrypt->mnemonic, operand, rolling_key );
generic_decrypt_2->operands[0].size,
generic_decrypt_2->mnemonic, operand, if ( generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID )
// check to see if this instruction has an IMM... {
transform::has_imm(generic_decrypt_2) ? operand = transform::apply(
generic_decrypt_2->operands[1].imm.value.u : 0); generic_decrypt_0->operands[ 0 ].size, generic_decrypt_0->mnemonic, operand,
// check to see if this instruction has an IMM...
operand = transform::apply( transform::has_imm( generic_decrypt_0 ) ? generic_decrypt_0->operands[ 1 ].imm.value.u : 0 );
generic_decrypt_1->operands[0].size, }
generic_decrypt_1->mnemonic, operand,
// check to see if this instruction has an IMM... return { operand, rolling_key };
transform::has_imm(generic_decrypt_1) ? }
generic_decrypt_1->operands[1].imm.value.u : 0);
} bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs )
{
operand = transform::apply(key_decrypt->operands[0].size, //
key_decrypt->mnemonic, operand, rolling_key); // find mov esi, [rsp+0xA0]
//
if (generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID)
{ auto result =
operand = transform::apply( std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
generic_decrypt_0->operands[0].size, if ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr_data.instr.operand_count == 2 &&
generic_decrypt_0->mnemonic, operand, instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI &&
// check to see if this instruction has an IMM... instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSP &&
transform::has_imm(generic_decrypt_0) ? instr_data.instr.operands[ 1 ].mem.disp.has_displacement &&
generic_decrypt_0->operands[1].imm.value.u : 0); instr_data.instr.operands[ 1 ].mem.disp.value == 0xA0 )
} return true;
return false;
return { operand, rolling_key }; } );
}
if ( result == vm_entry.end() )
bool get_rva_decrypt( return false;
const zydis_routine_t& vm_entry, std::vector<zydis_decoded_instr_t>& transform_instrs)
{ //
// // find the next three instruction with ESI as the dest...
// find mov esi, [rsp+0xA0] //
//
for ( auto idx = 0u; idx < 3; ++idx )
auto result = std::find_if(vm_entry.begin(), vm_entry.end(), {
[](const zydis_instr_t& instr_data) -> bool result = std::find_if( ++result, vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
{ return instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI;
if (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV && } );
instr_data.instr.operand_count == 2 &&
instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI && if ( result == vm_entry.end() )
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSP && return false;
instr_data.instr.operands[1].mem.disp.has_displacement &&
instr_data.instr.operands[1].mem.disp.value == 0xA0) transform_instrs.push_back( result->instr );
return true; }
return false;
} return true;
); }
} // namespace instrs
if (result == vm_entry.end()) } // namespace vm
return false;
//
// find the next three instruction with ESI as the dest...
//
for (auto idx = 0u; idx < 3; ++idx)
{
result = std::find_if(++result, vm_entry.end(),
[](const zydis_instr_t& instr_data) -> bool
{
return instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI;
}
);
if (result == vm_entry.end())
return false;
transform_instrs.push_back(result->instr);
}
return true;
}
}
}

@ -172,6 +172,9 @@
<Project>{88a23124-5640-35a0-b890-311d7a67a7d2}</Project> <Project>{88a23124-5640-35a0-b890-311d7a67a7d2}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\.clang-format" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

@ -27,6 +27,9 @@
<Filter Include="Source Files\vmprofiles"> <Filter Include="Source Files\vmprofiles">
<UniqueIdentifier>{388154c1-cb08-493f-88fb-7e16cfffa010}</UniqueIdentifier> <UniqueIdentifier>{388154c1-cb08-493f-88fb-7e16cfffa010}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Resources">
<UniqueIdentifier>{5bb0ecc9-da37-4a13-8958-3c8eef2ceab5}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="vmutils.cpp"> <ClCompile Include="vmutils.cpp">
@ -224,4 +227,9 @@
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\.clang-format">
<Filter>Resources</Filter>
</None>
</ItemGroup>
</Project> </Project>

@ -2,75 +2,61 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t addq = vm::handler::profile_t addq = {
{ // ADD [RBP+8], RAX
// ADD [RBP+8], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "ADDQ",
"ADDQ", ADDQ, NULL, ADDQ,
{ NULL,
{ { { // ADD [RBP+8], RAX
// ADD [RBP+8], RAX []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; // PUSHFQ
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
[](const zydis_decoded_instr_t& instr) -> bool },
{ // POP [RBP]
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
// POP [RBP] instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
{ } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
vm::handler::profile_t adddw = vm::handler::profile_t adddw = {
{ // ADD [RBP+8], EAX
// ADD [RBP+8], EAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "ADDDW",
"ADDDW", ADDDW, NULL, ADDDW,
{ NULL,
{ { { // ADD [RBP+8], EAX
// ADD [RBP+8], EAX []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_EAX; // PUSHFQ
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
[](const zydis_decoded_instr_t& instr) -> bool },
{ // POP [RBP]
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
// POP [RBP] instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
{ } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_POP && } // namespace profile
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && } // namespace handler
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP; } // namespace vm
}
}
}
};
}
}
}

@ -2,84 +2,73 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t divq = vm::handler::profile_t divq = {
{ // MOV RDX, [RBP]
// MOV RDX, [RBP] // MOV RAX, [RBP+0x8]
// MOV RAX, [RBP+0x8] // DIV [RBP+0x10]
// DIV [RBP+0x10] // MOV [RBP+0x8], RDX
// MOV [RBP+0x8], RDX // MOV [RBP+0x10], RAX
// MOV [RBP+0x10], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "DIVQ",
"DIVQ", DIVQ, NULL, DIVQ,
{ NULL,
{ { { // MOV RDX, [RBP]
// MOV RDX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// MOV RAX, [RBP+0x8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // DIV [RBP+0x10]
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_DIV &&
// DIV [RBP+0x10] instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 0 ].mem.index == 0x10;
return instr.mnemonic == ZYDIS_MNEMONIC_DIV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // MOV [RBP+0x8], RDX
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x10; return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// MOV [RBP+0x8], RDX instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.index == 0x8 &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && // MOV [RBP+0x10], RAX
instr.operands[0].mem.index == 0x8 && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP+0x10], RAX instr.operands[ 0 ].mem.index == 0x10 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x10 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; } } } };
}, }
// POP [RBP] } // namespace handler
[](const zydis_decoded_instr_t& instr) -> bool } // namespace vm
{
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,58 +2,50 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t jmp = vm::handler::profile_t jmp = {
{ // MOV ESI, [RBP]
// MOV ESI, [RBP] // ADD RSI, RAX
// ADD RSI, RAX // MOV RBX, RSI
// MOV RBX, RSI // ADD RSI, [RBP]
// ADD RSI, [RBP] "JMP",
"JMP", JMP, NULL, JMP,
{ NULL,
{ { { // MOV ESI, [RBP]
// MOV ESI, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_ESI && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// ADD RSI, RAX return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
instr.operands[0].reg.value == ZYDIS_REGISTER_RSI && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV RBX, RSI
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV RBX, RSI instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBX &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RSI;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBX && // ADD RSI, [RBP]
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].reg.value == ZYDIS_REGISTER_RSI; return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// ADD RSI, [RBP] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && } } } };
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && }
instr.operands[0].reg.value == ZYDIS_REGISTER_RSI && } // namespace handler
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && } // namespace vm
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,204 +2,161 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t lconstq = vm::handler::profile_t lconstq = {
{ // MOV RAX, [RSI]
// MOV RAX, [RSI] // SUB RBP, 8
// SUB RBP, 8 // MOV [RBP], RAX
// MOV [RBP], RAX "LCONSTQ",
"LCONSTQ", LCONSTQ, 64, LCONSTQ,
{ 64,
{ { { // SUB RBP, 8
// SUB RBP, 8 []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].imm.value.u == 0x8;
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 {
// MOV [RBP], RAX return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
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::profile_t lconstbzxw = vm::handler::profile_t lconstbzxw = {
{ // MOV AL, [RSI]
// MOV AL, [RSI] // SUB RBP, 2
// SUB RBP, 2 // MOV [RBP], AX
// MOV [RBP], AX "LCONSTBZXW",
"LCONSTBZXW", LCONSTBZXW, 8, LCONSTBZXW,
{ 8,
{ { { // SUB RBP, 2
// SUB RBP, 2 []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].imm.value.u == 0x2;
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 {
// MOV [RBP], AX return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && } } } };
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[1].reg.value == ZYDIS_REGISTER_AX;
}
}
}
};
vm::handler::profile_t lconstbsxdw = vm::handler::profile_t lconstbsxdw = {
{ // CWDE
// CWDE // SUB RBP, 4
// SUB RBP, 4 // MOV [RBP], EAX
// MOV [RBP], EAX "LCONSTBSXDW",
"LCONSTBSXDW", LCONSTBSXDW, 8, LCONSTBSXDW,
{ 8,
{ { { // CWDE
// CWDE []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; },
[](const zydis_decoded_instr_t& instr) -> bool // SUB RBP, 4
{ []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SUB RBP, 4 instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
{ instr.operands[ 1 ].imm.value.u == 0x4;
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP], EAX
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].imm.value.u == 0x4; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP], EAX instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
{ } } },
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && vm::handler::extention_t::sign_extend };
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
};
vm::handler::profile_t lconstdwsxq = vm::handler::profile_t lconstdwsxq = {
{ // CDQE
// CDQE // SUB RBP, 8
// SUB RBP, 8 // MOV [RBP], RAX
// MOV [RBP], RAX "LCONSTDWSXQ",
"LCONSTDWSXQ", LCONSTDWSXQ, 32, LCONSTDWSXQ,
{ 32,
// CDQE { // CDQE
[](const zydis_decoded_instr_t& instr) -> bool []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; },
{ // SUB RBP, 8
return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
// SUB RBP, 8 instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].imm.value.u == 0x8;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // MOV [RBP], RAX
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0x8; return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// MOV [RBP], RAX instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && } },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && vm::handler::extention_t::sign_extend };
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
};
vm::handler::profile_t lconstwsxq = vm::handler::profile_t lconstwsxq = {
{ // CDQE
// CDQE // SUB RBP, 8
// SUB RBP, 8 // MOV [RBP], RAX
// MOV [RBP], RAX "LCONSTWSXQ",
"LCONSTWSXQ", LCONSTWSXQ, 16, LCONSTWSXQ,
{ 16,
{ { { // CDQE
// CDQE []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; },
[](const zydis_decoded_instr_t& instr) -> bool // SUB RBP, 8
{ []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SUB RBP, 8 instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
{ instr.operands[ 1 ].imm.value.u == 0x8;
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP], RAX
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].imm.value.u == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP], RAX instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
{ } } },
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && vm::handler::extention_t::sign_extend };
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
};
vm::handler::profile_t lconstdw = vm::handler::profile_t lconstdw = {
{ // SUB RBP, 4
// SUB RBP, 4 // MOV [RBP], EAX
// MOV [RBP], EAX "LCONSTDW",
"LCONSTDW", LCONSTDW, 32, LCONSTDW,
{ 32,
{ { { // SUB RBP, 4
// SUB RBP, 4 []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].imm.value.u == 0x4;
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 {
// MOV [RBP], EAX return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && } } } };
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace profile
instr.operands[1].reg.value == ZYDIS_REGISTER_EAX; } // namespace handler
} } // namespace vm
}
}
};
}
}
}

@ -2,94 +2,80 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t lregq = vm::handler::profile_t lregq = {
{ // MOV RDX, [RAX+RDI]
// MOV RDX, [RAX+RDI] // SUB RBP, 8
// SUB RBP, 8 // MOV [RBP], RDX
// MOV [RBP], RDX "LREGQ",
"LREGQ", LREGQ, 8, LREGQ,
{ 8,
{ { { // MOV RDX, [RAX+RDI] or MOV RDX, [RDI+RAX]
// MOV RDX, [RAX+RDI] or MOV RDX, [RDI+RAX] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX && ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX ||
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) &&
(instr.operands[1].mem.base == ZYDIS_REGISTER_RAX || ( instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RDI ||
instr.operands[1].mem.base == ZYDIS_REGISTER_RDI) && instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX );
(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 {
// SUB RBP, 8 return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x8;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RBP], RDX
instr.operands[1].imm.value.u == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RBP], RDX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
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;
}
}
}
};
vm::handler::profile_t lregdw = vm::handler::profile_t lregdw = {
{ // MOVZX AL, [RSI]
// MOVZX AL, [RSI] // MOV RDX, [RAX + RDI]
// MOV RDX, [RAX + RDI] // SUB RBP, 0x4
// SUB RBP, 0x4 // MOV [RBP], EDX
// MOV [RBP], EDX "LREGDW",
"LREGDW", LREGDW, 8, LREGDW,
{ 8,
{ { { // MOV RDX, [RAX + RDI] or MOV RDX, [RDI + RAX]
// MOV RDX, [RAX + RDI] or MOV RDX, [RDI + RAX] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_EDX && ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX ||
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) &&
(instr.operands[1].mem.base == ZYDIS_REGISTER_RAX || ( instr.operands[ 1 ].mem.index == 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 || },
instr.operands[1].mem.index == ZYDIS_REGISTER_RDI); // SUB RBP, 0x4
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// SUB RBP, 0x4 return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x4;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RBP], EDX
instr.operands[1].imm.value.u == 0x4; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RBP], EDX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && } } } };
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && } // namespace profile
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace handler
instr.operands[1].reg.value == ZYDIS_REGISTER_EDX; } // namespace vm
}
}
}
};
}
}
}

@ -2,83 +2,72 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t mulq = vm::handler::profile_t mulq = {
{ // MOV RAX, [RBP+0x8]
// MOV RAX, [RBP+0x8] // SUB RBP, 0x8
// SUB RBP, 0x8 // MUL RDX
// MUL RDX // MOV [RBP+0x8], RDX
// MOV [RBP+0x8], RDX // MOV [RBP+0x10], RAX
// MOV [RBP+0x10], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "MULQ",
"MULQ", MULQ, NULL, MULQ,
{ NULL,
{ { { // MOV RAX, [RBP+0x8]
// MOV RAX, [RBP+0x8] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && },
instr.operands[1].mem.index == 0x8; // SUB RBP, 0x8
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// SUB RBP, 0x8 return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x8;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MUL RDX
instr.operands[1].imm.value.u == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MUL &&
// MUL RDX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
{ },
return instr.mnemonic == ZYDIS_MNEMONIC_MUL && // MOV [RBP+0x8], RDX
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX; return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// MOV [RBP+0x8], RDX instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.index == 0x8 &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && // MOV [RBP+0x10], RAX
instr.operands[0].mem.index == 0x8 && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP+0x10], RAX instr.operands[ 0 ].mem.index == 0x10 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x10 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; } } } };
}, }
// POP [RBP] } // namespace handler
[](const zydis_decoded_instr_t& instr) -> bool } // namespace vm
{
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,152 +2,129 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t nandq = vm::handler::profile_t nandq = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV RDX, [RBP+8]
// MOV RDX, [RBP+8] // NOT RAX
// NOT RAX // NOT RDX
// NOT RDX // AND RAX, RDX
// AND RAX, RDX // MOV [RBP], RAX
// MOV [RBP], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "NANDQ",
"NANDQ", NANDQ, NULL, NANDQ,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// MOV RDX, [RBP+8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // NOT RAX
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
// NOT RAX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX;
{ },
return instr.mnemonic == ZYDIS_MNEMONIC_NOT && // NOT RDX
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX; return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// NOT RDX instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
[](const zydis_decoded_instr_t& instr) -> bool },
{ // AND RAX, RDX
return instr.mnemonic == ZYDIS_MNEMONIC_NOT && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_AND &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
// AND RAX, RDX instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
{ },
return instr.mnemonic == ZYDIS_MNEMONIC_AND && // MOV [RBP], RAX
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[1].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
}, instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV [RBP], RAX instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
[](const zydis_decoded_instr_t& instr) -> bool },
{ // PUSHFQ
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && // POP [RBP]
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
// PUSHFQ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
{ } } } };
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;
}
}
}
};
vm::handler::profile_t nanddw = vm::handler::profile_t nanddw = {
{ // NOT DWORD PTR [RBP]
// NOT DWORD PTR [RBP] // MOV AX, [RBP]
// MOV AX, [RBP] // SUB RBP, 0x6
// SUB RBP, 0x6 // AND [RBP+0x8], AX
// AND [RBP+0x8], AX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "NANDDW",
"NANDDW", NANDDW, NULL, NANDDW,
{ NULL,
{ { { // NOT DWORD PTR [RBP]
// NOT DWORD PTR [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_NOT && instr.operands[ 0 ].size == 32 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[0].size == 32 && // MOV AX, [RBP]
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV AX, [RBP] instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_AX && // SUB RBP, 0x6
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP; return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SUB RBP, 0x6 instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
{ instr.operands[ 1 ].imm.value.u == 0x6;
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // AND [RBP+0x8], AX
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && return instr.mnemonic == ZYDIS_MNEMONIC_AND &&
instr.operands[1].imm.value.u == 0x6; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// AND [RBP+0x8], AX instr.operands[ 0 ].mem.index == 0x8 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
return instr.mnemonic == ZYDIS_MNEMONIC_AND && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x8 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_AX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; } } } };
}, } // namespace profile
// POP [RBP] } // namespace handler
[](const zydis_decoded_instr_t& instr) -> bool } // namespace vm
{
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,47 +2,40 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t pushvsp = vm::handler::profile_t pushvsp = {
{ // MOV RAX, RBP
// MOV RAX, RBP // SUB RBP, 8
// SUB RBP, 8 "PUSHVSP",
"PUSHVSP", PUSHVSP, NULL, PUSHVSP,
{ NULL,
{ { { // MOV RAX, RBP
// MOV RAX, RBP []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP;
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 {
// SUB RBP, 8 return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x8;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RBP], RAX
instr.operands[1].imm.value.u == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RBP], RAX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && } } } };
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && }
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace handler
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; } // namespace vm
}
}
}
};
}
}
}

@ -2,48 +2,41 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t readq = vm::handler::profile_t readq = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV RAX, [RAX]
// MOV RAX, [RAX] // MOV [RBP], RAX
// MOV [RBP], RAX "READQ",
"READQ", READQ, NULL, READQ,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// MOV RAX, [RAX] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX;
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && // MOV [RBP], RAX
instr.operands[1].mem.base == ZYDIS_REGISTER_RAX; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RBP], RAX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && } } } };
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && }
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace handler
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; } // namespace vm
}
}
}
};
}
}
}

@ -2,159 +2,137 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t shlq = vm::handler::profile_t shlq = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV CL, [RBP+0x8]
// MOV CL, [RBP+0x8] // SUB RBP, 0x6
// SUB RBP, 0x6 // SHL RAX, CL
// SHL RAX, CL // MOV [RBP+0x8], RAX
// MOV [RBP+0x8], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "SHLQ",
"SHLQ", SHLQ, NULL, SHLQ,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP; // MOV CL, [RBP+0x8]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// MOV CL, [RBP+0x8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_CL && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // SUB RBP, 0x6
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
// SUB RBP, 0x6 instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].imm.value.u == 0x6;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // SHL RAX, CL
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0x6; return instr.mnemonic == ZYDIS_MNEMONIC_SHL &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SHL RAX, CL instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL;
return instr.mnemonic == ZYDIS_MNEMONIC_SHL && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP+0x8], RAX
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].reg.value == ZYDIS_REGISTER_CL; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP+0x8], RAX instr.operands[ 0 ].mem.index == 0x8 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x8 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
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;
}
}
}
};
vm::handler::profile_t shldw = vm::handler::profile_t shldw = {
{ // MOV EAX, [RBP]
// MOV EAX, [RBP] // MOV CL, [RBP+0x4]
// MOV CL, [RBP+0x4] // SUB RBP, 0x6
// SUB RBP, 0x6 // SHL EAX, CL
// SHL EAX, CL // MOV [RBP+0x8], EAX
// MOV [RBP+0x8], EAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "SHLQ",
"SHLQ", SHLQ, NULL, SHLQ,
{ NULL,
{ { { // MOV EAX, [RBP]
// MOV EAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_EAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP; // MOV CL, [RBP+0x4]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// MOV CL, [RBP+0x4] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_CL && instr.operands[ 1 ].mem.index == 0x4;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // SUB RBP, 0x6
instr.operands[1].mem.index == 0x4; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
// SUB RBP, 0x6 instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].imm.value.u == 0x6;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // SHL EAX, CL
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0x6; return instr.mnemonic == ZYDIS_MNEMONIC_SHL &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SHL EAX, CL instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL;
return instr.mnemonic == ZYDIS_MNEMONIC_SHL && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP+0x8], EAX
instr.operands[0].reg.value == ZYDIS_REGISTER_EAX && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].reg.value == ZYDIS_REGISTER_CL; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP+0x8], EAX instr.operands[ 0 ].mem.index == 0x8 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x8 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_EAX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; } } } };
}, } // namespace profile
// POP [RBP] } // namespace handler
[](const zydis_decoded_instr_t& instr) -> bool } // namespace vm
{
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,84 +2,73 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t shrq = vm::handler::profile_t shrq = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV CL, [RBP+0x8]
// MOV CL, [RBP+0x8] // SUB RBP, 0x6
// SUB RBP, 0x6 // SHR RAX, CL
// SHR RAX, CL // MOV [RBP+0x8], RAX
// MOV [RBP+0x8], RAX // PUSHFQ
// PUSHFQ // POP [RBP]
// POP [RBP] "SHRQ",
"SHRQ", SHRQ, NULL, SHRQ,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP; // MOV CL, [RBP+0x8]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// MOV CL, [RBP+0x8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_CL && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // SUB RBP, 0x6
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
// SUB RBP, 0x6 instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 1 ].imm.value.u == 0x6;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // SHR RAX, CL
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0x6; return instr.mnemonic == ZYDIS_MNEMONIC_SHR &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// SHR RAX, CL instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL;
return instr.mnemonic == ZYDIS_MNEMONIC_SHR && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP+0x8], RAX
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[1].reg.value == ZYDIS_REGISTER_CL; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
// MOV [RBP+0x8], RAX instr.operands[ 0 ].mem.index == 0x8 &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[0].mem.index == 0x8 && return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[1].reg.value == ZYDIS_REGISTER_RAX; // POP [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// PUSHFQ return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; } } } };
}, }
// POP [RBP] } // namespace handler
[](const zydis_decoded_instr_t& instr) -> bool } // namespace vm
{
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RBP;
}
}
}
};
}
}
}

@ -2,135 +2,114 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t sregq = vm::handler::profile_t sregq = {
{ // MOV RDX, [RBP]
// MOV RDX, [RBP] // ADD RBP, 8
// ADD RBP, 8 // MOV [RAX+RDI], RDX
// MOV [RAX+RDI], RDX "SREGQ",
"SREGQ", SREGQ, 8, SREGQ,
{ 8,
{ { { // MOV RDX, [RBP]
// MOV RDX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// ADD RBP, 8 return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 8;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RAX+RDI], RDX or MOV [RDI+RAX], RDX
instr.operands[1].imm.value.u == 8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RAX+RDI], RDX or MOV [RDI+RAX], RDX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX ||
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI ||
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) &&
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX || instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
(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;
}
}
}
};
vm::handler::profile_t sregdw = vm::handler::profile_t sregdw = {
{ // MOV EDX, [RBP]
// MOV EDX, [RBP] // ADD RBP, 0x4
// ADD RBP, 0x4 // MOV [RAX+RDI], EDX
// MOV [RAX+RDI], EDX "SREGDW",
"SREGDW", SREGDW, 8, SREGDW,
{ 8,
{ { { // MOV EDX, [RBP]
// MOV EDX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_EDX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// ADD RBP, 0x4 return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x4;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RAX+RDI], EDX or MOV [RDI+RAX], EDX
instr.operands[1].imm.value.u == 0x4; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RAX+RDI], EDX or MOV [RDI+RAX], EDX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX ||
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ||
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI ) &&
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX || instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX;
(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;
}
}
}
};
vm::handler::profile_t sregw = vm::handler::profile_t sregw = {
{ // MOV DX, [RBP]
// MOV DX, [RBP] // ADD RBP, 0x2
// ADD RBP, 0x2 // MOV [RAX+RDI], DX
// MOV [RAX+RDI], DX "SREGW",
"SREGW", SREGW, 8, SREGW,
{ 8,
{ { { // MOV DX, [RBP]
// MOV DX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_DX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// ADD RBP, 0x2 return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].imm.value.u == 0x2;
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && },
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && // MOV [RAX+RDI], DX or MOV [RDI+RAX], DX
instr.operands[1].imm.value.u == 0x2; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RAX+RDI], DX or MOV [RDI+RAX], DX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[](const zydis_decoded_instr_t& instr) -> bool ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX ||
{ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI ||
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) &&
(instr.operands[0].mem.base == ZYDIS_REGISTER_RAX || instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].mem.base == ZYDIS_REGISTER_RDI) && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DX;
(instr.operands[0].mem.index == ZYDIS_REGISTER_RDI || } } } };
instr.operands[0].mem.index == ZYDIS_REGISTER_RAX) && } // namespace profile
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace handler
instr.operands[1].reg.value == ZYDIS_REGISTER_DX; } // namespace vm
}
}
}
};
}
}
}

@ -2,36 +2,31 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t vmexit = vm::handler::profile_t vmexit = {
{ // MOV RAX, RBP
// MOV RAX, RBP // POPFQ
// POPFQ // RET
// RET "VMEXIT",
"VMEXIT", VMEXIT, NULL, VMEXIT,
{ NULL,
{ { { // MOV RAX, RBP
// MOV RAX, RBP []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP;
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; },
// POPFQ // RET
[](const zydis_decoded_instr_t& instr) -> bool []( const zydis_decoded_instr_t &instr ) -> bool {
{ return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; }, return instr.mnemonic == ZYDIS_MNEMONIC_RET;
// RET } } } };
[](const zydis_decoded_instr_t& instr) -> bool }
{ return instr.mnemonic == ZYDIS_MNEMONIC_RET; } } // namespace handler
} } // namespace vm
}
};
}
}
}

@ -2,109 +2,93 @@
namespace vm namespace vm
{ {
namespace handler namespace handler
{ {
namespace profile namespace profile
{ {
vm::handler::profile_t writeq = vm::handler::profile_t writeq = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV RDX, [RBP+0x8]
// MOV RDX, [RBP+0x8] // ADD RBP, 0x10
// ADD RBP, 0x10 // MOV [RAX], RDX
// MOV [RAX], RDX "WRITEQ",
"WRITEQ", WRITEQ, NULL, WRITEQ,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// MOV RDX, [RBP+0x8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RDX && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // ADD RBP, 0x10
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
// ADD RBP, 0x10 instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].imm.value.u == 0x10;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // MOV [RAX], RDX
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0x10; return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// MOV [RAX], RDX instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
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;
}
}
}
};
vm::handler::profile_t writedw = vm::handler::profile_t writedw = {
{ // MOV RAX, [RBP]
// MOV RAX, [RBP] // MOV EDX, [RBP+0x8]
// MOV EDX, [RBP+0x8] // ADD RBP, 0xC
// ADD RBP, 0xC // MOV [RAX], EDX
// MOV [RAX], EDX "WRITEDW",
"WRITEDW", WRITEDW, NULL, WRITEDW,
{ NULL,
{ { { // MOV RAX, [RBP]
// MOV RAX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[](const zydis_decoded_instr_t& instr) -> bool return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
{ instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
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 {
// MOV EDX, [RBP+0x8] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[0].reg.value == ZYDIS_REGISTER_EDX && instr.operands[ 1 ].mem.index == 0x8;
instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[1].mem.base == ZYDIS_REGISTER_RBP && // ADD RBP, 0xC
instr.operands[1].mem.index == 0x8; []( const zydis_decoded_instr_t &instr ) -> bool {
}, return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
// ADD RBP, 0xC instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
{ instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].imm.value.u == 0xC;
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[0].reg.value == ZYDIS_REGISTER_RBP && // MOV [RAX], EDX
instr.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[1].imm.value.u == 0xC; return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// MOV [RAX], EDX instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
[](const zydis_decoded_instr_t& instr) -> bool instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && } } } };
instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && } // namespace profile
instr.operands[0].mem.base == ZYDIS_REGISTER_RAX && } // namespace handler
instr.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && } // namespace vm
instr.operands[1].reg.value == ZYDIS_REGISTER_EDX;
}
}
}
};
}
}
}

@ -7,48 +7,45 @@ namespace vm
{ {
namespace reg namespace reg
{ {
zydis_register_t to64(zydis_register_t reg) zydis_register_t to64( zydis_register_t reg )
{ {
return ZydisRegisterGetLargestEnclosing( return ZydisRegisterGetLargestEnclosing( ZYDIS_MACHINE_MODE_LONG_64, reg );
ZYDIS_MACHINE_MODE_LONG_64, reg);
} }
bool compare(zydis_register_t a, zydis_register_t b) bool compare( zydis_register_t a, zydis_register_t b )
{ {
return to64(a) == to64(b); return to64( a ) == to64( b );
} }
} } // namespace reg
void print(const zydis_decoded_instr_t& instr) void print( const zydis_decoded_instr_t &instr )
{ {
char buffer[256]; char buffer[ 256 ];
ZydisFormatter formatter; ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
ZydisFormatterFormatInstruction(&formatter, &instr, ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u );
buffer, sizeof(buffer), 0u);
puts(buffer); puts( buffer );
} }
void print(zydis_routine_t& routine) void print( zydis_routine_t &routine )
{ {
char buffer[256]; char buffer[ 256 ];
ZydisFormatter formatter; ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
for (auto [instr, raw, addr] : routine) for ( auto [ instr, raw, addr ] : routine )
{ {
std::printf("> 0x%p ", addr); std::printf( "> 0x%p ", addr );
ZydisFormatterFormatInstruction(&formatter, &instr, ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr );
buffer, sizeof(buffer), addr);
puts(buffer); puts( buffer );
} }
} }
bool is_jmp(const zydis_decoded_instr_t& instr) bool is_jmp( const zydis_decoded_instr_t &instr )
{ {
switch (instr.mnemonic) switch ( instr.mnemonic )
{ {
case ZYDIS_MNEMONIC_JB: case ZYDIS_MNEMONIC_JB:
case ZYDIS_MNEMONIC_JBE: case ZYDIS_MNEMONIC_JBE:
@ -79,150 +76,142 @@ namespace vm
return false; return false;
} }
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps) bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps )
{ {
ZydisDecoder decoder; ZydisDecoder decoder;
zydis_decoded_instr_t instr; zydis_decoded_instr_t instr;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); ZydisDecoderInit( &decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64 );
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, reinterpret_cast<void*>( while ( ZYAN_SUCCESS(
routine_addr), 0x1000, &instr))) ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) )
{ {
std::vector<u8> raw_instr; std::vector< u8 > raw_instr;
raw_instr.insert(raw_instr.begin(), raw_instr.insert( raw_instr.begin(), ( u8 * )routine_addr, ( u8 * )routine_addr + instr.length );
(u8*)routine_addr,
(u8*)routine_addr + instr.length);
if (is_jmp(instr)) if ( is_jmp( instr ) )
{ {
if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) if ( instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER )
{ {
routine.push_back({ instr, raw_instr, routine_addr }); routine.push_back( { instr, raw_instr, routine_addr } );
return true; return true;
} }
if (keep_jmps) if ( keep_jmps )
routine.push_back({ instr, raw_instr, routine_addr }); routine.push_back( { instr, raw_instr, routine_addr } );
ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr, &routine_addr); ZydisCalcAbsoluteAddress( &instr, &instr.operands[ 0 ], routine_addr, &routine_addr );
} }
else if (instr.mnemonic == ZYDIS_MNEMONIC_RET) else if ( instr.mnemonic == ZYDIS_MNEMONIC_RET )
{ {
routine.push_back({ instr, raw_instr, routine_addr }); routine.push_back( { instr, raw_instr, routine_addr } );
return true; return true;
} }
else else
{ {
routine.push_back({ instr, raw_instr, routine_addr }); routine.push_back( { instr, raw_instr, routine_addr } );
routine_addr += instr.length; routine_addr += instr.length;
} }
} }
return false; return false;
} }
void deobfuscate(zydis_routine_t& routine) void deobfuscate( zydis_routine_t &routine )
{ {
static const auto _uses = static const auto _uses = []( ZydisDecodedOperand &op, zydis_register_t reg ) -> bool {
[](ZydisDecodedOperand& op, zydis_register_t reg) -> bool switch ( op.type )
{
switch (op.type)
{ {
case ZYDIS_OPERAND_TYPE_MEMORY: case ZYDIS_OPERAND_TYPE_MEMORY:
{ {
return reg::compare(op.mem.base, reg) || reg::compare(op.mem.index, reg); return reg::compare( op.mem.base, reg ) || reg::compare( op.mem.index, reg );
} }
case ZYDIS_OPERAND_TYPE_REGISTER: case ZYDIS_OPERAND_TYPE_REGISTER:
{ {
return reg::compare(op.reg.value, reg); return reg::compare( op.reg.value, reg );
} }
} }
return false; return false;
}; };
static const auto _writes = static const auto _writes = []( zydis_decoded_instr_t &inst ) -> bool {
[](zydis_decoded_instr_t& inst) -> bool for ( auto idx = 0; idx < inst.operand_count; ++idx )
{ if ( inst.operands[ idx ].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE )
for (auto idx = 0; idx < inst.operand_count; ++idx)
if (inst.operands[idx].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE)
return true; return true;
return false; return false;
}; };
static const auto _remove = static const auto _remove = []( zydis_routine_t &routine, zydis_routine_t::iterator itr,
[](zydis_routine_t& routine, zydis_routine_t::iterator itr, zydis_register_t reg, u32 opcode_size ) -> void {
zydis_register_t reg, u32 opcode_size) -> void for ( ; itr >= routine.begin(); --itr )
{
for (; itr >= routine.begin(); --itr)
{ {
const auto instruction = &itr->instr; const auto instruction = &itr->instr;
bool stop = false; bool stop = false;
if (instruction->mnemonic == ZYDIS_MNEMONIC_JMP) if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP )
continue; continue;
for (auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx) for ( auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx )
{ {
const auto op = &instruction->operands[op_idx]; const auto op = &instruction->operands[ op_idx ];
if (!_uses(*op, reg)) if ( !_uses( *op, reg ) )
continue; continue;
if (op->type == ZYDIS_OPERAND_TYPE_MEMORY) if ( op->type == ZYDIS_OPERAND_TYPE_MEMORY )
{ {
stop = true; stop = true;
continue; continue;
} }
if (opcode_size < 32 && op->size > opcode_size) if ( opcode_size < 32 && op->size > opcode_size )
continue; continue;
if (op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE) if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE )
op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE; op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE;
else stop = true; else
stop = true;
} }
if (!_writes(*instruction)) if ( !_writes( *instruction ) )
routine.erase(itr); routine.erase( itr );
else if (stop) break; else if ( stop )
break;
} }
}; };
for (const auto& instr_data : routine) for ( const auto &instr_data : routine )
{ {
if (routine.empty() || routine.size() == 1 || if ( routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP )
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP)
continue; continue;
for (auto itr = routine.begin() + 1; itr != routine.end(); itr++) for ( auto itr = routine.begin() + 1; itr != routine.end(); itr++ )
{ {
if (itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || if ( itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || itr->instr.mnemonic == ZYDIS_MNEMONIC_RET )
itr->instr.mnemonic == ZYDIS_MNEMONIC_RET)
break; break;
// find the write operations that happen... // find the write operations that happen...
for (auto idx = 0u; idx < itr->instr.operand_count; ++idx) for ( auto idx = 0u; idx < itr->instr.operand_count; ++idx )
{ {
const auto op = &itr->instr.operands[idx]; const auto op = &itr->instr.operands[ idx ];
// if its a read, continue to next opcode... // if its a read, continue to next opcode...
if (op->actions & ZYDIS_OPERAND_ACTION_MASK_READ) if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_READ )
continue; continue;
// if its not a write then continue to next opcode... // if its not a write then continue to next opcode...
if (!(op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE)) if ( !( op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) )
continue; continue;
// if this operand is not a register then we continue... // if this operand is not a register then we continue...
if (op->type != ZYDIS_OPERAND_TYPE_REGISTER) if ( op->type != ZYDIS_OPERAND_TYPE_REGISTER )
continue; continue;
// else we see if we can remove dead writes to this register... // else we see if we can remove dead writes to this register...
_remove(routine, itr - 1, op->reg.value, op->size); _remove( routine, itr - 1, op->reg.value, op->size );
} }
} }
} }
} }
} } // namespace util
} } // namespace vm
Loading…
Cancel
Save