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;