From 8ef8a79751f8b887c16ee38201e79fb076a9229d Mon Sep 17 00:00:00 2001 From: devttys0 <heffnercj@gmail.com> Date: Fri, 13 Dec 2013 19:01:09 -0500 Subject: [PATCH] Consolidated code into the binwalk.module.Module parent class. --- src/binwalk/module.py | 250 +++++++++++++++++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/binwalk/modules/binvis.py | 3 +++ src/binwalk/modules/hashmatch.py | 3 +++ src/binwalk/modules/hexdiff.py | 3 +++ src/binwalk/modules/signature.py | 3 +++ 5 files changed, 29 insertions(+), 233 deletions(-) diff --git a/src/binwalk/module.py b/src/binwalk/module.py index ddc6739..4fdf0fe 100644 --- a/src/binwalk/module.py +++ b/src/binwalk/module.py @@ -3,6 +3,7 @@ import sys import inspect import argparse import binwalk.common +import binwalk.loader from binwalk.compat import * class ModuleOption(object): @@ -108,7 +109,6 @@ class Module(object): ''' All module classes must be subclassed from this. ''' - # The module name, as displayed in help output NAME = "" @@ -118,6 +118,9 @@ class Module(object): # A list of binwalk.module.ModuleKwargs accepted by __init__ KWARGS = [] + # A dictionary of module dependencies; all modules depend on binwalk.modules.configuration.Configuration + DEPENDS = {} + # Format string for printing the header during a scan HEADER_FORMAT = "%s\n" @@ -134,12 +137,19 @@ class Module(object): # Note that these will be formatted per the RESULT_FORMAT format string. RESULT = ['offset', 'description'] - def __init__(self, **kwargs): + def __init__(self, dependency=False, **kwargs): # TODO: Instantiate plugins object # self.plugins = x self.errors = [] self.results = [] + process_kwargs(self, kwargs) + + # If the module was loaded as a dependency, don't display or log any results + if dependency: + self.config.display.quiet = True + self.config.display.log = None + try: self.load() except KeyboardInterrupt as e: @@ -252,7 +262,7 @@ class Module(object): def main(self): ''' - Responsible for calling self.init, initializing self.config.display, printing the header and calling self.run. + Responsible for calling self.init, initializing self.config.display, and calling self.run. Returns the value returned from self.run. ''' @@ -264,7 +274,6 @@ class Module(object): self.error(exception=e) return False - self.header() self._plugins_pre_scan() try: @@ -276,254 +285,29 @@ class Module(object): return False self._plugins_post_scan() - self.footer() return retval -class Modules(object): - ''' - Main class used for running and managing modules. - ''' - - def __init__(self, argv=sys.argv[1:], dummy=False): - ''' - Class constructor. - - @argv - List of command line options. Must not include the program name (sys.argv[0]). - @dummy - Set to True if you only need the class instance for interrogating modules (run, load, execute will not work). - - Returns None. - ''' - self.ok = True - self.config = None - self.arguments = argv - self.dependency_results = {} - - if not dummy: - from binwalk.modules.configuration import Configuration - self.config = self.load(Configuration) - for e in self.config.errors: - if e.exception: - self.ok = False - break - - def list(self, attribute="run"): - ''' - Finds all modules with the specified attribute. - - @attribute - The desired module attribute. - - Returns a list of modules that contain the specified attribute. - ''' - import binwalk.modules - - modules = [] - - for (name, module) in inspect.getmembers(binwalk.modules): - if inspect.isclass(module) and hasattr(module, attribute): - modules.append(module) - - return modules - - def help(self): - help_string = "" - - for obj in self.list(attribute="CLI"): - if obj.CLI: - help_string += "\n%s Options:\n" % obj.NAME - - for module_option in obj.CLI: - if module_option.long: - long_opt = '--' + module_option.long - - if module_option.nargs > 0: - optargs = "=%s" % module_option.dtype - else: - optargs = "" - - if module_option.short: - short_opt = "-" + module_option.short + "," - else: - short_opt = " " - - fmt = " %%s %%s%%-%ds%%s\n" % (32-len(long_opt)) - help_string += fmt % (short_opt, long_opt, optargs, module_option.description) - - return help_string - - def execute(self): - run_modules = [] - for module in self.list(): - if self.run(module): - run_modules.append(module) - return run_modules - - def run(self, module): - obj = self.load(module) - - if isinstance(obj, Module) and obj.enabled: - try: - obj.main() - except AttributeError as e: - sys.stderr.write("WARNING: " + str(e) + "\n") - obj = None - else: - obj = None - - return obj - - def load(self, module): - if self.ok: - kwargs = self.argv(module, argv=self.arguments) - kwargs.update(self.dependencies(module)) - return module(**kwargs) - else: - return None - - def dependencies(self, module): - kwargs = {} - - if self.ok and hasattr(module, "DEPENDS"): - # Disable output when modules are loaded as dependencies - orig_log = self.config.display.log - orig_quiet = self.config.display.quiet - self.config.display.log = False - self.config.display.quiet = True - - for (kwarg, mod) in iterator(module.DEPENDS): - if not has_key(self.dependency_results, mod): - self.dependency_results[mod] = self.run(mod) - kwargs[kwarg] = self.dependency_results[mod] - - self.config.display.log = orig_log - self.config.display.quiet = orig_quiet - - return kwargs - - def argv(self, module, argv=sys.argv[1:]): - ''' - Processes argv for any options specific to the specified module. - - @module - The module to process argv for. - @argv - A list of command line arguments (excluding argv[0]). - - Returns a dictionary of kwargs for the specified module. - ''' - kwargs = {} - last_priority = {} - longs = [] - shorts = "" - parser = argparse.ArgumentParser(add_help=False) - - if hasattr(module, "CLI"): - - for module_option in module.CLI: - if not module_option.long: - continue - - if module_option.nargs == 0: - action = 'store_true' - else: - action = None - - if module_option.short: - parser.add_argument('-' + module_option.short, '--' + module_option.long, action=action, dest=module_option.long) - else: - parser.add_argument('--' + module_option.long, action=action, dest=module_option.long) - - args, unknown = parser.parse_known_args(argv) - args = args.__dict__ - - for module_option in module.CLI: - - if module_option.type in [io.FileIO, argparse.FileType, binwalk.common.BlockFile]: - - for k in get_keys(module_option.kwargs): - kwargs[k] = [] - for unk in unknown: - if not unk.startswith('-'): - kwargs[k].append(unk) - - elif has_key(args, module_option.long) and args[module_option.long] not in [None, False]: - - i = 0 - for (name, value) in iterator(module_option.kwargs): - if not has_key(last_priority, name) or last_priority[name] <= module_option.priority: - if module_option.nargs > i: - value = args[module_option.long] - i += 1 - - last_priority[name] = module_option.priority - - # Do this manually as argparse doesn't seem to be able to handle hexadecimal values - if module_option.type == int: - kwargs[name] = int(value, 0) - elif module_option.type == float: - kwargs[name] = float(value) - elif module_option.type == dict: - if not has_key(kwargs, name): - kwargs[name] = {} - kwargs[name][len(kwargs[name])] = value - elif module_option.type == list: - if not has_key(kwargs, name): - kwargs[name] = [] - kwargs[name].append(value) - else: - kwargs[name] = value - else: - raise Exception("binwalk.module.Modules.argv: %s has no attribute 'CLI'" % str(module)) - - if self.config is not None and not has_key(kwargs, 'config'): - kwargs['config'] = self.config - if not has_key(kwargs, 'enabled'): - kwargs['enabled'] = False - - return kwargs - - def kwargs(self, module, kwargs): - ''' - Processes a module's kwargs. All modules should use this for kwarg processing. - - @module - An instance of the module (e.g., self) - @kwargs - The kwargs passed to the module - - Returns None. - ''' - if hasattr(module, "KWARGS"): - for module_argument in module.KWARGS: - if has_key(kwargs, module_argument.name): - arg_value = kwargs[module_argument.name] - else: - arg_value = module_argument.default - - setattr(module, module_argument.name, arg_value) - - for (k, v) in iterator(kwargs): - if not hasattr(module, k): - setattr(module, k, v) - else: - raise Exception("binwalk.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.loader.Modules.kwargs. @obj - The class object (an instance of a sub-class of binwalk.module.Module). @kwargs - The kwargs provided to the object's __init__ method. Returns None. ''' - return Modules(dummy=True).kwargs(obj, kwargs) + return binwalk.loader.Modules().kwargs(obj, kwargs) def show_help(fd=sys.stdout): ''' - Convenience wrapper around binwalk.module.Modules.help. + Convenience wrapper around binwalk.loader.Modules.help. @fd - An object with a write method (e.g., sys.stdout, sys.stderr, etc). Returns None. ''' - fd.write(Modules(dummy=True).help()) + fd.write(binwalk.loader.Modules().help()) diff --git a/src/binwalk/modules/binvis.py b/src/binwalk/modules/binvis.py index 3bd5674..117a4b3 100644 --- a/src/binwalk/modules/binvis.py +++ b/src/binwalk/modules/binvis.py @@ -2,6 +2,7 @@ import os import binwalk.module from binwalk.compat import * from binwalk.common import BlockFile +from binwalk.modules.configuration import Configuration class Plotter(binwalk.module.Module): ''' @@ -14,6 +15,8 @@ class Plotter(binwalk.module.Module): NAME = "Binary Visualization" + DEPENDS = {'config' : Configuration} + CLI = [ binwalk.module.ModuleOption(short='3', long='3D', diff --git a/src/binwalk/modules/hashmatch.py b/src/binwalk/modules/hashmatch.py index bbf1298..8349689 100644 --- a/src/binwalk/modules/hashmatch.py +++ b/src/binwalk/modules/hashmatch.py @@ -8,6 +8,7 @@ import binwalk.common import binwalk.module import binwalk.smartstrings from binwalk.compat import * +from binwalk.modules.configuration import Configuration class HashResult(object): ''' @@ -27,6 +28,8 @@ class HashMatch(binwalk.module.Module): DEFAULT_CUTOFF = 0 CONSERVATIVE_CUTOFF = 90 + DEPENDS = {'config' : Configuration } + NAME = "Fuzzy Hash" CLI = [ binwalk.module.ModuleOption(short='F', diff --git a/src/binwalk/modules/hexdiff.py b/src/binwalk/modules/hexdiff.py index 172f6b7..f8794f3 100644 --- a/src/binwalk/modules/hexdiff.py +++ b/src/binwalk/modules/hexdiff.py @@ -5,6 +5,7 @@ import platform import binwalk.module import binwalk.common as common from binwalk.compat import * +from binwalk.modules.configuration import Configuration # TODO: This code is an effing mess. class HexDiff(binwalk.module.Module): @@ -22,6 +23,8 @@ class HexDiff(binwalk.module.Module): 'blue' : '34', } + DEPENDS = {'config' : Configuration} + NAME = "Binary Diffing" CLI = [ binwalk.module.ModuleOption(short='W', diff --git a/src/binwalk/modules/signature.py b/src/binwalk/modules/signature.py index 75436d6..768acdf 100644 --- a/src/binwalk/modules/signature.py +++ b/src/binwalk/modules/signature.py @@ -5,9 +5,12 @@ import binwalk.parser import binwalk.filter import binwalk.smartsignature from binwalk.compat import * +from binwalk.modules.configuration import Configuration class Signature(binwalk.module.Module): + DEPENDS = {'config' : Configuration} + CLI = [ binwalk.module.ModuleOption(short='B', long='signature', -- libgit2 0.26.0