Commit 578eeff2 by devttys0

Added preliminary entropy analysis module.

parent 7004a70b
......@@ -125,20 +125,24 @@ class Module(object):
DEPENDS = {'config' : 'Configuration', 'extractor' : 'Extractor'}
# Format string for printing the header during a scan
HEADER_FORMAT = "%s\n"
#HEADER_FORMAT = "%s\n"
HEADER_FORMAT = "%-12s %-12s %s\n"
# Format string for printing each result during a scan
RESULT_FORMAT = "%.8d %s\n"
#RESULT_FORMAT = "%.8d %s\n"
RESULT_FORMAT = "%-12d 0x%-12X %s\n"
# The header to print during a scan.
# Set to None to not print a header.
# Note that this will be formatted per the HEADER_FORMAT format string.
HEADER = ["OFFSET DESCRIPTION"]
#HEADER = ["OFFSET DESCRIPTION"]
HEADER = ["DECIMAL", "HEX", "DESCRIPTION"]
# The attribute names to print during a scan, as provided to the self.results method.
# Set to None to not print any results.
# Note that these will be formatted per the RESULT_FORMAT format string.
RESULT = ['offset', 'description']
#RESULT = ['offset', 'description']
RESULT = ["offset", "offset", "description"]
def __init__(self, dependency=False, **kwargs):
self.errors = []
......@@ -239,6 +243,15 @@ class Module(object):
return args
def clear(self, results=True, errors=True):
'''
Clears results and errors lists.
'''
if results:
self.results = []
if errors:
self.errors = []
def result(self, r=None, **kwargs):
'''
Validates a result, stores it in self.results and prints it.
......@@ -246,7 +259,7 @@ class Module(object):
@r - An existing instance of binwalk.core.module.Result.
Returns None.
Returns an instance of binwalk.core.module.Result.
'''
if r is None:
r = Result(**kwargs)
......@@ -278,6 +291,8 @@ class Module(object):
if display_args:
self.config.display.result(*display_args)
return r
def error(self, **kwargs):
'''
Stores the specified error in self.errors.
......
......@@ -4,3 +4,4 @@ from binwalk.modules.hexdiff import HexDiff
from binwalk.modules.hashmatch import HashMatch
from binwalk.modules.configuration import Configuration
from binwalk.modules.extractor import Extractor
from binwalk.modules.entropy import Entropy
import math
from binwalk.core.module import Module, Option, Kwarg
class Entropy(Module):
XLABEL = 'Offset'
YLABEL = 'Entropy'
XUNITS = 'B'
YUNITS = 'E'
TITLE = "Entropy"
CLI = [
Option(short='E',
long='entropy',
kwargs={'enabled' : True},
description='Calculate file entropy'),
]
KWARGS = [
Kwarg(name='enabled', default=False),
Kwarg(name='block_size', default=1024),
]
def init(self):
self.entropy_results = {}
self.algorithm = self.shannon
if self.config.block:
self.block_size = self.config.block
def run(self):
for fp in self.config.target_files:
self.header()
self.calculate_file_entropy(fp)
self.footer()
def calculate_file_entropy(self, fp):
# Clear results from any previously analyzed files
self.clear(results=True)
while True:
file_offset = fp.tell()
(data, dlen) = fp.read_block()
if not data:
break
i = 0
while i < dlen:
entropy = self.algorithm(data[i:i+self.block_size])
r = self.result(offset=(file_offset + i), file=fp, entropy=entropy, description=("%f" % entropy))
i += self.block_size
self.plot_entropy(fp.name)
def shannon(self, data):
'''
Performs a Shannon entropy analysis on a given block of data.
'''
entropy = 0
if data:
for x in range(0, 256):
p_x = float(data.count(chr(x))) / len(data)
if p_x > 0:
entropy += - p_x*math.log(p_x, 2)
return (entropy / 8)
def gzip(self, data, truncate=True):
'''
Performs an entropy analysis based on zlib compression ratio.
This is faster than the shannon entropy analysis, but not as accurate.
'''
# Entropy is a simple ratio of: <zlib compressed size> / <original size>
e = float(float(len(zlib.compress(data, 9))) / float(len(data)))
if truncate and e > 1.0:
e = 1.0
return e
def plot_entropy(self, title):
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
x = []
y = []
for r in self.results:
x.append(r.offset)
y.append(r.entropy)
plt = pg.plot(title=title, clear=True)
plt.plot(x, y, pen='y') #pen='b'
plt.setLabel('left', self.YLABEL, units=self.YUNITS)
plt.setLabel('bottom', self.XLABEL, units=self.XUNITS)
QtGui.QApplication.instance().exec_()
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