|
|
@ -11,9 +11,7 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
vm::util::deobfuscate( vm_handler );
|
|
|
|
vm::util::deobfuscate( vm_handler );
|
|
|
|
|
|
|
|
|
|
|
|
static const auto calc_jmp_check =
|
|
|
|
static const auto calc_jmp_check = [ & ]( std::uintptr_t addr ) -> bool {
|
|
|
|
[&](std::uintptr_t addr) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for ( const auto &[ instr, instr_raw, instr_addr ] : calc_jmp )
|
|
|
|
for ( const auto &[ instr, instr_raw, instr_addr ] : calc_jmp )
|
|
|
|
if ( instr_addr == addr )
|
|
|
|
if ( instr_addr == addr )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
@ -21,10 +19,7 @@ namespace vm
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
auto result = std::find_if(
|
|
|
|
auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr ) -> bool {
|
|
|
|
vm_handler.begin(), vm_handler.end(),
|
|
|
|
|
|
|
|
[](const zydis_instr_t& instr) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
|
|
|
|
if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
|
|
|
|
instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
|
|
|
|
instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX &&
|
|
|
|
instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI &&
|
|
|
|
instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI &&
|
|
|
@ -32,8 +27,7 @@ namespace vm
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
return calc_jmp_check( instr.addr );
|
|
|
|
return calc_jmp_check( instr.addr );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// remove calc_jmp from the vm handler vector...
|
|
|
|
// remove calc_jmp from the vm handler vector...
|
|
|
|
if ( result != vm_handler.end() )
|
|
|
|
if ( result != vm_handler.end() )
|
|
|
@ -46,10 +40,7 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
while ( result != vm_handler.end() )
|
|
|
|
while ( result != vm_handler.end() )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
result = std::find_if(
|
|
|
|
result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
++result, vm_handler.end(),
|
|
|
|
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
@ -61,8 +52,7 @@ namespace vm
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( result != vm_handler.end() )
|
|
|
|
if ( result != vm_handler.end() )
|
|
|
|
last = result;
|
|
|
|
last = result;
|
|
|
@ -74,8 +64,8 @@ namespace vm
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base,
|
|
|
|
bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry,
|
|
|
|
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<vm::handler::handler_t>& vm_handlers)
|
|
|
|
std::uintptr_t *vm_handler_table, std::vector< vm::handler::handler_t > &vm_handlers )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
zydis_decoded_instr_t instr;
|
|
|
|
zydis_decoded_instr_t instr;
|
|
|
|
if ( !vm::handler::table::get_transform( vm_entry, &instr ) )
|
|
|
|
if ( !vm::handler::table::get_transform( vm_entry, &instr ) )
|
|
|
@ -87,9 +77,7 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
for ( auto idx = 0u; idx < 256; ++idx )
|
|
|
|
for ( auto idx = 0u; idx < 256; ++idx )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto decrypt_val =
|
|
|
|
const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] );
|
|
|
|
vm::handler::table::decrypt(
|
|
|
|
|
|
|
|
instr, vm_handler_table[idx]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
handler_t vm_handler;
|
|
|
|
handler_t vm_handler;
|
|
|
|
vm::transform::map_t transforms;
|
|
|
|
vm::transform::map_t transforms;
|
|
|
@ -98,11 +86,9 @@ namespace vm
|
|
|
|
if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) )
|
|
|
|
if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
const auto has_imm =
|
|
|
|
const auto has_imm = vm::handler::has_imm( vm_handler_instrs );
|
|
|
|
vm::handler::has_imm(vm_handler_instrs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const auto imm_size =
|
|
|
|
const auto imm_size = vm::handler::imm_size( vm_handler_instrs );
|
|
|
|
vm::handler::imm_size(vm_handler_instrs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) )
|
|
|
|
if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -120,10 +106,8 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
bool has_imm( const zydis_routine_t &vm_handler )
|
|
|
|
bool has_imm( const zydis_routine_t &vm_handler )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto result = std::find_if(
|
|
|
|
const auto result =
|
|
|
|
vm_handler.begin(), vm_handler.end(),
|
|
|
|
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
@ -135,18 +119,15 @@ namespace vm
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result != vm_handler.end();
|
|
|
|
return result != vm_handler.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::uint8_t imm_size( const zydis_routine_t &vm_handler )
|
|
|
|
std::uint8_t imm_size( const zydis_routine_t &vm_handler )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto result = std::find_if(
|
|
|
|
const auto result =
|
|
|
|
vm_handler.begin(), vm_handler.end(),
|
|
|
|
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
@ -158,8 +139,7 @@ namespace vm
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( result == vm_handler.end() )
|
|
|
|
if ( result == vm_handler.end() )
|
|
|
|
return 0u;
|
|
|
|
return 0u;
|
|
|
@ -169,10 +149,8 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms )
|
|
|
|
bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto imm_fetch = std::find_if(
|
|
|
|
auto imm_fetch =
|
|
|
|
vm_handler.begin(), vm_handler.end(),
|
|
|
|
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
if ( instr_data.instr.operand_count > 1 &&
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
|
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
|
|
@ -184,42 +162,34 @@ namespace vm
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( imm_fetch == vm_handler.end() )
|
|
|
|
if ( imm_fetch == vm_handler.end() )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// this finds the first transformation which looks like:
|
|
|
|
// this finds the first transformation which looks like:
|
|
|
|
// transform rax, rbx <--- note these registers can be smaller so we to64 them...
|
|
|
|
// transform rax, rbx <--- note these registers can be smaller so we to64 them...
|
|
|
|
auto key_transform = std::find_if(imm_fetch, vm_handler.end(),
|
|
|
|
auto key_transform =
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
std::find_if( imm_fetch, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
|
|
|
|
if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
|
|
|
|
util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) )
|
|
|
|
util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( key_transform == vm_handler.end() )
|
|
|
|
if ( key_transform == vm_handler.end() )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// look for a primer/instruction that alters RAX prior to the 5 transformations...
|
|
|
|
// look for a primer/instruction that alters RAX prior to the 5 transformations...
|
|
|
|
auto generic0 = std::find_if(imm_fetch + 1, key_transform,
|
|
|
|
auto generic0 = std::find_if( imm_fetch + 1, key_transform, []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
return util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
|
|
|
|
{
|
|
|
|
|
|
|
|
return util::reg::compare(
|
|
|
|
|
|
|
|
instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX) &&
|
|
|
|
|
|
|
|
!util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX );
|
|
|
|
!util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zydis_decoded_instr_t nogeneric0;
|
|
|
|
zydis_decoded_instr_t nogeneric0;
|
|
|
|
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
|
|
|
|
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
|
|
|
|
|
|
|
|
|
|
|
|
transforms[transform::type::generic0] =
|
|
|
|
transforms[ transform::type::generic0 ] = generic0 != key_transform ? generic0->instr : nogeneric0;
|
|
|
|
generic0 != key_transform ? generic0->instr : nogeneric0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// last transformation is the same as the first except src and dest are swwapped...
|
|
|
|
// last transformation is the same as the first except src and dest are swwapped...
|
|
|
|
transforms[ transform::type::rolling_key ] = key_transform->instr;
|
|
|
|
transforms[ transform::type::rolling_key ] = key_transform->instr;
|
|
|
@ -233,15 +203,13 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
for ( auto idx = 2u; idx < 5; ++idx )
|
|
|
|
for ( auto idx = 2u; idx < 5; ++idx )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
generic_transform = std::find_if(++generic_transform, vm_handler.end(),
|
|
|
|
generic_transform =
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
std::find_if( ++generic_transform, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) )
|
|
|
|
if ( util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( generic_transform == vm_handler.end() )
|
|
|
|
if ( generic_transform == vm_handler.end() )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -254,22 +222,16 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
vm::handler::profile_t *get_profile( handler_t &vm_handler )
|
|
|
|
vm::handler::profile_t *get_profile( handler_t &vm_handler )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
static const auto vcontains =
|
|
|
|
static const auto vcontains = []( vm::handler::profile_t *vprofile, handler_t *vm_handler ) -> bool {
|
|
|
|
[](vm::handler::profile_t* vprofile, handler_t* vm_handler) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( vprofile->imm_size != vm_handler->imm_size )
|
|
|
|
if ( vprofile->imm_size != vm_handler->imm_size )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
for ( auto &instr : vprofile->signature )
|
|
|
|
for ( auto &instr : vprofile->signature )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto contains = std::find_if
|
|
|
|
const auto contains = std::find_if(
|
|
|
|
(
|
|
|
|
vm_handler->instrs.begin(), vm_handler->instrs.end(),
|
|
|
|
vm_handler->instrs.begin(),
|
|
|
|
|
|
|
|
vm_handler->instrs.end(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[&](zydis_instr_t& instr_data) -> bool
|
|
|
|
[ & ]( zydis_instr_t &instr_data ) -> bool { return instr( instr_data.instr ); } );
|
|
|
|
{ return instr(instr_data.instr); }
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( contains == vm_handler->instrs.end() )
|
|
|
|
if ( contains == vm_handler->instrs.end() )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -289,10 +251,8 @@ namespace vm
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::uintptr_t *get( const zydis_routine_t &vm_entry )
|
|
|
|
std::uintptr_t *get( const zydis_routine_t &vm_entry )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto result = std::find_if(
|
|
|
|
const auto result =
|
|
|
|
vm_entry.begin(), vm_entry.end(),
|
|
|
|
std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const auto instr = &instr_data.instr;
|
|
|
|
const auto instr = &instr_data.instr;
|
|
|
|
// lea r12, vm_handlers... (always r12)...
|
|
|
|
// lea r12, vm_handlers... (always r12)...
|
|
|
|
if ( instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
|
|
|
|
if ( instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
|
|
|
@ -302,15 +262,13 @@ namespace vm
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( result == vm_entry.end() )
|
|
|
|
if ( result == vm_entry.end() )
|
|
|
|
return nullptr;
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
std::uintptr_t ptr = 0u;
|
|
|
|
std::uintptr_t ptr = 0u;
|
|
|
|
ZydisCalcAbsoluteAddress(&result->instr,
|
|
|
|
ZydisCalcAbsoluteAddress( &result->instr, &result->instr.operands[ 1 ], result->addr, &ptr );
|
|
|
|
&result->instr.operands[1], result->addr, &ptr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reinterpret_cast< std::uintptr_t * >( ptr );
|
|
|
|
return reinterpret_cast< std::uintptr_t * >( ptr );
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -319,13 +277,10 @@ namespace vm
|
|
|
|
{
|
|
|
|
{
|
|
|
|
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
|
|
|
|
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
|
|
|
|
|
|
|
|
|
|
|
|
auto handler_fetch = std::find_if(
|
|
|
|
auto handler_fetch =
|
|
|
|
vm_entry.begin(), vm_entry.end(),
|
|
|
|
std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[&](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const auto instr = &instr_data.instr;
|
|
|
|
const auto instr = &instr_data.instr;
|
|
|
|
if (instr->mnemonic == ZYDIS_MNEMONIC_MOV &&
|
|
|
|
if ( instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 &&
|
|
|
|
instr->operand_count == 2 &&
|
|
|
|
|
|
|
|
instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
|
|
|
instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 &&
|
|
|
|
instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 &&
|
|
|
|
instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX &&
|
|
|
|
instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX &&
|
|
|
@ -339,8 +294,7 @@ namespace vm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check to see if we found the fetch instruction and if the next instruction
|
|
|
|
// check to see if we found the fetch instruction and if the next instruction
|
|
|
|
// is not the end of the vector...
|
|
|
|
// is not the end of the vector...
|
|
|
@ -351,16 +305,13 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
// 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 = std::find_if(
|
|
|
|
auto handler_transform =
|
|
|
|
handler_fetch, vm_entry.end(),
|
|
|
|
std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
|
|
|
|
[&](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx &&
|
|
|
|
if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx &&
|
|
|
|
instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE )
|
|
|
|
instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE )
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( handler_transform == vm_entry.end() )
|
|
|
|
if ( handler_transform == vm_entry.end() )
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -376,8 +327,8 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
const auto operation = vm::transform::inverse[ transform_instr.mnemonic ];
|
|
|
|
const auto operation = vm::transform::inverse[ transform_instr.mnemonic ];
|
|
|
|
const auto bitsize = transform_instr.operands[ 0 ].size;
|
|
|
|
const auto bitsize = transform_instr.operands[ 0 ].size;
|
|
|
|
const auto imm = vm::transform::has_imm(&transform_instr) ?
|
|
|
|
const auto imm =
|
|
|
|
transform_instr.operands[1].imm.value.u : 0u;
|
|
|
|
vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u;
|
|
|
|
|
|
|
|
|
|
|
|
return vm::transform::apply( bitsize, operation, val, imm );
|
|
|
|
return vm::transform::apply( bitsize, operation, val, imm );
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -389,11 +340,11 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
const auto operation = transform_instr.mnemonic;
|
|
|
|
const auto operation = transform_instr.mnemonic;
|
|
|
|
const auto bitsize = transform_instr.operands[ 0 ].size;
|
|
|
|
const auto bitsize = transform_instr.operands[ 0 ].size;
|
|
|
|
const auto imm = vm::transform::has_imm(&transform_instr) ?
|
|
|
|
const auto imm =
|
|
|
|
transform_instr.operands[1].imm.value.u : 0u;
|
|
|
|
vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u;
|
|
|
|
|
|
|
|
|
|
|
|
return vm::transform::apply( bitsize, operation, val, imm );
|
|
|
|
return vm::transform::apply( bitsize, operation, val, imm );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace table
|
|
|
|
}
|
|
|
|
} // namespace handler
|
|
|
|
}
|
|
|
|
} // namespace vm
|