import math import threading from PySide2.QtWidgets import QWidget from PySide2.QtGui import QImage, QColor, QPainter from PySide2.QtCore import Qt, QSize, QTimer import binaryninjaui from binaryninjaui import ViewFrame, UIContext from binaryninja.enums import ThemeColor class EntropyThread(threading.Thread): def __init__(self, data, image, block_size): super(EntropyThread, self).__init__() self.data = data self.image = image self.block_size = block_size self.updated = False def run(self): width = self.image.width() for i in range(0, width): v = int(self.data.get_entropy(self.data.start + i * self.block_size, self.block_size)[0] * 255) if v >= 240: color = binaryninjaui.getThemeColor(ThemeColor.YellowStandardHighlightColor) self.image.setPixelColor(i, 0, color) else: baseColor = binaryninjaui.getThemeColor(ThemeColor.FeatureMapBaseColor) entropyColor = binaryninjaui.getThemeColor(ThemeColor.BlueStandardHighlightColor) color = binaryninjaui.mixColor(baseColor, entropyColor, v) self.image.setPixelColor(i, 0, color) self.updated = True class EntropyWidget(QWidget): def __init__(self, parent, view, data): super(EntropyWidget, self).__init__(parent) self.view = view self.data = data self.raw_data = data.file.raw self.block_size = (len(self.raw_data) / 4096) + 1 if self.block_size < 1024: self.block_size = 1024 self.width = int(len(self.raw_data) / self.block_size) self.image = QImage(self.width, 1, QImage.Format_ARGB32) self.image.fill(QColor(0, 0, 0, 0)) self.thread = EntropyThread(self.raw_data, self.image, self.block_size) self.started = False self.timer = QTimer() self.timer.timeout.connect(self.timerEvent) self.timer.setInterval(100) self.timer.setSingleShot(False) self.timer.start() self.setMinimumHeight(UIContext.getScaledWindowSize(32, 32).height()) def paintEvent(self, event): p = QPainter(self) p.drawImage(self.rect(), self.image) p.drawRect(self.rect()) def sizeHint(self): return QSize(640, 32) def timerEvent(self): if not self.started: self.thread.start() self.started = True if self.thread.updated: self.thread.updated = False self.update() def mousePressEvent(self, event): if event.button() != Qt.LeftButton: return frac = float(event.x()) / self.rect().width() offset = int(frac * self.width * self.block_size) self.view.navigateToFileOffset(offset)