Commit e9d9055a by devttys0

Restructured binwalk directory

parent 659126cb
from binwalk.module import Modules
from binwalk.core.module import Modules
# Contains all the command line options and usage output for the binwlak script.
# Placed here so that other scripts can programmatically access the command line options list (e.g., for auto-completion generation).
import os
import sys
import binwalk.config
short_options = "23AaBbCcdEeGHhIiJkLMNnOPpQqrSTtUuVvWwz?D:F:f:g:j:K:o:l:m:R:s:X:x:Y:y:Z:"
long_options = [
"2D",
"3D",
"3d",
"rm",
"help",
"green",
"red",
"blue",
"rehash",
"examples",
"quiet",
"csv",
"verbose",
"opcodes",
"cast",
"update",
"binwalk",
"keep-going",
"show-invalid",
"show-grids",
"ignore-time-skew",
"honor-footers",
"profile",
"delay", # delay is depreciated, but kept for backwards compatability
"skip-unopened",
"term",
"tim",
"terse",
"diff",
"dumb",
"entropy",
"heuristic",
"math",
"gzip",
"save-plot",
"no-plot",
"no-legend",
"strings",
"carve",
"max-points=",
"matryoshka=",
"list-plugins",
"disable-plugins",
"disable-plugin=",
"enable-plugin=",
"max-size=",
"marker=",
"strlen=",
"file=",
"block=",
"offset=",
"length=",
"exclude=",
"include=",
"search=",
"extract=",
"dd=",
"grep=",
"magic=",
"raw-bytes=",
]
def usage(fd):
fd.write("\n")
fd.write("Binwalk v%s\n" % binwalk.config.Config.VERSION)
fd.write("Craig Heffner, http://www.devttys0.com\n")
fd.write("\n")
fd.write("Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n" % os.path.basename(sys.argv[0]))
fd.write("\n")
fd.write("Signature Analysis:\n")
fd.write("\t-B, --binwalk Perform a file signature scan (default)\n")
fd.write("\t-R, --raw-bytes=<string> Search for a custom signature\n")
fd.write("\t-A, --opcodes Scan for executable code signatures\n")
fd.write("\t-C, --cast Cast file contents as various data types\n")
fd.write("\t-m, --magic=<file> Specify an alternate magic file to use\n")
fd.write("\t-x, --exclude=<filter> Exclude matches that have <filter> in their description\n")
fd.write("\t-y, --include=<filter> Only search for matches that have <filter> in their description\n")
fd.write("\t-I, --show-invalid Show results marked as invalid\n")
fd.write("\t-T, --ignore-time-skew Do not show results that have timestamps more than 1 year in the future\n")
fd.write("\t-k, --keep-going Show all matching results at a given offset, not just the first one\n")
fd.write("\t-b, --dumb Disable smart signature keywords\n")
fd.write("\n")
fd.write("Strings Analysis:\n")
fd.write("\t-S, --strings Scan for ASCII strings (may be combined with -B, -R, -A, or -E)\n")
fd.write("\t-s, --strlen=<n> Set the minimum string length to search for (default: 3)\n")
fd.write("\n")
fd.write("Entropy Analysis:\n")
fd.write("\t-E, --entropy Plot file entropy (may be combined with -B, -R, -A, or -S)\n")
fd.write("\t-H, --heuristic Identify unknown compression/encryption based on entropy heuristics (implies -E)\n")
fd.write("\t-K, --block=<int> Set the block size for entropy analysis (default: %d)\n" % binwalk.entropy.FileEntropy.DEFAULT_BLOCK_SIZE)
fd.write("\t-a, --gzip Use gzip compression ratios to measure entropy\n")
fd.write("\t-N, --no-plot Do not generate an entropy plot graph\n")
fd.write("\t-F, --marker=<offset:name> Add a marker to the entropy plot graph\n")
fd.write("\t-Q, --no-legend Omit the legend from the entropy plot graph\n")
fd.write("\t-J, --save-plot Save plot as a PNG (implied if multiple files are specified)\n")
fd.write("\n")
fd.write("Binary Visualization:\n")
fd.write("\t-3, --3D Generate a 3D binary visualization\n")
fd.write("\t-2, --2D Project data points onto 3D cube walls only\n")
fd.write("\t-Z, --max-points Set the maximum number of plotted data points (defulat: %d)\n" % binwalk.plotter.Plotter.MAX_PLOT_POINTS)
fd.write("\t-V, --show-grids Display the x-y-z grids in the resulting plot\n")
fd.write("\n")
fd.write("Binary Diffing:\n")
fd.write("\t-W, --diff Hexdump / diff the specified files\n")
fd.write("\t-K, --block=<int> Number of bytes to display per line (default: %d)\n" % binwalk.hexdiff.HexDiff.DEFAULT_BLOCK_SIZE)
fd.write("\t-G, --green Only show hex dump lines that contain bytes which were the same in all files\n")
fd.write("\t-i, --red Only show hex dump lines that contain bytes which were different in all files\n")
fd.write("\t-U, --blue Only show hex dump lines that contain bytes which were different in some files\n")
fd.write("\t-w, --terse Diff all files, but only display a hex dump of the first file\n")
fd.write("\n")
fd.write("Extraction Options:\n")
fd.write("\t-D, --dd=<type:ext:cmd> Extract <type> signatures, give the files an extension of <ext>, and execute <cmd>\n")
fd.write("\t-e, --extract=[file] Automatically extract known file types; load rules from file, if specified\n")
fd.write("\t-M, --matryoshka=[n] Recursively scan extracted files, up to n levels deep (8 levels of recursion is the default)\n")
fd.write("\t-j, --max-size=<int> Limit extracted file sizes (default: no limit)\n")
fd.write("\t-r, --rm Cleanup extracted files and zero-size files\n")
fd.write("\t-d, --honor-footers Only extract files up to their corresponding footer signatures\n")
fd.write("\t-z, --carve Carve data from files, but don't execute extraction utilities (implies -d)\n")
fd.write("\t-P, --rehash Recursively diff data extracted from FILE1 with the data extracted from all other files.\n")
fd.write("\n")
fd.write("Plugin Options:\n")
fd.write("\t-X, --disable-plugin=<name> Disable a plugin by name\n")
fd.write("\t-Y, --enable-plugin=<name> Enable a plugin by name\n")
fd.write("\t-p, --disable-plugins Do not load any binwalk plugins\n")
fd.write("\t-L, --list-plugins List all user and system plugins by name\n")
fd.write("\n")
fd.write("General Options:\n")
fd.write("\t-o, --offset=<int> Start scan at this file offset\n")
fd.write("\t-l, --length=<int> Number of bytes to scan\n")
fd.write("\t-g, --grep=<text> Grep results for the specified text\n")
fd.write("\t-f, --file=<file> Log results to file\n")
fd.write("\t-c, --csv Log results to file in csv format\n")
fd.write("\t-O, --skip-unopened Ignore file open errors and process only the files that can be opened\n")
fd.write("\t-t, --term Format output to fit the terminal window\n")
fd.write("\t-q, --quiet Suppress output to stdout\n")
fd.write("\t-v, --verbose Be verbose (specify twice for very verbose)\n")
fd.write("\t-u, --update Update magic signature files\n")
fd.write("\t-?, --examples Show example usage\n")
fd.write("\t-h, --help Show help output\n")
fd.write("\n")
if fd == sys.stderr:
sys.exit(1)
else:
sys.exit(0)
#!/usr/bin/env python
# Routines to perform Monte Carlo Pi approximation and Chi Squared tests.
# Used for fingerprinting unknown areas of high entropy (e.g., is this block of high entropy data compressed or encrypted?).
# Inspired by people who actually know what they're doing: http://www.fourmilab.ch/random/
import math
import binwalk.common as common
from binwalk.compat import *
class MonteCarloPi(object):
'''
Performs a Monte Carlo Pi approximation.
Currently unused.
'''
def __init__(self):
'''
Class constructor.
Returns None.
'''
self.reset()
def reset(self):
'''
Reset state to the beginning.
'''
self.pi = 0
self.error = 0
self.m = 0
self.n = 0
def update(self, data):
'''
Update the pi approximation with new data.
@data - A string of bytes to update (length must be >= 6).
Returns None.
'''
c = 0
dlen = len(data)
while (c+6) < dlen:
# Treat 3 bytes as an x coordinate, the next 3 bytes as a y coordinate.
# Our box is 1x1, so divide by 2^24 to put the x y values inside the box.
x = ((ord(data[c]) << 16) + (ord(data[c+1]) << 8) + ord(data[c+2])) / 16777216.0
c += 3
y = ((ord(data[c]) << 16) + (ord(data[c+1]) << 8) + ord(data[c+2])) / 16777216.0
c += 3
# Does the x,y point lie inside the circle inscribed within our box, with diameter == 1?
if ((x**2) + (y**2)) <= 1:
self.m += 1
self.n += 1
def montecarlo(self):
'''
Approximates the value of Pi based on the provided data.
Returns a tuple of (approximated value of pi, percent deviation).
'''
if self.n:
self.pi = (float(self.m) / float(self.n) * 4.0)
if self.pi:
self.error = math.fabs(1.0 - (math.pi / self.pi)) * 100.0
return (self.pi, self.error)
else:
return (0.0, 0.0)
class ChiSquare(object):
'''
Performs a Chi Squared test against the provided data.
'''
IDEAL = 256.0
def __init__(self):
'''
Class constructor.
Returns None.
'''
self.bytes = {}
self.freedom = self.IDEAL - 1
# Initialize the self.bytes dictionary with keys for all possible byte values (0 - 255)
for i in range(0, int(self.IDEAL)):
self.bytes[chr(i)] = 0
self.reset()
def reset(self):
self.xc2 = 0.0
self.byte_count = 0
for key in self.bytes.keys():
self.bytes[key] = 0
def update(self, data):
'''
Updates the current byte counts with new data.
@data - String of bytes to update.
Returns None.
'''
# Count the number of occurances of each byte value
for i in data:
self.bytes[i] += 1
self.byte_count += len(data)
def chisq(self):
'''
Calculate the Chi Square critical value.
Returns the critical value.
'''
expected = self.byte_count / self.IDEAL
if expected:
for byte in self.bytes.values():
self.xc2 += ((byte - expected) ** 2 ) / expected
return self.xc2
class CompressionEntropyAnalyzer(object):
'''
Class wrapper around ChiSquare.
Performs analysis and attempts to interpret the results.
'''
BLOCK_SIZE = 32
CHI_CUTOFF = 512
DESCRIPTION = "Statistical Compression Analysis"
def __init__(self, fname, start, length, binwalk=None):
'''
Class constructor.
@fname - The file to scan.
@start - The start offset to begin analysis at.
@length - The number of bytes to analyze.
@binwalk - Binwalk class object.
Returns None.
'''
self.fp = common.BlockFile(fname, 'r', offset=start, length=length)
# Read block size must be at least as large as our analysis block size
if self.fp.READ_BLOCK_SIZE < self.BLOCK_SIZE:
self.fp.READ_BLOCK_SIZE = self.BLOCK_SIZE
self.start = self.fp.offset
self.length = length
self.binwalk = binwalk
def __del__(self):
try:
self.fp.close()
except KeyboardInterrupt as e:
raise e
except Exception:
pass
def analyze(self):
'''
Perform analysis and interpretation.
Returns a descriptive string containing the results and attempted interpretation.
'''
i = 0
num_error = 0
analyzer_results = []
if self.binwalk:
self.binwalk.display.header(file_name=self.fp.name, description=self.DESCRIPTION)
chi = ChiSquare()
while i < self.length:
j = 0
(d, dlen) = self.fp.read_block()
while j < dlen:
chi.reset()
data = d[j:j+self.BLOCK_SIZE]
if len(data) < self.BLOCK_SIZE:
break
chi.update(data)
if chi.chisq() >= self.CHI_CUTOFF:
num_error += 1
j += self.BLOCK_SIZE
i += dlen
if num_error > 0:
verdict = 'Moderate entropy data, best guess: compressed'
else:
verdict = 'High entropy data, best guess: encrypted'
result = [{'offset' : self.start, 'description' : '%s, size: %d, %d low entropy blocks' % (verdict, self.length, num_error)}]
if self.binwalk:
self.binwalk.display.results(self.start, result)
self.binwalk.display.footer()
return result
......@@ -5,7 +5,7 @@ import re
import ast
import hashlib
import operator as op
from binwalk.compat import *
from binwalk.core.compat import *
# This allows other modules/scripts to subclass BlockFile from a custom class. Defaults to io.FileIO.
if has_key(__builtins__, 'BLOCK_FILE_PARENT_CLASS'):
......
import os
import binwalk.common as common
from binwalk.compat import *
import binwalk.core.common as common
from binwalk.core.compat import *
class Config:
'''
......@@ -117,7 +117,7 @@ class Config:
root = __file__
if os.path.islink(root):
root = os.path.realpath(root)
return os.path.dirname(os.path.abspath(root))
return os.path.dirname(os.path.dirname(os.path.abspath(root)))
except KeyboardInterrupt as e:
raise e
except Exception:
......
import re
import binwalk.common as common
from binwalk.smartsignature import SmartSignature
from binwalk.compat import *
import binwalk.core.common as common
from binwalk.core.smartsignature import SmartSignature
from binwalk.core.compat import *
class MagicFilter:
'''
......
......@@ -3,12 +3,12 @@ import os
import sys
import inspect
import argparse
import binwalk.common
import binwalk.config
import binwalk.plugin
from binwalk.compat import *
import binwalk.core.common
import binwalk.core.config
import binwalk.core.plugin
from binwalk.core.compat import *
class ModuleOption(object):
class Option(object):
'''
A container class that allows modules to declare command line options.
'''
......@@ -22,7 +22,7 @@ class ModuleOption(object):
@description - A description to be displayed in the help output.
@short - The short option to use (optional).
@long - The long option to use (if None, this option will not be displayed in help output).
@type - The accepted data type (one of: io.FileIO/argparse.FileType/binwalk.common.BlockFile, list, str, int, float).
@type - The accepted data type (one of: io.FileIO/argparse.FileType/binwalk.core.common.BlockFile, list, str, int, float).
@dtype - The displayed accepted type string, to be shown in help output.
Returns None.
......@@ -36,14 +36,14 @@ class ModuleOption(object):
self.dtype = str(dtype)
if not self.dtype:
if self.type in [io.FileIO, argparse.FileType, binwalk.common.BlockFile]:
if self.type in [io.FileIO, argparse.FileType, binwalk.core.common.BlockFile]:
self.dtype = 'file'
elif self.type in [int, float, str]:
self.dtype = self.type.__name__
else:
self.dtype = str.__name__
class ModuleKwarg(object):
class Kwarg(object):
'''
A container class allowing modules to specify their expected __init__ kwarg(s).
'''
......@@ -93,12 +93,12 @@ class Result(object):
class Error(Result):
'''
A subclass of binwalk.module.Result.
A subclass of binwalk.core.module.Result.
'''
def __init__(self, **kwargs):
'''
Accepts all the same kwargs as binwalk.module.Result, but the following are also added:
Accepts all the same kwargs as binwalk.core.module.Result, but the following are also added:
@exception - In case of an exception, this is the exception object.
......@@ -114,13 +114,13 @@ class Module(object):
# The module title, as displayed in help output
TITLE = ""
# A list of binwalk.module.ModuleOption command line options
# A list of binwalk.core.module.ModuleOption command line options
CLI = []
# A list of binwalk.module.ModuleKwargs accepted by __init__
# A list of binwalk.core.module.ModuleKwargs accepted by __init__
KWARGS = []
# A dictionary of module dependencies; all modules depend on binwalk.modules.configuration.Configuration
# A dictionary of module dependencies; all modules depend on binwalk.core.modules.configuration.Configuration
DEPENDS = {'config' : 'Configuration', 'extractor' : 'Extractor'}
# Format string for printing the header during a scan
......@@ -144,7 +144,7 @@ class Module(object):
self.results = []
self.status = None
self.name = self.__class__.__name__
self.plugins = binwalk.plugin.Plugins(self)
self.plugins = binwalk.core.plugin.Plugins(self)
process_kwargs(self, kwargs)
......@@ -187,11 +187,11 @@ class Module(object):
'''
return False
def process_result(self, r):
def callback(self, r):
'''
Processes the result. Passed to all dependency modules when a valid result is found.
Processes the result from all modules. Called for all dependency modules when a valid result is found.
@r - The result, an instance of binwalk.module.Result.
@r - The result, an instance of binwalk.core.module.Result.
Returns None.
'''
......@@ -202,7 +202,7 @@ class Module(object):
Validates the result.
May be overridden by the module sub-class.
@r - The result, an instance of binwalk.module.Result.
@r - The result, an instance of binwalk.core.module.Result.
Returns None.
'''
......@@ -235,9 +235,9 @@ class Module(object):
def result(self, r=None, **kwargs):
'''
Validates a result, stores it in self.results and prints it.
Accepts the same kwargs as the binwalk.module.Result class.
Accepts the same kwargs as the binwalk.core.module.Result class.
@r - An existing instance of binwalk.module.Result.
@r - An existing instance of binwalk.core.module.Result.
Returns None.
'''
......@@ -245,13 +245,14 @@ class Module(object):
r = Result(**kwargs)
self.validate(r)
for (attribute, module) in iterator(self.DEPENDS):
dependency = getattr(self, attribute)
dependency.callback(r)
self._plugins_result(r)
if r.valid:
for (attribute, module) in iterator(self.DEPENDS):
dependency = getattr(self, attribute)
dependency.process_result(r)
self.results.append(r)
# Update the progress status automatically if it is not being done manually by the module
......@@ -268,7 +269,7 @@ class Module(object):
'''
Stores the specified error in self.errors.
Accepts the same kwargs as the binwalk.module.Error class.
Accepts the same kwargs as the binwalk.core.module.Error class.
Returns None.
'''
......@@ -331,7 +332,10 @@ class Module(object):
return retval
class Status(object):
'''
Class used for tracking module status (e.g., % complete).
'''
def __init__(self, **kwargs):
self.kwargs = kwargs
self.clear()
......@@ -391,17 +395,17 @@ class Modules(object):
Returns a list of modules that contain the specified attribute.
'''
import binwalk.modules
import binwalk.core.modules
modules = []
for (name, module) in inspect.getmembers(binwalk.modules):
for (name, module) in inspect.getmembers(binwalk.core.modules):
if inspect.isclass(module) and hasattr(module, attribute):
modules.append(module)
return modules
def help(self):
help_string = "\nBinwalk v%s\nCraig Heffner, http://www.binwalk.org\n" % binwalk.config.Config.VERSION
help_string = "\nBinwalk v%s\nCraig Heffner, http://www.binwalk.core.org\n" % binwalk.core.config.Config.VERSION
for obj in self.list(attribute="CLI"):
if obj.CLI:
......@@ -449,7 +453,7 @@ class Modules(object):
def run(self, module):
obj = self.load(module)
if isinstance(obj, binwalk.module.Module) and obj.enabled:
if isinstance(obj, binwalk.core.module.Module) and obj.enabled:
obj.main(status=self.status)
self.status.clear()
......@@ -465,17 +469,17 @@ class Modules(object):
return module(**kwargs)
def dependencies(self, module):
import binwalk.modules
import binwalk.core.modules
kwargs = {}
if hasattr(module, "DEPENDS"):
for (kwarg, dependency) in iterator(module.DEPENDS):
# The dependency module must be imported by binwalk.modules.__init__.py
if hasattr(binwalk.modules, dependency):
dependency = getattr(binwalk.modules, dependency)
# The dependency module must be imported by binwalk.core.modules.__init__.py
if hasattr(binwalk.core.modules, dependency):
dependency = getattr(binwalk.core.modules, dependency)
else:
sys.stderr.write("WARNING: %s depends on %s which was not found in binwalk.modules.__init__.py\n" % (str(module), dependency))
sys.stderr.write("WARNING: %s depends on %s which was not found in binwalk.core.modules.__init__.py\n" % (str(module), dependency))
continue
# No recursive dependencies, thanks
......@@ -530,7 +534,7 @@ class Modules(object):
# Only add parsed options pertinent to the requested module
for module_option in module.CLI:
if module_option.type == binwalk.common.BlockFile:
if module_option.type == binwalk.core.common.BlockFile:
for k in get_keys(module_option.kwargs):
kwargs[k] = []
......@@ -590,14 +594,14 @@ class Modules(object):
if not hasattr(module, k):
setattr(module, k, v)
else:
raise Exception("binwalk.module.Modules.process_kwargs: %s has no attribute 'KWARGS'" % str(module))
raise Exception("binwalk.core.module.Modules.process_kwargs: %s has no attribute 'KWARGS'" % str(module))
def process_kwargs(obj, kwargs):
'''
Convenience wrapper around binwalk.module.Modules.kwargs.
Convenience wrapper around binwalk.core.module.Modules.kwargs.
@obj - The class object (an instance of a sub-class of binwalk.module.Module).
@obj - The class object (an instance of a sub-class of binwalk.core.module.Module).
@kwargs - The kwargs provided to the object's __init__ method.
Returns None.
......@@ -606,7 +610,7 @@ def process_kwargs(obj, kwargs):
def show_help(fd=sys.stdout):
'''
Convenience wrapper around binwalk.module.Modules.help.
Convenience wrapper around binwalk.core.module.Modules.help.
@fd - An object with a write method (e.g., sys.stdout, sys.stderr, etc).
......
......@@ -2,8 +2,8 @@ import io
import re
import os.path
import tempfile
from binwalk.compat import *
from binwalk.common import str2int
from binwalk.core.compat import *
from binwalk.core.common import str2int
class MagicParser:
'''
......
import os
import sys
import imp
import binwalk.config
from binwalk.compat import *
import binwalk.core.config
from binwalk.core.compat import *
class Plugins:
'''
......@@ -54,7 +54,7 @@ class Plugins:
self.pre_scan = []
self.post_scan = []
self.parent = parent
self.config = binwalk.config.Config()
self.config = binwalk.core.config.Config()
def __del__(self):
pass
......
import re
import binwalk.module
from binwalk.compat import *
from binwalk.common import str2int, get_quoted_strings, MathExpression
import binwalk.core.module
from binwalk.core.compat import *
from binwalk.core.common import str2int, get_quoted_strings, MathExpression
class SmartSignature:
'''
......@@ -127,7 +127,7 @@ class SmartSignature:
results['valid'] = self.valid
return binwalk.module.Result(**results)
return binwalk.core.module.Result(**results)
def _is_valid(self, data):
'''
......
from signature import Signature
from binvis import Plotter
from hexdiff import HexDiff
from hashmatch import HashMatch
from configuration import Configuration
from extractor import Extractor
from binwalk.modules.signature import Signature
from binwalk.modules.binvis import Plotter
from binwalk.modules.hexdiff import HexDiff
from binwalk.modules.hashmatch import HashMatch
from binwalk.modules.configuration import Configuration
from binwalk.modules.extractor import Extractor
import os
import binwalk.module
from binwalk.compat import *
from binwalk.common import BlockFile
from binwalk.core.compat import *
from binwalk.core.common import BlockFile
from binwalk.core.module import Module, Option, Kwarg
class Plotter(binwalk.module.Module):
class Plotter(Module):
'''
Base class for visualizing binaries in Qt.
Other plotter classes are derived from this.
......@@ -15,29 +15,29 @@ class Plotter(binwalk.module.Module):
TITLE = "Binary Visualization"
CLI = [
binwalk.module.ModuleOption(short='3',
long='3D',
kwargs={'axis' : 3, 'enabled' : True},
description='Generate a 3D binary visualization'),
binwalk.module.ModuleOption(short='2',
long='2D',
kwargs={'axis' : 2, 'enabled' : True},
description='Project data points onto 3D cube walls only'),
binwalk.module.ModuleOption(short='Z',
long='max-points',
type=int,
kwargs={'max_points' : 0},
description='Set the maximum number of plotted data points'),
binwalk.module.ModuleOption(short='V',
long='show-grids',
kwargs={'show_grids' : True},
description='Display the x-y-z grids in the resulting plot'),
Option(short='3',
long='3D',
kwargs={'axis' : 3, 'enabled' : True},
description='Generate a 3D binary visualization'),
Option(short='2',
long='2D',
kwargs={'axis' : 2, 'enabled' : True},
description='Project data points onto 3D cube walls only'),
Option(short='Z',
long='max-points',
type=int,
kwargs={'max_points' : 0},
description='Set the maximum number of plotted data points'),
Option(short='V',
long='show-grids',
kwargs={'show_grids' : True},
description='Display the x-y-z grids in the resulting plot'),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='axis', default=3),
binwalk.module.ModuleKwarg(name='max_points', default=0),
binwalk.module.ModuleKwarg(name='show_grids', default=False),
Kwarg(name='axis', default=3),
Kwarg(name='max_points', default=0),
Kwarg(name='show_grids', default=False),
]
# There isn't really any useful data to print to console. Disable header and result output.
......
import os
import sys
import argparse
import binwalk.common
import binwalk.module
import binwalk.config
import binwalk.display
from binwalk.config import *
from binwalk.compat import *
import binwalk.core.common
import binwalk.core.config
import binwalk.core.display
from binwalk.core.config import *
from binwalk.core.compat import *
from binwalk.core.module import Module, Option, Kwarg, show_help
class Configuration(binwalk.module.Module):
class Configuration():
TITLE = "General"
DEPENDS = {}
CLI = [
binwalk.module.ModuleOption(long='length',
short='l',
type=int,
kwargs={'length' : 0},
description='Number of bytes to scan'),
binwalk.module.ModuleOption(long='offset',
short='o',
type=int,
kwargs={'offset' : 0},
description='Start scan at this file offset'),
binwalk.module.ModuleOption(long='block',
short='K',
type=int,
kwargs={'block' : 0},
description='Set file block size'),
binwalk.module.ModuleOption(long='swap',
short='g',
type=int,
kwargs={'swap_size' : 0},
description='Reverse every n bytes before scanning'),
binwalk.module.ModuleOption(long='log',
short='f',
type=argparse.FileType,
kwargs={'log_file' : None},
description='Log results to file'),
binwalk.module.ModuleOption(long='csv',
short='c',
kwargs={'csv' : True},
description='Log results to file in CSV format'),
binwalk.module.ModuleOption(long='term',
short='t',
kwargs={'format_to_terminal' : True},
description='Format output to fit the terminal window'),
binwalk.module.ModuleOption(long='quiet',
short='q',
kwargs={'quiet' : True},
description='Supress output to stdout'),
binwalk.module.ModuleOption(long='verbose',
short='v',
type=list,
kwargs={'verbose' : True},
description='Enable verbose output (specify twice for more verbosity)'),
binwalk.module.ModuleOption(short='h',
long='help',
kwargs={'show_help' : True},
description='Show help output'),
binwalk.module.ModuleOption(long=None,
short=None,
type=binwalk.common.BlockFile,
kwargs={'files' : []}),
Option(long='length',
short='l',
type=int,
kwargs={'length' : 0},
description='Number of bytes to scan'),
Option(long='offset',
short='o',
type=int,
kwargs={'offset' : 0},
description='Start scan at this file offset'),
Option(long='block',
short='K',
type=int,
kwargs={'block' : 0},
description='Set file block size'),
Option(long='swap',
short='g',
type=int,
kwargs={'swap_size' : 0},
description='Reverse every n bytes before scanning'),
Option(long='log',
short='f',
type=argparse.FileType,
kwargs={'log_file' : None},
description='Log results to file'),
Option(long='csv',
short='c',
kwargs={'csv' : True},
description='Log results to file in CSV format'),
Option(long='term',
short='t',
kwargs={'format_to_terminal' : True},
description='Format output to fit the terminal window'),
Option(long='quiet',
short='q',
kwargs={'quiet' : True},
description='Supress output to stdout'),
Option(long='verbose',
short='v',
type=list,
kwargs={'verbose' : True},
description='Enable verbose output (specify twice for more verbosity)'),
Option(short='h',
long='help',
kwargs={'show_help' : True},
description='Show help output'),
Option(long=None,
short=None,
type=binwalk.core.common.BlockFile,
kwargs={'files' : []}),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='length', default=0),
binwalk.module.ModuleKwarg(name='offset', default=0),
binwalk.module.ModuleKwarg(name='block', default=0),
binwalk.module.ModuleKwarg(name='swap_size', default=0),
binwalk.module.ModuleKwarg(name='log_file', default=None),
binwalk.module.ModuleKwarg(name='csv', default=False),
binwalk.module.ModuleKwarg(name='format_to_terminal', default=False),
binwalk.module.ModuleKwarg(name='quiet', default=False),
binwalk.module.ModuleKwarg(name='verbose', default=[]),
binwalk.module.ModuleKwarg(name='files', default=[]),
binwalk.module.ModuleKwarg(name='show_help', default=False),
Kwarg(name='length', default=0),
Kwarg(name='offset', default=0),
Kwarg(name='block', default=0),
Kwarg(name='swap_size', default=0),
Kwarg(name='log_file', default=None),
Kwarg(name='csv', default=False),
Kwarg(name='format_to_terminal', default=False),
Kwarg(name='quiet', default=False),
Kwarg(name='verbose', default=[]),
Kwarg(name='files', default=[]),
Kwarg(name='show_help', default=False),
]
def load(self):
......@@ -87,15 +87,15 @@ class Configuration(binwalk.module.Module):
self._set_verbosity()
self._open_target_files()
self.settings = binwalk.config.Config()
self.display = binwalk.display.Display(log=self.log_file,
csv=self.csv,
quiet=self.quiet,
verbose=self.verbose,
fit_to_screen=self.format_to_terminal)
self.settings = binwalk.core.config.Config()
self.display = binwalk.core.display.Display(log=self.log_file,
csv=self.csv,
quiet=self.quiet,
verbose=self.verbose,
fit_to_screen=self.format_to_terminal)
if self.show_help:
binwalk.module.show_help()
show_help()
sys.exit(0)
def __del__(self):
......@@ -134,7 +134,7 @@ class Configuration(binwalk.module.Module):
if not os.path.isdir(tfile):
# Make sure we can open the target files
try:
fp = binwalk.common.BlockFile(tfile, length=self.length, offset=self.offset, swap=self.swap_size)
fp = binwalk.core.common.BlockFile(tfile, length=self.length, offset=self.offset, swap=self.swap_size)
self.target_files.append(fp)
except KeyboardInterrupt as e:
raise e
......
......@@ -4,9 +4,9 @@ import magic
import fnmatch
import ctypes
import ctypes.util
import binwalk.common
import binwalk.module
from binwalk.compat import *
import binwalk.core.common
from binwalk.core.compat import *
from binwalk.core.module import Module, Option, Kwarg
class HashResult(object):
'''
......@@ -19,7 +19,7 @@ class HashResult(object):
self.hash = hash
self.strings = strings
class HashMatch(binwalk.module.Module):
class HashMatch(Module):
'''
Class for fuzzy hash matching of files and directories.
'''
......@@ -29,50 +29,50 @@ class HashMatch(binwalk.module.Module):
TITLE = "Fuzzy Hash"
CLI = [
binwalk.module.ModuleOption(short='F',
long='fuzzy',
kwargs={'enabled' : True},
description='Perform fuzzy hash matching on files/directories'),
binwalk.module.ModuleOption(short='u',
long='cutoff',
priority=100,
type=int,
kwargs={'cutoff' : DEFAULT_CUTOFF},
description='Set the cutoff percentage'),
binwalk.module.ModuleOption(short='S',
long='strings',
kwargs={'strings' : True},
description='Diff strings inside files instead of the entire file'),
binwalk.module.ModuleOption(short='s',
long='same',
kwargs={'same' : True, 'cutoff' : CONSERVATIVE_CUTOFF},
description='Only show files that are the same'),
binwalk.module.ModuleOption(short='p',
long='diff',
kwargs={'same' : False, 'cutoff' : CONSERVATIVE_CUTOFF},
description='Only show files that are different'),
binwalk.module.ModuleOption(short='n',
long='name',
kwargs={'filter_by_name' : True},
description='Only compare files whose base names are the same'),
binwalk.module.ModuleOption(short='L',
long='symlinks',
kwargs={'symlinks' : True},
description="Don't ignore symlinks"),
Option(short='F',
long='fuzzy',
kwargs={'enabled' : True},
description='Perform fuzzy hash matching on files/directories'),
Option(short='u',
long='cutoff',
priority=100,
type=int,
kwargs={'cutoff' : DEFAULT_CUTOFF},
description='Set the cutoff percentage'),
Option(short='S',
long='strings',
kwargs={'strings' : True},
description='Diff strings inside files instead of the entire file'),
Option(short='s',
long='same',
kwargs={'same' : True, 'cutoff' : CONSERVATIVE_CUTOFF},
description='Only show files that are the same'),
Option(short='p',
long='diff',
kwargs={'same' : False, 'cutoff' : CONSERVATIVE_CUTOFF},
description='Only show files that are different'),
Option(short='n',
long='name',
kwargs={'filter_by_name' : True},
description='Only compare files whose base names are the same'),
Option(short='L',
long='symlinks',
kwargs={'symlinks' : True},
description="Don't ignore symlinks"),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='cutoff', default=DEFAULT_CUTOFF),
binwalk.module.ModuleKwarg(name='strings', default=False),
binwalk.module.ModuleKwarg(name='same', default=True),
binwalk.module.ModuleKwarg(name='symlinks', default=False),
binwalk.module.ModuleKwarg(name='name', default=False),
binwalk.module.ModuleKwarg(name='max_results', default=None),
binwalk.module.ModuleKwarg(name='abspath', default=False),
binwalk.module.ModuleKwarg(name='matches', default={}),
binwalk.module.ModuleKwarg(name='types', default={}),
binwalk.module.ModuleKwarg(name='filter_by_name', default=False),
binwalk.module.ModuleKwarg(name='symlinks', default=False),
Kwarg(name='cutoff', default=DEFAULT_CUTOFF),
Kwarg(name='strings', default=False),
Kwarg(name='same', default=True),
Kwarg(name='symlinks', default=False),
Kwarg(name='name', default=False),
Kwarg(name='max_results', default=None),
Kwarg(name='abspath', default=False),
Kwarg(name='matches', default={}),
Kwarg(name='types', default={}),
Kwarg(name='filter_by_name', default=False),
Kwarg(name='symlinks', default=False),
]
# Requires libfuzzy.so
......@@ -89,21 +89,6 @@ class HashMatch(binwalk.module.Module):
RESULT = ["percentage", "description"]
def init(self):
'''
Class constructor.
@cutoff - The fuzzy cutoff which determines if files are different or not.
@strings - Only hash strings inside of the file, not the entire file itself.
@same - Set to True to show files that are the same, False to show files that are different.
@symlinks - Set to True to include symbolic link files.
@name - Set to True to only compare files whose base names match.
@max_results - Stop searching after x number of matches.
@abspath - Set to True to display absolute file paths.
@matches - A dictionary of file names to diff.
@types - A dictionary of file types to diff.
Returns None.
'''
self.total = 0
self.last_file1 = HashResult(None)
self.last_file2 = HashResult(None)
......@@ -118,7 +103,7 @@ class HashMatch(binwalk.module.Module):
self.types[k][i] = re.compile(self.types[k][i])
def _get_strings(self, fname):
return ''.join(list(binwalk.common.strings(fname, minimum=10)))
return ''.join(list(binwalk.core.common.strings(fname, minimum=10)))
def _show_result(self, match, fname):
if self.abspath:
......
......@@ -2,12 +2,12 @@ import os
import sys
import curses
import platform
import binwalk.module
import binwalk.common as common
from binwalk.compat import *
import binwalk.core.common as common
from binwalk.core.compat import *
from binwalk.core.module import Module, Option, Kwarg
# TODO: This code is an effing mess.
class HexDiff(binwalk.module.Module):
class HexDiff(Module):
ALL_SAME = 0
ALL_DIFF = 1
......@@ -25,33 +25,33 @@ class HexDiff(binwalk.module.Module):
TITLE = "Binary Diffing"
CLI = [
binwalk.module.ModuleOption(short='W',
long='hexdump',
kwargs={'enabled' : True},
description='Perform a hexdump / diff of a file or files'),
binwalk.module.ModuleOption(short='G',
long='green',
kwargs={'show_green' : True, 'show_blue' : False, 'show_red' : False},
description='Only show lines containing bytes that are the same among all files'),
binwalk.module.ModuleOption(short='i',
long='red',
kwargs={'show_red' : True, 'show_blue' : False, 'show_green' : False},
description='Only show lines containing bytes that are different among all files'),
binwalk.module.ModuleOption(short='U',
long='blue',
kwargs={'show_blue' : True, 'show_red' : False, 'show_green' : False},
description='Only show lines containing bytes that are different among some files'),
binwalk.module.ModuleOption(short='w',
long='terse',
kwargs={'terse' : True},
description='Diff all files, but only display a hex dump of the first file'),
Option(short='W',
long='hexdump',
kwargs={'enabled' : True},
description='Perform a hexdump / diff of a file or files'),
Option(short='G',
long='green',
kwargs={'show_green' : True, 'show_blue' : False, 'show_red' : False},
description='Only show lines containing bytes that are the same among all files'),
Option(short='i',
long='red',
kwargs={'show_red' : True, 'show_blue' : False, 'show_green' : False},
description='Only show lines containing bytes that are different among all files'),
Option(short='U',
long='blue',
kwargs={'show_blue' : True, 'show_red' : False, 'show_green' : False},
description='Only show lines containing bytes that are different among some files'),
Option(short='w',
long='terse',
kwargs={'terse' : True},
description='Diff all files, but only display a hex dump of the first file'),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='show_red', default=True),
binwalk.module.ModuleKwarg(name='show_blue', default=True),
binwalk.module.ModuleKwarg(name='show_green', default=True),
binwalk.module.ModuleKwarg(name='terse', default=False),
Kwarg(name='show_red', default=True),
Kwarg(name='show_blue', default=True),
Kwarg(name='show_green', default=True),
Kwarg(name='terse', default=False),
]
HEADER_FORMAT = "\n%s\n"
......
import magic
import binwalk.module
import binwalk.parser
import binwalk.filter
import binwalk.smartsignature
from binwalk.compat import *
import binwalk.core.parser
import binwalk.core.filter
import binwalk.core.smartsignature
from binwalk.core.compat import *
from binwalk.core.module import Module, Option, Kwarg
class Signature(binwalk.module.Module):
class Signature(Module):
TITLE = "Signature Scan"
CLI = [
binwalk.module.ModuleOption(short='B',
long='signature',
kwargs={'enabled' : True},
description='Scan target file(s) for file signatures'),
binwalk.module.ModuleOption(short='m',
long='magic',
kwargs={'magic_files' : []},
type=list,
dtype='file',
description='Specify a custom magic file to use'),
binwalk.module.ModuleOption(short='R',
long='raw-bytes',
kwargs={'raw_bytes' : None},
type=str,
description='Specify a sequence of bytes to search for'),
binwalk.module.ModuleOption(short='b',
long='dumb',
kwargs={'dumb_scan' : True},
description='Disable smart signature keywords'),
binwalk.module.ModuleOption(short='I',
long='show-invalid',
kwargs={'show_invalid' : True},
description='Show results marked as invalid'),
binwalk.module.ModuleOption(short='x',
long='exclude',
kwargs={'exclude_filters' : []},
type=list,
dtype=str.__name__,
description='Exclude results that match <str>'),
binwalk.module.ModuleOption(short='y',
long='include',
kwargs={'include_filters' : []},
type=list,
dtype=str.__name__,
description='Only show results that match <str>'),
Option(short='B',
long='signature',
kwargs={'enabled' : True},
description='Scan target file(s) for file signatures'),
Option(short='m',
long='magic',
kwargs={'magic_files' : []},
type=list,
dtype='file',
description='Specify a custom magic file to use'),
Option(short='R',
long='raw-bytes',
kwargs={'raw_bytes' : None},
type=str,
description='Specify a sequence of bytes to search for'),
Option(short='b',
long='dumb',
kwargs={'dumb_scan' : True},
description='Disable smart signature keywords'),
Option(short='I',
long='show-invalid',
kwargs={'show_invalid' : True},
description='Show results marked as invalid'),
Option(short='x',
long='exclude',
kwargs={'exclude_filters' : []},
type=list,
dtype=str.__name__,
description='Exclude results that match <str>'),
Option(short='y',
long='include',
kwargs={'include_filters' : []},
type=list,
dtype=str.__name__,
description='Only show results that match <str>'),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='enabled', default=False),
binwalk.module.ModuleKwarg(name='dumb_scan', default=False),
binwalk.module.ModuleKwarg(name='show_invalid', default=False),
binwalk.module.ModuleKwarg(name='raw_bytes', default=None),
binwalk.module.ModuleKwarg(name='magic_files', default=[]),
binwalk.module.ModuleKwarg(name='exclude_filters', default=[]),
binwalk.module.ModuleKwarg(name='include_filters', default=[]),
Kwarg(name='enabled', default=False),
Kwarg(name='dumb_scan', default=False),
Kwarg(name='show_invalid', default=False),
Kwarg(name='raw_bytes', default=None),
Kwarg(name='magic_files', default=[]),
Kwarg(name='exclude_filters', default=[]),
Kwarg(name='include_filters', default=[]),
]
HEADER = ["DECIMAL", "HEX", "DESCRIPTION"]
......@@ -67,9 +67,9 @@ class Signature(binwalk.module.Module):
def init(self):
# Create SmartSignature and MagicParser class instances. These are mostly for internal use.
self.filter = binwalk.filter.MagicFilter()
self.smart = binwalk.smartsignature.SmartSignature(self.filter, ignore_smart_signatures=self.dumb_scan)
self.parser = binwalk.parser.MagicParser(self.filter, self.smart)
self.filter = binwalk.core.filter.MagicFilter()
self.smart = binwalk.core.smartsignature.SmartSignature(self.filter, ignore_smart_signatures=self.dumb_scan)
self.parser = binwalk.core.parser.MagicParser(self.filter, self.smart)
# Set any specified include/exclude filters
for regex in self.exclude_filters:
......
import ctypes
import ctypes.util
from binwalk.common import *
from binwalk.core.common import *
class Plugin:
'''
......
from binwalk.plugin import *
class Plugin:
'''
Ensures that ASCII CPIO archive entries only get extracted once.
......
import os
import shutil
from binwalk.compat import *
from binwalk.common import BlockFile
from binwalk.core.compat import *
from binwalk.core.common import BlockFile
class Plugin:
'''
......@@ -15,22 +15,23 @@ class Plugin:
def __init__(self, module):
self.original_cmd = ''
self.enabled = (module.name == 'Signature')
self.module = module
#if module.extractor.enabled:
if self.enabled:
# Replace the existing LZMA extraction command with our own
# rules = self.binwalk.extractor.get_rules()
# for i in range(0, len(rules)):
# if rules[i]['regex'].match(self.SIGNATURE):
# self.original_cmd = rules[i]['cmd']
# rules[i]['cmd'] = self.lzma_cable_extractor
# break
rules = self.extractor.get_rules()
for i in range(0, len(rules)):
if rules[i]['regex'].match(self.SIGNATURE):
self.original_cmd = rules[i]['cmd']
rules[i]['cmd'] = self.lzma_cable_extractor
break
def lzma_cable_extractor(self, fname):
# Try extracting the LZMA file without modification first
if not self.binwalk.extractor.execute(self.original_cmd, fname):
if not self.module.extractor.execute(self.original_cmd, fname):
out_name = os.path.splitext(fname)[0] + '-patched' + os.path.splitext(fname)[1]
fp_out = BlockFile(out_name, 'w')
fp_in = BlockFile(fname)
fp_in = BlockFile(fname, swap=self.module.config.swap_size)
fp_in.MAX_TRAILING_SIZE = 0
i = 0
......@@ -51,11 +52,11 @@ class Plugin:
# Overwrite the original file so that it can be cleaned up if -r was specified
shutil.move(out_name, fname)
self.binwalk.extractor.execute(self.original_cmd, fname)
self.module.extractor.execute(self.original_cmd, fname)
def scan(self, result):
# The modified cable modem LZMA headers all have valid dictionary sizes and a properties byte of 0x5D.
if result.description.lower().startswith(self.SIGNATURE) and "invalid uncompressed size" in result.description:
if self.enabled and result.description.lower().startswith(self.SIGNATURE) and "invalid uncompressed size" in result.description:
if "properties: 0x5D" in result.description and "invalid dictionary size" not in result.description:
result.valid = True
result.description = result.description.split("invalid uncompressed size")[0] + "missing uncompressed size"
......
......@@ -7,11 +7,12 @@ class Plugin:
Searches for and validates zlib compressed data.
'''
MIN_DECOMP_SIZE = 16*1024
MIN_DECOMP_SIZE = 16 * 1024
MAX_DATA_SIZE = 33 * 1024
def __init__(self, module):
self.tinfl = None
self.module = module
# Only initialize this plugin if this is a signature scan
if module.name == 'Signature':
......@@ -22,8 +23,7 @@ class Plugin:
# If this result is a zlib signature match, try to decompress the data
if self.tinfl and result.file and result.description.lower().startswith('zlib'):
# Seek to and read the suspected zlib data
fd = BlockFile(result.file.name, "r")
fd.seek(result.offset)
fd = BlockFile(result.file.name, offset=result.offset, swap=self.module.config.swap_size)
data = fd.read(self.MAX_DATA_SIZE)
fd.close()
......
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