From 86ca2e31e00609beeac5f5341e08f9d54b961254 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sat, 21 Aug 2021 21:07:16 -0700 Subject: [PATCH 1/7] porting the project to support .vmp2 file format v4... --- dependencies/vmprofiler | 2 +- src/qvminspector.cpp | 306 ++++++---------------------------------- src/qvminspector.h | 12 +- src/qvminspector.ui | 115 ++++++++++++++- 4 files changed, 161 insertions(+), 274 deletions(-) diff --git a/dependencies/vmprofiler b/dependencies/vmprofiler index c231911..573cc04 160000 --- a/dependencies/vmprofiler +++ b/dependencies/vmprofiler @@ -1 +1 @@ -Subproject commit c2319117a07d95794f54db970aa7f72e8726349a +Subproject commit 573cc04fc1804ac328b555bb1136d132d858a6fe diff --git a/src/qvminspector.cpp b/src/qvminspector.cpp index 3e0b151..78279f2 100644 --- a/src/qvminspector.cpp +++ b/src/qvminspector.cpp @@ -19,14 +19,10 @@ void qvminspector_t::on_close() void qvminspector_t::on_open() { - if ( file_header && vmctx ) - { + if ( file_header ) free( file_header ); - delete vmctx; - } - file_header = nullptr, first_block = nullptr; - code_block_addrs.clear(); + file_header = nullptr; image_base = 0u, vm_entry_rva = 0u, module_base = 0u; file_path = QFileDialog::getOpenFileName( @@ -55,7 +51,7 @@ void qvminspector_t::on_open() } qfile_t open_file( file_path ); - file_header = reinterpret_cast< vmp2::v3::file_header * >( malloc( file_size ) ); + file_header = reinterpret_cast< vmp2::v4::file_header * >( malloc( file_size ) ); if ( !open_file.open( QIODevice::ReadOnly ) ) { @@ -70,8 +66,6 @@ void qvminspector_t::on_open() dbg_msg( "failed to init vmp2 file data..." ); return; } - - update_ui(); } void qvminspector_t::dbg_print( qstring_t dbg_output ) @@ -98,10 +92,10 @@ bool qvminspector_t::init_data() dbg_print( "valid magic bytes for vmp2 file..." ); - if ( file_header->version != vmp2::version_t::v3 ) + if ( file_header->version != vmp2::version_t::v4 ) { dbg_msg( "invalid vmp2 file version... " - "this vminspector is compiled for version 3...\n" ); + "this vminspector is compiled for version 4...\n" ); return false; } @@ -111,275 +105,59 @@ bool qvminspector_t::init_data() image_size = file_header->module_size; module_base = reinterpret_cast< std::uintptr_t >( file_header ) + file_header->module_offset; - vmctx = new vm::ctx_t( module_base, image_base, image_size, vm_entry_rva ); - - if ( !vmctx->init() ) - { - dbg_msg( "failed to init vm::ctx_t... this can happen for many reasons..." - "ensure that the vmp2 file is not corrupted...\n" ); - - return false; - } - - first_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + - file_header->code_block_offset ); return true; } void qvminspector_t::add_branch_children( qtree_widget_item_t *item, std::uintptr_t branch_addr ) { - if ( std::find( code_block_addrs.begin(), code_block_addrs.end(), branch_addr ) != code_block_addrs.end() ) - return; - - code_block_addrs.push_back( branch_addr ); - // for each code block find the one that starts with the desired branch... - for ( auto [ code_block, code_block_num ] = std::tuple{ first_block, 0u }; - code_block_num < file_header->code_block_count; - code_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( code_block ) + - code_block->next_block_offset ), - ++code_block_num ) - { - if ( code_block->vip_begin != branch_addr ) - continue; +} - dbg_print( qstring_t( "> code block %1 (block_%2), number of vinstrs = %3..." ) - .arg( code_block_num ) - .arg( code_block->vip_begin, 0, 16 ) - .arg( code_block->vinstr_count ) ); +void qvminspector_t::update_ui() +{ - // for each virtual instruction inside of this code block... - for ( auto idx = 0u; idx < code_block->vinstr_count; ++idx ) - { - const auto virt_instr = &code_block->vinstr[ idx ]; - const auto profile = vm::handler::get_profile( virt_instr->mnemonic_t ); - auto virt_instr_entry = new qtree_widget_item_t; - - // virtual instruction image base'ed rva... (column 1)... - virt_instr_entry->setText( - 0, QString( "block_%1+%2" ) - .arg( branch_addr, 0, 16 ) - .arg( idx ? code_block->vip_begin > - ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - ? code_block->vip_begin - - ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - : ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - - code_block->vip_begin - : 0u, - 0, 16 ) ); - - // virtual instruction operand bytes... (column 2)... - qstring_t operand_bytes; - operand_bytes.append( QString( "%1" ).arg( virt_instr->opcode, 0, 16 ) ); - - // if virt instruction has an imm... grab its bytes... - if ( virt_instr->operand.has_imm ) - { - operand_bytes.append( " - " ); - for ( auto _idx = 0u; _idx < virt_instr->operand.imm.imm_size / 8; ++_idx ) - operand_bytes.append( QString( "%1 " ).arg( - reinterpret_cast< std::uint8_t * >( &virt_instr->operand.imm.u )[ _idx ], 0, 16 ) ); - } - - virt_instr_entry->setText( 1, operand_bytes ); - - // virtual instruction string, includes imm... (colume 3)... - QString decoded_instr( QString( "%1" ).arg( - profile ? profile->name : QString( "UNK(%1)" ).arg( virt_instr->opcode, 0, 16 ) ) ); - - if ( virt_instr->operand.has_imm ) // if there is a second operand (imm) put its value... - decoded_instr.append( QString( " %1" ).arg( virt_instr->operand.imm.u, 0, 16 ) ); - - virt_instr_entry->setText( 2, decoded_instr ); - - // add comments to the virtual instruction... (colume 4)... - if ( virt_instr->mnemonic_t == vm::handler::LREGQ || virt_instr->mnemonic_t == vm::handler::SREGQ ) - virt_instr_entry->setText( - 3, - QString( "; vreg%1" ).arg( virt_instr->operand.imm.u ? ( virt_instr->operand.imm.u / 8 ) : 0u ) ); - - QVariant var; - var.setValue( virt_instr ); - virt_instr_entry->setData( 3, Qt::UserRole, var ); - - if ( virt_instr->mnemonic_t == vm::handler::JMP ) - { - if ( code_block->jcc.type == vm::instrs::jcc_type::branching ) - { - virt_instr_entry->setText( 3, QString( "; { %1, %2 }" ) - .arg( code_block->jcc.block_addr[ 0 ], 0, 16 ) - .arg( code_block->jcc.block_addr[ 1 ], 0, 16 ) ); - - auto branch_entry1 = new qtree_widget_item_t(), branch_entry2 = new qtree_widget_item_t(); - const auto block1_addr = code_block->jcc.block_addr[ 0 ]; - const auto block2_addr = code_block->jcc.block_addr[ 1 ]; - - branch_entry1->setText( 0, QString( "%1" ).arg( block1_addr, 0, 16 ) ); - branch_entry1->setText( 3, QString( "; block_%1" ).arg( block1_addr, 0, 16 ) ); - - branch_entry2->setText( 0, QString( "%1" ).arg( block2_addr, 0, 16 ) ); - branch_entry2->setText( 3, QString( "; block_%1" ).arg( block2_addr, 0, 16 ) ); - - add_branch_children( branch_entry1, code_block->jcc.block_addr[ 0 ] ); - add_branch_children( branch_entry2, code_block->jcc.block_addr[ 1 ] ); - - virt_instr_entry->addChildren( { branch_entry1, branch_entry2 } ); - // if its a JMP with branches we want to insert the next code block - // instructions into the child widget entries... - item->addChild( virt_instr_entry ); - return; - } - else - { - virt_instr_entry->setText( 3, QString( "; { %1 }" ).arg( code_block->jcc.block_addr[ 0 ], 0, 16 ) ); - - // else if this jmp doesnt have two branches add the next code block to it... - item->addChild( virt_instr_entry ); - add_branch_children( item, code_block->jcc.block_addr[ 0 ] ); - } - } - item->addChild( virt_instr_entry ); - } - } } -void qvminspector_t::update_ui() +bool qvminspector_t::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns, std::vector< std::uint8_t > &vmp2file ) { - // add vm handlers to the vm handler tree... - ui.virt_handlers_tree->clear(); - for ( auto idx = 0u; idx < vmctx->vm_handlers.size(); ++idx ) + const auto file_header = reinterpret_cast< vmp2::v4::file_header * >( vmp2file.data() ); + + if ( file_header->version != vmp2::version_t::v4 ) { - auto new_handler_entry = new qtree_widget_item_t; - new_handler_entry->setData( 0, Qt::UserRole, idx ); - new_handler_entry->setText( 0, QString( "%1" ).arg( idx ) ); - new_handler_entry->setText( - 1, QString( "%1" ).arg( - ABS_TO_IMG( vmctx->vm_handlers[ idx ].address, module_base, file_header->image_base ), 0, 16 ) ); - - new_handler_entry->setText( 2, vmctx->vm_handlers[ idx ].profile ? vmctx->vm_handlers[ idx ].profile->name - : "UNDEFINED" ); - - new_handler_entry->setText( 3, QString( "%1" ).arg( vmctx->vm_handlers[ idx ].imm_size ) ); - - if ( vmctx->vm_handlers[ idx ].profile && vmctx->vm_handlers[ idx ].imm_size ) - new_handler_entry->setText( 4, vmctx->vm_handlers[ idx ].profile->extention == - vm::handler::extention_t::sign_extend - ? "SIGN EXTENDED" - : "ZERO EXTENDED" ); - else - new_handler_entry->setText( 4, "UNDEFINED" ); - - ui.virt_handlers_tree->addTopLevelItem( new_handler_entry ); + std::printf( "[!] invalid vmp2 file version... this build uses v3...\n" ); + return false; } - ui.virt_handlers_tree->topLevelItem( 0 )->setSelected( true ); - - // for each code block insert their virtual instructions - // into the virtual instruction tree... also put meta data about the code - // block above the virtual instructions... if the code block has a JCC (with two branches) - // then make a child repeating this for loop... - - ui.virt_instrs->clear(); // clear old virtual instructions out since we are updating the UI... - for ( auto [ code_block, code_block_num ] = std::tuple{ first_block, 0u }; - code_block_num < file_header->code_block_count; - code_block = reinterpret_cast< vmp2::v3::code_block_t * >( reinterpret_cast< std::uintptr_t >( code_block ) + - code_block->next_block_offset ), - ++code_block_num ) + + auto first_rtn = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + + file_header->rtn_offset ); + + for ( auto [ rtn_block, rtn_idx ] = std::pair{ first_rtn, 0ull }; rtn_idx < file_header->rtn_count; + ++rtn_idx, rtn_block = reinterpret_cast< vmp2::v4::rtn_t * >( + reinterpret_cast< std::uintptr_t >( rtn_block ) + rtn_block->size ) ) { - code_block_addrs.push_back( code_block->vip_begin ); - dbg_print( qstring_t( "> code block %1 (block_%2), number of vinstrs = %3..." ) - .arg( code_block_num ) - .arg( code_block->vip_begin, 0, 16 ) - .arg( code_block->vinstr_count ) ); - - // for each virtual instruction inside of this code block... - for ( auto idx = 0u; idx < code_block->vinstr_count; ++idx ) + virt_rtns.push_back( { rtn_block->vm_enter_offset, {} } ); + for ( auto [ code_block, block_idx ] = std::pair{ &rtn_block->code_blocks[ 0 ], 0ull }; + block_idx < rtn_block->code_block_count; + ++block_idx, code_block = reinterpret_cast< vmp2::v4::code_block_t * >( + reinterpret_cast< std::uintptr_t >( code_block ) + code_block->next_block_offset ) ) { - const auto virt_instr = &code_block->vinstr[ idx ]; - const auto profile = vm::handler::get_profile( virt_instr->mnemonic_t ); - auto virt_instr_entry = new qtree_widget_item_t; - - // virtual instruction image base'ed rva... (column 1)... - virt_instr_entry->setText( - 0, QString( "block_%1+%2" ) - .arg( code_block->vip_begin, 0, 16 ) - .arg( idx ? code_block->vip_begin > - ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - ? code_block->vip_begin - - ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - : ( ( virt_instr->trace_data.vip - file_header->module_base ) + image_base ) - - code_block->vip_begin - : 0u, - 0, 16 ) ); - - // virtual instruction operand bytes... (column 2)... - qstring_t operand_bytes; - operand_bytes.append( QString( "%1" ).arg( virt_instr->opcode, 0, 16 ) ); - - // if virt instruction has an imm... grab its bytes... - if ( virt_instr->operand.has_imm ) - { - operand_bytes.append( " - " ); - for ( auto _idx = 0u; _idx < virt_instr->operand.imm.imm_size / 8; ++_idx ) - operand_bytes.append( QString( "%1 " ).arg( - reinterpret_cast< std::uint8_t * >( &virt_instr->operand.imm.u )[ _idx ], 0, 16 ) ); - } - - virt_instr_entry->setText( 1, operand_bytes ); - - // virtual instruction string, includes imm... (colume 3)... - QString decoded_instr( QString( "%1" ).arg( - profile ? profile->name : QString( "UNK(%1)" ).arg( virt_instr->opcode, 0, 16 ) ) ); - - if ( virt_instr->operand.has_imm ) // if there is a second operand (imm) put its value... - decoded_instr.append( QString( " %1" ).arg( virt_instr->operand.imm.u, 0, 16 ) ); - - virt_instr_entry->setText( 2, decoded_instr ); - - // add comments to the virtual instruction... (colume 4)... - if ( virt_instr->mnemonic_t == vm::handler::LREGQ || virt_instr->mnemonic_t == vm::handler::SREGQ ) - virt_instr_entry->setText( - 3, - QString( "; vreg%1" ).arg( virt_instr->operand.imm.u ? ( virt_instr->operand.imm.u / 8 ) : 0u ) ); - - // add virt_instr_t pointer for this current virtual instruction... - QVariant var; - var.setValue( virt_instr ); - virt_instr_entry->setData( 3, Qt::UserRole, var ); - - if ( virt_instr->mnemonic_t == vm::handler::JMP ) - { - if ( code_block->jcc.type == vm::instrs::jcc_type::branching ) - { - virt_instr_entry->setText( 3, QString( "; { %1, %2 }" ) - .arg( code_block->jcc.block_addr[ 0 ], 0, 16 ) - .arg( code_block->jcc.block_addr[ 1 ], 0, 16 ) ); - - auto branch_entry1 = new qtree_widget_item_t(), branch_entry2 = new qtree_widget_item_t(); - const auto block1_addr = code_block->jcc.block_addr[ 0 ]; - const auto block2_addr = code_block->jcc.block_addr[ 1 ]; - - branch_entry1->setText( 0, QString( "%1" ).arg( block1_addr, 0, 16 ) ); - branch_entry1->setText( 3, QString( "; block_%1" ).arg( block1_addr, 0, 16 ) ); - - branch_entry2->setText( 0, QString( "%1" ).arg( block2_addr, 0, 16 ) ); - branch_entry2->setText( 3, QString( "; block_%1" ).arg( block2_addr, 0, 16 ) ); - - add_branch_children( branch_entry1, code_block->jcc.block_addr[ 0 ] ); - add_branch_children( branch_entry2, code_block->jcc.block_addr[ 1 ] ); - - virt_instr_entry->addChildren( { branch_entry1, branch_entry2 } ); - // if its a JMP with branches we want to insert the next code block - // instructions into the child widget entries... - ui.virt_instrs->addTopLevelItem( virt_instr_entry ); - goto finish; // bad code... - } - else if ( code_block->jcc.type == vm::instrs::jcc_type::absolute ) - virt_instr_entry->setText( 3, QString( "; { %1 }" ).arg( code_block->jcc.block_addr[ 0 ], 0, 16 ) ); - } - ui.virt_instrs->addTopLevelItem( virt_instr_entry ); + auto block_vinstrs = reinterpret_cast< vm::instrs::virt_instr_t * >( + reinterpret_cast< std::uintptr_t >( code_block ) + sizeof vmp2::v4::code_block_t + + ( code_block->num_block_addrs * 8 ) ); + + vm::instrs::code_block_t _code_block{ code_block->vip_begin }; + _code_block.jcc.has_jcc = code_block->has_jcc; + _code_block.jcc.type = code_block->jcc_type; + + for ( auto idx = 0u; idx < code_block->num_block_addrs; ++idx ) + _code_block.jcc.block_addr.push_back( code_block->branch_addr[ idx ] ); + + for ( auto idx = 0u; idx < code_block->vinstr_count; ++idx ) + _code_block.vinstrs.push_back( block_vinstrs[ idx ] ); + + virt_rtns.back().rtn_blks.push_back( _code_block ); } } -finish: // bad code... - ui.virt_instrs->topLevelItem( 0 )->setSelected( true ); + return true; } \ No newline at end of file diff --git a/src/qvminspector.h b/src/qvminspector.h index 5f80b65..a3a0b3c 100644 --- a/src/qvminspector.h +++ b/src/qvminspector.h @@ -26,6 +26,12 @@ using qfile_t = QFile; using qtree_widget_item_t = QTreeWidgetItem; using qmsg_box_t = QMessageBox; +struct rtn_data_t +{ + std::uint32_t rtn_rva; + std::vector< vm::instrs::code_block_t > rtn_blks; +}; + class qvminspector_t : public qmain_window_t { friend class qvirt_instrs_t; @@ -33,6 +39,7 @@ class qvminspector_t : public qmain_window_t Q_OBJECT public: qvminspector_t( qwidget_t *parent = Q_NULLPTR ); + static bool serialize_vmp2( std::vector< rtn_data_t > &virt_rtns, std::vector< std::uint8_t > &vmp2file ); private slots: void on_open(); @@ -50,8 +57,5 @@ class qvminspector_t : public qmain_window_t qstring_t VMProtectedFilePath; std::uint64_t image_base, vm_entry_rva, module_base, image_size; vm::ctx_t *vmctx; - - vmp2::v3::file_header *file_header; - vmp2::v3::code_block_t *first_block; - std::vector< std::uintptr_t > code_block_addrs; + vmp2::v4::file_header *file_header; }; \ No newline at end of file diff --git a/src/qvminspector.ui b/src/qvminspector.ui index 1561742..a108884 100644 --- a/src/qvminspector.ui +++ b/src/qvminspector.ui @@ -6,7 +6,7 @@ 0 0 - 1496 + 1414 1093 @@ -27,7 +27,7 @@ - 0 + 1 @@ -44,7 +44,7 @@ 0 0 - 1452 + 1370 854 @@ -414,7 +414,7 @@ 0 0 - 672 + 631 228 @@ -604,6 +604,111 @@ + + + Virtual Routines + + + + + + Virtual Machine Enters + + + + + + + Name + + + + + Address + + + + + Number Of Code Blocks + + + + + + + + + + + + + + + + Virtual Machine Enter Information + + + + + + Virtual Machine - Enter Instructions + + + + + + + Address + + + + + Instruction + + + + + + + + + + + + + + + + Virtual Machine - Calc Jmp + + + + + + + Address + + + + + Instruction + + + + + + + + + + + + + + + + + @@ -613,7 +718,7 @@ 0 0 - 1496 + 1414 21 From e7e84336813bdc73e74ffd5b16f924abcfa62612 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sun, 22 Aug 2021 22:52:41 -0700 Subject: [PATCH 2/7] beginning to change things to upper case + added some more code to update virtual routines... --- CMakeLists.txt | 1 + cmake.toml | 1 + .../framelesswindow/framelesswindow.ui | 4 +- src/main.cpp | 6 +- src/qvirt_handlers.cpp | 26 ++-- src/qvirt_handlers.h | 12 +- src/qvirt_instrs.cpp | 47 ++++--- src/qvirt_instrs.h | 17 +-- src/qvminspector.cpp | 115 ++++++++++-------- src/qvminspector.h | 40 +++--- src/qvminspector.ui | 27 +--- 11 files changed, 147 insertions(+), 149 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8835914..7d5012c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ list(APPEND vmprofiler-qt_SOURCES "src/darkstyle/mainwindow.h" "src/darkstyle/mainwindow.ui" "src/darkstyle/framelesswindow.qrc" + "src/darkstyle/framelesswindow/framelesswindow.ui" "dependencies/ia32-doc/out/ia32.hpp" ) diff --git a/cmake.toml b/cmake.toml index 248c7a5..137513e 100644 --- a/cmake.toml +++ b/cmake.toml @@ -29,6 +29,7 @@ sources = [ "src/darkstyle/**.h", "src/darkstyle/mainwindow.ui", "src/darkstyle/framelesswindow.qrc", + "src/darkstyle/framelesswindow/framelesswindow.ui", "dependencies/ia32-doc/out/ia32.hpp" ] diff --git a/src/darkstyle/framelesswindow/framelesswindow.ui b/src/darkstyle/framelesswindow/framelesswindow.ui index 4bc3f0d..2421768 100644 --- a/src/darkstyle/framelesswindow/framelesswindow.ui +++ b/src/darkstyle/framelesswindow/framelesswindow.ui @@ -6,8 +6,8 @@ 0 0 - 1737 - 1157 + 1311 + 897 diff --git a/src/main.cpp b/src/main.cpp index bb0ceab..feda939 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,9 +14,9 @@ int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int QApplication app( __argc, __argv ); QApplication::setStyle( new DarkStyle ); FramelessWindow frameless_window; - const auto window = new qvminspector_t; - qvirt_instrs_t virt_instr( window ); - qvirt_handlers_t virt_handlers( window ); + const auto window = new QVMInspector; + QVirtualMachineInstructions virt_instr( window ); + QVirtualMachineHandlers virt_handlers( window ); frameless_window.setContent( window ); frameless_window.setWindowIcon( QIcon( "icon.ico" ) ); diff --git a/src/qvirt_handlers.cpp b/src/qvirt_handlers.cpp index 00c412b..78b5030 100644 --- a/src/qvirt_handlers.cpp +++ b/src/qvirt_handlers.cpp @@ -1,11 +1,12 @@ #include "qvirt_handlers.h" -qvirt_handlers_t::qvirt_handlers_t( qvminspector_t *vminspector ) : vminspector( vminspector ), ui( &vminspector->ui ) +QVirtualMachineHandlers::QVirtualMachineHandlers( QVMInspector *MainWindow ) + : MainWindow( MainWindow ), ui( &MainWindow->ui ) { - connect( ui->virt_handlers_tree, &QTreeWidget::itemSelectionChanged, this, &qvirt_handlers_t::on_select ); + connect( ui->virt_handlers_tree, &QTreeWidget::itemSelectionChanged, this, &QVirtualMachineHandlers::OnSelect ); } -void qvirt_handlers_t::update_transforms( vm::handler::handler_t &vm_handler ) +void QVirtualMachineHandlers::UpdateTransforms( vm::handler::handler_t &vm_handler ) { char buffer[ 256 ]; ZydisFormatter formatter; @@ -19,7 +20,7 @@ void qvirt_handlers_t::update_transforms( vm::handler::handler_t &vm_handler ) if ( transform_type == vm::transform::type::generic0 && transform_instr.mnemonic == ZYDIS_MNEMONIC_INVALID ) continue; - auto new_transform_entry = new qtree_widget_item_t(); + auto new_transform_entry = new QTreeWidgetItem(); switch ( transform_type ) { @@ -52,7 +53,7 @@ void qvirt_handlers_t::update_transforms( vm::handler::handler_t &vm_handler ) } } -void qvirt_handlers_t::update_instrs( vm::handler::handler_t &vm_handler ) +void QVirtualMachineHandlers::UpdateInstrs( vm::handler::handler_t &vm_handler ) { char buffer[ 256 ]; ZydisFormatter formatter; @@ -64,19 +65,18 @@ void qvirt_handlers_t::update_instrs( vm::handler::handler_t &vm_handler ) // display vm handler instructions... for ( const auto &instr : vm_handler_instrs ) { - auto new_instr = new qtree_widget_item_t(); - new_instr->setText( - 0, qstring_t::number( ( instr.addr - vminspector->module_base ) + vminspector->image_base, 16 ) ); + auto new_instr = new QTreeWidgetItem(); + new_instr->setText( 0, QString::number( ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase, 16 ) ); ZydisFormatterFormatInstruction( &formatter, &instr.instr, buffer, sizeof( buffer ), - ( instr.addr - vminspector->module_base ) + vminspector->image_base ); + ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase ); new_instr->setText( 1, buffer ); ui->virt_handler_instrs_tree->addTopLevelItem( new_instr ); } } -void qvirt_handlers_t::on_select() +void QVirtualMachineHandlers::OnSelect() { if ( ui->virt_handlers_tree->selectedItems().empty() ) return; @@ -86,10 +86,10 @@ void qvirt_handlers_t::on_select() if ( !item ) return; - if ( !vminspector->vmctx ) + if ( !MainWindow->vmctx ) return; const auto handler_idx = item->data( 0, Qt::UserRole ).value< std::uint8_t >(); - update_instrs( vminspector->vmctx->vm_handlers[ handler_idx ] ); - update_transforms( vminspector->vmctx->vm_handlers[ handler_idx ] ); + UpdateInstrs( MainWindow->vmctx->vm_handlers[ handler_idx ] ); + UpdateTransforms( MainWindow->vmctx->vm_handlers[ handler_idx ] ); } \ No newline at end of file diff --git a/src/qvirt_handlers.h b/src/qvirt_handlers.h index 2022692..1270c8d 100644 --- a/src/qvirt_handlers.h +++ b/src/qvirt_handlers.h @@ -2,18 +2,18 @@ #define NOMINMAX #include "qvminspector.h" -class qvirt_handlers_t : public QObject +class QVirtualMachineHandlers : public QObject { Q_OBJECT public: - explicit qvirt_handlers_t( qvminspector_t *vminspector ); + explicit QVirtualMachineHandlers( QVMInspector *MainWindow ); private: Ui::QVMProfilerClass *ui; - qvminspector_t *vminspector; - void update_transforms( vm::handler::handler_t &vm_handler ); - void update_instrs( vm::handler::handler_t &vm_handler ); + QVMInspector *MainWindow; + void UpdateTransforms( vm::handler::handler_t &vm_handler ); + void UpdateInstrs( vm::handler::handler_t &vm_handler ); private slots: - void on_select(); + void OnSelect(); }; \ No newline at end of file diff --git a/src/qvirt_instrs.cpp b/src/qvirt_instrs.cpp index f8dbb8e..1cd493f 100644 --- a/src/qvirt_instrs.cpp +++ b/src/qvirt_instrs.cpp @@ -1,11 +1,12 @@ #include "qvirt_instrs.h" -qvirt_instrs_t::qvirt_instrs_t( qvminspector_t *vminspector ) : vminspector( vminspector ), ui( &vminspector->ui ) +QVirtualMachineInstructions::QVirtualMachineInstructions( QVMInspector *MainWindow ) + : MainWindow( MainWindow ), ui( &MainWindow->ui ) { - connect( ui->virt_instrs, &QTreeWidget::itemSelectionChanged, this, &qvirt_instrs_t::on_select ); + connect( ui->virt_instrs, &QTreeWidget::itemSelectionChanged, this, &QVirtualMachineInstructions::OnSelect ); } -void qvirt_instrs_t::on_select() +void QVirtualMachineInstructions::OnSelect() { if ( ui->virt_instrs->selectedItems().empty() ) return; @@ -20,13 +21,13 @@ void qvirt_instrs_t::on_select() if ( !virt_instr ) return; - update_native_regs( virt_instr ); - update_virtual_regs( virt_instr ); - update_virtual_stack( virt_instr ); - update_vm_handler_info( virt_instr ); + UpdateNativeRegisters( virt_instr ); + UpdateVirtualRegisters( virt_instr ); + UpdateVirtualStack( virt_instr ); + UpdateVMHandlerInfo( virt_instr ); } -void qvirt_instrs_t::update_native_regs( vm::instrs::virt_instr_t *virt_instr ) +void QVirtualMachineInstructions::UpdateNativeRegisters( vm::instrs::virt_instr_t *virt_instr ) { const auto &trace_data = virt_instr->trace_data; @@ -52,15 +53,14 @@ void qvirt_instrs_t::update_native_regs( vm::instrs::virt_instr_t *virt_instr ) ui->native_regs->topLevelItem( 16 )->child( 8 )->setText( 1, QString::number( flags.interrupt_enable_flag ) ); } -void qvirt_instrs_t::update_virtual_regs( vm::instrs::virt_instr_t *virt_instr ) +void QVirtualMachineInstructions::UpdateVirtualRegisters( vm::instrs::virt_instr_t *virt_instr ) { const auto &trace_data = virt_instr->trace_data; // set VIP in virtual registers window... ui->virt_regs->topLevelItem( 0 )->setText( - 1, - QString::number( - ( trace_data.vip - vminspector->file_header->module_base ) + vminspector->file_header->image_base, 16 ) ); + 1, QString::number( ( trace_data.vip - MainWindow->FileHeader->ModuleBase ) + MainWindow->FileHeader->ImgBase, + 16 ) ); // set VSP in virtual registers window... ui->virt_regs->topLevelItem( 1 )->setText( 1, QString::number( trace_data.regs.rbp, 16 ) ); @@ -73,38 +73,37 @@ void qvirt_instrs_t::update_virtual_regs( vm::instrs::virt_instr_t *virt_instr ) ui->virt_regs->topLevelItem( idx )->setText( 1, QString::number( trace_data.vregs.qword[ idx - 4 ], 16 ) ); } -void qvirt_instrs_t::update_virtual_stack( vm::instrs::virt_instr_t *virt_instr ) +void QVirtualMachineInstructions::UpdateVirtualStack( vm::instrs::virt_instr_t *virt_instr ) { ui->virt_stack->clear(); const auto &trace_data = virt_instr->trace_data; for ( auto idx = 0u; idx < sizeof( trace_data.vsp ) / 8; ++idx ) { - auto new_stack_entry = new qtree_widget_item_t(); - new_stack_entry->setText( 0, qstring_t::number( trace_data.regs.rbp + ( idx * 8 ), 16 ) ); - new_stack_entry->setText( 1, qstring_t::number( trace_data.vsp.qword[ idx ], 16 ) ); + auto new_stack_entry = new QTreeWidgetItem(); + new_stack_entry->setText( 0, QString::number( trace_data.regs.rbp + ( idx * 8 ), 16 ) ); + new_stack_entry->setText( 1, QString::number( trace_data.vsp.qword[ idx ], 16 ) ); ui->virt_stack->addTopLevelItem( new_stack_entry ); } } -void qvirt_instrs_t::update_vm_handler_info( vm::instrs::virt_instr_t *virt_instr ) +void QVirtualMachineInstructions::UpdateVMHandlerInfo( vm::instrs::virt_instr_t *virt_instr ) { char buffer[ 256 ]; ZydisFormatter formatter; ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); ui->vm_handler_instrs->clear(); - const auto &vm_handler_instrs = vminspector->vmctx->vm_handlers[ virt_instr->opcode ].instrs; + const auto &vm_handler_instrs = MainWindow->vmctx->vm_handlers[ virt_instr->opcode ].instrs; // display vm handler instructions... for ( const auto &instr : vm_handler_instrs ) { - auto new_instr = new qtree_widget_item_t(); - new_instr->setText( - 0, qstring_t::number( ( instr.addr - vminspector->module_base ) + vminspector->image_base, 16 ) ); + auto new_instr = new QTreeWidgetItem(); + new_instr->setText( 0, QString::number( ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase, 16 ) ); ZydisFormatterFormatInstruction( &formatter, &instr.instr, buffer, sizeof( buffer ), - ( instr.addr - vminspector->module_base ) + vminspector->image_base ); + ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase ); new_instr->setText( 1, buffer ); ui->vm_handler_instrs->addTopLevelItem( new_instr ); @@ -112,14 +111,14 @@ void qvirt_instrs_t::update_vm_handler_info( vm::instrs::virt_instr_t *virt_inst // display vm handler transformations... ui->vm_handler_transforms->clear(); - const auto &vm_handler_transforms = vminspector->vmctx->vm_handlers[ virt_instr->opcode ].transforms; + const auto &vm_handler_transforms = MainWindow->vmctx->vm_handlers[ virt_instr->opcode ].transforms; for ( auto [ transform_type, transform_instr ] : vm_handler_transforms ) { if ( transform_type == vm::transform::type::generic0 && transform_instr.mnemonic == ZYDIS_MNEMONIC_INVALID ) continue; - auto new_transform_entry = new qtree_widget_item_t(); + auto new_transform_entry = new QTreeWidgetItem(); switch ( transform_type ) { diff --git a/src/qvirt_instrs.h b/src/qvirt_instrs.h index d09326f..1e512ed 100644 --- a/src/qvirt_instrs.h +++ b/src/qvirt_instrs.h @@ -2,20 +2,21 @@ #define NOMINMAX #include "qvminspector.h" -class qvirt_instrs_t : public QObject +class QVirtualMachineInstructions : public QObject { Q_OBJECT public: - explicit qvirt_instrs_t( qvminspector_t *vminspector ); + explicit QVirtualMachineInstructions( QVMInspector *MainWindow ); private: Ui::QVMProfilerClass *ui; - qvminspector_t *vminspector; - void update_native_regs( vm::instrs::virt_instr_t *virt_instr ); - void update_virtual_regs( vm::instrs::virt_instr_t *virt_instr ); - void update_virtual_stack( vm::instrs::virt_instr_t *virt_instr ); - void update_vm_handler_info( vm::instrs::virt_instr_t *virt_instr ); + QVMInspector *MainWindow; + + void UpdateNativeRegisters( vm::instrs::virt_instr_t *virt_instr ); + void UpdateVirtualRegisters( vm::instrs::virt_instr_t *virt_instr ); + void UpdateVirtualStack( vm::instrs::virt_instr_t *virt_instr ); + void UpdateVMHandlerInfo( vm::instrs::virt_instr_t *virt_instr ); private slots: - void on_select(); + void OnSelect(); }; \ No newline at end of file diff --git a/src/qvminspector.cpp b/src/qvminspector.cpp index 78279f2..3079746 100644 --- a/src/qvminspector.cpp +++ b/src/qvminspector.cpp @@ -1,29 +1,30 @@ #include "qvminspector.h" -qvminspector_t::qvminspector_t( qwidget_t *parent ) : qmain_window_t( parent ), file_header( nullptr ), vmctx( nullptr ) +QVMInspector::QVMInspector( QWidget *parent ) : QMainWindow( parent ), FileHeader( nullptr ), vmctx( nullptr ) { ui.setupUi( this ); ui.virt_instrs->setColumnWidth( 0, 180 ); ui.virt_instrs->setColumnWidth( 1, 150 ); ui.virt_instrs->setColumnWidth( 2, 190 ); ui.virt_instrs->setColumnWidth( 3, 200 ); + ui.virtual_machine_enters->setColumnWidth( 0, 180 ); - connect( ui.action_open, &QAction::triggered, this, &qvminspector_t::on_open ); - connect( ui.action_close, &QAction::triggered, this, &qvminspector_t::on_close ); + connect( ui.action_open, &QAction::triggered, this, &QVMInspector::OnOpen ); + connect( ui.action_close, &QAction::triggered, this, &QVMInspector::OnClose ); } -void qvminspector_t::on_close() +void QVMInspector::OnClose() { exit( 0 ); } -void qvminspector_t::on_open() +void QVMInspector::OnOpen() { - if ( file_header ) - free( file_header ); + if ( FileHeader ) + free( FileHeader ); - file_header = nullptr; - image_base = 0u, vm_entry_rva = 0u, module_base = 0u; + FileHeader = nullptr; + ImgBase = 0u, ModuleBase = 0u; file_path = QFileDialog::getOpenFileName( this, tr( "open vmp2 file" ), std::filesystem::current_path().string().c_str(), tr( "vmp2 file (*.vmp2)" ) ); @@ -32,13 +33,13 @@ void qvminspector_t::on_open() if ( file_path.isEmpty() ) { - dbg_msg( "invalid vmp2 file... no file selected..." ); + DbgMsg( "invalid vmp2 file... no file selected..." ); return; } if ( !std::filesystem::exists( _file_path ) ) { - dbg_msg( "vmp2 file does not exist..." ); + DbgMsg( "vmp2 file does not exist..." ); return; } @@ -46,96 +47,112 @@ void qvminspector_t::on_open() if ( !file_size ) { - dbg_msg( "invalid vmp2 file size..." ); + DbgMsg( "invalid vmp2 file size..." ); return; } - qfile_t open_file( file_path ); - file_header = reinterpret_cast< vmp2::v4::file_header * >( malloc( file_size ) ); + QFile open_file( file_path ); + FileHeader = reinterpret_cast< vmp2::v4::FileHeader * >( malloc( file_size ) ); if ( !open_file.open( QIODevice::ReadOnly ) ) { - dbg_msg( "failed to open vmp2 file..." ); + DbgMsg( "failed to open vmp2 file..." ); return; } - memcpy( file_header, open_file.readAll().data(), file_size ); + memcpy( FileHeader, open_file.readAll().data(), file_size ); - if ( !init_data() ) + if ( !InitData() ) { - dbg_msg( "failed to init vmp2 file data..." ); + DbgMsg( "failed to init vmp2 file data..." ); return; } } -void qvminspector_t::dbg_print( qstring_t dbg_output ) +void QVMInspector::DbgPrint( QString dbg_output ) { ui.dbg_output_window->appendPlainText( dbg_output ); } -void qvminspector_t::dbg_msg( qstring_t dbg_output ) +void QVMInspector::DbgMsg( QString dbg_output ) { - qmsg_box_t msg_box; + QMessageBox msg_box; msg_box.setText( dbg_output ); msg_box.exec(); - dbg_print( dbg_output ); + DbgPrint( dbg_output ); } -bool qvminspector_t::init_data() +bool QVMInspector::InitData() { - if ( file_header->magic != VMP_MAGIC ) + if ( FileHeader->magic != VMP_MAGIC ) { - dbg_msg( "invalid magic bytes for vmp2 file..." ); + DbgMsg( "invalid magic bytes for vmp2 file..." ); return false; } - dbg_print( "valid magic bytes for vmp2 file..." ); + DbgPrint( "valid magic bytes for vmp2 file..." ); - if ( file_header->version != vmp2::version_t::v4 ) + if ( FileHeader->version != vmp2::version_t::v4 ) { - dbg_msg( "invalid vmp2 file version... " - "this vminspector is compiled for version 4...\n" ); + DbgMsg( "invalid vmp2 file version... " + "this vminspector is compiled for version 4...\n" ); return false; } - vm_entry_rva = file_header->vm_entry_rva; - image_base = file_header->image_base; - image_size = file_header->module_size; + ImgBase = FileHeader->ImgBase; + ImgSize = FileHeader->module_size; + ModuleBase = reinterpret_cast< std::uintptr_t >( FileHeader ) + FileHeader->module_offset; - module_base = reinterpret_cast< std::uintptr_t >( file_header ) + file_header->module_offset; - return true; -} - -void qvminspector_t::add_branch_children( qtree_widget_item_t *item, std::uintptr_t branch_addr ) -{ + if ( !SerializeVmp2( VirtRtns ) ) + { + DbgMsg( "failed to serialize vmp2 file format...\n" ); + return false; + } + UpdateUI(); + return true; } -void qvminspector_t::update_ui() +void QVMInspector::UpdateUI() { - + ui.virtual_machine_enters->clear(); + for ( auto &[ rtn_rva, rtn_blks ] : VirtRtns ) + { + auto new_item = new QTreeWidgetItem(); + new_item->setText( 0, QString( "rtn_%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); + new_item->setText( 1, QString( "%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); + new_item->setText( 2, QString( "%1" ).arg( rtn_blks.size() ) ); + + std::for_each( rtn_blks.begin(), rtn_blks.end(), [ & ]( vm::instrs::code_block_t &code_blk ) { + auto new_child = new QTreeWidgetItem(); + new_child->setText( 0, QString( "blk_%1" ).arg( code_blk.vip_begin, 0, 16 ) ); + new_child->setText( 1, QString( "%1" ).arg( code_blk.vip_begin, 0, 16 ) ); + new_child->setText( 2, QString( "%1" ).arg( code_blk.vinstrs.size() ) ); + new_item->addChild( new_child ); + } ); + + ui.virtual_machine_enters->addTopLevelItem( new_item ); + } } -bool qvminspector_t::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns, std::vector< std::uint8_t > &vmp2file ) +bool QVMInspector::SerializeVmp2( std::vector< rtn_data_t > &VirtRtns ) { - const auto file_header = reinterpret_cast< vmp2::v4::file_header * >( vmp2file.data() ); - - if ( file_header->version != vmp2::version_t::v4 ) + if ( FileHeader->version != vmp2::version_t::v4 ) { std::printf( "[!] invalid vmp2 file version... this build uses v3...\n" ); return false; } - auto first_rtn = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + - file_header->rtn_offset ); + auto first_rtn = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( FileHeader ) + + FileHeader->rtn_offset ); - for ( auto [ rtn_block, rtn_idx ] = std::pair{ first_rtn, 0ull }; rtn_idx < file_header->rtn_count; + for ( auto [ rtn_block, rtn_idx ] = std::pair{ first_rtn, 0ull }; rtn_idx < FileHeader->rtn_count; ++rtn_idx, rtn_block = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( rtn_block ) + rtn_block->size ) ) { - virt_rtns.push_back( { rtn_block->vm_enter_offset, {} } ); + VirtRtns.push_back( { rtn_block->vm_enter_offset, {} } ); for ( auto [ code_block, block_idx ] = std::pair{ &rtn_block->code_blocks[ 0 ], 0ull }; block_idx < rtn_block->code_block_count; ++block_idx, code_block = reinterpret_cast< vmp2::v4::code_block_t * >( @@ -155,7 +172,7 @@ bool qvminspector_t::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns, std:: for ( auto idx = 0u; idx < code_block->vinstr_count; ++idx ) _code_block.vinstrs.push_back( block_vinstrs[ idx ] ); - virt_rtns.back().rtn_blks.push_back( _code_block ); + VirtRtns.back().rtn_blks.push_back( _code_block ); } } diff --git a/src/qvminspector.h b/src/qvminspector.h index a3a0b3c..37625e0 100644 --- a/src/qvminspector.h +++ b/src/qvminspector.h @@ -19,43 +19,37 @@ #define ABS_TO_IMG( addr, mod_base, img_base ) ( addr - mod_base ) + img_base Q_DECLARE_METATYPE( vm::instrs::virt_instr_t * ) -using qmain_window_t = QMainWindow; -using qwidget_t = QWidget; -using qstring_t = QString; -using qfile_t = QFile; -using qtree_widget_item_t = QTreeWidgetItem; -using qmsg_box_t = QMessageBox; - struct rtn_data_t { std::uint32_t rtn_rva; std::vector< vm::instrs::code_block_t > rtn_blks; }; -class qvminspector_t : public qmain_window_t +class QVMInspector : public QMainWindow { - friend class qvirt_instrs_t; - friend class qvirt_handlers_t; + friend class QVirtualMachineInstructions; + friend class QVirtualMachineHandlers; Q_OBJECT public: - qvminspector_t( qwidget_t *parent = Q_NULLPTR ); - static bool serialize_vmp2( std::vector< rtn_data_t > &virt_rtns, std::vector< std::uint8_t > &vmp2file ); + QVMInspector( QWidget *parent = Q_NULLPTR ); private slots: - void on_open(); - void on_close(); + void OnOpen(); + void OnClose(); private: - void dbg_print( qstring_t DbgOutput ); - void dbg_msg( qstring_t DbgOutput ); - void update_ui(); - void add_branch_children( qtree_widget_item_t *item, std::uintptr_t branch_addr ); - bool init_data(); + void DbgPrint( QString DbgOutput ); + void DbgMsg( QString DbgOutput ); + void UpdateUI(); + bool SerializeVmp2( std::vector< rtn_data_t > &VirtRtns ); + bool InitData(); Ui::QVMProfilerClass ui; - qstring_t file_path; - qstring_t VMProtectedFilePath; - std::uint64_t image_base, vm_entry_rva, module_base, image_size; + QString file_path; + + std::uint64_t ImgBase, ModuleBase, ImgSize; vm::ctx_t *vmctx; - vmp2::v4::file_header *file_header; + + vmp2::v4::FileHeader *FileHeader; + std::vector< rtn_data_t > VirtRtns; }; \ No newline at end of file diff --git a/src/qvminspector.ui b/src/qvminspector.ui index a108884..ded20a2 100644 --- a/src/qvminspector.ui +++ b/src/qvminspector.ui @@ -27,7 +27,7 @@ - 1 + 2 @@ -44,8 +44,8 @@ 0 0 - 1370 - 854 + 428 + 408 @@ -414,8 +414,8 @@ 0 0 - 631 - 228 + 98 + 89 @@ -629,14 +629,9 @@ - Number Of Code Blocks + Number Of Nodes - - - - - @@ -666,11 +661,6 @@ Instruction - - - - - @@ -694,11 +684,6 @@ Instruction - - - - - From 82f17aba3a72005f74ceecaee11908016a2b55ab Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Mon, 23 Aug 2021 13:47:16 -0700 Subject: [PATCH 3/7] cleaned the code some more... added some code for the new tab... --- CMakeLists.txt | 18 ++--- cmake.toml | 9 +-- ...ndlers.cpp => QVirtualMachineHandlers.cpp} | 8 +-- ...t_handlers.h => QVirtualMachineHandlers.h} | 3 +- ...rs.cpp => QVirtualMachineInstructions.cpp} | 6 +- ...instrs.h => QVirtualMachineInstructions.h} | 3 +- src/QVirtualRoutines.cpp | 66 +++++++++++++++++++ src/QVirtualRoutines.h | 18 +++++ src/main.cpp | 23 ++++--- src/qvminspector.cpp | 5 +- src/qvminspector.h | 4 +- src/qvminspector.ui | 6 +- 12 files changed, 126 insertions(+), 43 deletions(-) rename src/{qvirt_handlers.cpp => QVirtualMachineHandlers.cpp} (93%) rename src/{qvirt_handlers.h => QVirtualMachineHandlers.h} (89%) rename src/{qvirt_instrs.cpp => QVirtualMachineInstructions.cpp} (95%) rename src/{qvirt_instrs.h => QVirtualMachineInstructions.h} (92%) create mode 100644 src/QVirtualRoutines.cpp create mode 100644 src/QVirtualRoutines.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d5012c..6b13b6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,22 +59,24 @@ set(vmprofiler-qt_SOURCES "") list(APPEND vmprofiler-qt_SOURCES "src/qvminspector.ui" "src/qvminspector.qrc" - "src/qvminspector.cpp" - "src/qvirt_instrs.cpp" - "src/qvirt_handlers.cpp" - "src/main.cpp" - "src/qvirt_handlers.h" - "src/qvirt_instrs.h" - "src/qvminspector.h" - "src/icon.rc" + "src/QVMInspector.cpp" + "src/QVirtualMachineHandlers.cpp" + "src/QVirtualMachineInstructions.cpp" + "src/QVirtualRoutines.cpp" "src/darkstyle/DarkStyle.cpp" "src/darkstyle/framelesswindow/framelesswindow.cpp" "src/darkstyle/framelesswindow/windowdragger.cpp" "src/darkstyle/mainwindow.cpp" + "src/main.cpp" + "src/QVMInspector.h" + "src/QVirtualMachineHandlers.h" + "src/QVirtualMachineInstructions.h" + "src/QVirtualRoutines.h" "src/darkstyle/DarkStyle.h" "src/darkstyle/framelesswindow/framelesswindow.h" "src/darkstyle/framelesswindow/windowdragger.h" "src/darkstyle/mainwindow.h" + "src/icon.rc" "src/darkstyle/mainwindow.ui" "src/darkstyle/framelesswindow.qrc" "src/darkstyle/framelesswindow/framelesswindow.ui" diff --git a/cmake.toml b/cmake.toml index 137513e..ea6f7af 100644 --- a/cmake.toml +++ b/cmake.toml @@ -19,14 +19,9 @@ compile-features = ["cxx_std_20"] sources = [ "src/qvminspector.ui", "src/qvminspector.qrc", - "src/qvminspector.cpp", - "src/qvirt_instrs.cpp", - "src/qvirt_handlers.cpp", - "src/main.cpp", - "src/*.h", + "src/**.cpp", + "src/**.h", "src/icon.rc", - "src/darkstyle/**.cpp", - "src/darkstyle/**.h", "src/darkstyle/mainwindow.ui", "src/darkstyle/framelesswindow.qrc", "src/darkstyle/framelesswindow/framelesswindow.ui", diff --git a/src/qvirt_handlers.cpp b/src/QVirtualMachineHandlers.cpp similarity index 93% rename from src/qvirt_handlers.cpp rename to src/QVirtualMachineHandlers.cpp index 78b5030..edc9efd 100644 --- a/src/qvirt_handlers.cpp +++ b/src/QVirtualMachineHandlers.cpp @@ -1,4 +1,4 @@ -#include "qvirt_handlers.h" +#include "QVirtualMachineHandlers.h" QVirtualMachineHandlers::QVirtualMachineHandlers( QVMInspector *MainWindow ) : MainWindow( MainWindow ), ui( &MainWindow->ui ) @@ -86,10 +86,10 @@ void QVirtualMachineHandlers::OnSelect() if ( !item ) return; - if ( !MainWindow->vmctx ) + if ( !MainWindow->g_vm_ctx ) return; const auto handler_idx = item->data( 0, Qt::UserRole ).value< std::uint8_t >(); - UpdateInstrs( MainWindow->vmctx->vm_handlers[ handler_idx ] ); - UpdateTransforms( MainWindow->vmctx->vm_handlers[ handler_idx ] ); + UpdateInstrs( MainWindow->g_vm_ctx->vm_handlers[ handler_idx ] ); + UpdateTransforms( MainWindow->g_vm_ctx->vm_handlers[ handler_idx ] ); } \ No newline at end of file diff --git a/src/qvirt_handlers.h b/src/QVirtualMachineHandlers.h similarity index 89% rename from src/qvirt_handlers.h rename to src/QVirtualMachineHandlers.h index 1270c8d..3dc6eb0 100644 --- a/src/qvirt_handlers.h +++ b/src/QVirtualMachineHandlers.h @@ -1,6 +1,5 @@ #pragma once -#define NOMINMAX -#include "qvminspector.h" +#include "QVMInspector.h" class QVirtualMachineHandlers : public QObject { diff --git a/src/qvirt_instrs.cpp b/src/QVirtualMachineInstructions.cpp similarity index 95% rename from src/qvirt_instrs.cpp rename to src/QVirtualMachineInstructions.cpp index 1cd493f..398d6f0 100644 --- a/src/qvirt_instrs.cpp +++ b/src/QVirtualMachineInstructions.cpp @@ -1,4 +1,4 @@ -#include "qvirt_instrs.h" +#include "QVirtualMachineInstructions.h" QVirtualMachineInstructions::QVirtualMachineInstructions( QVMInspector *MainWindow ) : MainWindow( MainWindow ), ui( &MainWindow->ui ) @@ -94,7 +94,7 @@ void QVirtualMachineInstructions::UpdateVMHandlerInfo( vm::instrs::virt_instr_t ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); ui->vm_handler_instrs->clear(); - const auto &vm_handler_instrs = MainWindow->vmctx->vm_handlers[ virt_instr->opcode ].instrs; + const auto &vm_handler_instrs = MainWindow->g_vm_ctx->vm_handlers[ virt_instr->opcode ].instrs; // display vm handler instructions... for ( const auto &instr : vm_handler_instrs ) @@ -111,7 +111,7 @@ void QVirtualMachineInstructions::UpdateVMHandlerInfo( vm::instrs::virt_instr_t // display vm handler transformations... ui->vm_handler_transforms->clear(); - const auto &vm_handler_transforms = MainWindow->vmctx->vm_handlers[ virt_instr->opcode ].transforms; + const auto &vm_handler_transforms = MainWindow->g_vm_ctx->vm_handlers[ virt_instr->opcode ].transforms; for ( auto [ transform_type, transform_instr ] : vm_handler_transforms ) { diff --git a/src/qvirt_instrs.h b/src/QVirtualMachineInstructions.h similarity index 92% rename from src/qvirt_instrs.h rename to src/QVirtualMachineInstructions.h index 1e512ed..6466253 100644 --- a/src/qvirt_instrs.h +++ b/src/QVirtualMachineInstructions.h @@ -1,6 +1,5 @@ #pragma once -#define NOMINMAX -#include "qvminspector.h" +#include "QVMInspector.h" class QVirtualMachineInstructions : public QObject { diff --git a/src/QVirtualRoutines.cpp b/src/QVirtualRoutines.cpp new file mode 100644 index 0000000..4ee5e91 --- /dev/null +++ b/src/QVirtualRoutines.cpp @@ -0,0 +1,66 @@ +#include "QVirtualRoutines.h" + +QVirtualRoutines::QVirtualRoutines( QVMInspector *MainWindow ) : MainWindow( MainWindow ), ui( &MainWindow->ui ) +{ + connect( ui->virtual_machine_enters, &QTreeWidget::itemSelectionChanged, this, &QVirtualRoutines::OnSelect ); +} + +void QVirtualRoutines::UpdateVirtualMachineEnter( vm::ctx_t *g_vm_ctx ) +{ + char buffer[ 256 ]; + ZydisFormatter formatter; + ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); + + ui->virtual_machine_enter_instrs->clear(); + for ( auto [ instr, raw, addr ] : g_vm_ctx->vm_entry ) + { + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + auto newItem = new QTreeWidgetItem(); + newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 1, buffer ); + ui->virtual_machine_enter_instrs->addTopLevelItem( newItem ); + } +} + +void QVirtualRoutines::UpdateCalcJmp( vm::ctx_t *g_vm_ctx ) +{ + char buffer[ 256 ]; + ZydisFormatter formatter; + ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); + + ui->virtual_machine_enter_calc_jmp->clear(); + for ( auto [ instr, raw, addr ] : g_vm_ctx->calc_jmp ) + { + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + auto newItem = new QTreeWidgetItem(); + newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 1, buffer ); + ui->virtual_machine_enter_calc_jmp->addTopLevelItem( newItem ); + } +} + +void QVirtualRoutines::OnSelect() +{ + if ( ui->virtual_machine_enters->selectedItems().empty() ) + return; + + if ( MainWindow->g_vm_ctx ) + delete MainWindow->g_vm_ctx; + + auto item = ui->virtual_machine_enters->selectedItems()[ 0 ]; + + if ( !item ) + return; + + auto EntryRva = item->data( 0, Qt::UserRole ).value< std::uint32_t >(); + MainWindow->g_vm_ctx = new vm::ctx_t( MainWindow->ModuleBase, MainWindow->ImgBase, MainWindow->ImgSize, EntryRva ); + + if ( !MainWindow->g_vm_ctx->init() ) + { + MainWindow->DbgMsg( "[!] failed to init vm::ctx_t...\n" ); + return; + } + + UpdateVirtualMachineEnter( MainWindow->g_vm_ctx ); + UpdateCalcJmp( MainWindow->g_vm_ctx ); +} \ No newline at end of file diff --git a/src/QVirtualRoutines.h b/src/QVirtualRoutines.h new file mode 100644 index 0000000..6121749 --- /dev/null +++ b/src/QVirtualRoutines.h @@ -0,0 +1,18 @@ +#pragma once +#include "QVMInspector.h" + +class QVirtualRoutines : public QObject +{ + Q_OBJECT + public: + explicit QVirtualRoutines( QVMInspector *MainWindow ); + + private: + Ui::QVMProfilerClass *ui; + QVMInspector *MainWindow; + + void UpdateVirtualMachineEnter(vm::ctx_t* g_vm_ctx); + void UpdateCalcJmp( vm::ctx_t *g_vm_ctx ); + private slots: + void OnSelect(); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index feda939..1e3c3f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,23 +3,26 @@ #include #include +#include "QVMInspector.h" +#include "QVirtualMachineHandlers.h" +#include "QVirtualMachineInstructions.h" +#include "QVirtualRoutines.h" #include "darkstyle/DarkStyle.h" #include "darkstyle/framelesswindow/framelesswindow.h" -#include "qvirt_handlers.h" -#include "qvirt_instrs.h" -#include "qvminspector.h" int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { QApplication app( __argc, __argv ); QApplication::setStyle( new DarkStyle ); - FramelessWindow frameless_window; - const auto window = new QVMInspector; - QVirtualMachineInstructions virt_instr( window ); - QVirtualMachineHandlers virt_handlers( window ); + FramelessWindow FW; - frameless_window.setContent( window ); - frameless_window.setWindowIcon( QIcon( "icon.ico" ) ); - frameless_window.show(); + const auto MainWindow = new QVMInspector; + QVirtualMachineInstructions VirtInstrsPanel( MainWindow ); + QVirtualMachineHandlers VirtHandlerPanel( MainWindow ); + QVirtualRoutines VirtualRoutinesPanel( MainWindow ); + + FW.setContent( MainWindow ); + FW.setWindowIcon( QIcon( "icon.ico" ) ); + FW.show(); return app.exec(); } \ No newline at end of file diff --git a/src/qvminspector.cpp b/src/qvminspector.cpp index 3079746..1bbfe8e 100644 --- a/src/qvminspector.cpp +++ b/src/qvminspector.cpp @@ -1,6 +1,6 @@ -#include "qvminspector.h" +#include "QVMInspector.h" -QVMInspector::QVMInspector( QWidget *parent ) : QMainWindow( parent ), FileHeader( nullptr ), vmctx( nullptr ) +QVMInspector::QVMInspector( QWidget *parent ) : QMainWindow( parent ), FileHeader( nullptr ), g_vm_ctx( nullptr ) { ui.setupUi( this ); ui.virt_instrs->setColumnWidth( 0, 180 ); @@ -124,6 +124,7 @@ void QVMInspector::UpdateUI() new_item->setText( 0, QString( "rtn_%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); new_item->setText( 1, QString( "%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); new_item->setText( 2, QString( "%1" ).arg( rtn_blks.size() ) ); + new_item->setData( 0, Qt::UserRole, QVariant( rtn_rva ) ); std::for_each( rtn_blks.begin(), rtn_blks.end(), [ & ]( vm::instrs::code_block_t &code_blk ) { auto new_child = new QTreeWidgetItem(); diff --git a/src/qvminspector.h b/src/qvminspector.h index 37625e0..1955bc6 100644 --- a/src/qvminspector.h +++ b/src/qvminspector.h @@ -1,5 +1,4 @@ #pragma once -#define NOMINMAX #include #include #include @@ -29,6 +28,7 @@ class QVMInspector : public QMainWindow { friend class QVirtualMachineInstructions; friend class QVirtualMachineHandlers; + friend class QVirtualRoutines; Q_OBJECT public: QVMInspector( QWidget *parent = Q_NULLPTR ); @@ -48,7 +48,7 @@ class QVMInspector : public QMainWindow QString file_path; std::uint64_t ImgBase, ModuleBase, ImgSize; - vm::ctx_t *vmctx; + vm::ctx_t *g_vm_ctx; vmp2::v4::FileHeader *FileHeader; std::vector< rtn_data_t > VirtRtns; diff --git a/src/qvminspector.ui b/src/qvminspector.ui index ded20a2..4b9f608 100644 --- a/src/qvminspector.ui +++ b/src/qvminspector.ui @@ -6,8 +6,8 @@ 0 0 - 1414 - 1093 + 1089 + 849 @@ -703,7 +703,7 @@ 0 0 - 1414 + 1089 21 From 5bf0732d7f5716a88f7bce46271ffc4cb6b38dd0 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 24 Aug 2021 22:19:56 -0700 Subject: [PATCH 4/7] cleaned the code... --- CMakeLists.txt | 16 +-- src/QVirtualMachineHandlers.h | 18 --- src/QVirtualMachineInstructions.h | 21 ---- src/QVirtualRoutines.cpp | 66 ----------- src/QVirtualRoutines.h | 18 --- src/main.cpp | 18 +-- ...alMachineHandlers.cpp => qvm_handlers.cpp} | 24 ++-- src/qvm_handlers.h | 18 +++ src/{qvminspector.cpp => qvm_inspector.cpp} | 105 +++++++++--------- src/{qvminspector.h => qvm_inspector.h} | 33 +++--- ...tions.cpp => qvm_virtual_instructions.cpp} | 38 +++---- src/qvm_virtual_instructions.h | 21 ++++ src/qvm_virtual_routines.cpp | 105 ++++++++++++++++++ src/qvm_virtual_routines.h | 19 ++++ src/qvminspector.ui | 14 +-- 15 files changed, 288 insertions(+), 246 deletions(-) delete mode 100644 src/QVirtualMachineHandlers.h delete mode 100644 src/QVirtualMachineInstructions.h delete mode 100644 src/QVirtualRoutines.cpp delete mode 100644 src/QVirtualRoutines.h rename src/{QVirtualMachineHandlers.cpp => qvm_handlers.cpp} (74%) create mode 100644 src/qvm_handlers.h rename src/{qvminspector.cpp => qvm_inspector.cpp} (55%) rename src/{qvminspector.h => qvm_inspector.h} (51%) rename src/{QVirtualMachineInstructions.cpp => qvm_virtual_instructions.cpp} (78%) create mode 100644 src/qvm_virtual_instructions.h create mode 100644 src/qvm_virtual_routines.cpp create mode 100644 src/qvm_virtual_routines.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b13b6a..b89a94b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,23 +59,23 @@ set(vmprofiler-qt_SOURCES "") list(APPEND vmprofiler-qt_SOURCES "src/qvminspector.ui" "src/qvminspector.qrc" - "src/QVMInspector.cpp" - "src/QVirtualMachineHandlers.cpp" - "src/QVirtualMachineInstructions.cpp" - "src/QVirtualRoutines.cpp" "src/darkstyle/DarkStyle.cpp" "src/darkstyle/framelesswindow/framelesswindow.cpp" "src/darkstyle/framelesswindow/windowdragger.cpp" "src/darkstyle/mainwindow.cpp" "src/main.cpp" - "src/QVMInspector.h" - "src/QVirtualMachineHandlers.h" - "src/QVirtualMachineInstructions.h" - "src/QVirtualRoutines.h" + "src/qvm_handlers.cpp" + "src/qvm_inspector.cpp" + "src/qvm_virtual_instructions.cpp" + "src/qvm_virtual_routines.cpp" "src/darkstyle/DarkStyle.h" "src/darkstyle/framelesswindow/framelesswindow.h" "src/darkstyle/framelesswindow/windowdragger.h" "src/darkstyle/mainwindow.h" + "src/qvm_handlers.h" + "src/qvm_inspector.h" + "src/qvm_virtual_instructions.h" + "src/qvm_virtual_routines.h" "src/icon.rc" "src/darkstyle/mainwindow.ui" "src/darkstyle/framelesswindow.qrc" diff --git a/src/QVirtualMachineHandlers.h b/src/QVirtualMachineHandlers.h deleted file mode 100644 index 3dc6eb0..0000000 --- a/src/QVirtualMachineHandlers.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "QVMInspector.h" - -class QVirtualMachineHandlers : public QObject -{ - Q_OBJECT - public: - explicit QVirtualMachineHandlers( QVMInspector *MainWindow ); - - private: - Ui::QVMProfilerClass *ui; - QVMInspector *MainWindow; - void UpdateTransforms( vm::handler::handler_t &vm_handler ); - void UpdateInstrs( vm::handler::handler_t &vm_handler ); - - private slots: - void OnSelect(); -}; \ No newline at end of file diff --git a/src/QVirtualMachineInstructions.h b/src/QVirtualMachineInstructions.h deleted file mode 100644 index 6466253..0000000 --- a/src/QVirtualMachineInstructions.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "QVMInspector.h" - -class QVirtualMachineInstructions : public QObject -{ - Q_OBJECT - public: - explicit QVirtualMachineInstructions( QVMInspector *MainWindow ); - - private: - Ui::QVMProfilerClass *ui; - QVMInspector *MainWindow; - - void UpdateNativeRegisters( vm::instrs::virt_instr_t *virt_instr ); - void UpdateVirtualRegisters( vm::instrs::virt_instr_t *virt_instr ); - void UpdateVirtualStack( vm::instrs::virt_instr_t *virt_instr ); - void UpdateVMHandlerInfo( vm::instrs::virt_instr_t *virt_instr ); - - private slots: - void OnSelect(); -}; \ No newline at end of file diff --git a/src/QVirtualRoutines.cpp b/src/QVirtualRoutines.cpp deleted file mode 100644 index 4ee5e91..0000000 --- a/src/QVirtualRoutines.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "QVirtualRoutines.h" - -QVirtualRoutines::QVirtualRoutines( QVMInspector *MainWindow ) : MainWindow( MainWindow ), ui( &MainWindow->ui ) -{ - connect( ui->virtual_machine_enters, &QTreeWidget::itemSelectionChanged, this, &QVirtualRoutines::OnSelect ); -} - -void QVirtualRoutines::UpdateVirtualMachineEnter( vm::ctx_t *g_vm_ctx ) -{ - char buffer[ 256 ]; - ZydisFormatter formatter; - ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); - - ui->virtual_machine_enter_instrs->clear(); - for ( auto [ instr, raw, addr ] : g_vm_ctx->vm_entry ) - { - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - auto newItem = new QTreeWidgetItem(); - newItem->setText( 0, QString::number( addr, 16 ) ); - newItem->setText( 1, buffer ); - ui->virtual_machine_enter_instrs->addTopLevelItem( newItem ); - } -} - -void QVirtualRoutines::UpdateCalcJmp( vm::ctx_t *g_vm_ctx ) -{ - char buffer[ 256 ]; - ZydisFormatter formatter; - ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); - - ui->virtual_machine_enter_calc_jmp->clear(); - for ( auto [ instr, raw, addr ] : g_vm_ctx->calc_jmp ) - { - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - auto newItem = new QTreeWidgetItem(); - newItem->setText( 0, QString::number( addr, 16 ) ); - newItem->setText( 1, buffer ); - ui->virtual_machine_enter_calc_jmp->addTopLevelItem( newItem ); - } -} - -void QVirtualRoutines::OnSelect() -{ - if ( ui->virtual_machine_enters->selectedItems().empty() ) - return; - - if ( MainWindow->g_vm_ctx ) - delete MainWindow->g_vm_ctx; - - auto item = ui->virtual_machine_enters->selectedItems()[ 0 ]; - - if ( !item ) - return; - - auto EntryRva = item->data( 0, Qt::UserRole ).value< std::uint32_t >(); - MainWindow->g_vm_ctx = new vm::ctx_t( MainWindow->ModuleBase, MainWindow->ImgBase, MainWindow->ImgSize, EntryRva ); - - if ( !MainWindow->g_vm_ctx->init() ) - { - MainWindow->DbgMsg( "[!] failed to init vm::ctx_t...\n" ); - return; - } - - UpdateVirtualMachineEnter( MainWindow->g_vm_ctx ); - UpdateCalcJmp( MainWindow->g_vm_ctx ); -} \ No newline at end of file diff --git a/src/QVirtualRoutines.h b/src/QVirtualRoutines.h deleted file mode 100644 index 6121749..0000000 --- a/src/QVirtualRoutines.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "QVMInspector.h" - -class QVirtualRoutines : public QObject -{ - Q_OBJECT - public: - explicit QVirtualRoutines( QVMInspector *MainWindow ); - - private: - Ui::QVMProfilerClass *ui; - QVMInspector *MainWindow; - - void UpdateVirtualMachineEnter(vm::ctx_t* g_vm_ctx); - void UpdateCalcJmp( vm::ctx_t *g_vm_ctx ); - private slots: - void OnSelect(); -}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1e3c3f1..8c375a0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,10 +3,10 @@ #include #include -#include "QVMInspector.h" -#include "QVirtualMachineHandlers.h" -#include "QVirtualMachineInstructions.h" -#include "QVirtualRoutines.h" +#include "qvm_inspector.h" +#include "qvm_handlers.h" +#include "qvm_virtual_instructions.h" +#include "qvm_virtual_routines.h" #include "darkstyle/DarkStyle.h" #include "darkstyle/framelesswindow/framelesswindow.h" @@ -16,12 +16,12 @@ int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int QApplication::setStyle( new DarkStyle ); FramelessWindow FW; - const auto MainWindow = new QVMInspector; - QVirtualMachineInstructions VirtInstrsPanel( MainWindow ); - QVirtualMachineHandlers VirtHandlerPanel( MainWindow ); - QVirtualRoutines VirtualRoutinesPanel( MainWindow ); + 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 ); - FW.setContent( MainWindow ); + FW.setContent( g_main_window ); FW.setWindowIcon( QIcon( "icon.ico" ) ); FW.show(); return app.exec(); diff --git a/src/QVirtualMachineHandlers.cpp b/src/qvm_handlers.cpp similarity index 74% rename from src/QVirtualMachineHandlers.cpp rename to src/qvm_handlers.cpp index edc9efd..0d5117f 100644 --- a/src/QVirtualMachineHandlers.cpp +++ b/src/qvm_handlers.cpp @@ -1,12 +1,12 @@ -#include "QVirtualMachineHandlers.h" +#include "qvm_handlers.h" -QVirtualMachineHandlers::QVirtualMachineHandlers( QVMInspector *MainWindow ) - : MainWindow( MainWindow ), ui( &MainWindow->ui ) +qvm_handlers::qvm_handlers( qvm_inspector *g_main_window ) + : g_main_window( g_main_window ), ui( &g_main_window->ui ) { - connect( ui->virt_handlers_tree, &QTreeWidget::itemSelectionChanged, this, &QVirtualMachineHandlers::OnSelect ); + connect( ui->virt_handlers_tree, &QTreeWidget::itemSelectionChanged, this, &qvm_handlers::on_select ); } -void QVirtualMachineHandlers::UpdateTransforms( vm::handler::handler_t &vm_handler ) +void qvm_handlers::update_transforms( vm::handler::handler_t &vm_handler ) { char buffer[ 256 ]; ZydisFormatter formatter; @@ -53,7 +53,7 @@ void QVirtualMachineHandlers::UpdateTransforms( vm::handler::handler_t &vm_handl } } -void QVirtualMachineHandlers::UpdateInstrs( vm::handler::handler_t &vm_handler ) +void qvm_handlers::update_instrs( vm::handler::handler_t &vm_handler ) { char buffer[ 256 ]; ZydisFormatter formatter; @@ -66,17 +66,17 @@ void QVirtualMachineHandlers::UpdateInstrs( vm::handler::handler_t &vm_handler ) for ( const auto &instr : vm_handler_instrs ) { auto new_instr = new QTreeWidgetItem(); - new_instr->setText( 0, QString::number( ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase, 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 - MainWindow->ModuleBase ) + MainWindow->ImgBase ); + ( instr.addr - g_main_window->module_base ) + g_main_window->img_base ); new_instr->setText( 1, buffer ); ui->virt_handler_instrs_tree->addTopLevelItem( new_instr ); } } -void QVirtualMachineHandlers::OnSelect() +void qvm_handlers::on_select() { if ( ui->virt_handlers_tree->selectedItems().empty() ) return; @@ -86,10 +86,10 @@ void QVirtualMachineHandlers::OnSelect() if ( !item ) return; - if ( !MainWindow->g_vm_ctx ) + if ( !g_main_window->g_vm_ctx ) return; const auto handler_idx = item->data( 0, Qt::UserRole ).value< std::uint8_t >(); - UpdateInstrs( MainWindow->g_vm_ctx->vm_handlers[ handler_idx ] ); - UpdateTransforms( MainWindow->g_vm_ctx->vm_handlers[ handler_idx ] ); + update_instrs( g_main_window->g_vm_ctx->vm_handlers[ handler_idx ] ); + update_transforms( g_main_window->g_vm_ctx->vm_handlers[ handler_idx ] ); } \ No newline at end of file diff --git a/src/qvm_handlers.h b/src/qvm_handlers.h new file mode 100644 index 0000000..faf0805 --- /dev/null +++ b/src/qvm_handlers.h @@ -0,0 +1,18 @@ +#pragma once +#include "qvm_inspector.h" + +class qvm_handlers : public QObject +{ + Q_OBJECT + public: + explicit qvm_handlers( qvm_inspector *g_main_window ); + + private: + Ui::QVMProfilerClass *ui; + qvm_inspector *g_main_window; + void update_transforms( vm::handler::handler_t &vm_handler ); + void update_instrs( vm::handler::handler_t &vm_handler ); + + private slots: + void on_select(); +}; \ No newline at end of file diff --git a/src/qvminspector.cpp b/src/qvm_inspector.cpp similarity index 55% rename from src/qvminspector.cpp rename to src/qvm_inspector.cpp index 1bbfe8e..3de0d22 100644 --- a/src/qvminspector.cpp +++ b/src/qvm_inspector.cpp @@ -1,6 +1,6 @@ -#include "QVMInspector.h" +#include "qvm_inspector.h" -QVMInspector::QVMInspector( QWidget *parent ) : QMainWindow( parent ), FileHeader( nullptr ), g_vm_ctx( nullptr ) +qvm_inspector::qvm_inspector( QWidget *parent ) : QMainWindow( parent ), file_header( nullptr ), g_vm_ctx( nullptr ) { ui.setupUi( this ); ui.virt_instrs->setColumnWidth( 0, 180 ); @@ -9,120 +9,118 @@ QVMInspector::QVMInspector( QWidget *parent ) : QMainWindow( parent ), FileHeade ui.virt_instrs->setColumnWidth( 3, 200 ); ui.virtual_machine_enters->setColumnWidth( 0, 180 ); - connect( ui.action_open, &QAction::triggered, this, &QVMInspector::OnOpen ); - connect( ui.action_close, &QAction::triggered, this, &QVMInspector::OnClose ); + connect( ui.action_open, &QAction::triggered, this, &qvm_inspector::on_open ); + connect( ui.action_close, &QAction::triggered, this, &qvm_inspector::on_close ); } -void QVMInspector::OnClose() +void qvm_inspector::on_close() { exit( 0 ); } -void QVMInspector::OnOpen() +void qvm_inspector::on_open() { - if ( FileHeader ) - free( FileHeader ); + if ( file_header ) + free( file_header ); - FileHeader = nullptr; - ImgBase = 0u, ModuleBase = 0u; + file_header = nullptr; + img_base = 0u, module_base = 0u; - file_path = QFileDialog::getOpenFileName( + auto file_path = QFileDialog::getOpenFileName( this, tr( "open vmp2 file" ), std::filesystem::current_path().string().c_str(), tr( "vmp2 file (*.vmp2)" ) ); - const auto &_file_path = file_path.toStdString(); - if ( file_path.isEmpty() ) { - DbgMsg( "invalid vmp2 file... no file selected..." ); + dbg_msg( "invalid vmp2 file... no file selected..." ); return; } - if ( !std::filesystem::exists( _file_path ) ) + if ( !std::filesystem::exists( file_path.toStdString() ) ) { - DbgMsg( "vmp2 file does not exist..." ); + dbg_msg( "vmp2 file does not exist..." ); return; } - const auto file_size = std::filesystem::file_size( _file_path ); + const auto file_size = std::filesystem::file_size( file_path.toStdString() ); if ( !file_size ) { - DbgMsg( "invalid vmp2 file size..." ); + dbg_msg( "invalid vmp2 file size..." ); return; } QFile open_file( file_path ); - FileHeader = reinterpret_cast< vmp2::v4::FileHeader * >( malloc( file_size ) ); + file_header = reinterpret_cast< vmp2::v4::file_header * >( malloc( file_size ) ); if ( !open_file.open( QIODevice::ReadOnly ) ) { - DbgMsg( "failed to open vmp2 file..." ); + dbg_msg( "failed to open vmp2 file..." ); return; } - memcpy( FileHeader, open_file.readAll().data(), file_size ); + memcpy( file_header, open_file.readAll().data(), file_size ); - if ( !InitData() ) + if ( !init_data() ) { - DbgMsg( "failed to init vmp2 file data..." ); + dbg_msg( "failed to init vmp2 file data..." ); return; } } -void QVMInspector::DbgPrint( QString dbg_output ) +void qvm_inspector::dbg_print( QString dbg_output ) { ui.dbg_output_window->appendPlainText( dbg_output ); } -void QVMInspector::DbgMsg( QString dbg_output ) +void qvm_inspector::dbg_msg( QString dbg_output ) { QMessageBox msg_box; msg_box.setText( dbg_output ); msg_box.exec(); - DbgPrint( dbg_output ); + dbg_print( dbg_output ); } -bool QVMInspector::InitData() +bool qvm_inspector::init_data() { - if ( FileHeader->magic != VMP_MAGIC ) + if ( file_header->magic != VMP_MAGIC ) { - DbgMsg( "invalid magic bytes for vmp2 file..." ); + dbg_msg( "invalid magic bytes for vmp2 file..." ); return false; } - DbgPrint( "valid magic bytes for vmp2 file..." ); + dbg_print( "valid magic bytes for vmp2 file..." ); - if ( FileHeader->version != vmp2::version_t::v4 ) + if ( file_header->version != vmp2::version_t::v4 ) { - DbgMsg( "invalid vmp2 file version... " - "this vminspector is compiled for version 4...\n" ); + dbg_msg( "invalid vmp2 file version... " + "this vminspector is compiled for version 4...\n" ); return false; } - ImgBase = FileHeader->ImgBase; - ImgSize = FileHeader->module_size; - ModuleBase = reinterpret_cast< std::uintptr_t >( FileHeader ) + FileHeader->module_offset; + img_base = file_header->image_base; + img_size = file_header->module_size; + module_base = reinterpret_cast< std::uintptr_t >( file_header ) + file_header->module_offset; - if ( !SerializeVmp2( VirtRtns ) ) + if ( !serialize_vmp2( virt_rtns ) ) { - DbgMsg( "failed to serialize vmp2 file format...\n" ); + dbg_msg( "failed to serialize vmp2 file format...\n" ); return false; } - UpdateUI(); + update_ui(); return true; } -void QVMInspector::UpdateUI() +void qvm_inspector::update_ui() { ui.virtual_machine_enters->clear(); - for ( auto &[ rtn_rva, rtn_blks ] : VirtRtns ) + for ( auto &[ rtn_rva, rtn_blks ] : virt_rtns ) { auto new_item = new QTreeWidgetItem(); - new_item->setText( 0, QString( "rtn_%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); - new_item->setText( 1, QString( "%1" ).arg( rtn_rva + FileHeader->ImgBase, 0, 16 ) ); + new_item->setText( 0, QString( "rtn_%1" ).arg( rtn_rva + file_header->image_base, 0, 16 ) ); + new_item->setText( 1, QString( "%1" ).arg( rtn_rva + file_header->image_base, 0, 16 ) ); new_item->setText( 2, QString( "%1" ).arg( rtn_blks.size() ) ); new_item->setData( 0, Qt::UserRole, QVariant( rtn_rva ) ); @@ -138,22 +136,22 @@ void QVMInspector::UpdateUI() } } -bool QVMInspector::SerializeVmp2( std::vector< rtn_data_t > &VirtRtns ) +bool qvm_inspector::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns ) { - if ( FileHeader->version != vmp2::version_t::v4 ) + if ( file_header->version != vmp2::version_t::v4 ) { std::printf( "[!] invalid vmp2 file version... this build uses v3...\n" ); return false; } - auto first_rtn = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( FileHeader ) + - FileHeader->rtn_offset ); + auto first_rtn = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( file_header ) + + file_header->rtn_offset ); - for ( auto [ rtn_block, rtn_idx ] = std::pair{ first_rtn, 0ull }; rtn_idx < FileHeader->rtn_count; + for ( auto [ rtn_block, rtn_idx ] = std::pair{ first_rtn, 0ull }; rtn_idx < file_header->rtn_count; ++rtn_idx, rtn_block = reinterpret_cast< vmp2::v4::rtn_t * >( reinterpret_cast< std::uintptr_t >( rtn_block ) + rtn_block->size ) ) { - VirtRtns.push_back( { rtn_block->vm_enter_offset, {} } ); + virt_rtns.push_back( { rtn_block->vm_enter_offset, {} } ); for ( auto [ code_block, block_idx ] = std::pair{ &rtn_block->code_blocks[ 0 ], 0ull }; block_idx < rtn_block->code_block_count; ++block_idx, code_block = reinterpret_cast< vmp2::v4::code_block_t * >( @@ -173,9 +171,14 @@ bool QVMInspector::SerializeVmp2( std::vector< rtn_data_t > &VirtRtns ) for ( auto idx = 0u; idx < code_block->vinstr_count; ++idx ) _code_block.vinstrs.push_back( block_vinstrs[ idx ] ); - VirtRtns.back().rtn_blks.push_back( _code_block ); + virt_rtns.back().rtn_blks.push_back( _code_block ); } } return true; -} \ No newline at end of file +} + +void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, QTreeWidgetItem *parent ) +{ + +} diff --git a/src/qvminspector.h b/src/qvm_inspector.h similarity index 51% rename from src/qvminspector.h rename to src/qvm_inspector.h index 1955bc6..59b6131 100644 --- a/src/qvminspector.h +++ b/src/qvm_inspector.h @@ -24,32 +24,31 @@ struct rtn_data_t std::vector< vm::instrs::code_block_t > rtn_blks; }; -class QVMInspector : public QMainWindow +class qvm_inspector : public QMainWindow { - friend class QVirtualMachineInstructions; - friend class QVirtualMachineHandlers; - friend class QVirtualRoutines; + friend class qvm_virtual_instructions; + friend class qvm_handlers; + friend class qvm_virtual_routines; Q_OBJECT public: - QVMInspector( QWidget *parent = Q_NULLPTR ); + qvm_inspector( QWidget *parent = Q_NULLPTR ); private slots: - void OnOpen(); - void OnClose(); + void on_open(); + void on_close(); private: - void DbgPrint( QString DbgOutput ); - void DbgMsg( QString DbgOutput ); - void UpdateUI(); - bool SerializeVmp2( std::vector< rtn_data_t > &VirtRtns ); - bool InitData(); + void dbg_print( QString DbgOutput ); + 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 ); + bool init_data(); Ui::QVMProfilerClass ui; - QString file_path; - - std::uint64_t ImgBase, ModuleBase, ImgSize; + std::uint64_t img_base, module_base, img_size; vm::ctx_t *g_vm_ctx; - vmp2::v4::FileHeader *FileHeader; - std::vector< rtn_data_t > VirtRtns; + vmp2::v4::file_header *file_header; + std::vector< rtn_data_t > virt_rtns; }; \ No newline at end of file diff --git a/src/QVirtualMachineInstructions.cpp b/src/qvm_virtual_instructions.cpp similarity index 78% rename from src/QVirtualMachineInstructions.cpp rename to src/qvm_virtual_instructions.cpp index 398d6f0..4058a2a 100644 --- a/src/QVirtualMachineInstructions.cpp +++ b/src/qvm_virtual_instructions.cpp @@ -1,12 +1,12 @@ -#include "QVirtualMachineInstructions.h" +#include "qvm_virtual_instructions.h" -QVirtualMachineInstructions::QVirtualMachineInstructions( QVMInspector *MainWindow ) - : MainWindow( MainWindow ), ui( &MainWindow->ui ) +qvm_virtual_instructions::qvm_virtual_instructions( qvm_inspector *g_main_window ) + : g_main_window( g_main_window ), ui( &g_main_window->ui ) { - connect( ui->virt_instrs, &QTreeWidget::itemSelectionChanged, this, &QVirtualMachineInstructions::OnSelect ); + connect( ui->virt_instrs, &QTreeWidget::itemSelectionChanged, this, &qvm_virtual_instructions::on_select ); } -void QVirtualMachineInstructions::OnSelect() +void qvm_virtual_instructions::on_select() { if ( ui->virt_instrs->selectedItems().empty() ) return; @@ -21,13 +21,13 @@ void QVirtualMachineInstructions::OnSelect() if ( !virt_instr ) return; - UpdateNativeRegisters( virt_instr ); - UpdateVirtualRegisters( virt_instr ); - UpdateVirtualStack( virt_instr ); - UpdateVMHandlerInfo( virt_instr ); + update_native_registers( virt_instr ); + update_virtual_registers( virt_instr ); + update_virtual_stack( virt_instr ); + update_vmhandler_info( virt_instr ); } -void QVirtualMachineInstructions::UpdateNativeRegisters( vm::instrs::virt_instr_t *virt_instr ) +void qvm_virtual_instructions::update_native_registers( vm::instrs::virt_instr_t *virt_instr ) { const auto &trace_data = virt_instr->trace_data; @@ -53,14 +53,14 @@ void QVirtualMachineInstructions::UpdateNativeRegisters( vm::instrs::virt_instr_ ui->native_regs->topLevelItem( 16 )->child( 8 )->setText( 1, QString::number( flags.interrupt_enable_flag ) ); } -void QVirtualMachineInstructions::UpdateVirtualRegisters( vm::instrs::virt_instr_t *virt_instr ) +void qvm_virtual_instructions::update_virtual_registers( vm::instrs::virt_instr_t *virt_instr ) { const auto &trace_data = virt_instr->trace_data; // set VIP in virtual registers window... ui->virt_regs->topLevelItem( 0 )->setText( - 1, QString::number( ( trace_data.vip - MainWindow->FileHeader->ModuleBase ) + MainWindow->FileHeader->ImgBase, - 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 ) ); @@ -73,7 +73,7 @@ void QVirtualMachineInstructions::UpdateVirtualRegisters( vm::instrs::virt_instr ui->virt_regs->topLevelItem( idx )->setText( 1, QString::number( trace_data.vregs.qword[ idx - 4 ], 16 ) ); } -void QVirtualMachineInstructions::UpdateVirtualStack( vm::instrs::virt_instr_t *virt_instr ) +void qvm_virtual_instructions::update_virtual_stack( vm::instrs::virt_instr_t *virt_instr ) { ui->virt_stack->clear(); const auto &trace_data = virt_instr->trace_data; @@ -87,23 +87,23 @@ void QVirtualMachineInstructions::UpdateVirtualStack( vm::instrs::virt_instr_t * } } -void QVirtualMachineInstructions::UpdateVMHandlerInfo( vm::instrs::virt_instr_t *virt_instr ) +void qvm_virtual_instructions::update_vmhandler_info( vm::instrs::virt_instr_t *virt_instr ) { char buffer[ 256 ]; ZydisFormatter formatter; ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); ui->vm_handler_instrs->clear(); - const auto &vm_handler_instrs = MainWindow->g_vm_ctx->vm_handlers[ virt_instr->opcode ].instrs; + const auto &vm_handler_instrs = g_main_window->g_vm_ctx->vm_handlers[ virt_instr->opcode ].instrs; // display vm handler instructions... for ( const auto &instr : vm_handler_instrs ) { auto new_instr = new QTreeWidgetItem(); - new_instr->setText( 0, QString::number( ( instr.addr - MainWindow->ModuleBase ) + MainWindow->ImgBase, 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 - MainWindow->ModuleBase ) + MainWindow->ImgBase ); + ( instr.addr - g_main_window->module_base ) + g_main_window->img_base ); new_instr->setText( 1, buffer ); ui->vm_handler_instrs->addTopLevelItem( new_instr ); @@ -111,7 +111,7 @@ void QVirtualMachineInstructions::UpdateVMHandlerInfo( vm::instrs::virt_instr_t // display vm handler transformations... ui->vm_handler_transforms->clear(); - const auto &vm_handler_transforms = MainWindow->g_vm_ctx->vm_handlers[ virt_instr->opcode ].transforms; + const auto &vm_handler_transforms = g_main_window->g_vm_ctx->vm_handlers[ virt_instr->opcode ].transforms; for ( auto [ transform_type, transform_instr ] : vm_handler_transforms ) { diff --git a/src/qvm_virtual_instructions.h b/src/qvm_virtual_instructions.h new file mode 100644 index 0000000..890ce37 --- /dev/null +++ b/src/qvm_virtual_instructions.h @@ -0,0 +1,21 @@ +#pragma once +#include "qvm_inspector.h" + +class qvm_virtual_instructions : public QObject +{ + Q_OBJECT + public: + explicit qvm_virtual_instructions( qvm_inspector *g_main_window ); + + private: + Ui::QVMProfilerClass *ui; + qvm_inspector *g_main_window; + + void update_native_registers( vm::instrs::virt_instr_t *virt_instr ); + void update_virtual_registers( vm::instrs::virt_instr_t *virt_instr ); + void update_virtual_stack( vm::instrs::virt_instr_t *virt_instr ); + void update_vmhandler_info( vm::instrs::virt_instr_t *virt_instr ); + + private slots: + void on_select(); +}; \ No newline at end of file diff --git a/src/qvm_virtual_routines.cpp b/src/qvm_virtual_routines.cpp new file mode 100644 index 0000000..4c3e8be --- /dev/null +++ b/src/qvm_virtual_routines.cpp @@ -0,0 +1,105 @@ +#include "qvm_virtual_routines.h" + +qvm_virtual_routines::qvm_virtual_routines( qvm_inspector *g_main_window ) + : g_main_window( g_main_window ), ui( &g_main_window->ui ) +{ + connect( ui->virtual_machine_enters, &QTreeWidget::itemSelectionChanged, this, &qvm_virtual_routines::on_select ); +} + +void qvm_virtual_routines::update_vm_enter( vm::ctx_t *g_vm_ctx ) +{ + char buffer[ 256 ]; + ZydisFormatter formatter; + ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); + + ui->virtual_machine_enter_instrs->clear(); + for ( auto [ instr, raw, addr ] : g_vm_ctx->vm_entry ) + { + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + auto newItem = new QTreeWidgetItem(); + newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 1, buffer ); + ui->virtual_machine_enter_instrs->addTopLevelItem( newItem ); + } +} + +void qvm_virtual_routines::update_calc_jmp( vm::ctx_t *g_vm_ctx ) +{ + char buffer[ 256 ]; + ZydisFormatter formatter; + ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); + + ui->virtual_machine_enter_calc_jmp->clear(); + for ( auto [ instr, raw, addr ] : g_vm_ctx->calc_jmp ) + { + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + auto newItem = new QTreeWidgetItem(); + newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 1, buffer ); + ui->virtual_machine_enter_calc_jmp->addTopLevelItem( newItem ); + } +} + +void qvm_virtual_routines::update_vm_handlers( vm::ctx_t *g_vm_ctx ) +{ + ui->virt_handlers_tree->clear(); + for ( auto idx = 0u; idx < g_vm_ctx->vm_handlers.size(); ++idx ) + { + auto newItem = new QTreeWidgetItem; + newItem->setData( 0, Qt::UserRole, idx ); + newItem->setText( 0, QString( "%1" ).arg( idx ) ); + newItem->setText( 1, QString( "%1" ).arg( ABS_TO_IMG( g_vm_ctx->vm_handlers[ idx ].address, + g_main_window->file_header->module_base, + g_main_window->file_header->image_base ), + 0, 16 ) ); + + newItem->setText( 2, g_vm_ctx->vm_handlers[ idx ].profile ? g_vm_ctx->vm_handlers[ idx ].profile->name + : "UNDEFINED" ); + + newItem->setText( 3, QString( "%1" ).arg( g_vm_ctx->vm_handlers[ idx ].imm_size ) ); + + if ( g_vm_ctx->vm_handlers[ idx ].profile && g_vm_ctx->vm_handlers[ idx ].imm_size ) + newItem->setText( 4, + g_vm_ctx->vm_handlers[ idx ].profile->extention == vm::handler::extention_t::sign_extend + ? "SIGN EXTENDED" + : "ZERO EXTENDED" ); + else + newItem->setText( 4, "UNDEFINED" ); + + ui->virt_handlers_tree->addTopLevelItem( newItem ); + } + ui->virt_handlers_tree->topLevelItem( 0 )->setSelected( true ); +} + +void qvm_virtual_routines::on_select() +{ + if ( ui->virtual_machine_enters->selectedItems().empty() ) + return; + + auto item = ui->virtual_machine_enters->selectedItems()[ 0 ]; + + if ( !item || !item->childCount() ) + return; + + auto entry_rva = item->data( 0, Qt::UserRole ).value< std::uint32_t >(); + + if ( !entry_rva ) + return; + + if ( g_main_window->g_vm_ctx ) + delete g_main_window->g_vm_ctx; + + g_main_window->g_vm_ctx = + new vm::ctx_t( g_main_window->module_base, g_main_window->img_base, g_main_window->img_size, entry_rva ); + + if ( !g_main_window->g_vm_ctx->init() ) + { + g_main_window->dbg_msg( "[!] failed to init vm::ctx_t...\n" ); + return; + } + + 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 ); + g_main_window->update_virtual_instructions( g_main_window->img_base + entry_rva ); +} \ No newline at end of file diff --git a/src/qvm_virtual_routines.h b/src/qvm_virtual_routines.h new file mode 100644 index 0000000..39053d0 --- /dev/null +++ b/src/qvm_virtual_routines.h @@ -0,0 +1,19 @@ +#pragma once +#include "qvm_inspector.h" + +class qvm_virtual_routines : public QObject +{ + Q_OBJECT + public: + explicit qvm_virtual_routines( qvm_inspector *g_main_window ); + + private: + Ui::QVMProfilerClass *ui; + qvm_inspector *g_main_window; + + void update_vm_enter( vm::ctx_t *g_vm_ctx ); + void update_calc_jmp( vm::ctx_t *g_vm_ctx ); + void update_vm_handlers( vm::ctx_t *g_vm_ctx ); + private slots: + void on_select(); +}; \ No newline at end of file diff --git a/src/qvminspector.ui b/src/qvminspector.ui index 4b9f608..3c08ead 100644 --- a/src/qvminspector.ui +++ b/src/qvminspector.ui @@ -6,7 +6,7 @@ 0 0 - 1089 + 1247 849 @@ -27,7 +27,7 @@ - 2 + 1 @@ -44,8 +44,8 @@ 0 0 - 428 - 408 + 1203 + 610 @@ -414,8 +414,8 @@ 0 0 - 98 - 89 + 556 + 149 @@ -703,7 +703,7 @@ 0 0 - 1089 + 1247 21 From b5fb4da5bb676c4482cfd5085aab690e9a595648 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 24 Aug 2021 22:28:21 -0700 Subject: [PATCH 5/7] almost done with update... some more to code but getting there... --- src/qvm_inspector.cpp | 41 ++++++++++++++++++++++++++++++++++++ src/qvm_virtual_routines.cpp | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/qvm_inspector.cpp b/src/qvm_inspector.cpp index 3de0d22..45b73a2 100644 --- a/src/qvm_inspector.cpp +++ b/src/qvm_inspector.cpp @@ -180,5 +180,46 @@ bool qvm_inspector::serialize_vmp2( std::vector< rtn_data_t > &virt_rtns ) void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_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; } ); + if ( _rtn == virt_rtns.end() ) + return; + + for ( const auto &vinstr : _rtn->rtn_blks[ 0 ].vinstrs ) + { + const auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); + auto virt_instr_entry = new QTreeWidgetItem(); + + // virtual instruction operand bytes... (column 2)... + QString operand_bytes; + operand_bytes.append( QString( "%1" ).arg( vinstr.opcode, 0, 16 ) ); + + // if virt instruction has an imm... grab its bytes... + if ( vinstr.operand.has_imm ) + { + operand_bytes.append( " - " ); + for ( auto _idx = 0u; _idx < vinstr.operand.imm.imm_size / 8; ++_idx ) + operand_bytes.append( QString( "%1 " ).arg( + reinterpret_cast< const std::uint8_t * >( &vinstr.operand.imm.u )[ _idx ], 0, 16 ) ); + } + + virt_instr_entry->setText( 1, operand_bytes ); + + // virtual instruction string, includes imm... (colume 3)... + QString decoded_instr( + QString( "%1" ).arg( profile ? profile->name : QString( "UNK(%1)" ).arg( vinstr.opcode, 0, 16 ) ) ); + + if ( vinstr.operand.has_imm ) // if there is a second operand (imm) put its value... + decoded_instr.append( QString( " %1" ).arg( vinstr.operand.imm.u, 0, 16 ) ); + + virt_instr_entry->setText( 2, decoded_instr ); + + // add comments to the virtual instruction... (colume 4)... + if ( vinstr.mnemonic_t == vm::handler::LREGQ || vinstr.mnemonic_t == vm::handler::SREGQ ) + 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 ); + } } diff --git a/src/qvm_virtual_routines.cpp b/src/qvm_virtual_routines.cpp index 4c3e8be..efab1d3 100644 --- a/src/qvm_virtual_routines.cpp +++ b/src/qvm_virtual_routines.cpp @@ -101,5 +101,5 @@ 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 ); - g_main_window->update_virtual_instructions( g_main_window->img_base + entry_rva ); + g_main_window->update_virtual_instructions( entry_rva ); } \ No newline at end of file From b6a094cf1211babce6e3c8e7639437911d7a9c36 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 25 Aug 2021 11:27:22 -0700 Subject: [PATCH 6/7] 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 From e22ee422da4a8edebdf499059a892882c0a0b69f Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sat, 28 Aug 2021 12:37:46 -0700 Subject: [PATCH 7/7] bug fix for multi-vm stuff... also updated to newest vmprofiler... --- dependencies/vmprofiler | 2 +- .../framelesswindow/framelesswindow.ui | 2 +- src/qvm_inspector.cpp | 48 +++++++++++++++++-- src/qvm_virtual_routines.cpp | 20 ++++---- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/dependencies/vmprofiler b/dependencies/vmprofiler index 573cc04..0511401 160000 --- a/dependencies/vmprofiler +++ b/dependencies/vmprofiler @@ -1 +1 @@ -Subproject commit 573cc04fc1804ac328b555bb1136d132d858a6fe +Subproject commit 051140175db16b38acee882cfca714b4a1000a41 diff --git a/src/darkstyle/framelesswindow/framelesswindow.ui b/src/darkstyle/framelesswindow/framelesswindow.ui index 7751a56..87648a2 100644 --- a/src/darkstyle/framelesswindow/framelesswindow.ui +++ b/src/darkstyle/framelesswindow/framelesswindow.ui @@ -143,7 +143,7 @@ color:rgb(153,153,153); - VMProtect 2 - Virtual Instruction Inspector (v1.8 BETA) + VMProtect 2 - Virtual Instruction Inspector - v2.0 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/src/qvm_inspector.cpp b/src/qvm_inspector.cpp index 8e66589..4321662 100644 --- a/src/qvm_inspector.cpp +++ b/src/qvm_inspector.cpp @@ -204,7 +204,6 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, std::u 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)... @@ -251,7 +250,7 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, std::u .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 entry_rva = g_vm_ctx->vm_handlers[ vinstr.opcode ].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 ]; @@ -273,13 +272,24 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, std::u } update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 0 ], branch_entry1 ); + + 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[ 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; + auto entry_rva = g_vm_ctx->vm_handlers[ vinstr.opcode ].address - module_base; virt_instr_entry->setText( 3, QString( "; { 0x%1 }" ).arg( code_blk->jcc.block_addr[ 0 ], 0, 16 ) ); if ( g_vm_ctx ) @@ -292,7 +302,37 @@ void qvm_inspector::update_virtual_instructions( std::uintptr_t rtn_addr, std::u return; } - update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 0 ], parent ); + auto branch_entry1 = new QTreeWidgetItem(); + branch_entry1->setText( 0, QString( "0x%1" ).arg( code_blk->jcc.block_addr[ 0 ], 0, 16 ) ); + branch_entry1->setText( 3, QString( "; blk_0x%1" ).arg( code_blk->jcc.block_addr[ 0 ], 0, 16 ) ); + update_virtual_instructions( rtn_addr, code_blk->jcc.block_addr[ 0 ], branch_entry1 ); + virt_instr_entry->addChild( branch_entry1 ); + break; + } + case vm::instrs::jcc_type::switch_case: + { + auto entry_rva = g_vm_ctx->vm_handlers[ vinstr.opcode ].address - module_base; + + 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; + } + + for ( auto branch_addr : code_blk->jcc.block_addr ) + { + virt_instr_entry->setText( 3, QString( "; switch case" ) ); + + auto branch_entry = new QTreeWidgetItem(); + branch_entry->setText( 0, QString( "0x%1" ).arg( branch_addr, 0, 16 ) ); + + update_virtual_instructions( rtn_addr, branch_addr, branch_entry ); + virt_instr_entry->addChild( branch_entry ); + } break; } default: diff --git a/src/qvm_virtual_routines.cpp b/src/qvm_virtual_routines.cpp index ca64e63..a230dd5 100644 --- a/src/qvm_virtual_routines.cpp +++ b/src/qvm_virtual_routines.cpp @@ -15,9 +15,11 @@ void qvm_virtual_routines::update_vm_enter( vm::ctx_t *g_vm_ctx ) ui->virtual_machine_enter_instrs->clear(); for ( auto [ instr, raw, addr ] : g_vm_ctx->vm_entry ) { - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), + ( addr - g_main_window->module_base ) + g_vm_ctx->image_base ); + auto newItem = new QTreeWidgetItem(); - newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 0, QString::number( ( addr - g_main_window->module_base ) + g_vm_ctx->image_base, 16 ) ); newItem->setText( 1, buffer ); ui->virtual_machine_enter_instrs->addTopLevelItem( newItem ); } @@ -32,9 +34,11 @@ void qvm_virtual_routines::update_calc_jmp( vm::ctx_t *g_vm_ctx ) ui->virtual_machine_enter_calc_jmp->clear(); for ( auto [ instr, raw, addr ] : g_vm_ctx->calc_jmp ) { - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), + ( addr - g_main_window->module_base ) + g_vm_ctx->image_base ); + auto newItem = new QTreeWidgetItem(); - newItem->setText( 0, QString::number( addr, 16 ) ); + newItem->setText( 0, QString::number( ( addr - g_main_window->module_base ) + g_vm_ctx->image_base, 16 ) ); newItem->setText( 1, buffer ); ui->virtual_machine_enter_calc_jmp->addTopLevelItem( newItem ); } @@ -48,10 +52,10 @@ void qvm_virtual_routines::update_vm_handlers( vm::ctx_t *g_vm_ctx ) auto newItem = new QTreeWidgetItem; newItem->setData( 0, Qt::UserRole, idx ); newItem->setText( 0, QString( "%1" ).arg( idx ) ); - newItem->setText( 1, QString( "%1" ).arg( ABS_TO_IMG( g_vm_ctx->vm_handlers[ idx ].address, - g_main_window->file_header->module_base, - g_main_window->file_header->image_base ), - 0, 16 ) ); + newItem->setText( 1, + QString( "%1" ).arg( ( g_vm_ctx->vm_handlers[ idx ].address - g_main_window->module_base ) + + g_main_window->img_base, + 0, 16 ) ); newItem->setText( 2, g_vm_ctx->vm_handlers[ idx ].profile ? g_vm_ctx->vm_handlers[ idx ].profile->name : "UNDEFINED" );