You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.8 KiB
116 lines
3.8 KiB
#include "vmhook.hpp"
|
|
|
|
namespace vm
|
|
{
|
|
namespace handler
|
|
{
|
|
table_t::table_t( u64 module_base, u64 image_base, u32 table_rva, vm::handler::edit_entry_t edit_entry,
|
|
vm::decrypt_handler_t decrypt_handler, vm::encrypt_handler_t encrypt_handler )
|
|
: module_base( module_base ), image_base( image_base ), table_rva( table_rva ), edit_entry( edit_entry ),
|
|
decrypt_handler( decrypt_handler ), encrypt_handler( encrypt_handler )
|
|
{
|
|
table_addr = reinterpret_cast< u64 * >( module_base + table_rva );
|
|
for ( auto idx = 0u; idx < 256; ++idx )
|
|
{
|
|
entry_t entry;
|
|
entry.decrypted = decrypt( idx );
|
|
entry.encrypted = get_entry( idx );
|
|
entry.virt = ( entry.decrypted - image_base ) + module_base;
|
|
entry.callback = nullptr;
|
|
handlers[ idx ] = entry;
|
|
}
|
|
}
|
|
|
|
u64 table_t::get_entry( u8 idx ) const
|
|
{
|
|
return table_addr[ idx ];
|
|
}
|
|
|
|
entry_t table_t::get_meta_data( u8 idx ) const
|
|
{
|
|
return handlers[ idx ];
|
|
}
|
|
|
|
void table_t::set_entry( u8 idx, u64 entry )
|
|
{
|
|
edit_entry( table_addr + idx, entry );
|
|
}
|
|
|
|
void table_t::set_meta_data( u8 idx, const entry_t &entry )
|
|
{
|
|
handlers[ idx ] = entry;
|
|
}
|
|
|
|
void table_t::set_callback( u8 idx, entry_callback_t callback )
|
|
{
|
|
handlers[ idx ].callback = callback;
|
|
}
|
|
|
|
u64 table_t::decrypt( u8 idx )
|
|
{
|
|
return decrypt_handler( get_entry( idx ) );
|
|
}
|
|
|
|
u64 table_t::encrypt( u64 val )
|
|
{
|
|
return encrypt_handler( val );
|
|
}
|
|
} // namespace handler
|
|
|
|
hook_t::hook_t( void ) : table_count( 0 )
|
|
{
|
|
for ( auto idx = 0u; idx < 10; ++idx )
|
|
handler_tables[ idx ] = nullptr;
|
|
}
|
|
|
|
void hook_t::add_table( vm::handler::table_t *table )
|
|
{
|
|
handler_tables[ table_count ] = table;
|
|
++table_count;
|
|
}
|
|
|
|
void hook_t::start( void )
|
|
{
|
|
for ( auto idx = 0u; idx < table_count; ++idx )
|
|
{
|
|
auto enc_trap_hndlr = handler_tables[ idx ]->encrypt(
|
|
( reinterpret_cast< std::uintptr_t >( &__vtrap ) - handler_tables[ idx ]->module_base ) +
|
|
handler_tables[ idx ]->image_base );
|
|
|
|
for ( auto table_idx = 0u; table_idx < 256; ++table_idx )
|
|
handler_tables[ idx ]->set_entry( table_idx, enc_trap_hndlr );
|
|
}
|
|
}
|
|
|
|
void hook_t::stop( void )
|
|
{
|
|
for ( auto idx = 0u; idx < table_count; ++idx )
|
|
for ( auto table_idx = 0u; table_idx < 256; ++table_idx )
|
|
handler_tables[ idx ]->set_entry( table_idx, // restore vm handler table encrypted values...
|
|
handler_tables[ idx ]->get_meta_data( table_idx ).encrypted );
|
|
}
|
|
|
|
} // namespace vm
|
|
|
|
void vtrap_wrapper( vm::registers *regs, u8 handler_idx )
|
|
{
|
|
// r12: vm handler linear virtual address
|
|
// r13: module base linear virtual address
|
|
auto table_rva = regs->r12 - ( regs->r13 + vm::g_vmctx->handler_tables[ 0 ]->image_base );
|
|
|
|
// can only be a max of 10 vms... so idx < 10...
|
|
for ( auto idx = 0u; idx < 10; ++idx )
|
|
{
|
|
if ( vm::g_vmctx->handler_tables[ idx ] && vm::g_vmctx->handler_tables[ idx ]->table_rva == table_rva )
|
|
{
|
|
regs->vm_handler = vm::g_vmctx->handler_tables[ idx ]->get_meta_data( handler_idx ).virt;
|
|
const auto callback = vm::g_vmctx->handler_tables[ idx ]->get_meta_data( handler_idx ).callback;
|
|
|
|
// per-virtual instruction callbacks...
|
|
if ( callback )
|
|
callback( regs, handler_idx );
|
|
|
|
return;
|
|
}
|
|
}
|
|
} |