Merge branch 'dev' into 'master'

Dev

See merge request vmp2/vmprofiler!4
merge-requests/5/merge
_xeroxz 3 years ago
commit 169015429b

@ -136,19 +136,24 @@ namespace vm
template < class T > inline const auto _dec = []( T a, T b ) -> T { return a - 1; };
template < class T >
inline std::map< ZydisMnemonic, transform_t< T > > transforms = {
inline std::map< zydis_mnemonic_t, transform_t< T > > transforms = {
{ ZYDIS_MNEMONIC_ADD, _add< T > }, { ZYDIS_MNEMONIC_XOR, _xor< T > }, { ZYDIS_MNEMONIC_BSWAP, _bswap< T > },
{ ZYDIS_MNEMONIC_SUB, _sub< T > }, { ZYDIS_MNEMONIC_NEG, _neg< T > }, { ZYDIS_MNEMONIC_NOT, _not< T > },
{ ZYDIS_MNEMONIC_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > },
{ ZYDIS_MNEMONIC_DEC, _dec< T > } };
inline std::map< ZydisMnemonic, ZydisMnemonic > inverse = {
inline std::map< zydis_mnemonic_t, zydis_mnemonic_t > inverse = {
{ ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR },
{ ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD },
{ ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT },
{ ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR },
{ ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } };
inline bool valid( zydis_mnemonic_t op )
{
return transforms< std::uint8_t >.find( op ) != transforms< std::uint8_t >.end();
}
inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse )
{
inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ];

@ -31,6 +31,7 @@ namespace vm
enum mnemonic_t
{
INVALID,
LRFLAGS,
PUSHVSP,
MULQ,
DIVQ,
@ -75,7 +76,8 @@ namespace vm
SHRW,
NANDQ,
NANDDW
NANDDW,
NANDW
};
enum extention_t
@ -153,6 +155,7 @@ namespace vm
extern vm::handler::profile_t nandq;
extern vm::handler::profile_t nanddw;
extern vm::handler::profile_t nandw;
extern vm::handler::profile_t writeq;
extern vm::handler::profile_t writedw;
@ -164,6 +167,7 @@ namespace vm
extern vm::handler::profile_t shrq;
extern vm::handler::profile_t shrw;
extern vm::handler::profile_t lrflags;
extern vm::handler::profile_t call;
extern vm::handler::profile_t pushvsp;
extern vm::handler::profile_t mulq;
@ -172,14 +176,14 @@ namespace vm
extern vm::handler::profile_t vmexit;
inline std::vector< vm::handler::profile_t * > all = {
&sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw,
&lconstbsxdw, &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw,
&addq, &adddw, &addw,
&sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw,
&lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw,
&addw,
&shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw,
&shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw,
&shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq,
&jmp, &vmexit, &call };
&shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp,
&lrflags, &vmexit, &call };
} // namespace profile
} // namespace handler
} // namespace vm

@ -12,6 +12,7 @@ using u128 = __m128;
using zydis_decoded_instr_t = ZydisDecodedInstruction;
using zydis_register_t = ZydisRegister;
using zydis_mnemonic_t = ZydisMnemonic;
struct zydis_instr_t
{

@ -9,16 +9,14 @@ namespace vm
auto result =
std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
if ( 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 )
return true;
return false;
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 == vm_entry.end() )
@ -32,8 +30,9 @@ namespace vm
{
auto result =
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...
return instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
// 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 &&
instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI;
} );
@ -45,45 +44,22 @@ namespace vm
switch ( instr->mnemonic )
{
case ZYDIS_MNEMONIC_LEA:
{
// if operand type is memory, then return advancement type
// based off of the disposition value... (neg == backward, pos == forward)
if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY )
{
if ( instr->operands[ 1 ].mem.disp.value > 0 )
return vmp2::exec_type_t::forward;
else
return vmp2::exec_type_t::backward;
}
// else we dont know what we are looking at...
return {};
}
return instr->operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward
: vmp2::exec_type_t::backward;
break;
case ZYDIS_MNEMONIC_ADD:
{
// ADD RSI, IMM...
if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE )
{
// see if IMM is negitive...
if ( instr->operands[ 1 ].imm.value.s > 0 )
return vmp2::exec_type_t::forward;
else // adding a negitive number is sub...
return vmp2::exec_type_t::backward;
}
// else we dont know what we are looking at...
return {};
}
return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward
: vmp2::exec_type_t::backward;
break;
case ZYDIS_MNEMONIC_SUB:
{
// SUB RSI, IMM...
if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE )
{
// see if IMM is negitive...
if ( instr->operands[ 1 ].imm.value.s > 0 )
return vmp2::exec_type_t::backward;
else // subtracting a negitive number means you are adding...
return vmp2::exec_type_t::forward;
}
// else we dont know what we are looking at...
return {};
}
return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward
: vmp2::exec_type_t::forward;
break;
case ZYDIS_MNEMONIC_INC:
return vmp2::exec_type_t::forward;
case ZYDIS_MNEMONIC_DEC:

@ -19,14 +19,14 @@ namespace vm
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 {
if ( instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
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 )
return true;
return calc_jmp_check( instr.addr );
instr.instr.operands[ 1 ].mem.disp.value == 0xE0
? true
: calc_jmp_check( instr.addr );
} );
// remove calc_jmp from the vm handler vector...
@ -42,16 +42,14 @@ namespace vm
{
result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
if ( 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 )
return true;
return false;
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 != vm_handler.end() )
@ -77,17 +75,15 @@ namespace vm
for ( auto idx = 0u; idx < 256; ++idx )
{
const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] );
handler_t vm_handler;
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;
const auto has_imm = vm::handler::has_imm( vm_handler_instrs );
const auto imm_size = vm::handler::imm_size( vm_handler_instrs );
if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) )
@ -109,16 +105,14 @@ namespace vm
const auto result =
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
if ( 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 )
return true;
return false;
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;
} );
return result != vm_handler.end();
@ -129,16 +123,14 @@ namespace vm
const auto result =
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
if ( 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_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 )
return true;
return false;
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI;
} );
if ( result == vm_handler.end() )
@ -152,16 +144,14 @@ namespace vm
auto imm_fetch =
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool {
// mov/movsx/movzx rax/eax/ax/al, [rsi]
if ( 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 )
return true;
return false;
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 ( imm_fetch == vm_handler.end() )
@ -169,52 +159,51 @@ namespace vm
// this finds the first transformation which looks like:
// transform rax, rbx <--- note these registers can be smaller so we to64 them...
auto key_transform =
auto transform_instr =
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 ) &&
util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) )
return true;
return false;
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 ( key_transform == vm_handler.end() )
if ( transform_instr == vm_handler.end() )
return false;
// look for a primer/instruction that alters RAX prior to the 5 transformations...
auto generic0 = std::find_if( imm_fetch + 1, key_transform, []( const zydis_instr_t &instr_data ) -> bool {
return util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
auto generic0 = std::find_if( imm_fetch, 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;
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
transforms[ transform::type::generic0 ] = generic0 != key_transform ? generic0->instr : nogeneric0;
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 ] = key_transform->instr;
auto instr_copy = key_transform->instr;
instr_copy.operands[ 0 ].reg.value = key_transform->instr.operands[ 1 ].reg.value;
instr_copy.operands[ 1 ].reg.value = key_transform->instr.operands[ 0 ].reg.value;
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;
// three generic transformations...
auto generic_transform = key_transform;
for ( auto idx = 2u; idx < 5; ++idx )
for ( auto idx = static_cast< unsigned >( vm::transform::type::generic1 );
idx < static_cast< unsigned >( vm::transform::type::update_key ); ++idx )
{
generic_transform =
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 ) )
return true;
return false;
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 ) &&
instr_data.instr.operands[0].actions & ZYDIS_OPERAND_ACTION_WRITE &&
util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX );
} );
if ( generic_transform == vm_handler.end() )
if ( transform_instr == vm_handler.end() )
return false;
transforms[ ( transform::type )( idx ) ] = generic_transform->instr;
transforms[ static_cast< vm::transform::type >( idx ) ] = transform_instr->instr;
}
return true;
@ -255,13 +244,10 @@ namespace vm
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)...
if ( 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 true;
return false;
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...
} );
if ( result == vm_entry.end() )
@ -275,42 +261,35 @@ namespace vm
bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr )
{
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
auto handler_fetch =
std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
const auto instr = &instr_data.instr;
if ( instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 &&
instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
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 ) )
{
rcx_or_rdx = instr->operands[ 0 ].reg.value;
return true;
}
return false;
return instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 &&
instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
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() || ++handler_fetch == vm_entry.end() ||
if ( handler_fetch == vm_entry.end() ||
// must be RCX or RDX... else something went wrong...
( rcx_or_rdx != ZYDIS_REGISTER_RCX && rcx_or_rdx != ZYDIS_REGISTER_RDX ) )
( 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...
// the register is determined by the vm handler fetch above...
auto handler_transform =
std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool {
if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx &&
instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE )
return true;
return false;
return vm::transform::valid( instr_data.instr.mnemonic ) &&
instr_data.instr.operands[ 0 ].reg.value ==
handler_fetch->instr.operands[ 0 ].reg.value &&
instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE;
} );
if ( handler_transform == vm_entry.end() )

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

@ -75,14 +75,66 @@ namespace vm
} } } };
vm::handler::profile_t nanddw = {
// NOT QWORD PTR [RBP]
// MOV EAX, [RBP]
// SUB RBP, 0x4
// AND [RBP+0x8], EAX
// PUSHFQ
// POP [RBP]
"NANDDW",
NANDDW,
NULL,
{ { // NOT QWORD PTR [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_NOT &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
},
// MOV EAX, [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP;
},
// SUB RBP, 0x4
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_SUB &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
instr.operands[ 1 ].imm.value.u == 0x4;
},
// AND [RBP+0x8], EAX
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_AND &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP &&
instr.operands[ 0 ].mem.disp.value == 0x8 &&
instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX;
},
// PUSHFQ
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ;
},
// POP [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {
return instr.mnemonic == ZYDIS_MNEMONIC_POP &&
instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP;
} } } };
vm::handler::profile_t nandw = {
// NOT DWORD PTR [RBP]
// MOV AX, [RBP]
// SUB RBP, 0x6
// AND [RBP+0x8], AX
// PUSHFQ
// POP [RBP]
"NANDDW",
NANDDW,
"NANDW",
NANDW,
NULL,
{ { // NOT DWORD PTR [RBP]
[]( const zydis_decoded_instr_t &instr ) -> bool {

@ -24,7 +24,6 @@ namespace vm
ZydisFormatter formatter;
ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u );
puts( buffer );
}
@ -38,7 +37,6 @@ namespace vm
{
std::printf( "> 0x%p ", addr );
ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr );
puts( buffer );
}
}

Loading…
Cancel
Save