diff options
| author | Jordan Wiens <github@psifertex.com> | 2026-01-01 12:21:22 -0500 |
|---|---|---|
| committer | Jordan Wiens <github@psifertex.com> | 2026-01-01 12:21:22 -0500 |
| commit | 37a0604d805991b85a0590279ad993a19ddee7bb (patch) | |
| tree | fa8054497a4761f134ab5b537dfb0dbfc9a64f32 /examples/triage | |
| parent | 2448131059638409902821451115872036230328 (diff) | |
add whole-file entropy calculation to triage
Diffstat (limited to 'examples/triage')
| -rw-r--r-- | examples/triage/entropy.cpp | 30 | ||||
| -rw-r--r-- | examples/triage/entropy.h | 11 | ||||
| -rw-r--r-- | examples/triage/fileinfo.cpp | 26 | ||||
| -rw-r--r-- | examples/triage/fileinfo.h | 10 | ||||
| -rw-r--r-- | examples/triage/view.cpp | 5 | ||||
| -rw-r--r-- | examples/triage/view.h | 2 |
6 files changed, 79 insertions, 5 deletions
diff --git a/examples/triage/entropy.cpp b/examples/triage/entropy.cpp index da089fd6..dd643af7 100644 --- a/examples/triage/entropy.cpp +++ b/examples/triage/entropy.cpp @@ -12,6 +12,8 @@ EntropyThread::EntropyThread(BinaryViewRef data, size_t blockSize, QImage* image m_blockSize = blockSize; m_updated = false; m_running = true; + m_averageEntropy = 0.0; + m_sampleCount = 0; m_thread = std::thread([=, this]() { Run(); }); } @@ -33,10 +35,22 @@ void EntropyThread::Run() std::vector<float> entropy = m_data->GetEntropy(m_data->GetStart() + ((uint64_t)i * m_blockSize), m_blockSize, m_blockSize); int v; + float entropyValue = 0.0f; if (entropy.size() == 0) v = 0; else - v = (int)(entropy[0] * 255); + { + entropyValue = entropy[0]; + v = (int)(entropyValue * 255); + } + + // Update running average + { + std::lock_guard<std::mutex> lock(m_mutex); + m_sampleCount++; + m_averageEntropy += (entropyValue - m_averageEntropy) / m_sampleCount; + } + if (v >= 240) { QColor color = getThemeColor(YellowStandardHighlightColor); @@ -54,6 +68,13 @@ void EntropyThread::Run() } +double EntropyThread::GetAverageEntropy() const +{ + std::lock_guard<std::mutex> lock(m_mutex); + return m_averageEntropy; +} + + EntropyWidget::EntropyWidget(QWidget* parent, TriageView* view, BinaryViewRef data) : QWidget(parent) { m_view = view; @@ -106,6 +127,7 @@ void EntropyWidget::timerExpired() { m_thread->ResetUpdated(); update(); + emit entropyUpdated(m_thread->GetAverageEntropy()); } } @@ -131,3 +153,9 @@ void EntropyWidget::mouseMoveEvent(QMouseEvent* event) else setToolTip(QString("File offset: 0x%1").arg(offset, 0, 16)); } + + +double EntropyWidget::getAverageEntropy() const +{ + return m_thread->GetAverageEntropy(); +} diff --git a/examples/triage/entropy.h b/examples/triage/entropy.h index 821dfb7b..bd50081d 100644 --- a/examples/triage/entropy.h +++ b/examples/triage/entropy.h @@ -3,6 +3,7 @@ #include <QtWidgets/QWidget> #include <QtGui/QImage> #include <thread> +#include <mutex> #include "uitypes.h" @@ -13,6 +14,9 @@ class EntropyThread size_t m_blockSize; bool m_updated, m_running; std::thread m_thread; + double m_averageEntropy; + int m_sampleCount; + mutable std::mutex m_mutex; public: EntropyThread(BinaryViewRef data, size_t blockSize, QImage* image); @@ -21,6 +25,7 @@ class EntropyThread void Run(); bool IsUpdated() { return m_updated; } void ResetUpdated() { m_updated = false; } + double GetAverageEntropy() const; }; @@ -28,6 +33,8 @@ class TriageView; class EntropyWidget : public QWidget { + Q_OBJECT + TriageView* m_view; BinaryViewRef m_data, m_rawData; size_t m_blockSize; @@ -40,6 +47,10 @@ class EntropyWidget : public QWidget virtual ~EntropyWidget(); virtual QSize sizeHint() const override; + double getAverageEntropy() const; + + Q_SIGNALS: + void entropyUpdated(double avgEntropy); protected: virtual void paintEvent(QPaintEvent* event) override; diff --git a/examples/triage/fileinfo.cpp b/examples/triage/fileinfo.cpp index e18c94d8..22ce2423 100644 --- a/examples/triage/fileinfo.cpp +++ b/examples/triage/fileinfo.cpp @@ -1,4 +1,5 @@ #include "fileinfo.h" +#include "entropy.h" #include "fontsettings.h" #include "theme.h" #include "copyablelabel.h" @@ -129,7 +130,7 @@ void FileInfoWidget::addHashFields(BinaryViewRef view) }); } -FileInfoWidget::FileInfoWidget(QWidget* parent, BinaryViewRef bv) +FileInfoWidget::FileInfoWidget(QWidget* parent, BinaryViewRef bv, EntropyWidget* entropyWidget) { this->m_layout = new QGridLayout(); this->m_layout->setContentsMargins(0, 0, 0, 0); @@ -157,10 +158,33 @@ FileInfoWidget::FileInfoWidget(QWidget* parent, BinaryViewRef bv) const auto fileSize = QString::number(view->GetLength(), 16).prepend("0x"); this->addCopyableField("Size: ", fileSize); + // Display entropy value from the entropy widget + if (entropyWidget) + { + auto& [row, column] = this->m_fieldPosition; + m_entropyLabel = new CopyableLabel("Calculating...", getThemeColor(AlphanumericHighlightColor)); + m_entropyLabel->setFont(getMonospaceFont(this)); + this->m_layout->addWidget(new QLabel("Entropy: "), row, column); + this->m_layout->addWidget(m_entropyLabel, row++, column + 1); + + // Connect to entropy updates + connect(entropyWidget, &EntropyWidget::entropyUpdated, this, &FileInfoWidget::updateEntropy); + } + this->addHashFields(view); const auto scaledWidth = UIContext::getScaledWindowSize(20, 20).width(); this->m_layout->setColumnMinimumWidth(FileInfoWidget::m_maxColumns * 3 - 1, scaledWidth); this->m_layout->setColumnStretch(FileInfoWidget::m_maxColumns * 3 - 1, 1); setLayout(this->m_layout); +} + + +void FileInfoWidget::updateEntropy(double avgEntropy) +{ + if (m_entropyLabel) + { + const auto entropyStr = QString::number(avgEntropy, 'f', 6); + m_entropyLabel->setText(entropyStr); + } }
\ No newline at end of file diff --git a/examples/triage/fileinfo.h b/examples/triage/fileinfo.h index 78ba578b..8eac3fbe 100644 --- a/examples/triage/fileinfo.h +++ b/examples/triage/fileinfo.h @@ -5,11 +5,16 @@ #include "uitypes.h" #include "viewframe.h" +class EntropyWidget; + class FileInfoWidget : public QWidget { + Q_OBJECT + static constexpr std::int32_t m_maxColumns {2}; std::pair<std::int32_t, std::int32_t> m_fieldPosition {}; // row, column QGridLayout* m_layout {}; + QLabel* m_entropyLabel {}; void addField(const QString& name, const QVariant& value); void addCopyableField(const QString& name, const QVariant& value); @@ -17,5 +22,8 @@ class FileInfoWidget : public QWidget void addHashFields(BinaryViewRef view); public: - FileInfoWidget(QWidget* parent, BinaryViewRef bv); + FileInfoWidget(QWidget* parent, BinaryViewRef bv, EntropyWidget* entropyWidget); + + private Q_SLOTS: + void updateEntropy(double avgEntropy); }; diff --git a/examples/triage/view.cpp b/examples/triage/view.cpp index 2c563470..0e995ae2 100644 --- a/examples/triage/view.cpp +++ b/examples/triage/view.cpp @@ -27,13 +27,14 @@ TriageView::TriageView(QWidget* parent, BinaryViewRef data) : QScrollArea(parent QGroupBox* entropyGroup = new QGroupBox("Entropy", container); QVBoxLayout* entropyLayout = new QVBoxLayout(); - entropyLayout->addWidget(new EntropyWidget(entropyGroup, this, m_data)); + m_entropyWidget = new EntropyWidget(entropyGroup, this, m_data); + entropyLayout->addWidget(m_entropyWidget); entropyGroup->setLayout(entropyLayout); layout->addWidget(entropyGroup); QGroupBox* fileInfoGroup = new QGroupBox("File Info", container); QVBoxLayout* fileInfoLayout = new QVBoxLayout(); - fileInfoLayout->addWidget(new FileInfoWidget(fileInfoGroup, m_data)); + fileInfoLayout->addWidget(new FileInfoWidget(fileInfoGroup, m_data, m_entropyWidget)); fileInfoGroup->setLayout(fileInfoLayout); layout->addWidget(fileInfoGroup); diff --git a/examples/triage/view.h b/examples/triage/view.h index ab4f1024..fc9c7ff3 100644 --- a/examples/triage/view.h +++ b/examples/triage/view.h @@ -7,6 +7,7 @@ class HeaderWidget; +class EntropyWidget; class TriageView : public QScrollArea, public View { @@ -16,6 +17,7 @@ class TriageView : public QScrollArea, public View QPushButton* m_fullAnalysisButton = nullptr; QSplitter* m_importExportSplitter = nullptr; HeaderWidget* m_headerWidget = nullptr; + EntropyWidget* m_entropyWidget = nullptr; public: TriageView(QWidget* parent, BinaryViewRef data); |
