|
|
@ -7,12 +7,12 @@ namespace vm
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand,
|
|
|
|
std::uint64_t rolling_key )
|
|
|
|
std::uint64_t rolling_key )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const auto& generic_decrypt_0 = transforms[ transform::type::generic0 ];
|
|
|
|
const auto &generic_decrypt_0 = transforms[ transform::type::generic0 ];
|
|
|
|
const auto& key_decrypt = transforms[ transform::type::rolling_key ];
|
|
|
|
const auto &key_decrypt = transforms[ transform::type::rolling_key ];
|
|
|
|
const auto& generic_decrypt_1 = transforms[ transform::type::generic1 ];
|
|
|
|
const auto &generic_decrypt_1 = transforms[ transform::type::generic1 ];
|
|
|
|
const auto& generic_decrypt_2 = transforms[ transform::type::generic2 ];
|
|
|
|
const auto &generic_decrypt_2 = transforms[ transform::type::generic2 ];
|
|
|
|
const auto& generic_decrypt_3 = transforms[ transform::type::generic3 ];
|
|
|
|
const auto &generic_decrypt_3 = transforms[ transform::type::generic3 ];
|
|
|
|
const auto& update_key = transforms[ transform::type::update_key ];
|
|
|
|
const auto &update_key = transforms[ transform::type::update_key ];
|
|
|
|
|
|
|
|
|
|
|
|
if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID )
|
|
|
|
if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID )
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -44,8 +44,7 @@ namespace vm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// update rolling key...
|
|
|
|
// update rolling key...
|
|
|
|
auto result =
|
|
|
|
auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand );
|
|
|
|
transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update decryption key correctly...
|
|
|
|
// update decryption key correctly...
|
|
|
|
switch ( update_key.operands[ 0 ].size )
|
|
|
|
switch ( update_key.operands[ 0 ].size )
|
|
|
@ -70,15 +69,14 @@ namespace vm
|
|
|
|
transform::map_t inverse;
|
|
|
|
transform::map_t inverse;
|
|
|
|
inverse_transforms( transforms, inverse );
|
|
|
|
inverse_transforms( transforms, inverse );
|
|
|
|
|
|
|
|
|
|
|
|
const auto& generic_decrypt_0 = inverse[ transform::type::generic0 ];
|
|
|
|
const auto &generic_decrypt_0 = inverse[ transform::type::generic0 ];
|
|
|
|
const auto& key_decrypt = inverse[ transform::type::rolling_key ];
|
|
|
|
const auto &key_decrypt = inverse[ transform::type::rolling_key ];
|
|
|
|
const auto& generic_decrypt_1 = inverse[ transform::type::generic1 ];
|
|
|
|
const auto &generic_decrypt_1 = inverse[ transform::type::generic1 ];
|
|
|
|
const auto& generic_decrypt_2 = inverse[ transform::type::generic2 ];
|
|
|
|
const auto &generic_decrypt_2 = inverse[ transform::type::generic2 ];
|
|
|
|
const auto& generic_decrypt_3 = inverse[ transform::type::generic3 ];
|
|
|
|
const auto &generic_decrypt_3 = inverse[ transform::type::generic3 ];
|
|
|
|
const auto& update_key = inverse[ transform::type::update_key ];
|
|
|
|
const auto &update_key = inverse[ transform::type::update_key ];
|
|
|
|
|
|
|
|
|
|
|
|
auto result =
|
|
|
|
auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand );
|
|
|
|
transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// make sure we update the rolling decryption key correctly...
|
|
|
|
// make sure we update the rolling decryption key correctly...
|
|
|
|
switch ( update_key.operands[ 0 ].size )
|
|
|
|
switch ( update_key.operands[ 0 ].size )
|
|
|
@ -162,5 +160,41 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( !imm_size )
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ctx.exec_type == vmp2::exec_type_t::forward
|
|
|
|
|
|
|
|
? *reinterpret_cast< std::uintptr_t * >( vip + ( imm_size / 8 ) )
|
|
|
|
|
|
|
|
: *reinterpret_cast< std::uintptr_t * >( vip - ( imm_size / 8 ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
virt_instr_t result;
|
|
|
|
|
|
|
|
const auto &vm_handler = ctx.vm_handlers[ entry.handler_idx ];
|
|
|
|
|
|
|
|
const auto profile = vm_handler.profile;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.mnemonic_t = profile ? profile->mnemonic : vm::handler::mnemonic_t::INVALID;
|
|
|
|
|
|
|
|
result.opcode = entry.handler_idx;
|
|
|
|
|
|
|
|
result.trace_data = entry;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( vm_handler.imm_size )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
result.operand.has_imm = true;
|
|
|
|
|
|
|
|
const auto imm_val = get_imm( ctx, vm_handler.imm_size, entry.vip );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( !imm_val.has_value() )
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.operand.imm.u = imm_val.value();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
result.operand.has_imm = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
} // namespace instrs
|
|
|
|
} // namespace instrs
|
|
|
|
} // namespace vm
|
|
|
|
} // namespace vm
|