Commit 2a4606e4 by Craig Heffner

Initial switch from pyqtgraph to matplotlib for graphing features

parent 20dfcf86
...@@ -38,11 +38,11 @@ then ...@@ -38,11 +38,11 @@ then
else else
APT_CANDIDATES="git build-essential libqt4-opengl mtd-utils gzip bzip2 tar arj lhasa p7zip p7zip-full cabextract cramfsprogs cramfsswap squashfs-tools zlib1g-dev liblzma-dev liblzo2-dev sleuthkit default-jdk lzop srecord" APT_CANDIDATES="git build-essential libqt4-opengl mtd-utils gzip bzip2 tar arj lhasa p7zip p7zip-full cabextract cramfsprogs cramfsswap squashfs-tools zlib1g-dev liblzma-dev liblzo2-dev sleuthkit default-jdk lzop srecord"
fi fi
PYTHON2_APT_CANDIDATES="python-crypto python-lzo python-lzma python-pip python-opengl python-qt4 python-qt4-gl python-numpy python-scipy" PYTHON2_APT_CANDIDATES="python-crypto python-lzo python-lzma python-pip"
PYTHON3_APT_CANDIDATES="python3-crypto python3-pip python3-opengl python3-pyqt4 python3-pyqt4.qtopengl python3-numpy python3-scipy" PYTHON3_APT_CANDIDATES="python3-crypto python3-pip"
PYTHON3_YUM_CANDIDATES="" PYTHON3_YUM_CANDIDATES=""
YUM_CANDIDATES="git gcc gcc-c++ make openssl-devel qtwebkit-devel qt-devel gzip bzip2 tar arj p7zip p7zip-plugins cabextract squashfs-tools zlib zlib-devel lzo lzo-devel xz xz-compat-libs xz-libs xz-devel xz-lzma-compat python-backports-lzma lzip pyliblzma perl-Compress-Raw-Lzma lzop srecord" YUM_CANDIDATES="git gcc gcc-c++ make openssl-devel qtwebkit-devel qt-devel gzip bzip2 tar arj p7zip p7zip-plugins cabextract squashfs-tools zlib zlib-devel lzo lzo-devel xz xz-compat-libs xz-libs xz-devel xz-lzma-compat python-backports-lzma lzip pyliblzma perl-Compress-Raw-Lzma lzop srecord"
PYTHON2_YUM_CANDIDATES="python-pip python-opengl python-qt4 numpy python-numdisplay numpy-2f python-Bottleneck scipy" PYTHON2_YUM_CANDIDATES="python-pip python-Bottleneck"
APT_CANDIDATES="$APT_CANDIDATES $PYTHON2_APT_CANDIDATES" APT_CANDIDATES="$APT_CANDIDATES $PYTHON2_APT_CANDIDATES"
YUM_CANDIDATES="$YUM_CANDIDATES $PYTHON2_YUM_CANDIDATES" YUM_CANDIDATES="$YUM_CANDIDATES $PYTHON2_YUM_CANDIDATES"
PIP_COMMANDS="pip" PIP_COMMANDS="pip"
...@@ -226,7 +226,7 @@ if [ $? -ne 0 ] ...@@ -226,7 +226,7 @@ if [ $? -ne 0 ]
echo "Package installation failed: $PKG_CANDIDATES" echo "Package installation failed: $PKG_CANDIDATES"
exit 1 exit 1
fi fi
install_pip_package pyqtgraph install_pip_package matplotlib
install_pip_package capstone install_pip_package capstone
install_sasquatch install_sasquatch
install_yaffshiv install_yaffshiv
......
...@@ -120,19 +120,15 @@ class Entropy(Module): ...@@ -120,19 +120,15 @@ class Entropy(Module):
print ("FUck it all.") print ("FUck it all.")
def run(self): def run(self):
# If generating a graphical plot, this function will never return, as it invokes
# pg.exit. Calling pg.exit is pretty much required, but pg.exit calls os._exit in
# order to work around QT cleanup issues.
self._run() self._run()
def _run(self): def _run(self):
# Sanity check and warning if pyqtgraph isn't found # Sanity check and warning if matplotlib isn't found
if self.do_plot: if self.do_plot:
try: try:
import pyqtgraph as pg import matplotlib.pyplot as plt
except ImportError as e: except ImportError as e:
binwalk.core.common.warning( binwalk.core.common.warning("Failed to import matplotlib module, visual entropy graphing will be disabled")
"Failed to import pyqtgraph module, visual entropy graphing will be disabled")
self.do_plot = False self.do_plot = False
for fp in iter(self.next_file, None): for fp in iter(self.next_file, None):
...@@ -145,12 +141,6 @@ class Entropy(Module): ...@@ -145,12 +141,6 @@ class Entropy(Module):
if self.display_results: if self.display_results:
self.footer() self.footer()
if self.do_plot:
if not self.save_plot:
from pyqtgraph.Qt import QtGui
QtGui.QApplication.instance().exec_()
pg.exit()
def calculate_file_entropy(self, fp): def calculate_file_entropy(self, fp):
# Tracks the last displayed rising/falling edge (0 for falling, 1 for # Tracks the last displayed rising/falling edge (0 for falling, 1 for
# rising, None if nothing has been printed yet) # rising, None if nothing has been printed yet)
...@@ -260,9 +250,7 @@ class Entropy(Module): ...@@ -260,9 +250,7 @@ class Entropy(Module):
def plot_entropy(self, fname): def plot_entropy(self, fname):
try: try:
import numpy as np import matplotlib.pyplot as plt
import pyqtgraph as pg
import pyqtgraph.exporters as exporters
except ImportError as e: except ImportError as e:
return return
...@@ -275,54 +263,60 @@ class Entropy(Module): ...@@ -275,54 +263,60 @@ class Entropy(Module):
x.append(r.offset) x.append(r.offset)
y.append(r.entropy) y.append(r.entropy)
plt = pg.plot(title=fname, clear=True) fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, autoscale_on=True)
ax.set_title(fname)
ax.set_xlabel(self.XLABEL)
ax.set_ylabel(self.YLABEL)
ax.plot(x, y)
# Disable auto-ranging of the Y (entropy) axis, as it if self.save_plot:
# can cause some very un-intuitive graphs, particularly out_file = os.path.join(os.getcwd(), os.path.basename(fname)) + '.png'
# for files with only high-entropy data. fig.savefig(out_file)
plt.setYRange(0, 1) else:
plt.show()
if self.show_legend and has_key(self.file_markers, fname): #if self.show_legend and has_key(self.file_markers, fname):
plt.addLegend(size=(self.max_description_length * 10, 0)) # plt.addLegend(size=(self.max_description_length * 10, 0))
for (offset, description) in self.file_markers[fname]: # for (offset, description) in self.file_markers[fname]:
# If this description has already been plotted at a different offset, we need to # If this description has already been plotted at a different offset, we need to
# use the same color for the marker, but set the description to None to prevent # use the same color for the marker, but set the description to None to prevent
# duplicate entries in the graph legend. # duplicate entries in the graph legend.
# #
# Else, get the next color and use it to mark descriptions of # Else, get the next color and use it to mark descriptions of
# this type. # this type.
if has_key(plotted_colors, description): # if has_key(plotted_colors, description):
color = plotted_colors[description] # color = plotted_colors[description]
description = None # description = None
else: # else:
color = self.COLORS[i] # color = self.COLORS[i]
plotted_colors[description] = color # plotted_colors[description] = color
i += 1 # i += 1
if i >= len(self.COLORS): # if i >= len(self.COLORS):
i = 0 # i = 0
plt.plot(x=[offset, offset], y=[0, 1.1], # plt.plot(x=[offset, offset], y=[0, 1.1],
name=description, pen=pg.mkPen(color, width=2.5)) # name=description, pen=pg.mkPen(color, width=2.5))
# Plot data points # Plot data points
plt.plot(x, y, pen='y') #plt.plot(x, y, pen='y')
# TODO: legend is not displayed properly when saving plots to disk # TODO: legend is not displayed properly when saving plots to disk
if self.save_plot: #if self.save_plot:
# Save graph to CWD # Save graph to CWD
out_file = os.path.join(os.getcwd(), os.path.basename(fname)) # out_file = os.path.join(os.getcwd(), os.path.basename(fname))
# exporters.ImageExporter is different in different versions of # exporters.ImageExporter is different in different versions of
# pyqtgraph # pyqtgraph
try: # try:
exporter = exporters.ImageExporter(plt.plotItem) # exporter = exporters.ImageExporter(plt.plotItem)
except TypeError: # except TypeError:
exporter = exporters.ImageExporter.ImageExporter(plt.plotItem) # exporter = exporters.ImageExporter.ImageExporter(plt.plotItem)
exporter.parameters()['width'] = self.FILE_WIDTH # exporter.parameters()['width'] = self.FILE_WIDTH
exporter.export( # exporter.export(
binwalk.core.common.unique_file_name(out_file, self.FILE_FORMAT)) # binwalk.core.common.unique_file_name(out_file, self.FILE_FORMAT))
else: #else:
plt.setLabel('left', self.YLABEL, units=self.YUNITS) # plt.setLabel('left', self.YLABEL, units=self.YUNITS)
plt.setLabel('bottom', self.XLABEL, units=self.XUNITS) # plt.setLabel('bottom', self.XLABEL, units=self.XUNITS)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment