@ -4,11 +4,22 @@ namespace vm
{
namespace handler
{
table_t : : table_t ( u64 * table_addr , edit_entry_t edit_entry )
:
table_addr ( table_addr ) ,
edit_entry ( edit_entry )
{ }
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
{
@ -34,81 +45,72 @@ namespace vm
{
handlers [ idx ] . callback = callback ;
}
}
hook_t : : hook_t (
u64 module_base ,
u64 image_base ,
decrypt_handler_t decrypt_handler ,
encrypt_handler_t encrypt_handler ,
vm : : handler : : table_t * vm_handler_table
)
:
decrypt_handler ( decrypt_handler ) ,
encrypt_handler ( encrypt_handler ) ,
handler_table ( vm_handler_table ) ,
module_base ( module_base ) ,
image_base ( image_base )
{
for ( auto idx = 0u ; idx < 256 ; + + idx )
u64 table_t : : decrypt ( u8 idx )
{
vm : : handler : : entry_t entry =
vm_handler_table - > get_meta_data ( idx ) ;
entry . encrypted = vm_handler_table - > get_entry ( idx ) ;
entry . decrypted = decrypt ( entry . encrypted ) ;
entry . virt = ( entry . decrypted - image_base ) + module_base ;
vm_handler_table - > set_meta_data ( idx , entry ) ;
}
vm : : g_vmctx = this ;
vtrap_encrypted = encrypt (
( reinterpret_cast < std : : uintptr_t > (
& __vtrap ) - module_base ) + image_base ) ;
return decrypt_handler ( get_entry ( idx ) ) ;
}
u64 hook_t : : encrypt ( u64 val ) const
u64 table_t : : encrypt ( u64 val )
{
return encrypt_handler ( val ) ;
}
} // namespace handler
u64 hook_t : : decrypt ( u64 val ) const
hook_t : : hook_t ( void ) : table_count ( 0 )
{
return decrypt_handler ( val ) ;
for ( auto idx = 0u ; idx < 10 ; + + idx )
handler_tables [ idx ] = nullptr ;
}
void hook_t : : set_trap ( u64 val ) const
void hook_t : : add_table ( vm : : handler : : table_t * table )
{
for ( auto idx = 0u ; idx < 256 ; + + idx )
handler_table - > set_entry ( idx , val ) ;
handler_tables [ table_count ] = table ;
+ + table_count ;
}
void hook_t : : start ( ) const
void hook_t : : start ( void )
{
for ( auto idx = 0u ; idx < 256 ; + + idx )
handler_table - > set_entry ( idx , vtrap_encrypted ) ;
}
void hook_t : : stop ( ) const
for ( auto idx = 0u ; idx < table_count ; + + idx )
{
for ( auto idx = 0u ; idx < 256 ; + + idx )
{
const auto handler_entry =
handler_table - > get_meta_data ( idx ) . encrypted ;
auto enc_trap_hndlr = handler_tables [ idx ] - > encrypt (
( reinterpret_cast < std : : uintptr_t > ( & __vtrap ) - handler_tables [ idx ] - > module_base ) +
handler_tables [ idx ] - > image_base ) ;
handler_table - > set_entry ( idx , handler_entry ) ;
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 )
{
regs - > vm_handler = vm : : g_vmctx - >
handler_table - > get_meta_data ( handler_idx ) . virt ;
// 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 ) ;
const auto callback = vm : : g_vmctx - >
handler_table - > get_meta_data ( handler_idx ) . callback ;
// 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 ) ;
if ( callback )
callback ( regs , handler_idx ) ;
return ;
}
}
}