From d7c4e19d6a4df2311c89a1d8e8302fe6c4d31e39 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Fri, 4 Jun 2021 01:18:43 -0700 Subject: [PATCH] works good, works REALLY well... todo: fix clicking child tree widget items... it doesnt update the gui... --- .../framelesswindow/framelesswindow.ui | 4 +- src/main.cpp | 6 +- src/qvirt_instrs.cpp | 139 +++++++++++++++++- src/qvirt_instrs.h | 8 +- src/qvminspector.cpp | 19 ++- src/qvminspector.h | 2 + 6 files changed, 165 insertions(+), 13 deletions(-) diff --git a/src/DarkStyle/framelesswindow/framelesswindow.ui b/src/DarkStyle/framelesswindow/framelesswindow.ui index 3da636e..7bb5ecd 100644 --- a/src/DarkStyle/framelesswindow/framelesswindow.ui +++ b/src/DarkStyle/framelesswindow/framelesswindow.ui @@ -6,8 +6,8 @@ 0 0 - 1642 - 983 + 1737 + 1157 diff --git a/src/main.cpp b/src/main.cpp index 0987188..1c4cbbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include "qvminspector.h" +#include "qvirt_instrs.h" #include "framelesswindow.h" #include "DarkStyle.h" @@ -11,7 +12,10 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); QApplication::setStyle(new DarkStyle); FramelessWindow frameless_window; - frameless_window.setContent(new qvminspector_t); + const auto window = new qvminspector_t; + qvirt_instrs_t virt_instr( window ); + + frameless_window.setContent( window ); frameless_window.setWindowIcon(QIcon("icon.ico")); frameless_window.show(); return app.exec(); diff --git a/src/qvirt_instrs.cpp b/src/qvirt_instrs.cpp index 3918bd3..caa1a93 100644 --- a/src/qvirt_instrs.cpp +++ b/src/qvirt_instrs.cpp @@ -2,10 +2,145 @@ qvirt_instrs_t::qvirt_instrs_t( qvminspector_t *vminspector ) : vminspector( vminspector ), ui( &vminspector->ui ) { - connect( ui->virt_instrs, &QTreeWidget::itemExpanded, this, &qvirt_instrs_t::on_expand ); + connect( ui->virt_instrs, &QTreeWidget::itemSelectionChanged, this, &qvirt_instrs_t::on_select ); } -void qvirt_instrs_t::on_expand( qtree_widget_item_t *item ) +void qvirt_instrs_t::on_select() { + auto item = ui->virt_instrs->selectedItems()[ 0 ]; + const auto virt_instr = item->data( 3, Qt::UserRole ).value< vm::instrs::virt_instr_t * >(); + 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 ); +} + +void qvirt_instrs_t::update_native_regs( vm::instrs::virt_instr_t *virt_instr ) +{ + const auto &trace_data = virt_instr->trace_data; + + // set native register values.... + for ( auto idx = 0u; idx < 15; ++idx ) + ui->native_regs->topLevelItem( idx )->setText( 1, QString::number( trace_data.regs.raw[ idx ], 16 ) ); + + // set RFLAGs and its bits... + ui->native_regs->topLevelItem( 16 )->setText( 1, QString::number( trace_data.regs.rflags, 16 ) ); + + rflags flags; + flags.flags = trace_data.regs.rflags; + + // could probably use a for loop here and shift bits around maybe... + ui->native_regs->topLevelItem( 16 )->child( 0 )->setText( 1, QString::number( flags.zero_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 1 )->setText( 1, QString::number( flags.parity_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 2 )->setText( 1, QString::number( flags.auxiliary_carry_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 3 )->setText( 1, QString::number( flags.overflow_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 4 )->setText( 1, QString::number( flags.sign_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 5 )->setText( 1, QString::number( flags.direction_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 6 )->setText( 1, QString::number( flags.carry_flag ) ); + ui->native_regs->topLevelItem( 16 )->child( 7 )->setText( 1, QString::number( flags.trap_flag ) ); + 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 ) +{ + 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 ) ); + + // set VSP in virtual registers window... + ui->virt_regs->topLevelItem( 1 )->setText( 1, QString::number( trace_data.regs.rbp, 16 ) ); + + // set decrypt key in virtual registers window... + ui->virt_regs->topLevelItem( 2 )->setText( 1, QString::number( trace_data.regs.rdx, 16 ) ); + + // set the virtual register values.... + for ( auto idx = 4u; idx < 28; ++idx ) + 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 ) +{ + 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 ) ); + ui->virt_stack->addTopLevelItem( new_stack_entry ); + } +} + +void qvirt_instrs_t::update_vm_handler_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 = vminspector->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 ) ); + + ZydisFormatterFormatInstruction( &formatter, &instr.instr, buffer, sizeof( buffer ), + ( instr.addr - vminspector->module_base ) + vminspector->image_base ); + + new_instr->setText( 1, buffer ); + ui->vm_handler_instrs->addTopLevelItem( new_instr ); + } + + // display vm handler transformations... + ui->vm_handler_transforms->clear(); + const auto &vm_handler_transforms = vminspector->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(); + + switch ( transform_type ) + { + case vm::transform::type::rolling_key: + { + new_transform_entry->setText( 0, "Key Transform" ); + break; + } + case vm::transform::type::generic0: + case vm::transform::type::generic1: + case vm::transform::type::generic2: + case vm::transform::type::generic3: + { + new_transform_entry->setText( 0, "Generic" ); + break; + } + case vm::transform::type::update_key: + { + new_transform_entry->setText( 0, "Update Key" ); + break; + } + default: + throw std::invalid_argument( "invalid transformation type..." ); + } + + ZydisFormatterFormatInstruction( &formatter, &transform_instr, buffer, sizeof( buffer ), NULL ); + + new_transform_entry->setText( 1, buffer ); + ui->vm_handler_transforms->addTopLevelItem( new_transform_entry ); + } } \ No newline at end of file diff --git a/src/qvirt_instrs.h b/src/qvirt_instrs.h index 6636ae3..3d4a83d 100644 --- a/src/qvirt_instrs.h +++ b/src/qvirt_instrs.h @@ -10,7 +10,11 @@ class qvirt_instrs_t : public QObject 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 ); - private slots: - void on_expand( qtree_widget_item_t *item ); + private slots: + void on_select(); }; \ No newline at end of file diff --git a/src/qvminspector.cpp b/src/qvminspector.cpp index af44093..dafcb9b 100644 --- a/src/qvminspector.cpp +++ b/src/qvminspector.cpp @@ -192,7 +192,7 @@ void qvminspector_t::add_branch_children( qtree_widget_item_t *item, std::uintpt // 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..." ) + virt_instr_entry->setText( 3, QString( "; vreg%1" ) .arg( virt_instr->operand.imm.u ? ( virt_instr->operand.imm.u / 8 ) - 1 /* zero based vreg... */ : 0u ) ); @@ -309,10 +309,14 @@ void qvminspector_t::update_ui() // 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 ) - - 1 /* zero based vreg... */ - : 0u ) ); + 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 && code_block->jcc.has_jcc ) { @@ -344,7 +348,7 @@ void qvminspector_t::update_ui() // 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 ); - return; + goto finish; // bad code... } else if ( virt_instr->mnemonic_t == vm::handler::JMP ) virt_instr_entry->setText( 3, QString( "; { %1 }" ) @@ -355,4 +359,7 @@ void qvminspector_t::update_ui() ui.virt_instrs->addTopLevelItem( virt_instr_entry ); } } + +finish: // bad code... + ui.virt_instrs->topLevelItem( 0 )->setSelected( true ); } \ No newline at end of file diff --git a/src/qvminspector.h b/src/qvminspector.h index 3c67d84..2a1133b 100644 --- a/src/qvminspector.h +++ b/src/qvminspector.h @@ -12,6 +12,8 @@ #include "ui_qvminspector.h" #include "vmp2.hpp" +Q_DECLARE_METATYPE( vm::instrs::virt_instr_t * ) + using qmain_window_t = QMainWindow; using qwidget_t = QWidget; using qstring_t = QString;