fixed some issues with getting operand decryption transforms

merge-requests/4/head
_xeroxz 4 years ago
parent 8d564257b2
commit 0115f85798

@ -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 const auto _dec = []( T a, T b ) -> T { return a - 1; };
template < class T > 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_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_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_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > },
{ ZYDIS_MNEMONIC_DEC, _dec< 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_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR },
{ ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD }, { 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_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT },
{ ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR }, { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR },
{ ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } }; { 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 ) inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse )
{ {
inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ]; inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ];

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

@ -152,16 +152,14 @@ namespace vm
auto imm_fetch = auto imm_fetch =
std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { std::find_if( vm_handler.begin(), 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 && return ( instr_data.instr.operand_count > 1 &&
( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) &&
instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX &&
instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY &&
instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI ) instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI );
return true;
return false;
} ); } );
if ( imm_fetch == vm_handler.end() ) if ( imm_fetch == vm_handler.end() )
@ -169,52 +167,51 @@ namespace vm
// 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 = auto transform_instr =
std::find_if( imm_fetch, vm_handler.end(), []( 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 ) && return vm::transform::valid( instr_data.instr.mnemonic ) &&
util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ) ) instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE &&
return true; util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) &&
return false; util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX );
} ); } );
if ( key_transform == 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... // 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 { auto generic0 = std::find_if( imm_fetch, transform_instr, []( const zydis_instr_t &instr_data ) -> bool {
return util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && 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 ); !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 ] = generic0 != transform_instr ? generic0->instr : nogeneric0;
transforms[ transform::type::generic0 ] = 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 ] = transform_instr->instr;
auto instr_copy = key_transform->instr; auto instr_copy = transform_instr->instr;
instr_copy.operands[ 0 ].reg.value = key_transform->instr.operands[ 1 ].reg.value; instr_copy.operands[ 0 ].reg.value = transform_instr->instr.operands[ 1 ].reg.value;
instr_copy.operands[ 1 ].reg.value = key_transform->instr.operands[ 0 ].reg.value; instr_copy.operands[ 1 ].reg.value = transform_instr->instr.operands[ 0 ].reg.value;
transforms[ transform::type::update_key ] = instr_copy; transforms[ transform::type::update_key ] = instr_copy;
// three generic transformations... // three generic transformations...
auto generic_transform = key_transform; for ( auto idx = static_cast< unsigned >( vm::transform::type::generic1 );
idx < static_cast< unsigned >( vm::transform::type::update_key ); ++idx )
for ( auto idx = 2u; idx < 5; ++idx )
{ {
generic_transform = transform_instr =
std::find_if( ++generic_transform, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { std::find_if( ++transform_instr, 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 vm::transform::valid( instr_data.instr.mnemonic ) &&
return true; instr_data.instr.operands[0].actions & ZYDIS_OPERAND_ACTION_WRITE &&
util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX );
return false;
} ); } );
if ( generic_transform == vm_handler.end() ) if ( transform_instr == vm_handler.end() )
return false; return false;
transforms[ ( transform::type )( idx ) ] = generic_transform->instr; transforms[ static_cast< vm::transform::type >( idx ) ] = transform_instr->instr;
} }
return true; return true;
@ -255,13 +252,10 @@ namespace vm
std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { std::find_if( vm_entry.begin(), vm_entry.end(), []( 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 && return instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 && instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 &&
!instr->raw.sib.base ) // no register used for the sib base... !instr->raw.sib.base; // no register used for the sib base...
return true;
return false;
} ); } );
if ( result == vm_entry.end() ) if ( result == vm_entry.end() )
@ -275,42 +269,34 @@ namespace vm
bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ) bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr )
{ {
zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE;
auto handler_fetch = auto handler_fetch =
std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( 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 && instr->operand_count == 2 && return instr->mnemonic == ZYDIS_MNEMONIC_MOV && 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 &&
instr->operands[ 1 ].mem.scale == 8 && instr->operands[ 1 ].mem.scale == 8 &&
instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER &&
( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX || ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX ||
instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ) ) instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX );
{
rcx_or_rdx = instr->operands[ 0 ].reg.value;
return true;
}
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...
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... // 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; 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 {
if ( instr_data.instr.operands[ 0 ].reg.value == rcx_or_rdx && return instr_data.instr.operands[ 0 ].reg.value ==
instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE ) handler_fetch->instr.operands[ 0 ].reg.value &&
return true; instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE;
return false;
} ); } );
if ( handler_transform == vm_entry.end() ) if ( handler_transform == vm_entry.end() )

Loading…
Cancel
Save