GUI: added a very simple entropy graph in the dump (selection), memory map (page) and symbol view (file)
This commit is contained in:
parent
0c80b46056
commit
fd044407a7
|
|
@ -7,6 +7,7 @@
|
|||
#include "HexEditDialog.h"
|
||||
#include "YaraRuleSelectionDialog.h"
|
||||
#include "DataCopyDialog.h"
|
||||
#include "EntropyDialog.h"
|
||||
|
||||
CPUDump::CPUDump(CPUDisassembly* disas, QWidget* parent) : HexDump(parent)
|
||||
{
|
||||
|
|
@ -158,6 +159,10 @@ void CPUDump::setupContextMenu()
|
|||
#endif //_WIN64
|
||||
connect(mFollowDataDump, SIGNAL(triggered()), this, SLOT(followDataDumpSlot()));
|
||||
|
||||
//Entropy
|
||||
mEntropy = new QAction(QIcon(":/icons/images/entropy.png"), "Entropy...", this);
|
||||
connect(mEntropy, SIGNAL(triggered()), this, SLOT(entropySlot()));
|
||||
|
||||
//Label
|
||||
mSetLabelAction = new QAction("Set Label", this);
|
||||
mSetLabelAction->setShortcutContext(Qt::WidgetShortcut);
|
||||
|
|
@ -536,6 +541,7 @@ void CPUDump::contextMenuEvent(QContextMenuEvent* event)
|
|||
wMenu->addAction(mYaraAction);
|
||||
wMenu->addAction(mDataCopyAction);
|
||||
wMenu->addMenu(mGotoMenu);
|
||||
wMenu->addAction(mEntropy);
|
||||
wMenu->addSeparator();
|
||||
wMenu->addMenu(mHexMenu);
|
||||
wMenu->addMenu(mTextMenu);
|
||||
|
|
@ -1447,3 +1453,18 @@ void CPUDump::dataCopySlot()
|
|||
DataCopyDialog dataDialog(&data, this);
|
||||
dataDialog.exec();
|
||||
}
|
||||
|
||||
void CPUDump::entropySlot()
|
||||
{
|
||||
int_t selStart = getSelectionStart();
|
||||
int_t selSize = getSelectionEnd() - selStart + 1;
|
||||
QVector<byte_t> data;
|
||||
data.resize(selSize);
|
||||
mMemPage->read(data.data(), selStart, selSize);
|
||||
|
||||
EntropyDialog entropyDialog(this);
|
||||
entropyDialog.setWindowTitle(QString().sprintf("Entropy (Address: %p, Size: %p)", selStart, selSize));
|
||||
entropyDialog.show();
|
||||
entropyDialog.GraphMemory(data.constData(), data.size());
|
||||
entropyDialog.exec();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public slots:
|
|||
void selectionUpdatedSlot();
|
||||
void yaraSlot();
|
||||
void dataCopySlot();
|
||||
void entropySlot();
|
||||
|
||||
private:
|
||||
QMenu* mBreakpointMenu;
|
||||
|
|
@ -175,6 +176,7 @@ private:
|
|||
QAction* mUndoSelection;
|
||||
QAction* mFollowData;
|
||||
QAction* mFollowDataDump;
|
||||
QAction* mEntropy;
|
||||
|
||||
QMenu* mSpecialMenu;
|
||||
QMenu* mCustomMenu;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#include "EntropyDialog.h"
|
||||
#include "ui_EntropyDialog.h"
|
||||
|
||||
EntropyDialog::EntropyDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::EntropyDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint);
|
||||
#endif
|
||||
setFixedSize(this->size()); //fixed size
|
||||
|
||||
mBlockSize = 128;
|
||||
mPointCount = 300;
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
EntropyDialog::~EntropyDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EntropyDialog::GraphMemory(const unsigned char* data, int dataSize, QColor color)
|
||||
{
|
||||
initializeGraph();
|
||||
ui->entropyView->GraphMemory(data, dataSize, mBlockSize, mPointCount, color);
|
||||
}
|
||||
|
||||
void EntropyDialog::GraphFile(const QString & fileName, QColor color)
|
||||
{
|
||||
initializeGraph();
|
||||
ui->entropyView->GraphFile(fileName, mBlockSize, mPointCount, color);
|
||||
}
|
||||
|
||||
void EntropyDialog::initializeGraph()
|
||||
{
|
||||
if(mInitialized)
|
||||
return;
|
||||
mInitialized = true;
|
||||
ui->entropyView->InitializeGraph();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef ENTROPYDIALOG_H
|
||||
#define ENTROPYDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EntropyDialog;
|
||||
}
|
||||
|
||||
class EntropyDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EntropyDialog(QWidget* parent = 0);
|
||||
~EntropyDialog();
|
||||
void GraphMemory(const unsigned char* data, int dataSize, QColor color = Qt::darkGreen);
|
||||
void GraphFile(const QString & fileName, QColor color = Qt::darkGreen);
|
||||
|
||||
private:
|
||||
Ui::EntropyDialog* ui;
|
||||
int mBlockSize;
|
||||
int mPointCount;
|
||||
bool mInitialized;
|
||||
|
||||
void initializeGraph();
|
||||
};
|
||||
|
||||
#endif // ENTROPYDIALOG_H
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EntropyDialog</class>
|
||||
<widget class="QDialog" name="EntropyDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>744</width>
|
||||
<height>226</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Entropy</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/entropy.png</normaloff>:/icons/images/entropy.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QEntropyView" name="entropyView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QEntropyView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>QEntropyView\QEntropyView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../resource.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include "Bridge.h"
|
||||
#include "PageMemoryRights.h"
|
||||
#include "YaraRuleSelectionDialog.h"
|
||||
#include "EntropyDialog.h"
|
||||
|
||||
MemoryMapView::MemoryMapView(StdTable* parent) : StdTable(parent)
|
||||
{
|
||||
|
|
@ -97,6 +98,10 @@ void MemoryMapView::setupContextMenu()
|
|||
this->addAction(mMemoryExecuteSingleshootToggle);
|
||||
connect(mMemoryExecuteSingleshootToggle, SIGNAL(triggered()), this, SLOT(memoryExecuteSingleshootToggleSlot()));
|
||||
|
||||
//Entropy
|
||||
mEntropy = new QAction(QIcon(":/icons/images/entropy.png"), "Entropy...", this);
|
||||
connect(mEntropy, SIGNAL(triggered()), this, SLOT(entropy()));
|
||||
|
||||
refreshShortcutsSlot();
|
||||
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot()));
|
||||
}
|
||||
|
|
@ -116,6 +121,7 @@ void MemoryMapView::contextMenuSlot(const QPoint & pos)
|
|||
wMenu->addAction(mFollowDisassembly);
|
||||
wMenu->addAction(mFollowDump);
|
||||
wMenu->addAction(mYara);
|
||||
wMenu->addAction(mEntropy);
|
||||
wMenu->addAction(mSwitchView);
|
||||
wMenu->addSeparator();
|
||||
wMenu->addAction(mPageMemoryRights);
|
||||
|
|
@ -400,3 +406,19 @@ void MemoryMapView::switchView()
|
|||
setTableOffset(0);
|
||||
stateChangedSlot(paused);
|
||||
}
|
||||
|
||||
void MemoryMapView::entropy()
|
||||
{
|
||||
uint_t addr = getCellContent(getInitialSelection(), 0).toULongLong(0, 16);
|
||||
uint_t size = getCellContent(getInitialSelection(), 1).toULongLong(0, 16);
|
||||
unsigned char* data = new unsigned char[size];
|
||||
DbgMemRead(addr, data, size);
|
||||
|
||||
EntropyDialog entropyDialog(this);
|
||||
entropyDialog.setWindowTitle(QString().sprintf("Entropy (Address: %p, Size: %p)", addr, size));
|
||||
entropyDialog.show();
|
||||
entropyDialog.GraphMemory(data, size);
|
||||
entropyDialog.exec();
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public slots:
|
|||
void switchView();
|
||||
void pageMemoryRights();
|
||||
void refreshMap();
|
||||
void entropy();
|
||||
|
||||
private:
|
||||
QString getProtectionString(DWORD Protect);
|
||||
|
|
@ -55,7 +56,7 @@ private:
|
|||
QAction* mMemoryExecuteRestore;
|
||||
QAction* mMemoryRemove;
|
||||
QAction* mMemoryExecuteSingleshootToggle;
|
||||
|
||||
QAction* mEntropy;
|
||||
};
|
||||
|
||||
#endif // MEMORYMAPVIEW_H
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "Bridge.h"
|
||||
#include "YaraRuleSelectionDialog.h"
|
||||
#include "EntropyDialog.h"
|
||||
|
||||
SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView)
|
||||
{
|
||||
|
|
@ -127,6 +128,9 @@ void SymbolView::setupContextMenu()
|
|||
mYaraAction = new QAction(QIcon(":/icons/images/yara.png"), "&Yara...", this);
|
||||
connect(mYaraAction, SIGNAL(triggered()), this, SLOT(moduleYara()));
|
||||
|
||||
mEntropyAction = new QAction(QIcon(":/icons/images/entropy.png"), "Entropy...", this);
|
||||
connect(mEntropyAction, SIGNAL(triggered()), this, SLOT(moduleEntropy()));
|
||||
|
||||
//Shortcuts
|
||||
refreshShortcutsSlot();
|
||||
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot()));
|
||||
|
|
@ -249,6 +253,7 @@ void SymbolView::moduleContextMenu(const QPoint & pos)
|
|||
if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
wMenu->addAction(mCopyPathAction);
|
||||
wMenu->addAction(mYaraAction);
|
||||
wMenu->addAction(mEntropyAction);
|
||||
QMenu wCopyMenu("&Copy", this);
|
||||
mModuleList->setupCopyMenu(&wCopyMenu);
|
||||
if(wCopyMenu.actions().length())
|
||||
|
|
@ -359,3 +364,17 @@ void SymbolView::toggleBookmark()
|
|||
}
|
||||
GuiUpdateAllViews();
|
||||
}
|
||||
|
||||
void SymbolView::moduleEntropy()
|
||||
{
|
||||
int_t modbase = DbgValFromString(mModuleList->getCellContent(mModuleList->getInitialSelection(), 0).toUtf8().constData());
|
||||
char szModPath[MAX_PATH] = "";
|
||||
if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
{
|
||||
EntropyDialog entropyDialog(this);
|
||||
entropyDialog.setWindowTitle(QString("Entropy (%1)").arg(mModuleList->getCellContent(mModuleList->getInitialSelection(), 1)));
|
||||
entropyDialog.show();
|
||||
entropyDialog.GraphFile(QString(szModPath));
|
||||
entropyDialog.exec();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ private slots:
|
|||
void toggleBreakpoint();
|
||||
void toggleBookmark();
|
||||
void refreshShortcutsSlot();
|
||||
void moduleEntropy();
|
||||
|
||||
signals:
|
||||
void showCpu();
|
||||
|
|
@ -61,6 +62,7 @@ private:
|
|||
QAction* mDownloadAllSymbolsAction;
|
||||
QAction* mCopyPathAction;
|
||||
QAction* mYaraAction;
|
||||
QAction* mEntropyAction;
|
||||
|
||||
static void cbSymbolEnum(SYMBOLINFO* symbol, void* user);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef ENTROPY_H
|
||||
#define ENTROPY_H
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
class Entropy
|
||||
{
|
||||
public:
|
||||
static double MeasureData(const unsigned char* data, int dataSize)
|
||||
{
|
||||
int occurrences[256] = {};
|
||||
for(int i = 0; i < dataSize; i++)
|
||||
occurrences[data[i]]++;
|
||||
double entropy = 0.0;
|
||||
double logBase = log(256);
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
if(occurrences[i] == 0)
|
||||
continue;
|
||||
double p = (double)occurrences[i] / (double)dataSize;
|
||||
entropy += p * log(p) / logBase;
|
||||
}
|
||||
return -entropy;
|
||||
}
|
||||
|
||||
static double MeasureByte(const unsigned char* data, int dataSize, int index, unsigned char* block, int blockSize)
|
||||
{
|
||||
if(dataSize < blockSize)
|
||||
return -1;
|
||||
int start = index - blockSize / 2;
|
||||
int end = index + blockSize / 2;
|
||||
if(start < 0)
|
||||
{
|
||||
end += -start;
|
||||
start = 0;
|
||||
}
|
||||
else if(end > dataSize)
|
||||
{
|
||||
start -= end - dataSize;
|
||||
end = dataSize;
|
||||
}
|
||||
for(int i = start; i < end; i++)
|
||||
block[i - start] = data[i];
|
||||
return MeasureData(block, blockSize);
|
||||
}
|
||||
|
||||
static void MeasurePoints(const unsigned char* data, int dataSize, int blockSize, std::vector<double> & points, int pointCount)
|
||||
{
|
||||
points.clear();
|
||||
if(dataSize < pointCount)
|
||||
return;
|
||||
if(dataSize % pointCount != 0)
|
||||
pointCount += dataSize % pointCount;
|
||||
|
||||
unsigned char* block = new unsigned char[blockSize];
|
||||
int interval = dataSize / pointCount;
|
||||
points.reserve(pointCount);
|
||||
for(int i = 0; i < dataSize; i += interval)
|
||||
points.push_back(MeasureByte(data, dataSize, i, block, blockSize));
|
||||
delete[] block;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ENTROPY_H
|
||||
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include "QEntropyView.h"
|
||||
#include <QFile>
|
||||
#include "Entropy.h"
|
||||
|
||||
QEntropyView::QEntropyView(QWidget* parent) : QGraphicsView(parent)
|
||||
{
|
||||
mScene = new QGraphicsScene(this);
|
||||
}
|
||||
|
||||
void QEntropyView::InitializeGraph(int penSize)
|
||||
{
|
||||
//initialize scene
|
||||
qreal width = this->width() - 5;
|
||||
qreal height = this->height() - 5;
|
||||
mRect = QRectF(25, 10, width - 35, height - 20);
|
||||
mPenSize = penSize;
|
||||
mScene->clear();
|
||||
|
||||
//draw bounding box
|
||||
mScene->addRect(QRectF(1, 1, width, height), QPen(Qt::black));
|
||||
|
||||
//draw scale
|
||||
mScene->addLine(15, mRect.top(), 15, mRect.bottom(), QPen(Qt::black, 2));
|
||||
const int xBegin = 10;
|
||||
const int xEnd = 20;
|
||||
qreal intervalY = mRect.height() / 10;
|
||||
for(int i = 0; i < 11; i++)
|
||||
{
|
||||
qreal y = mRect.top() + i * intervalY;
|
||||
mScene->addLine(xBegin, y, xEnd, y, QPen(Qt::black, 2));
|
||||
}
|
||||
|
||||
//set scene
|
||||
setRenderHints(QPainter::Antialiasing);
|
||||
setScene(mScene);
|
||||
}
|
||||
|
||||
void QEntropyView::AddGraph(const std::vector<double> & points, QColor color)
|
||||
{
|
||||
int pointCount = (int)points.size();
|
||||
if(!pointCount)
|
||||
return;
|
||||
qreal intervalX = mRect.width() / ((qreal)pointCount - 1);
|
||||
qreal intervalY = mRect.height() / 1;
|
||||
QPolygonF polyLine;
|
||||
for(int i = 0; i < pointCount; i++)
|
||||
{
|
||||
qreal x = i * intervalX;
|
||||
qreal y = points[i] * intervalY;
|
||||
QPointF point(mRect.x() + x, mRect.bottom() - y); //y direction is inverted...
|
||||
polyLine.append(point);
|
||||
}
|
||||
QPainterPath path;
|
||||
path.addPolygon(polyLine);
|
||||
mScene->addPath(path, QPen(color, mPenSize));
|
||||
}
|
||||
|
||||
void QEntropyView::GraphFile(const QString & fileName, int blockSize, int pointCount, QColor color)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if(!file.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
|
||||
QByteArray fileData = file.readAll();
|
||||
file.close();
|
||||
|
||||
GraphMemory((unsigned char*)fileData.constData(), fileData.size(), blockSize, pointCount, color);
|
||||
}
|
||||
|
||||
void QEntropyView::GraphMemory(const unsigned char* data, int dataSize, int blockSize, int pointCount, QColor color)
|
||||
{
|
||||
std::vector<double> points;
|
||||
if(dataSize < blockSize)
|
||||
{
|
||||
blockSize = dataSize / 2;
|
||||
if(!blockSize)
|
||||
blockSize = 1;
|
||||
}
|
||||
if(dataSize < pointCount)
|
||||
pointCount = (int)dataSize;
|
||||
Entropy::MeasurePoints(data, dataSize, blockSize, points, pointCount);
|
||||
AddGraph(points, color);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef QENTROPYVIEW_H
|
||||
#define QENTROPYVIEW_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsScene>
|
||||
|
||||
class QEntropyView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QEntropyView(QWidget* parent = 0);
|
||||
void InitializeGraph(int penSize = 1);
|
||||
void AddGraph(const std::vector<double> & points, QColor color = Qt::black);
|
||||
void GraphFile(const QString & fileName, int blockSize, int pointCount, QColor = Qt::black);
|
||||
void GraphMemory(const unsigned char* data, int dataSize, int blockSize, int pointCount, QColor = Qt::black);
|
||||
|
||||
private:
|
||||
QGraphicsScene* mScene;
|
||||
QRectF mRect;
|
||||
int mPenSize;
|
||||
};
|
||||
|
||||
#endif // QENTROPYVIEW_H
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 659 B |
|
|
@ -62,5 +62,6 @@
|
|||
<file>images/highlight.png</file>
|
||||
<file>images/label.png</file>
|
||||
<file>images/snowman.png</file>
|
||||
<file>images/entropy.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,9 @@ SOURCES += \
|
|||
Src/Utils/ValidateExpressionThread.cpp \
|
||||
Src/Utils/MainWindowCloseThread.cpp \
|
||||
Src/Gui/TimeWastedCounter.cpp \
|
||||
Src/Utils/FlickerThread.cpp
|
||||
Src/Utils/FlickerThread.cpp \
|
||||
Src/QEntropyView/QEntropyView.cpp \
|
||||
Src/Gui/EntropyDialog.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
|
@ -168,7 +170,10 @@ HEADERS += \
|
|||
Src/Utils/ValidateExpressionThread.h \
|
||||
Src/Utils/MainWindowCloseThread.h \
|
||||
Src/Gui/TimeWastedCounter.h \
|
||||
Src/Utils/FlickerThread.h
|
||||
Src/Utils/FlickerThread.h \
|
||||
Src/QEntropyView/Entropy.h \
|
||||
Src/QEntropyView/QEntropyView.h \
|
||||
Src/Gui/EntropyDialog.h
|
||||
|
||||
|
||||
INCLUDEPATH += \
|
||||
|
|
@ -205,7 +210,8 @@ FORMS += \
|
|||
Src/Gui/PageMemoryRights.ui \
|
||||
Src/Gui/SelectFields.ui \
|
||||
Src/Gui/YaraRuleSelectionDialog.ui \
|
||||
Src/Gui/DataCopyDialog.ui
|
||||
Src/Gui/DataCopyDialog.ui \
|
||||
Src/Gui/EntropyDialog.ui
|
||||
|
||||
INCLUDEPATH += $$PWD/Src/Bridge
|
||||
INCLUDEPATH += $$PWD/Src/ThirdPartyLibs/snowman
|
||||
|
|
|
|||
Loading…
Reference in New Issue