diff --git a/src/main.cpp b/src/main.cpp
index bda59f8..edcb6d3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,6 +5,7 @@
#include "qvminspector.h"
#include "qvirt_instrs.h"
+#include "qvirt_handlers.h"
#include "framelesswindow.h"
#include "DarkStyle.h"
@@ -15,6 +16,7 @@ int main(int argc, char *argv[])
FramelessWindow frameless_window;
const auto window = new qvminspector_t;
qvirt_instrs_t virt_instr( window );
+ qvirt_handlers_t 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
new file mode 100644
index 0000000..47ef49a
--- /dev/null
+++ b/src/qvirt_handlers.cpp
@@ -0,0 +1,92 @@
+#include "qvirt_handlers.h"
+
+qvirt_handlers_t::qvirt_handlers_t( qvminspector_t *vminspector ) : vminspector( vminspector ), ui( &vminspector->ui )
+{
+ connect( ui->virt_handlers_tree, &QTreeWidget::itemSelectionChanged, this, &qvirt_handlers_t::on_select );
+}
+
+void qvirt_handlers_t::update_transforms( vm::handler::handler_t &vm_handler )
+{
+ char buffer[ 256 ];
+ ZydisFormatter formatter;
+ ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
+
+ ui->virt_handler_transforms_tree->clear();
+ const auto &vm_handler_transforms = vm_handler.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->virt_handler_transforms_tree->addTopLevelItem( new_transform_entry );
+ }
+}
+
+void qvirt_handlers_t::update_instrs( vm::handler::handler_t &vm_handler )
+{
+ char buffer[ 256 ];
+ ZydisFormatter formatter;
+ ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL );
+
+ ui->virt_handler_instrs_tree->clear();
+ const auto &vm_handler_instrs = vm_handler.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->virt_handler_instrs_tree->addTopLevelItem( new_instr );
+ }
+}
+
+void qvirt_handlers_t::on_select()
+{
+ auto item = ui->virt_handlers_tree->selectedItems()[ 0 ];
+
+ if ( !item )
+ return;
+
+ if ( !vminspector->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 ] );
+}
\ No newline at end of file
diff --git a/src/qvirt_handlers.h b/src/qvirt_handlers.h
new file mode 100644
index 0000000..2022692
--- /dev/null
+++ b/src/qvirt_handlers.h
@@ -0,0 +1,19 @@
+#pragma once
+#define NOMINMAX
+#include "qvminspector.h"
+
+class qvirt_handlers_t : public QObject
+{
+ Q_OBJECT
+ public:
+ explicit qvirt_handlers_t( qvminspector_t *vminspector );
+
+ 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 );
+
+ private slots:
+ void on_select();
+};
\ No newline at end of file
diff --git a/src/qvminspector.cpp b/src/qvminspector.cpp
index 336c355..1d7e89c 100644
--- a/src/qvminspector.cpp
+++ b/src/qvminspector.cpp
@@ -11,7 +11,6 @@ qvminspector_t::qvminspector_t( qwidget_t *parent ) : qmain_window_t( parent ),
connect( ui.action_open, &QAction::triggered, this, &qvminspector_t::on_open );
connect( ui.action_close, &QAction::triggered, this, &qvminspector_t::on_close );
connect( ui.lift_all_button, &QAction::triggered, this, &qvminspector_t::on_lift_all );
- connect( ui.lift_specific_block_button, &QAction::triggered, this, &qvminspector_t::on_lift_block );
}
void qvminspector_t::on_lift_all()
@@ -53,13 +52,8 @@ void qvminspector_t::on_lift_all()
auto vinstr = &code_block->vinstr[ idx ];
if ( vinstr->mnemonic_t == vm::handler::INVALID )
{
- std::printf( "> unable to lift to VTIL... unknown virtual instruction handler #%d... "
- "please define a vm handler profile for this virtual instruction and try again..."
- " you can also create your first contribution to this open source project by submitting"
- " a merge request with your changes! :)\n",
- vinstr->opcode );
-
- return;
+ rtn->nop();
+ continue;
}
const auto result = std::find_if(
@@ -68,13 +62,8 @@ void qvminspector_t::on_lift_all()
if ( result == vm::lifters::all.end() )
{
- std::printf( "> unable to lift to VTIL... unknown virtual instruction handler lifter for #%d... "
- "please define a vm handler lifter for this vm handler and try again..."
- " you can also create your first contribution to this open source project by submitting"
- " a merge request with your changes! :)\n",
- vinstr->opcode );
-
- return;
+ rtn->nop();
+ continue;
}
// lift the virtual instruction...
@@ -86,37 +75,6 @@ void qvminspector_t::on_lift_all()
vtil::debug::dump( first );
}
-void qvminspector_t::on_lift_block()
-{
- if ( !file_header )
- return;
-
- auto lift_block_select = new QDialog();
- auto layout = new QVBoxLayout();
-
- 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 new_button = new QPushButton();
- new_button->setText(
- QString( "block_%1" )
- .arg( ABS_TO_IMG( code_block->vip_begin, file_header->module_base, file_header->image_base ), 0u,
- 16 ) );
-
- new_button->setProperty(
- "addr", ABS_TO_IMG( code_block->vip_begin, file_header->module_base, file_header->image_base ) );
-
- layout->addWidget( new_button );
- }
-
- lift_block_select->setWindowTitle( "Select A Block" );
- lift_block_select->setLayout( layout );
- lift_block_select->exec();
-}
-
void qvminspector_t::on_close()
{
exit( 0 );
@@ -161,7 +119,6 @@ void qvminspector_t::on_open()
qfile_t open_file( file_path );
file_header = reinterpret_cast< vmp2::v3::file_header * >( malloc( file_size ) );
- dbg_msg( qstring_t( "loading vmp2 file %1..." ).arg( file_path ) );
if ( !open_file.open( QIODevice::ReadOnly ) )
{
@@ -214,9 +171,10 @@ bool qvminspector_t::init_data()
vm_entry_rva = file_header->vm_entry_rva;
image_base = file_header->image_base;
+ 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_base, vm_entry_rva );
+ vmctx = new vm::ctx_t( module_base, image_base, image_size, vm_entry_rva );
if ( !vmctx->init() )
{
@@ -356,6 +314,34 @@ void qvminspector_t::add_branch_children( qtree_widget_item_t *item, std::uintpt
void qvminspector_t::update_ui()
{
+ // add vm handlers to the vm handler tree...
+ ui.virt_handlers_tree->clear();
+ for ( auto idx = 0u; idx < vmctx->vm_handlers.size(); ++idx )
+ {
+ 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 );
+ }
+ 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)
@@ -470,18 +456,4 @@ void qvminspector_t::update_ui()
finish: // bad code...
ui.virt_instrs->topLevelItem( 0 )->setSelected( true );
-}
-
-bool qvminspector_t::event( QEvent *event )
-{
- if ( event->type() == QEvent::KeyPress )
- {
- auto kevent = static_cast< QKeyEvent * >( event );
- if ( kevent->key() == Qt::Key::Key_F5 )
- {
-
- return true;
- }
- }
- return false;
}
\ No newline at end of file
diff --git a/src/qvminspector.h b/src/qvminspector.h
index 2eaf615..cffd635 100644
--- a/src/qvminspector.h
+++ b/src/qvminspector.h
@@ -28,6 +28,7 @@ using qmsg_box_t = QMessageBox;
class qvminspector_t : public qmain_window_t
{
friend class qvirt_instrs_t;
+ friend class qvirt_handlers_t;
Q_OBJECT
public:
qvminspector_t( qwidget_t *parent = Q_NULLPTR );
@@ -36,10 +37,6 @@ class qvminspector_t : public qmain_window_t
void on_open();
void on_close();
void on_lift_all();
- void on_lift_block();
-
- protected:
- bool event( QEvent *event );
private:
void dbg_print( qstring_t DbgOutput );
@@ -51,7 +48,7 @@ class qvminspector_t : public qmain_window_t
Ui::QVMProfilerClass ui;
qstring_t file_path;
qstring_t VMProtectedFilePath;
- std::uint64_t image_base, vm_entry_rva, module_base;
+ std::uint64_t image_base, vm_entry_rva, module_base, image_size;
vm::ctx_t *vmctx;
vmp2::v3::file_header *file_header;
diff --git a/src/qvminspector.ui b/src/qvminspector.ui
index ca9e741..26fa6a6 100644
--- a/src/qvminspector.ui
+++ b/src/qvminspector.ui
@@ -7,7 +7,7 @@
0
0
1496
- 1038
+ 1093
@@ -29,7 +29,7 @@
0
-
+
Virtual Instructions
@@ -45,7 +45,7 @@
0
0
1452
- 799
+ 854
@@ -415,7 +415,7 @@
0
0
672
- 210
+ 228
@@ -508,6 +508,101 @@
Virtual Machine Handlers
+
+ -
+
+
+ Virtual Machine Handler List
+
+
+
-
+
+
+
+ Index
+
+
+
+
+ Address
+
+
+
+
+ Name
+
+
+
+
+ Imm Size
+
+
+
+
+ Sign Extended Imm
+
+
+
+
+
+
+
+ -
+
+
+ Virtual Machine Handler Information
+
+
+
-
+
+
+ Virtual Machine Handler Instructions
+
+
+
-
+
+
+
+ Address
+
+
+
+
+ Instruction
+
+
+
+
+
+
+
+ -
+
+
+ Virtual Machine Handler Transforms
+
+
+
-
+
+
+
+ Address
+
+
+
+
+ Instruction
+
+
+
+
+
+
+
+
+
+
+
@@ -533,7 +628,6 @@
VTIL
-
@@ -599,7 +693,7 @@
Close
-
+
Lift Specific Block
diff --git a/vmprofiler-qt.vcxproj b/vmprofiler-qt.vcxproj
index 8a53167..623c921 100644
--- a/vmprofiler-qt.vcxproj
+++ b/vmprofiler-qt.vcxproj
@@ -44,12 +44,10 @@
+
-
-
-
@@ -67,6 +65,8 @@
+
+
diff --git a/vmprofiler-qt.vcxproj.filters b/vmprofiler-qt.vcxproj.filters
index 32375cd..b6359a4 100644
--- a/vmprofiler-qt.vcxproj.filters
+++ b/vmprofiler-qt.vcxproj.filters
@@ -42,11 +42,11 @@
Source Files\darkstyle
+
+ Source Files
+
-
- Header Files
-
Header Files
@@ -59,6 +59,12 @@
Header Files\darkstyle\framelesswindow
+
+ Header Files
+
+
+ Header Files
+