cleaned the code a bunch more...

merge-requests/11/head
_xeroxz 3 years ago
parent ae9f255180
commit 13fef335fe

@ -119,7 +119,33 @@ namespace vm::handler
extern vm::handler::profile_t lregq; extern vm::handler::profile_t lregq;
extern vm::handler::profile_t lregdw; extern vm::handler::profile_t lregdw;
/// <summary>
/// mov rax, [rsi]
/// xor rax, rbx ; transformation
/// bswap rax ; transformation
/// lea rsi, [rsi+8] ; advance VIP…
/// rol rax, 0Ch ; transformation
/// inc rax ; transformation
/// xor rbx, rax ; transformation (update rolling decrypt key)
/// sub rbp, 8
/// mov [rbp+0], rax
/// </summary>
extern vm::handler::profile_t lconstq; extern vm::handler::profile_t lconstq;
/// <summary>
/// mov eax, [rsi-0x04]
/// bswap eax
/// add eax, ebx
/// dec eax
/// neg eax
/// xor eax, 0x2FFD187C
/// push rbx
/// add [rsp], eax
/// pop rbx
/// sub rbp, 0x04
/// mov [rbp], eax
/// add rsi, 0xFFFFFFFFFFFFFFFC
/// </summary>
extern vm::handler::profile_t lconstdw; extern vm::handler::profile_t lconstdw;
extern vm::handler::profile_t lconstw; extern vm::handler::profile_t lconstw;
@ -130,7 +156,21 @@ namespace vm::handler
extern vm::handler::profile_t lconstwsxq; extern vm::handler::profile_t lconstwsxq;
extern vm::handler::profile_t lconstwsxdw; extern vm::handler::profile_t lconstwsxdw;
/// <summary>
/// mov rax, [rbp+0]
/// add [rbp+8], rax
/// pushfq
/// pop qword ptr [rbp+0]
/// </summary>
extern vm::handler::profile_t addq; extern vm::handler::profile_t addq;
/// <summary>
/// mov ax, [rbp]
/// sub rbp, 0x06
/// add [rbp+0x08], ax
/// pushfq
/// pop [rbp]
/// </summary>
extern vm::handler::profile_t adddw; extern vm::handler::profile_t adddw;
extern vm::handler::profile_t addw; extern vm::handler::profile_t addw;
@ -152,10 +192,36 @@ namespace vm::handler
extern vm::handler::profile_t shrw; extern vm::handler::profile_t shrw;
extern vm::handler::profile_t lrflags; extern vm::handler::profile_t lrflags;
/// <summary>
/// mov rdx, [rbp]
/// add rbp, 0x08
/// call rdx
/// </summary>
extern vm::handler::profile_t call; extern vm::handler::profile_t call;
extern vm::handler::profile_t pushvsp; extern vm::handler::profile_t pushvsp;
extern vm::handler::profile_t mulq; extern vm::handler::profile_t mulq;
/// <summary>
/// mov rdx, [rbp]
/// mov rax, [rbp+0x08]
/// div [rbp+0x10]
/// mov [rbp+0x08], rdx
/// mov [rbp+0x10], rax
/// pushfq
/// pop [rbp]
/// </summary>
extern vm::handler::profile_t divq; extern vm::handler::profile_t divq;
/// <summary>
/// mov esi, [rbp]
/// add rbp, 0x08
/// lea r12, [0x0000000000048F29]
/// mov rax, 0x00 ; image base bytes above 32bits...
/// add rsi, rax
/// mov rbx, rsi ; update decrypt key
/// add rsi, [rbp] ; add module base address
/// </summary>
extern vm::handler::profile_t jmp; extern vm::handler::profile_t jmp;
extern vm::handler::profile_t vmexit; extern vm::handler::profile_t vmexit;

@ -1,62 +1,56 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::calc_jmp
{ {
namespace calc_jmp bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp )
{ {
bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ) auto result = vm::util::get_fetch_operand( vm_entry );
{
auto result = vm::util::get_fetch_operand( vm_entry );
if ( !result.has_value() ) if ( !result.has_value() )
return false; return false;
calc_jmp.insert( calc_jmp.end(), result.value(), vm_entry.end() ); calc_jmp.insert( calc_jmp.end(), result.value(), vm_entry.end() );
return true; return true;
} }
std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ) std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp )
{ {
auto result = auto result = std::find_if( calc_jmp.begin(), calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool {
std::find_if( calc_jmp.begin(), calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { // look for any instruction with RSI being the first operand and its being written too..
// look for any instruction with RSI being the first operand and its being written too.. return instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE &&
return instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI;
instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI; } );
} );
if ( result == calc_jmp.end() ) if ( result == calc_jmp.end() )
return {}; return {};
const auto &instr = result->instr; const auto &instr = result->instr;
switch ( instr.mnemonic ) switch ( instr.mnemonic )
{ {
case ZYDIS_MNEMONIC_LEA: case ZYDIS_MNEMONIC_LEA:
// if operand type is memory, then return advancement type // if operand type is memory, then return advancement type
// based off of the disposition value... (neg == backward, pos == forward) // based off of the disposition value... (neg == backward, pos == forward)
if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY )
return instr.operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward return instr.operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward
: vmp2::exec_type_t::backward; : vmp2::exec_type_t::backward;
break; break;
case ZYDIS_MNEMONIC_ADD: case ZYDIS_MNEMONIC_ADD:
if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE )
return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward : vmp2::exec_type_t::backward;
: vmp2::exec_type_t::backward; break;
break; case ZYDIS_MNEMONIC_SUB:
case ZYDIS_MNEMONIC_SUB: if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE )
if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward : vmp2::exec_type_t::forward;
return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward break;
: vmp2::exec_type_t::forward; case ZYDIS_MNEMONIC_INC:
break; return vmp2::exec_type_t::forward;
case ZYDIS_MNEMONIC_INC: case ZYDIS_MNEMONIC_DEC:
return vmp2::exec_type_t::forward; return vmp2::exec_type_t::backward;
case ZYDIS_MNEMONIC_DEC: default:
return vmp2::exec_type_t::backward; break;
default:
break;
}
return {};
} }
} // namespace calc_jmp return {};
} // namespace vm }
} // namespace vm::calc_jmp

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

@ -1,91 +1,73 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t addq = {
{ // ADD [RBP+8], RAX
namespace profile // PUSHFQ
{ // POP [RBP]
vm::handler::profile_t addq = { "ADDQ",
// ADD [RBP+8], RAX ADDQ,
// PUSHFQ NULL,
// POP [RBP] { { // ADD [RBP+8], RAX
"ADDQ", []( const zydis_decoded_instr_t &instr ) -> bool {
ADDQ, return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
NULL, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
{ { // ADD [RBP+8], RAX instr.operands[ 0 ].mem.disp.value == 0x8 &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && // PUSHFQ
instr.operands[ 0 ].mem.disp.value == 0x8 && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
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 && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// PUSHFQ instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
[]( const zydis_decoded_instr_t &instr ) -> bool { } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
},
// POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
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, ADDDW,
NULL, 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 && return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 0 ].mem.disp.value == 0x8 && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; },
}, // PUSHFQ
// PUSHFQ []( const zydis_decoded_instr_t &instr ) -> bool { 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 && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// POP [RBP] instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_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 addw = { vm::handler::profile_t addw = {
// ADD [RBP+8], AX // ADD [RBP+8], AX
// PUSHFQ // PUSHFQ
// POP [RBP] // POP [RBP]
"ADDW", "ADDW",
ADDW, ADDW,
NULL, NULL,
{ { // ADD [RBP+8], AX { { // ADD [RBP+8], AX
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 0 ].mem.disp.value == 0x8 && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; },
}, // PUSHFQ
// PUSHFQ []( const zydis_decoded_instr_t &instr ) -> bool { 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 && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
// POP [RBP] instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
[]( const zydis_decoded_instr_t &instr ) -> bool { } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_POP && } // namespace vm::handler::profile
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
} // namespace profile
} // namespace handler
} // namespace vm

@ -1,40 +1,34 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t call = {
{ // MOV RDX, [RBP]
namespace profile // ADD RBP, 0x8
{ // CALL RDX
vm::handler::profile_t call = { "CALL",
// MOV RDX, [RBP] CALL,
// ADD RBP, 0x8 NULL,
// CALL RDX { { // MOV RDX, [RBP]
"CALL", []( const zydis_decoded_instr_t &instr ) -> bool {
CALL, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RDX, [RBP] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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_RDX && // ADD RBP, 0x8
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_ADD &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// ADD RBP, 0x8 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_ADD && instr.operands[ 1 ].imm.value.u == 0x8;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && // CALL RDX
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_CALL &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// CALL RDX instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
[]( const zydis_decoded_instr_t &instr ) -> bool { } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_CALL && } // namespace vm::handler::profile
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
} } } };
}
} // namespace handler
} // namespace vm

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

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

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

@ -1,36 +1,27 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t lrflags = {
{ // PUSH [RBP]
namespace profile // ADD RBP, 0x8
{ // POPFQ
vm::handler::profile_t lrflags = { "LRFLAGS",
// PUSH [RBP] LRFLAGS,
// ADD RBP, 0x8 NULL,
// POPFQ { { // PUSH [RBP]
"LRFLAGS", []( const zydis_decoded_instr_t &instr ) -> bool {
LRFLAGS, return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
NULL, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
{ { // PUSH [RBP] },
[]( const zydis_decoded_instr_t &instr ) -> bool { // ADD RBP, 0x8
return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
// ADD RBP, 0x8 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_ADD && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // POPFQ
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; } } } };
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && } // namespace vm::handler::profile
instr.operands[ 1 ].imm.value.u == 0x8;
},
// POPFQ
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ;
} } } };
}
} // namespace handler
} // namespace vm

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

@ -1,73 +1,61 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t mulq = {
{ // MOV RAX, [RBP+0x8]
namespace profile // SUB RBP, 0x8
{ // MUL RDX
vm::handler::profile_t mulq = { // MOV [RBP+0x8], RDX
// MOV RAX, [RBP+0x8] // MOV [RBP+0x10], RAX
// SUB RBP, 0x8 // PUSHFQ
// MUL RDX // POP [RBP]
// MOV [RBP+0x8], RDX "MULQ",
// MOV [RBP+0x10], RAX MULQ,
// PUSHFQ NULL,
// POP [RBP] { { // MOV RAX, [RBP+0x8]
"MULQ", []( const zydis_decoded_instr_t &instr ) -> bool {
MULQ, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RAX, [RBP+0x8] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && // SUB RBP, 0x8
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[ 1 ].mem.disp.value == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
// SUB RBP, 0x8 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_SUB && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // MUL RDX
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_MUL &&
instr.operands[ 1 ].imm.value.u == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
// MUL RDX },
[]( const zydis_decoded_instr_t &instr ) -> bool { // MOV [RBP+0x8], RDX
return instr.mnemonic == ZYDIS_MNEMONIC_MUL && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
}, instr.operands[ 0 ].mem.disp.value == 0x8 &&
// MOV [RBP+0x8], 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_MOV && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && // MOV [RBP+0x10], RAX
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 0 ].mem.disp.value == 0x8 && return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; instr.operands[ 0 ].mem.disp.value == 0x10 &&
}, instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV [RBP+0x10], RAX instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
[]( const zydis_decoded_instr_t &instr ) -> bool { },
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && // PUSHFQ
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && // POP [RBP]
instr.operands[ 0 ].mem.disp.value == 0x10 && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
}, } } } };
// PUSHFQ } // namespace vm::handler::profile
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
},
// POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
}
} // namespace handler
} // namespace vm

@ -1,183 +1,161 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t nandq = {
{ // MOV RAX, [RBP]
namespace profile // MOV RDX, [RBP+8]
{ // NOT RAX
vm::handler::profile_t nandq = { // NOT RDX
// MOV RAX, [RBP] // AND RAX, RDX
// MOV RDX, [RBP+8] // MOV [RBP], RAX
// NOT RAX // PUSHFQ
// NOT RDX // POP [RBP]
// AND RAX, RDX "NANDQ",
// MOV [RBP], RAX NANDQ,
// PUSHFQ NULL,
// POP [RBP] { { // MOV RAX, [RBP]
"NANDQ", []( const zydis_decoded_instr_t &instr ) -> bool {
NANDQ, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RAX, [RBP] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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_RAX && // MOV RDX, [RBP+8]
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_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV RDX, [RBP+8] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && // NOT RAX
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_NOT &&
instr.operands[ 1 ].mem.disp.value == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX;
// NOT RAX },
[]( const zydis_decoded_instr_t &instr ) -> bool { // NOT 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_NOT &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX;
// NOT 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 && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP], 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[ 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 { },
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && // PUSHFQ
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && // POP [RBP]
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_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
// PUSHFQ } } } };
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
},
// POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
vm::handler::profile_t nanddw = { vm::handler::profile_t nanddw = {
// NOT QWORD PTR [RBP] // NOT QWORD PTR [RBP]
// MOV EAX, [RBP] // MOV EAX, [RBP]
// SUB RBP, 0x4 // SUB RBP, 0x4
// AND [RBP+0x8], EAX // AND [RBP+0x8], EAX
// PUSHFQ // PUSHFQ
// POP [RBP] // POP [RBP]
"NANDDW", "NANDDW",
NANDDW, NANDDW,
NULL, NULL,
{ { // NOT QWORD PTR [RBP] { { // NOT QWORD PTR [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_NOT && return instr.mnemonic == ZYDIS_MNEMONIC_NOT && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; },
}, // 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 &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; },
}, // SUB RBP, 0x4
// SUB RBP, 0x4 []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].imm.value.u == 0x4;
instr.operands[ 1 ].imm.value.u == 0x4; },
}, // AND [RBP+0x8], EAX
// AND [RBP+0x8], EAX []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_AND && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_AND && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].mem.disp.value == 0x8 && 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 { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
// PUSHFQ // POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
// 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 nandw = { vm::handler::profile_t nandw = {
// 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]
"NANDW", "NANDW",
NANDW, NANDW,
NULL, 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 && return instr.mnemonic == ZYDIS_MNEMONIC_NOT && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].size == 32 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[ 0 ].size == 32 && },
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; // MOV AX, [RBP]
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// MOV AX, [RBP] return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && },
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; // SUB RBP, 0x6
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// SUB RBP, 0x6 return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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 == 0x6;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && },
instr.operands[ 1 ].imm.value.u == 0x6; // AND [RBP+0x8], AX
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// AND [RBP+0x8], AX return instr.mnemonic == ZYDIS_MNEMONIC_AND && 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_AND && instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
instr.operands[ 0 ].mem.disp.value == 0x8 && },
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // PUSHFQ
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
}, // POP [RBP]
// PUSHFQ []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
}, } } } };
// POP [RBP] } // namespace vm::handler::profile
[]( 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;
} } } };
} // namespace profile
} // namespace handler
} // namespace vm

@ -1,41 +1,34 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t pushvsp = {
{ // MOV RAX, RBP
namespace profile // SUB RBP, 8
{ "PUSHVSP",
vm::handler::profile_t pushvsp = { PUSHVSP,
// MOV RAX, RBP NULL,
// SUB RBP, 8 { { // MOV RAX, RBP
"PUSHVSP", []( const zydis_decoded_instr_t &instr ) -> bool {
PUSHVSP, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RAX, RBP 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_RBP;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && // SUB RBP, 8
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; 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 &&
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 &&
}, 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 && } } } };
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && } // namespace vm::handler::profile
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
} } } };
}
} // namespace handler
} // namespace vm

@ -1,66 +1,57 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t readq = {
{ // MOV RAX, [RAX]
namespace profile // MOV [RBP], RAX
{ "READQ",
vm::handler::profile_t readq = { READQ,
// MOV RAX, [RAX] NULL,
// MOV [RBP], RAX { { // MOV RAX, [RAX]
"READQ", []( const zydis_decoded_instr_t &instr ) -> bool {
READQ, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
// MOV RAX, [RAX] instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX;
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RBP], RAX
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && []( const zydis_decoded_instr_t &instr ) -> bool {
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; 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 { } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX;
} } } };
vm::handler::profile_t readdw = { vm::handler::profile_t readdw = {
// ADD RBP, 0x4 // ADD RBP, 0x4
// MOV EAX, [RAX] // MOV EAX, [RAX]
// MOV [RBP], EAX // MOV [RBP], EAX
"READDW", "READDW",
READDW, READDW,
NULL, NULL,
{ { // ADD RBP, 0x4 { { // ADD RBP, 0x4
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].imm.value.u == 0x4; instr.operands[ 1 ].imm.value.u == 0x4;
}, },
// MOV EAX, [RAX] // MOV EAX, [RAX]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX;
}, },
// MOV [RBP], EAX // MOV [RBP], EAX
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; } } } };
} } } }; } // namespace vm::handler::profile
}
} // namespace handler
} // namespace vm

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

@ -1,138 +1,122 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t shrq = {
{ // MOV RAX, [RBP]
namespace profile // MOV CL, [RBP+0x8]
{ // SUB RBP, 0x6
vm::handler::profile_t shrq = { // SHR RAX, CL
// MOV RAX, [RBP] // MOV [RBP+0x8], RAX
// MOV CL, [RBP+0x8] // PUSHFQ
// SUB RBP, 0x6 // POP [RBP]
// SHR RAX, CL "SHRQ",
// MOV [RBP+0x8], RAX SHRQ,
// PUSHFQ NULL,
// POP [RBP] { { // MOV RAX, [RBP]
"SHRQ", []( const zydis_decoded_instr_t &instr ) -> bool {
SHRQ, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RAX, [RBP] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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_RAX && // MOV CL, [RBP+0x8]
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_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV CL, [RBP+0x8] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && // 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[ 1 ].mem.disp.value == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
// SUB RBP, 0x6 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_SUB && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // SHR RAX, CL
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_SHR &&
instr.operands[ 1 ].imm.value.u == 0x6; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
// SHR RAX, CL instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
}, instr.operands[ 0 ].mem.disp.value == 0x8 &&
// MOV [RBP+0x8], 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 && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && // PUSHFQ
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
instr.operands[ 0 ].mem.disp.value == 0x8 && // POP [RBP]
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_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
}, instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
// PUSHFQ } } } };
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; vm::handler::profile_t shrw = {
}, // MOV AX, [RBP]
// POP [RBP] // MOV CL, [RBP+0x2]
[]( const zydis_decoded_instr_t &instr ) -> bool { // SUB RBP, 0x6
return instr.mnemonic == ZYDIS_MNEMONIC_POP && // SHR AX, CL
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && // MOV [RBP+0x8], AX
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; // PUSHFQ
} } } }; // POP [RBP]
"SHRW",
vm::handler::profile_t shrw = { SHRW,
// MOV AX, [RBP] NULL,
// MOV CL, [RBP+0x2] { { // MOV AX, [RBP]
// SUB RBP, 0x6 []( const zydis_decoded_instr_t &instr ) -> bool {
// SHR AX, CL return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
// MOV [RBP+0x8], AX instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// PUSHFQ instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX &&
// POP [RBP] instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
"SHRW", instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
SHRW, },
NULL, // MOV CL, [RBP+0x2]
{ { // MOV AX, [RBP] []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x2;
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; },
}, // SUB RBP, 0x6
// MOV CL, [RBP+0x2] []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].imm.value.u == 0x6;
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && },
instr.operands[ 1 ].mem.disp.value == 0x2; // SHR AX, CL
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// SUB RBP, 0x6 return instr.mnemonic == ZYDIS_MNEMONIC_SHR &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && },
instr.operands[ 1 ].imm.value.u == 0x6; // MOV [RBP+0x8], AX
}, []( const zydis_decoded_instr_t &instr ) -> bool {
// SHR AX, CL return instr.mnemonic == ZYDIS_MNEMONIC_MOV && 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_SHR && instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; // PUSHFQ
}, []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; },
// MOV [RBP+0x8], AX // POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && } } } };
instr.operands[ 0 ].mem.disp.value == 0x8 && } // namespace vm::handler::profile
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX;
},
// PUSHFQ
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
},
// POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
}
} // namespace handler
} // namespace vm

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

@ -1,29 +1,21 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t vmexit = {
{ // MOV RSP, RBP
namespace profile // RET
{ "VMEXIT",
vm::handler::profile_t vmexit = { VMEXIT,
// MOV RSP, RBP NULL,
// RET { { // MOV RSP, RBP
"VMEXIT", []( const zydis_decoded_instr_t &instr ) -> bool {
VMEXIT, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RSP, RBP instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSP &&
[]( 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_RBP;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSP && // RET
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_RET; } } } };
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; } // namespace vm::handler::profile
},
// RET
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_RET;
} } } };
}
} // namespace handler
} // namespace vm

@ -1,136 +1,124 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::handler::profile
{ {
namespace handler vm::handler::profile_t writeq = {
{ // MOV RAX, [RBP]
namespace profile // MOV RDX, [RBP+0x8]
{ // ADD RBP, 0x10
vm::handler::profile_t writeq = { // MOV [RAX], RDX
// MOV RAX, [RBP] "WRITEQ",
// MOV RDX, [RBP+0x8] WRITEQ,
// ADD RBP, 0x10 NULL,
// MOV [RAX], RDX { { // MOV RAX, [RBP]
"WRITEQ", []( const zydis_decoded_instr_t &instr ) -> bool {
WRITEQ, return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
NULL, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
{ { // MOV RAX, [RBP] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { 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_RAX && // MOV RDX, [RBP+0x8]
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_MOV &&
}, instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV RDX, [RBP+0x8] instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX &&
[]( const zydis_decoded_instr_t &instr ) -> bool { instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && },
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && // ADD RBP, 0x10
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_ADD &&
instr.operands[ 1 ].mem.disp.value == 0x8; instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
}, instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
// ADD RBP, 0x10 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_ADD && },
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && // MOV [RAX], RDX
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[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].imm.value.u == 0x10; instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
}, instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// MOV [RAX], RDX instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
[]( const zydis_decoded_instr_t &instr ) -> bool { } } } };
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX;
} } } };
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, WRITEDW,
NULL, 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 && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
}, },
// MOV EDX, [RBP+0x8] // MOV EDX, [RBP+0x8]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 1 ].mem.disp.value == 0x8; },
}, // ADD RBP, 0xC
// ADD RBP, 0xC []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].imm.value.u == 0xC;
instr.operands[ 1 ].imm.value.u == 0xC; },
}, // MOV [RAX], EDX
// MOV [RAX], EDX []( 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_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && } } } };
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX;
} } } };
vm::handler::profile_t writeb = { vm::handler::profile_t writeb = {
// MOV RAX, [RBP] // MOV RAX, [RBP]
// MOV DL, [RBP+0x8] // MOV DL, [RBP+0x8]
// ADD RBP, 0xA // ADD RBP, 0xA
// MOV [RAX], DL // MOV [RAX], DL
"WRITEB", "WRITEB",
WRITEB, WRITEB,
NULL, 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 && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
}, },
// MOV DL, [RBP+0x8] // MOV DL, [RBP+0x8]
[]( const zydis_decoded_instr_t &instr ) -> bool { []( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DL && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DL &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8;
instr.operands[ 1 ].mem.disp.value == 0x8; },
}, // ADD RBP, 0xA
// ADD RBP, 0xA []( const zydis_decoded_instr_t &instr ) -> bool {
[]( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_ADD &&
return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].imm.value.u == 0xA;
instr.operands[ 1 ].imm.value.u == 0xA; },
}, // MOV [RAX], DL
// MOV [RAX], DL []( 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_MEMORY &&
return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DL;
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && } } } };
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DL; } // namespace vm::handler::profile
} } } };
} // namespace profile
} // namespace handler
} // namespace vm

@ -1,47 +1,24 @@
#include <vmprofiler.hpp> #include <vmprofiler.hpp>
namespace vm namespace vm::util
{ {
namespace util namespace reg
{ {
namespace reg zydis_register_t to64( zydis_register_t reg )
{ {
zydis_register_t to64( zydis_register_t reg ) return ZydisRegisterGetLargestEnclosing( ZYDIS_MACHINE_MODE_LONG_64, reg );
{ }
return ZydisRegisterGetLargestEnclosing( ZYDIS_MACHINE_MODE_LONG_64, reg );
}
bool compare( zydis_register_t a, zydis_register_t b )
{
return to64( a ) == to64( b );
}
} // namespace reg
bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ) bool compare( zydis_register_t a, zydis_register_t b )
{ {
const auto result = return to64( a ) == to64( b );
std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
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 &&
instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI;
} );
if ( result == routine.end() )
return false;
fetch_instr = *result;
return true;
} }
} // namespace reg
std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ) bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr )
{ {
auto result = std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { const auto result =
std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi] // mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 && return instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
@ -53,209 +30,229 @@ namespace vm
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI;
} ); } );
if ( result == routine.end() ) if ( result == routine.end() )
return {}; return false;
return result; fetch_instr = *result;
} return true;
}
void print( const zydis_decoded_instr_t &instr ) std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine )
{
auto result = std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
return instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
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 &&
instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI;
} );
if ( result == routine.end() )
return {};
return result;
}
void print( const zydis_decoded_instr_t &instr )
{
char buffer[ 256 ];
ZydisFormatter formatter;
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u );
std::puts( buffer );
}
void print( zydis_routine_t &routine )
{
char buffer[ 256 ];
ZydisFormatter formatter;
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
for ( auto [ instr, raw, addr ] : routine )
{ {
char buffer[ 256 ]; ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr );
ZydisFormatter formatter; std::printf( "> 0x%p %s", addr, buffer );
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u );
std::puts( buffer );
} }
}
void print( zydis_routine_t &routine ) bool is_jmp( const zydis_decoded_instr_t &instr )
{
switch ( instr.mnemonic )
{ {
char buffer[ 256 ]; case ZYDIS_MNEMONIC_JB:
ZydisFormatter formatter; case ZYDIS_MNEMONIC_JBE:
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); case ZYDIS_MNEMONIC_JCXZ:
case ZYDIS_MNEMONIC_JECXZ:
for ( auto [ instr, raw, addr ] : routine ) case ZYDIS_MNEMONIC_JKNZD:
{ case ZYDIS_MNEMONIC_JKZD:
ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); case ZYDIS_MNEMONIC_JL:
std::printf( "> 0x%p %s", addr, buffer ); case ZYDIS_MNEMONIC_JLE:
} case ZYDIS_MNEMONIC_JMP:
case ZYDIS_MNEMONIC_JNB:
case ZYDIS_MNEMONIC_JNBE:
case ZYDIS_MNEMONIC_JNL:
case ZYDIS_MNEMONIC_JNLE:
case ZYDIS_MNEMONIC_JNO:
case ZYDIS_MNEMONIC_JNP:
case ZYDIS_MNEMONIC_JNS:
case ZYDIS_MNEMONIC_JNZ:
case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JP:
case ZYDIS_MNEMONIC_JRCXZ:
case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ:
return true;
default:
break;
} }
return false;
}
bool is_jmp( const zydis_decoded_instr_t &instr ) bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps )
{
ZydisDecoder decoder;
zydis_decoded_instr_t instr;
ZydisDecoderInit( &decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64 );
while ( ZYAN_SUCCESS(
ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) )
{ {
switch ( instr.mnemonic ) // detect if we have already been at this instruction... if so that means there is a loop and we are
{ // going to just return...
case ZYDIS_MNEMONIC_JB: if ( std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool {
case ZYDIS_MNEMONIC_JBE: return zydis_instr.addr == routine_addr;
case ZYDIS_MNEMONIC_JCXZ: } ) != routine.end() )
case ZYDIS_MNEMONIC_JECXZ:
case ZYDIS_MNEMONIC_JKNZD:
case ZYDIS_MNEMONIC_JKZD:
case ZYDIS_MNEMONIC_JL:
case ZYDIS_MNEMONIC_JLE:
case ZYDIS_MNEMONIC_JMP:
case ZYDIS_MNEMONIC_JNB:
case ZYDIS_MNEMONIC_JNBE:
case ZYDIS_MNEMONIC_JNL:
case ZYDIS_MNEMONIC_JNLE:
case ZYDIS_MNEMONIC_JNO:
case ZYDIS_MNEMONIC_JNP:
case ZYDIS_MNEMONIC_JNS:
case ZYDIS_MNEMONIC_JNZ:
case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JP:
case ZYDIS_MNEMONIC_JRCXZ:
case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ:
return true; return true;
default:
break;
}
return false;
}
bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps ) std::vector< u8 > raw_instr;
{ raw_instr.insert( raw_instr.begin(), ( u8 * )routine_addr, ( u8 * )routine_addr + instr.length );
ZydisDecoder decoder;
zydis_decoded_instr_t instr;
ZydisDecoderInit( &decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64 );
while ( ZYAN_SUCCESS( if ( is_jmp( instr ) )
ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) )
{ {
// detect if we have already been at this instruction... if so that means there is a loop and we are if ( instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER )
// going to just return...
if ( std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool {
return zydis_instr.addr == routine_addr;
} ) != routine.end() )
return true;
std::vector< u8 > raw_instr;
raw_instr.insert( raw_instr.begin(), ( u8 * )routine_addr, ( u8 * )routine_addr + instr.length );
if ( is_jmp( instr ) )
{
if ( instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER )
{
routine.push_back( { instr, raw_instr, routine_addr } );
return true;
}
if ( keep_jmps )
routine.push_back( { instr, raw_instr, routine_addr } );
ZydisCalcAbsoluteAddress( &instr, &instr.operands[ 0 ], routine_addr, &routine_addr );
}
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
{ if ( keep_jmps )
routine.push_back( { instr, raw_instr, routine_addr } ); routine.push_back( { instr, raw_instr, routine_addr } );
routine_addr += instr.length;
} ZydisCalcAbsoluteAddress( &instr, &instr.operands[ 0 ], routine_addr, &routine_addr );
}
else if ( instr.mnemonic == ZYDIS_MNEMONIC_RET )
{
routine.push_back( { instr, raw_instr, routine_addr } );
return true;
}
else
{
routine.push_back( { instr, raw_instr, routine_addr } );
routine_addr += instr.length;
} }
return false;
} }
return false;
}
void deobfuscate( zydis_routine_t &routine ) void deobfuscate( zydis_routine_t &routine )
{ {
static const auto _uses = []( ZydisDecodedOperand &op, zydis_register_t reg ) -> bool { static const auto _uses = []( 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 );
} }
default: default:
break; break;
} }
return false; return false;
}; };
static const auto _writes = []( zydis_decoded_instr_t &inst ) -> bool { static const auto _writes = []( zydis_decoded_instr_t &inst ) -> bool {
for ( auto idx = 0; idx < inst.operand_count; ++idx ) for ( auto idx = 0; idx < inst.operand_count; ++idx )
if ( inst.operands[ idx ].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) if ( inst.operands[ idx ].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE )
return true; return true;
return false; return false;
}; };
static const auto _remove = []( zydis_routine_t &routine, zydis_routine_t::iterator itr, static const auto _remove = []( zydis_routine_t &routine, zydis_routine_t::iterator itr, zydis_register_t reg,
zydis_register_t reg, u32 opcode_size ) -> void { u32 opcode_size ) -> void {
for ( ; itr >= routine.begin(); --itr ) for ( ; itr >= routine.begin(); --itr )
{
const auto instruction = &itr->instr;
auto stop = false;
if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP )
continue;
for ( auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx )
{ {
const auto instruction = &itr->instr; const auto op = &instruction->operands[ op_idx ];
auto stop = false;
if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP ) if ( !_uses( *op, reg ) )
continue; continue;
for ( auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx ) if ( op->type == ZYDIS_OPERAND_TYPE_MEMORY )
{ {
const auto op = &instruction->operands[ op_idx ]; stop = true;
continue;
if ( !_uses( *op, reg ) ) }
continue;
if ( op->type == ZYDIS_OPERAND_TYPE_MEMORY ) if ( opcode_size < 32 && op->size > opcode_size )
{ continue;
stop = true;
continue;
}
if ( opcode_size < 32 && op->size > opcode_size ) op->actions &ZYDIS_OPERAND_ACTION_MASK_WRITE ? op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE
continue; : stop = true;
}
op->actions &ZYDIS_OPERAND_ACTION_MASK_WRITE ? op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE if ( !_writes( *instruction ) )
: stop = true; routine.erase( itr );
}
if ( !_writes( *instruction ) ) else if ( stop )
routine.erase( itr ); break;
}
};
else if ( stop ) for ( const auto &instr_data : routine )
break; {
} if ( routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP )
}; continue;
for ( const auto &instr_data : routine ) for ( auto itr = routine.begin() + 1; itr != routine.end(); itr++ )
{ {
if ( routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP ) if ( itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || itr->instr.mnemonic == ZYDIS_MNEMONIC_RET )
continue; break;
for ( auto itr = routine.begin() + 1; itr != routine.end(); itr++ ) // find the write operations that happen...
for ( auto idx = 0u; idx < itr->instr.operand_count; ++idx )
{ {
if ( itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || itr->instr.mnemonic == ZYDIS_MNEMONIC_RET ) const auto op = &itr->instr.operands[ idx ];
break; // if its a read, continue to next opcode...
if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_READ )
// find the write operations that happen... continue;
for ( auto idx = 0u; idx < itr->instr.operand_count; ++idx )
{
const auto op = &itr->instr.operands[ idx ];
// if its a read, continue to next opcode...
if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_READ )
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 } // namespace vm::util
Loading…
Cancel
Save