|
|
@ -166,30 +166,36 @@ namespace vm
|
|
|
|
if ( !imm_size )
|
|
|
|
if ( !imm_size )
|
|
|
|
return {};
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
|
|
return ctx.exec_type == vmp2::exec_type_t::forward
|
|
|
|
std::uint64_t result = 0u;
|
|
|
|
? *reinterpret_cast< std::uintptr_t * >( vip + ( imm_size / 8 ) )
|
|
|
|
if ( ctx.exec_type == vmp2::exec_type_t::forward )
|
|
|
|
: *reinterpret_cast< std::uintptr_t * >( vip - ( imm_size / 8 ) );
|
|
|
|
std::memcpy( &result, reinterpret_cast< void * >( vip ), imm_size / 8 );
|
|
|
|
|
|
|
|
else // else the second operand is below vip...
|
|
|
|
|
|
|
|
std::memcpy( &result, reinterpret_cast< void * >( vip - ( imm_size / 8 ) ), imm_size / 8 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry )
|
|
|
|
std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
virt_instr_t result;
|
|
|
|
virt_instr_t result;
|
|
|
|
const auto &vm_handler = ctx.vm_handlers[ entry.handler_idx ];
|
|
|
|
auto &vm_handler = ctx.vm_handlers[ entry.handler_idx ];
|
|
|
|
const auto profile = vm_handler.profile;
|
|
|
|
const auto profile = vm_handler.profile;
|
|
|
|
|
|
|
|
|
|
|
|
result.mnemonic_t = profile ? profile->mnemonic : vm::handler::mnemonic_t::INVALID;
|
|
|
|
result.mnemonic_t = profile ? profile->mnemonic : vm::handler::INVALID;
|
|
|
|
result.opcode = entry.handler_idx;
|
|
|
|
result.opcode = entry.handler_idx;
|
|
|
|
result.trace_data = entry;
|
|
|
|
result.trace_data = entry;
|
|
|
|
|
|
|
|
|
|
|
|
if ( vm_handler.imm_size )
|
|
|
|
if ( vm_handler.imm_size )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
result.operand.has_imm = true;
|
|
|
|
result.operand.has_imm = true;
|
|
|
|
|
|
|
|
result.operand.imm.imm_size = vm_handler.imm_size;
|
|
|
|
const auto imm_val = get_imm( ctx, vm_handler.imm_size, entry.vip );
|
|
|
|
const auto imm_val = get_imm( ctx, vm_handler.imm_size, entry.vip );
|
|
|
|
|
|
|
|
|
|
|
|
if ( !imm_val.has_value() )
|
|
|
|
if ( !imm_val.has_value() )
|
|
|
|
return {};
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
|
|
result.operand.imm.u = imm_val.value();
|
|
|
|
result.operand.imm.u =
|
|
|
|
|
|
|
|
vm::instrs::decrypt_operand( vm_handler.transforms, imm_val.value(), entry.decrypt_key ).first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
result.operand.has_imm = false;
|
|
|
|
result.operand.has_imm = false;
|
|
|
@ -266,12 +272,13 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry )
|
|
|
|
std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return ( ( entry.vsp.qword[ 0 ] + ctx.image_base & ~0xFFFFFFFFull ) - ctx.image_base ) + ctx.module_base;
|
|
|
|
return ( ( entry.vsp.qword[ 0 ] + ( ctx.image_base & ~0xFFFFFFFFull ) ) - ctx.image_base ) +
|
|
|
|
|
|
|
|
ctx.module_base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits )
|
|
|
|
std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return ( ( lower_32bits + ctx.image_base & ~0xFFFFFFFFull ) - ctx.image_base ) + ctx.module_base;
|
|
|
|
return ( ( lower_32bits + ( ctx.image_base & ~0xFFFFFFFFull ) ) - ctx.image_base ) + ctx.module_base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace instrs
|
|
|
|
} // namespace instrs
|
|
|
|
} // namespace vm
|
|
|
|
} // namespace vm
|