From b6a094cf1211babce6e3c8e7639437911d7a9c36 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 25 Aug 2021 11:27:22 -0700 Subject: [PATCH] crashing but getting there... --- .../framelesswindow/framelesswindow.ui | 2 +- src/main.cpp | 14 +-- src/qvm_inspector.cpp | 91 ++++++++++++++++++- src/qvm_inspector.h | 6 +- src/qvm_virtual_instructions.cpp | 22 ++--- src/qvm_virtual_routines.cpp | 3 + src/qvminspector.ui | 2 +- 7 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/darkstyle/framelesswindow/framelesswindow.ui b/src/darkstyle/framelesswindow/framelesswindow.ui index 2421768..7751a56 100644 --- a/src/darkstyle/framelesswindow/framelesswindow.ui +++ b/src/darkstyle/framelesswindow/framelesswindow.ui @@ -6,7 +6,7 @@ 0 0 - 1311 + 1404 897 diff --git a/src/main.cpp b/src/main.cpp index 8c375a0..9b282de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,12 +3,12 @@ #include #include -#include "qvm_inspector.h" +#include "darkstyle/DarkStyle.h" +#include "darkstyle/framelesswindow/framelesswindow.h" #include "qvm_handlers.h" +#include "qvm_inspector.h" #include "qvm_virtual_instructions.h" #include "qvm_virtual_routines.h" -#include "darkstyle/DarkStyle.h" -#include "darkstyle/framelesswindow/framelesswindow.h" int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { @@ -16,10 +16,10 @@ int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int QApplication::setStyle( new DarkStyle ); FramelessWindow FW; - const auto g_main_window = new qvm_inspector; - qvm_virtual_instructions VirtInstrsPanel( g_main_window ); - qvm_handlers VirtHandlerPanel( g_main_window ); - qvm_virtual_routines VirtualRoutinesPanel( g_main_window ); + auto g_main_window = new qvm_inspector; + qvm_virtual_instructions virt_instrs_panel( g_main_window ); + qvm_handlers virt_handler_panel( g_main_window ); + qvm_virtual_routines virt_routine_panel( g_main_window ); FW.setContent( g_main_window ); FW.setWindowIcon( QIcon( "icon.ico" ) ); diff --git a/src/qvm_inspector.cpp b/src/qvm_inspector.cpp index 45b73a2..8e66589 100644 --- a/src/qvm_inspector.cpp +++ b/src/qvm_inspector.cpp @@ -3,7 +3,7 @@ qvm_inspector::qvm_inspector( QWidget *parent ) : QMainWindow( parent ), file_header( nullptr ), g_vm_ctx( nullptr ) { ui.setupUi( this ); - ui.virt_instrs->setColumnWidth( 0, 180 ); + ui.virt_instrs->setColumnWidth( 0, 125 ); ui.virt_instrs->setColumnWidth( 1, 150 ); ui.virt_instrs->setColumnWidth( 2, 190 ); ui.virt_instrs->setColumnWidth( 3, 200 ); @@ -178,7 +178,8 @@ bool qvm_inspector::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns ) return true; } -void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, QTreeWidgetItem *parent ) +void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, std::uintptr_t blk_addr, + QTreeWidgetItem *parent ) { auto _rtn = std::find_if( virt_rtns.begin(), virt_rtns.end(), [ & ]( rtn_data_t &rtn ) -> bool { return rtn.rtn_rva == rtn_addr; } ); @@ -186,11 +187,31 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, QTreeW if ( _rtn == virt_rtns.end() ) return; - for ( const auto &vinstr : _rtn->rtn_blks[ 0 ].vinstrs ) + auto code_blk = blk_addr ? std::find_if( _rtn->rtn_blks.begin(), _rtn->rtn_blks.end(), + [ & ]( const vm::instrs::code_block_t &code_block ) -> bool { + return code_block.vip_begin == blk_addr; + } ) + : _rtn->rtn_blks.begin(); + + if ( code_blk == _rtn->rtn_blks.end() ) + return; + + if ( std::find( code_block_addrs.begin(), code_block_addrs.end(), code_blk->vip_begin ) != code_block_addrs.end() ) + return; + + code_block_addrs.push_back( code_blk->vip_begin ); + + for ( auto &vinstr : code_blk->vinstrs ) { const auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); + const auto &vm_handler = g_vm_ctx->vm_handlers[ vinstr.opcode ]; auto virt_instr_entry = new QTreeWidgetItem(); + // virtual instruction image base'ed rva... (column 1)... + virt_instr_entry->setText( + 0, QString( "0x%1" ).arg( QString::number( + ( vinstr.trace_data.vip - file_header->module_base ) + file_header->image_base, 16 ) ) ); + // virtual instruction operand bytes... (column 2)... QString operand_bytes; operand_bytes.append( QString( "%1" ).arg( vinstr.opcode, 0, 16 ) ); @@ -220,6 +241,68 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, QTreeW virt_instr_entry->setText( 3, QString( "; vreg%1" ).arg( vinstr.operand.imm.u ? ( vinstr.operand.imm.u / 8 ) : 0u ) ); - ui.virt_instrs->addTopLevelItem( virt_instr_entry ); + if ( vinstr.mnemonic_t == vm::handler::JMP ) + { + switch ( code_blk->jcc.type ) + { + case vm::instrs::jcc_type::branching: + { + virt_instr_entry->setText( 3, QString( "; { 0x%1, 0x%2 }" ) + .arg( code_blk->jcc.block_addr[ 0 ], 0, 16 ) + .arg( code_blk->jcc.block_addr[ 1 ], 0, 16 ) ); + + auto entry_rva = vm_handler.address - module_base; + auto branch_entry1 = new QTreeWidgetItem(), branch_entry2 = new QTreeWidgetItem(); + const auto block1_addr = code_blk->jcc.block_addr[ 0 ]; + const auto block2_addr = code_blk->jcc.block_addr[ 1 ]; + + branch_entry1->setText( 0, QString( "0x%1" ).arg( block1_addr, 0, 16 ) ); + branch_entry1->setText( 3, QString( "; blk_0x%1" ).arg( block1_addr, 0, 16 ) ); + + branch_entry2->setText( 0, QString( "0x%1" ).arg( block2_addr, 0, 16 ) ); + branch_entry2->setText( 3, QString( "; blk_0x%1" ).arg( block2_addr, 0, 16 ) ); + + if ( g_vm_ctx ) + delete g_vm_ctx; + + if ( !( g_vm_ctx = new vm::ctx_t( module_base, img_base, img_size, entry_rva ) )->init() ) + { + dbg_print( QString( "> failed to init vm::ctx_t for jmp at = %1..." ) + .arg( QString::number( code_blk->vip_begin, 16 ) ) ); + return; + } + + update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 0 ], branch_entry1 ); + update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 1 ], branch_entry2 ); + virt_instr_entry->addChildren( { branch_entry1, branch_entry2 } ); + break; + } + case vm::instrs::jcc_type::absolute: + { + auto entry_rva = vm_handler.address - module_base; + virt_instr_entry->setText( 3, QString( "; { 0x%1 }" ).arg( code_blk->jcc.block_addr[ 0 ], 0, 16 ) ); + + if ( g_vm_ctx ) + delete g_vm_ctx; + + if ( !( g_vm_ctx = new vm::ctx_t( module_base, img_base, img_size, entry_rva ) )->init() ) + { + dbg_print( QString( "> failed to init vm::ctx_t for jmp at = %1..." ) + .arg( QString::number( code_blk->vip_begin, 16 ) ) ); + return; + } + + update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 0 ], parent ); + break; + } + default: + break; + } + } + + QVariant var; + var.setValue( vinstr ); + virt_instr_entry->setData( 3, Qt::UserRole, var ); + parent ? parent->addChild( virt_instr_entry ) : ui.virt_instrs->addTopLevelItem( virt_instr_entry ); } } diff --git a/src/qvm_inspector.h b/src/qvm_inspector.h index 59b6131..1327e50 100644 --- a/src/qvm_inspector.h +++ b/src/qvm_inspector.h @@ -16,7 +16,7 @@ #include #define ABS_TO_IMG( addr, mod_base, img_base ) ( addr - mod_base ) + img_base -Q_DECLARE_METATYPE( vm::instrs::virt_instr_t * ) +Q_DECLARE_METATYPE( vm::instrs::virt_instr_t ) struct rtn_data_t { @@ -42,7 +42,8 @@ class qvm_inspector : public QMainWindow void dbg_msg( QString DbgOutput ); void update_ui(); bool serialize_vmp2( std::vector< rtn_data_t > &virt_rtns ); - void update_virtual_instructions( std::uintptr_t rtn_addr, QTreeWidgetItem *parent = nullptr ); + void update_virtual_instructions( std::uintptr_t rtn_addr, std::uintptr_t blk_addr = 0ull, + QTreeWidgetItem *parent = nullptr ); bool init_data(); Ui::QVMProfilerClass ui; @@ -51,4 +52,5 @@ class qvm_inspector : public QMainWindow vmp2::v4::file_header *file_header; std::vector< rtn_data_t > virt_rtns; + std::vector< std::uintptr_t > code_block_addrs; }; \ No newline at end of file diff --git a/src/qvm_virtual_instructions.cpp b/src/qvm_virtual_instructions.cpp index 4058a2a..490121a 100644 --- a/src/qvm_virtual_instructions.cpp +++ b/src/qvm_virtual_instructions.cpp @@ -16,15 +16,11 @@ void qvm_virtual_instructions::on_select() if ( !item ) return; - const auto virt_instr = item->data( 3, Qt::UserRole ).value< vm::instrs::virt_instr_t * >(); - - if ( !virt_instr ) - return; - - update_native_registers( virt_instr ); - update_virtual_registers( virt_instr ); - update_virtual_stack( virt_instr ); - update_vmhandler_info( virt_instr ); + auto virt_instr = item->data( 3, Qt::UserRole ).value< vm::instrs::virt_instr_t >(); + update_native_registers( &virt_instr ); + update_virtual_registers( &virt_instr ); + update_virtual_stack( &virt_instr ); + update_vmhandler_info( &virt_instr ); } void qvm_virtual_instructions::update_native_registers( vm::instrs::virt_instr_t *virt_instr ) @@ -59,8 +55,9 @@ void qvm_virtual_instructions::update_virtual_registers( vm::instrs::virt_instr_ // set VIP in virtual registers window... ui->virt_regs->topLevelItem( 0 )->setText( - 1, QString::number( - ( trace_data.vip - g_main_window->file_header->module_base ) + g_main_window->file_header->image_base, 16 ) ); + 1, QString::number( ( trace_data.vip - g_main_window->file_header->module_base ) + + g_main_window->file_header->image_base, + 16 ) ); // set VSP in virtual registers window... ui->virt_regs->topLevelItem( 1 )->setText( 1, QString::number( trace_data.regs.rbp, 16 ) ); @@ -100,7 +97,8 @@ void qvm_virtual_instructions::update_vmhandler_info( vm::instrs::virt_instr_t * for ( const auto &instr : vm_handler_instrs ) { auto new_instr = new QTreeWidgetItem(); - new_instr->setText( 0, QString::number( ( instr.addr - g_main_window->module_base ) + g_main_window->img_base, 16 ) ); + new_instr->setText( + 0, QString::number( ( instr.addr - g_main_window->module_base ) + g_main_window->img_base, 16 ) ); ZydisFormatterFormatInstruction( &formatter, &instr.instr, buffer, sizeof( buffer ), ( instr.addr - g_main_window->module_base ) + g_main_window->img_base ); diff --git a/src/qvm_virtual_routines.cpp b/src/qvm_virtual_routines.cpp index efab1d3..ca64e63 100644 --- a/src/qvm_virtual_routines.cpp +++ b/src/qvm_virtual_routines.cpp @@ -101,5 +101,8 @@ void qvm_virtual_routines::on_select() update_vm_enter( g_main_window->g_vm_ctx ); update_calc_jmp( g_main_window->g_vm_ctx ); update_vm_handlers( g_main_window->g_vm_ctx ); + + ui->virt_instrs->clear(); + g_main_window->code_block_addrs.clear(); g_main_window->update_virtual_instructions( entry_rva ); } \ No newline at end of file diff --git a/src/qvminspector.ui b/src/qvminspector.ui index 3c08ead..e59fcfc 100644 --- a/src/qvminspector.ui +++ b/src/qvminspector.ui @@ -27,7 +27,7 @@ - 1 + 2