|
|
|
@ -56,12 +56,13 @@ namespace vm
|
|
|
|
|
virt_labels.push_back( { label_data->label_name } );
|
|
|
|
|
for ( const auto &vinstr : label_data->vinstrs )
|
|
|
|
|
{
|
|
|
|
|
for ( auto itr = vmctx->vm_handlers.begin(); itr != vmctx->vm_handlers.end(); ++itr )
|
|
|
|
|
for ( auto idx = 0u; idx < 256; ++idx )
|
|
|
|
|
{
|
|
|
|
|
if ( itr->profile && itr->profile->name == vinstr.name )
|
|
|
|
|
const auto &vm_handler = vmctx->vm_handlers[ idx ];
|
|
|
|
|
if ( vm_handler.profile && !vinstr.name.compare( vm_handler.profile->name ) )
|
|
|
|
|
{
|
|
|
|
|
virt_labels.back().vinstrs.push_back( { ( std::uint8_t )( itr - vmctx->vm_handlers.begin() ),
|
|
|
|
|
vinstr.imm, itr->profile->imm_size } );
|
|
|
|
|
virt_labels.back().vinstrs.push_back(
|
|
|
|
|
{ ( std::uint8_t )idx, vinstr.imm, vm_handler.profile->imm_size } );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -81,59 +82,85 @@ namespace vm
|
|
|
|
|
// base address of the virtual instructions...
|
|
|
|
|
std::uintptr_t decrypt_key = end_of_module, start_addr;
|
|
|
|
|
if ( vmctx->exec_type == vmp2::exec_type_t::backward )
|
|
|
|
|
{
|
|
|
|
|
std::for_each( virt_labels.begin()->vinstrs.begin(), virt_labels.begin()->vinstrs.end(),
|
|
|
|
|
[ & ]( const vinstr_data &vinstr ) {
|
|
|
|
|
( ++decrypt_key ) += vinstr.imm_size ? vinstr.imm_size / 8 : 0;
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
std::reverse( virt_labels.begin(), virt_labels.end() );
|
|
|
|
|
}
|
|
|
|
|
start_addr = decrypt_key - 1; // make it zero based...
|
|
|
|
|
std::for_each( virt_labels.begin(), virt_labels.end(), [ & ]( vm::vlabel_data &label ) {
|
|
|
|
|
decrypt_key = start_addr;
|
|
|
|
|
result.push_back( { label.label_name, start_addr } );
|
|
|
|
|
|
|
|
|
|
start_addr = decrypt_key;
|
|
|
|
|
if ( vmctx->exec_type == vmp2::exec_type_t::forward )
|
|
|
|
|
{
|
|
|
|
|
std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) {
|
|
|
|
|
std::uint8_t opcode = vinstr.vm_handler;
|
|
|
|
|
std::uint64_t operand = 0u;
|
|
|
|
|
|
|
|
|
|
// loop over the instructions and encrypt them...
|
|
|
|
|
for ( auto &label : virt_labels )
|
|
|
|
|
{
|
|
|
|
|
result.push_back( { label.label_name, start_addr } );
|
|
|
|
|
// encrypt opcode...
|
|
|
|
|
std::tie( opcode, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key );
|
|
|
|
|
|
|
|
|
|
// if there is an operand then we will encrypt that as well..
|
|
|
|
|
if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size )
|
|
|
|
|
{
|
|
|
|
|
auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms;
|
|
|
|
|
std::tie( operand, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key );
|
|
|
|
|
}
|
|
|
|
|
else // else just push back the opcode...
|
|
|
|
|
{
|
|
|
|
|
result.back().vinstrs.push_back( opcode );
|
|
|
|
|
return; // finished here...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( auto &vinstr : label.vinstrs )
|
|
|
|
|
result.back().vinstrs.push_back( opcode );
|
|
|
|
|
for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx )
|
|
|
|
|
result.back().vinstrs.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto vm_handler_idx = vinstr.vm_handler;
|
|
|
|
|
std::tie( vinstr.vm_handler, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key );
|
|
|
|
|
std::for_each( label.vinstrs.begin(), label.vinstrs.end(), [ & ]( vm::vinstr_data &vinstr ) {
|
|
|
|
|
std::uint8_t opcode = vinstr.vm_handler, opcode_test = 0u;
|
|
|
|
|
std::uint64_t operand = 0u;
|
|
|
|
|
std::uint64_t test_decrypt_key;
|
|
|
|
|
|
|
|
|
|
if ( !vinstr.imm_size )
|
|
|
|
|
{
|
|
|
|
|
result.back().vinstrs.push_back( vinstr.vm_handler );
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// encrypt opcode...
|
|
|
|
|
std::tie( opcode, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( calc_jmp_transforms, vinstr.vm_handler, decrypt_key );
|
|
|
|
|
|
|
|
|
|
auto transforms = vmctx->vm_handlers.at( vm_handler_idx ).transforms;
|
|
|
|
|
std::tie( opcode_test, test_decrypt_key ) =
|
|
|
|
|
vm::instrs::decrypt_operand( calc_jmp_transforms, opcode, decrypt_key );
|
|
|
|
|
|
|
|
|
|
std::tie( vinstr.operand, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( transforms, vinstr.operand, decrypt_key );
|
|
|
|
|
// if there is an operand then we will encrypt that as well..
|
|
|
|
|
if ( vmctx->vm_handlers[ vinstr.vm_handler ].imm_size )
|
|
|
|
|
{
|
|
|
|
|
auto &vm_handler_transforms = vmctx->vm_handlers[ vinstr.vm_handler ].transforms;
|
|
|
|
|
|
|
|
|
|
// operands must be backwards if VIP advances backward...
|
|
|
|
|
if ( vmctx->exec_type == vmp2::exec_type_t::backward )
|
|
|
|
|
{
|
|
|
|
|
for ( auto idx = 0u; idx < vinstr.imm_size / 8; ++idx )
|
|
|
|
|
result.back().vinstrs.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] );
|
|
|
|
|
std::tie( operand, decrypt_key ) =
|
|
|
|
|
vm::instrs::encrypt_operand( vm_handler_transforms, vinstr.operand, decrypt_key );
|
|
|
|
|
}
|
|
|
|
|
else // else just push back the opcode...
|
|
|
|
|
{
|
|
|
|
|
result.back().vinstrs.insert( result.back().vinstrs.begin(), 1, opcode );
|
|
|
|
|
return; // finished here...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.back().vinstrs.push_back( vinstr.vm_handler );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result.back().vinstrs.push_back( vinstr.vm_handler );
|
|
|
|
|
// operand goes first, then opcode when vip advances backwards...
|
|
|
|
|
std::vector< std::uint8_t > _temp;
|
|
|
|
|
for ( auto idx = 0u; idx < vmctx->vm_handlers[ vinstr.vm_handler ].imm_size / 8; ++idx )
|
|
|
|
|
_temp.push_back( reinterpret_cast< std::uint8_t * >( &operand )[ idx ] );
|
|
|
|
|
|
|
|
|
|
for ( auto idx = 0u; idx < vinstr.imm_size / 8; ++idx )
|
|
|
|
|
result.back().vinstrs.push_back( reinterpret_cast< std::uint8_t * >( &vinstr.operand )[ idx ] );
|
|
|
|
|
}
|
|
|
|
|
result.back().vinstrs.insert( result.back().vinstrs.begin(), _temp.begin(), _temp.end() );
|
|
|
|
|
result.back().vinstrs.insert( result.back().vinstrs.begin() + _temp.size(), opcode );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.back().enc_alloc_rva = encrypt_rva( start_addr );
|
|
|
|
|
start_addr += result.back().vinstrs.size();
|
|
|
|
|
}
|
|
|
|
|
start_addr += result.back().vinstrs.size() - 1; // make it zero based...
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|