1
0
Fork 0

Implement infobox in trace browser

This commit is contained in:
torusrxxx 2020-07-12 23:14:23 +08:00 committed by Duncan Ogilvie
parent b0c2702a10
commit e046b86901
7 changed files with 268 additions and 32 deletions

View File

@ -836,11 +836,7 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
}); });
if(cp.OpCount() && cp[0].type == ZYDIS_OPERAND_TYPE_MEMORY) if(cp.OpCount() && cp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
{ {
#ifdef _WIN64 auto const tebseg = ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS);
auto const tebseg = ZYDIS_REGISTER_GS;
#else
auto const tebseg = ZYDIS_REGISTER_FS;
#endif //_WIN64
if(cp[0].mem.segment == tebseg) if(cp[0].mem.segment == tebseg)
opValue += duint(GetTEBLocation(hActiveThread)); opValue += duint(GetTEBLocation(hActiveThread));
if(MemRead(opValue, &opValue, sizeof(opValue))) if(MemRead(opValue, &opValue, sizeof(opValue)))

View File

@ -55,6 +55,11 @@ TraceBrowser::TraceBrowser(QWidget* parent) : AbstractTableView(parent)
TraceBrowser::~TraceBrowser() TraceBrowser::~TraceBrowser()
{ {
if(mTraceFile)
{
mTraceFile->Close();
delete mTraceFile;
}
delete mDisasm; delete mDisasm;
} }
@ -741,7 +746,7 @@ void TraceBrowser::mousePressEvent(QMouseEvent* event)
setSingleSelection(index); setSingleSelection(index);
mHistory.addVaToHistory(index); mHistory.addVaToHistory(index);
updateViewport(); updateViewport();
selectionChanged(); emit selectionChanged(getInitialSelection());
return; return;
break; break;
@ -873,20 +878,16 @@ void TraceBrowser::keyPressEvent(QKeyEvent* event)
mHistory.addVaToHistory(visibleindex); mHistory.addVaToHistory(visibleindex);
updateViewport(); updateViewport();
selectionChanged(); emit selectionChanged(getInitialSelection());
} }
else else
AbstractTableView::keyPressEvent(event); AbstractTableView::keyPressEvent(event);
} }
void TraceBrowser::selectionChanged() void TraceBrowser::onSelectionChanged(unsigned long long selection)
{ {
if(mAutoDisassemblyFollowSelection) if(mAutoDisassemblyFollowSelection)
followDisassemblySlot(); followDisassemblySlot();
REGDUMP temp;
temp = mTraceFile->Registers(getInitialSelection());
emit updateTraceRegistersView(&temp);
} }
void TraceBrowser::tokenizerConfigUpdatedSlot() void TraceBrowser::tokenizerConfigUpdatedSlot()
@ -1103,7 +1104,7 @@ void TraceBrowser::gotoNextSlot()
setSingleSelection(index); setSingleSelection(index);
makeVisible(index); makeVisible(index);
updateViewport(); updateViewport();
selectionChanged(); emit selectionChanged(getInitialSelection());
} }
} }
@ -1115,7 +1116,7 @@ void TraceBrowser::gotoPreviousSlot()
setSingleSelection(index); setSingleSelection(index);
makeVisible(index); makeVisible(index);
updateViewport(); updateViewport();
selectionChanged(); emit selectionChanged(getInitialSelection());
} }
} }
@ -1527,9 +1528,6 @@ void TraceBrowser::updateSlot()
mTraceFile->purgeLastPage(); mTraceFile->purgeLastPage();
setRowCount(mTraceFile->Length()); setRowCount(mTraceFile->Length());
} }
REGDUMP reg;
reg = mTraceFile->Registers(getInitialSelection());
emit updateTraceRegistersView(&reg);
} }
else else
setRowCount(0); setRowCount(0);

View File

@ -29,6 +29,7 @@ public:
duint getSelectionEnd(); duint getSelectionEnd();
bool isFileOpened() const; bool isFileOpened() const;
TraceFileReader* getTraceFile() { return mTraceFile; }
private: private:
enum TableColumnIndex enum TableColumnIndex
@ -48,7 +49,6 @@ private:
void pushSelectionInto(bool copyBytes, QTextStream & stream, QTextStream* htmlStream = nullptr); void pushSelectionInto(bool copyBytes, QTextStream & stream, QTextStream* htmlStream = nullptr);
void copySelectionSlot(bool copyBytes); void copySelectionSlot(bool copyBytes);
void copySelectionToFileSlot(bool copyBytes); void copySelectionToFileSlot(bool copyBytes);
void selectionChanged();
void contextMenuEvent(QContextMenuEvent* event) override; void contextMenuEvent(QContextMenuEvent* event) override;
void mousePressEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override;
@ -117,7 +117,7 @@ private:
signals: signals:
void displayReferencesWidget(); void displayReferencesWidget();
void updateTraceRegistersView(void* registers); void selectionChanged(unsigned long long selection);
public slots: public slots:
void openFileSlot(); void openFileSlot();
@ -127,6 +127,7 @@ public slots:
void closeDeleteSlot(); void closeDeleteSlot();
void parseFinishedSlot(); void parseFinishedSlot();
void tokenizerConfigUpdatedSlot(); void tokenizerConfigUpdatedSlot();
void onSelectionChanged(unsigned long long selection);
void gotoSlot(); void gotoSlot();
void gotoPreviousSlot(); void gotoPreviousSlot();

View File

@ -1,8 +1,9 @@
#include "TraceWidget.h" #include "TraceWidget.h"
#include "ui_TraceWidget.h" #include "ui_TraceWidget.h"
#include "TraceBrowser.h" #include "TraceBrowser.h"
#include "TraceFileReader.h"
#include "TraceRegisters.h" #include "TraceRegisters.h"
#include "CPUInfoBox.h" #include "StdTable.h"
TraceWidget::TraceWidget(QWidget* parent) : TraceWidget::TraceWidget(QWidget* parent) :
QWidget(parent), QWidget(parent),
@ -12,7 +13,7 @@ TraceWidget::TraceWidget(QWidget* parent) :
mTraceWidget = new TraceBrowser(this); mTraceWidget = new TraceBrowser(this);
mOverview = new StdTable(this); mOverview = new StdTable(this);
mInfo = new CPUInfoBox(this); mInfo = new StdTable(this);
mGeneralRegs = new TraceRegisters(this); mGeneralRegs = new TraceRegisters(this);
//disasm //disasm
ui->mTopLeftUpperRightFrameLayout->addWidget(mTraceWidget); ui->mTopLeftUpperRightFrameLayout->addWidget(mTraceWidget);
@ -30,7 +31,7 @@ TraceWidget::TraceWidget(QWidget* parent) :
QPushButton* button_changeview = new QPushButton("", this); QPushButton* button_changeview = new QPushButton("", this);
button_changeview->setStyleSheet("Text-align:left;padding: 4px;padding-left: 10px;"); button_changeview->setStyleSheet("Text-align:left;padding: 4px;padding-left: 10px;");
connect(button_changeview, SIGNAL(clicked()), mGeneralRegs, SLOT(onChangeFPUViewAction())); connect(button_changeview, SIGNAL(clicked()), mGeneralRegs, SLOT(onChangeFPUViewAction()));
connect(mTraceWidget, SIGNAL(updateTraceRegistersView(void*)), this, SLOT(updateTraceRegistersView(void*))); connect(mTraceWidget, SIGNAL(selectionChanged(unsigned long long)), this, SLOT(traceSelectionChanged(unsigned long long)));
connect(Bridge::getBridge(), SIGNAL(updateTraceBrowser()), this, SLOT(updateSlot())); connect(Bridge::getBridge(), SIGNAL(updateTraceBrowser()), this, SLOT(updateSlot()));
mGeneralRegs->SetChangeButton(button_changeview); mGeneralRegs->SetChangeButton(button_changeview);
@ -39,13 +40,22 @@ TraceWidget::TraceWidget(QWidget* parent) :
ui->mTopRightUpperFrameLayout->addWidget(upperScrollArea); ui->mTopRightUpperFrameLayout->addWidget(upperScrollArea);
//info //info
ui->mTopLeftLowerFrameLayout->addWidget(mInfo); ui->mTopLeftLowerFrameLayout->addWidget(mInfo);
int height = mInfo->getHeight(); int height = (mInfo->getRowHeight() + 1) * 4;
ui->mTopLeftLowerFrame->setMinimumHeight(height + 2); ui->mTopLeftLowerFrame->setMinimumHeight(height + 2);
mInfo->addColumnAt(0, "", true);
mInfo->setShowHeader(false);
mInfo->setRowCount(4);
mInfo->setCellContent(0, 0, QString());
mInfo->setCellContent(1, 0, QString());
mInfo->setCellContent(2, 0, QString());
mInfo->setCellContent(3, 0, QString());
//overview //overview
ui->mTopRightLowerFrameLayout->addWidget(mOverview); ui->mTopRightLowerFrameLayout->addWidget(mOverview);
//set up overview //set up overview
mOverview->addColumnAt(500, tr("Overview"), true); mOverview->addColumnAt(0, "", true);
mOverview->setShowHeader(false);
mOverview->setRowCount(4); mOverview->setRowCount(4);
mOverview->setCellContent(0, 0, "hello"); mOverview->setCellContent(0, 0, "hello");
mOverview->setCellContent(1, 0, "world"); mOverview->setCellContent(1, 0, "world");
@ -58,9 +68,22 @@ TraceWidget::~TraceWidget()
delete ui; delete ui;
} }
void TraceWidget::updateTraceRegistersView(void* registers) void TraceWidget::traceSelectionChanged(unsigned long long selection)
{ {
mGeneralRegs->setRegisters((REGDUMP*)registers); REGDUMP registers;
TraceFileReader* traceFile;
traceFile = mTraceWidget->getTraceFile();
if(traceFile != nullptr && traceFile->Progress() == 100)
{
if(selection < traceFile->Length())
{
registers = traceFile->Registers(selection);
updateInfobox(selection, traceFile, registers);
}
else
memset(&registers, 0, sizeof(registers));
}
mGeneralRegs->setRegisters(&registers);
} }
void TraceWidget::updateSlot() void TraceWidget::updateSlot()
@ -72,3 +95,198 @@ TraceBrowser* TraceWidget::getTraceBrowser()
{ {
return mTraceWidget; return mTraceWidget;
} }
void TraceWidget::updateInfobox(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers)
{
int infoline = 0;
Zydis zydis;
unsigned char opcode[16];
QString line;
int opsize;
traceFile->OpCode(selection, opcode, &opsize);
mInfo->setRowCount(4);
mInfo->setCellContent(0, 0, QString());
mInfo->setCellContent(1, 0, QString());
mInfo->setCellContent(2, 0, QString());
mInfo->setCellContent(3, 0, QString());
auto resolveRegValue = [registers](ZydisRegister regname)
{
switch(regname)
{
#ifdef _WIN64
case ZYDIS_REGISTER_RAX:
return registers.regcontext.cax;
case ZYDIS_REGISTER_RCX:
return registers.regcontext.ccx;
case ZYDIS_REGISTER_RDX:
return registers.regcontext.cdx;
case ZYDIS_REGISTER_RBX:
return registers.regcontext.cbx;
case ZYDIS_REGISTER_RSP:
return registers.regcontext.csp;
case ZYDIS_REGISTER_RBP:
return registers.regcontext.cbp;
case ZYDIS_REGISTER_RSI:
return registers.regcontext.csi;
case ZYDIS_REGISTER_RDI:
return registers.regcontext.cdi;
case ZYDIS_REGISTER_R8:
return registers.regcontext.r8;
case ZYDIS_REGISTER_R9:
return registers.regcontext.r9;
case ZYDIS_REGISTER_R10:
return registers.regcontext.r10;
case ZYDIS_REGISTER_R11:
return registers.regcontext.r11;
case ZYDIS_REGISTER_R12:
return registers.regcontext.r12;
case ZYDIS_REGISTER_R13:
return registers.regcontext.r13;
case ZYDIS_REGISTER_R14:
return registers.regcontext.r14;
case ZYDIS_REGISTER_R15:
return registers.regcontext.r15;
case ZYDIS_REGISTER_R8D:
return registers.regcontext.r8 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R9D:
return registers.regcontext.r9 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R10D:
return registers.regcontext.r10 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R11D:
return registers.regcontext.r11 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R12D:
return registers.regcontext.r12 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R13D:
return registers.regcontext.r13 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R15D:
return registers.regcontext.r15 & 0xFFFFFFFF;
case ZYDIS_REGISTER_R8W:
return registers.regcontext.r8 & 0xFFFF;
case ZYDIS_REGISTER_R9W:
return registers.regcontext.r9 & 0xFFFF;
case ZYDIS_REGISTER_R10W:
return registers.regcontext.r10 & 0xFFFF;
case ZYDIS_REGISTER_R11W:
return registers.regcontext.r11 & 0xFFFF;
case ZYDIS_REGISTER_R12W:
return registers.regcontext.r12 & 0xFFFF;
case ZYDIS_REGISTER_R13W:
return registers.regcontext.r13 & 0xFFFF;
case ZYDIS_REGISTER_R15W:
return registers.regcontext.r15 & 0xFFFF;
case ZYDIS_REGISTER_R8B:
return registers.regcontext.r8 & 0xFF;
case ZYDIS_REGISTER_R9B:
return registers.regcontext.r9 & 0xFF;
case ZYDIS_REGISTER_R10B:
return registers.regcontext.r10 & 0xFF;
case ZYDIS_REGISTER_R11B:
return registers.regcontext.r11 & 0xFF;
case ZYDIS_REGISTER_R12B:
return registers.regcontext.r12 & 0xFF;
case ZYDIS_REGISTER_R13B:
return registers.regcontext.r13 & 0xFF;
case ZYDIS_REGISTER_R15B:
return registers.regcontext.r15 & 0xFF;
#endif //_WIN64
case ZYDIS_REGISTER_EAX:
return registers.regcontext.cax & 0xFFFFFFFF;
case ZYDIS_REGISTER_ECX:
return registers.regcontext.ccx & 0xFFFFFFFF;
case ZYDIS_REGISTER_EDX:
return registers.regcontext.cdx & 0xFFFFFFFF;
case ZYDIS_REGISTER_EBX:
return registers.regcontext.cbx & 0xFFFFFFFF;
case ZYDIS_REGISTER_ESP:
return registers.regcontext.csp & 0xFFFFFFFF;
case ZYDIS_REGISTER_EBP:
return registers.regcontext.cbp & 0xFFFFFFFF;
case ZYDIS_REGISTER_ESI:
return registers.regcontext.csi & 0xFFFFFFFF;
case ZYDIS_REGISTER_EDI:
return registers.regcontext.cdi & 0xFFFFFFFF;
case ZYDIS_REGISTER_AX:
return registers.regcontext.cax & 0xFFFF;
case ZYDIS_REGISTER_CX:
return registers.regcontext.ccx & 0xFFFF;
case ZYDIS_REGISTER_DX:
return registers.regcontext.cdx & 0xFFFF;
case ZYDIS_REGISTER_BX:
return registers.regcontext.cbx & 0xFFFF;
case ZYDIS_REGISTER_SP:
return registers.regcontext.csp & 0xFFFF;
case ZYDIS_REGISTER_BP:
return registers.regcontext.cbp & 0xFFFF;
case ZYDIS_REGISTER_SI:
return registers.regcontext.csi & 0xFFFF;
case ZYDIS_REGISTER_DI:
return registers.regcontext.cdi & 0xFFFF;
case ZYDIS_REGISTER_AL:
return registers.regcontext.cax & 0xFF;
case ZYDIS_REGISTER_CL:
return registers.regcontext.ccx & 0xFF;
case ZYDIS_REGISTER_DL:
return registers.regcontext.cdx & 0xFF;
case ZYDIS_REGISTER_BL:
return registers.regcontext.cbx & 0xFF;
case ZYDIS_REGISTER_AH:
return (registers.regcontext.cax & 0xFF00) >> 8;
case ZYDIS_REGISTER_CH:
return (registers.regcontext.ccx & 0xFF00) >> 8;
case ZYDIS_REGISTER_DH:
return (registers.regcontext.cdx & 0xFF00) >> 8;
case ZYDIS_REGISTER_BH:
return (registers.regcontext.cbx & 0xFF00) >> 8;
default:
return static_cast<size_t>(0);
}
};
if(zydis.Disassemble(registers.regcontext.cip, opcode, opsize))
{
int opindex;
//Jumps
if(zydis.IsBranchType(Zydis::BTCondJmp))
{
if(zydis.IsBranchGoingToExecute(registers.regcontext.eflags, registers.regcontext.ccx))
{
line = tr("Jump is taken");
}
else
{
line = tr("Jump is not taken");
}
mInfo->setCellContent(infoline, 0, line);
infoline++;
}
//Operands
for(opindex = 0; opindex < zydis.OpCount(); opindex++)
{
line.clear();
size_t value = zydis.ResolveOpValue(opindex, resolveRegValue);
if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
const char* memsize = zydis.MemSizeName(zydis[opindex].size / 8);
if(memsize != nullptr)
{
line += memsize;
}
line += " ptr ";
line += zydis.RegName(zydis[opindex].mem.segment);
line += ":[";
line += ToPtrString(value);
line += "]";
mInfo->setCellContent(infoline, 0, line);
infoline++;
}
else if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_REGISTER)
{
line += zydis.RegName(zydis[opindex].reg.value);
line += " = ";
line += ToPtrString(value);
mInfo->setCellContent(infoline, 0, line);
infoline++;
}
}
}
mInfo->reloadData();
}

View File

@ -2,12 +2,13 @@
#define TRACEWIDGET_H #define TRACEWIDGET_H
#include <QWidget> #include <QWidget>
#include "Bridge.h"
class QVBoxLayout; class QVBoxLayout;
class CPUWidget; class CPUWidget;
class TraceRegisters; class TraceRegisters;
class TraceBrowser; class TraceBrowser;
class CPUInfoBox; class TraceFileReader;
class StdTable; class StdTable;
namespace Ui namespace Ui
@ -26,15 +27,17 @@ public:
TraceBrowser* getTraceBrowser(); TraceBrowser* getTraceBrowser();
protected slots: protected slots:
void updateTraceRegistersView(void* registers); void traceSelectionChanged(unsigned long long selection);
void updateSlot(); void updateSlot();
protected: protected:
TraceBrowser* mTraceWidget; TraceBrowser* mTraceWidget;
TraceRegisters* mGeneralRegs; TraceRegisters* mGeneralRegs;
CPUInfoBox* mInfo; StdTable* mInfo;
StdTable* mOverview; StdTable* mOverview;
void updateInfobox(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers);
private: private:
Ui::TraceWidget* ui; Ui::TraceWidget* ui;
}; };

View File

@ -67,7 +67,7 @@
<number>1</number> <number>1</number>
</property> </property>
<property name="childrenCollapsible"> <property name="childrenCollapsible">
<bool>false</bool> <bool>true</bool>
</property> </property>
<widget class="QFrame" name="mTopLeftUpperRightFrame"> <widget class="QFrame" name="mTopLeftUpperRightFrame">
<property name="frameShape"> <property name="frameShape">
@ -95,6 +95,12 @@
</layout> </layout>
</widget> </widget>
<widget class="QFrame" name="mTopLeftLowerFrame"> <widget class="QFrame" name="mTopLeftLowerFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
@ -137,6 +143,12 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<widget class="QFrame" name="mTopRightUpperFrame"> <widget class="QFrame" name="mTopRightUpperFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
@ -162,6 +174,12 @@
</layout> </layout>
</widget> </widget>
<widget class="QFrame" name="mTopRightLowerFrame"> <widget class="QFrame" name="mTopRightLowerFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>

View File

@ -560,7 +560,7 @@ bool Zydis::IsNop() const
case ZYDIS_MNEMONIC_JRCXZ: case ZYDIS_MNEMONIC_JRCXZ:
case ZYDIS_MNEMONIC_JS: case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ: case ZYDIS_MNEMONIC_JZ:
// jmp 0 // jmp $0
return ops[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE return ops[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE
&& ops[0].imm.value.u == this->Address() + this->Size(); && ops[0].imm.value.u == this->Address() + this->Size();
case ZYDIS_MNEMONIC_SHL: case ZYDIS_MNEMONIC_SHL:
@ -615,7 +615,9 @@ bool Zydis::IsUnusual() const
|| id == ZYDIS_MNEMONIC_RDRAND || id == ZYDIS_MNEMONIC_RDRAND
|| id == ZYDIS_MNEMONIC_RDSEED || id == ZYDIS_MNEMONIC_RDSEED
|| id == ZYDIS_MNEMONIC_UD1 || id == ZYDIS_MNEMONIC_UD1
|| id == ZYDIS_MNEMONIC_UD2; || id == ZYDIS_MNEMONIC_UD2
|| id == ZYDIS_MNEMONIC_VMCALL
|| id == ZYDIS_MNEMONIC_VMFUNC;
} }
std::string Zydis::Mnemonic() const std::string Zydis::Mnemonic() const