Commit 7af59510 by devttys0

Added Configuration module as a dependency for other modules

parent 8ef8a797
......@@ -3,7 +3,6 @@ import sys
import inspect
import argparse
import binwalk.common
import binwalk.loader
from binwalk.compat import *
class ModuleOption(object):
......@@ -274,6 +273,8 @@ class Module(object):
self.error(exception=e)
return False
self.config.display.format_strings(self.HEADER_FORMAT, self.RESULT_FORMAT)
self._plugins_pre_scan()
try:
......@@ -288,26 +289,225 @@ class Module(object):
return retval
class Modules(object):
'''
Main class used for running and managing modules.
'''
def __init__(self, argv=sys.argv[1:]):
'''
Class constructor.
@argv - List of command line options. Must not include the program name (sys.argv[0]).
Returns None.
'''
self.arguments = argv
self.dependency_results = {}
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.
'''
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, binwalk.module.Module) and obj.enabled:
try:
obj.main()
except AttributeError as e:
sys.stderr.write("WARNING: " + str(e) + "\n")
obj = None
return obj
def load(self, module):
kwargs = self.argv(module, argv=self.arguments)
kwargs.update(self.dependencies(module))
return module(**kwargs)
def dependencies(self, module):
kwargs = {}
if hasattr(module, "DEPENDS"):
for (kwarg, mod) in iterator(module.DEPENDS):
if mod == module:
continue
if not has_key(self.dependency_results, mod):
# TODO: What to do if a dependency fails?
self.dependency_results[mod] = self.run(mod)
kwargs[kwarg] = self.dependency_results[mod]
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 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.loader.Modules.kwargs.
Convenience wrapper around binwalk.module.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 binwalk.loader.Modules().kwargs(obj, kwargs)
return Modules().kwargs(obj, kwargs)
def show_help(fd=sys.stdout):
'''
Convenience wrapper around binwalk.loader.Modules.help.
Convenience wrapper around binwalk.module.Modules.help.
@fd - An object with a write method (e.g., sys.stdout, sys.stderr, etc).
Returns None.
'''
fd.write(binwalk.loader.Modules().help())
fd.write(Modules().help())
......@@ -343,7 +343,9 @@ class HashMatch(binwalk.module.Module):
'''
needle = self.config.target_files[0].name
haystack = []
self.header()
for fp in self.config.target_files[1:]:
haystack.append(fp.name)
......@@ -355,4 +357,6 @@ class HashMatch(binwalk.module.Module):
else:
self.hash_directories(needle, haystack)
self.footer()
return True
......@@ -147,6 +147,8 @@ class HexDiff(binwalk.module.Module):
size = self.config.length
block = self.config.block
self.header()
if not block:
block = self.DEFAULT_BLOCK_SIZE
......@@ -248,6 +250,7 @@ class HexDiff(binwalk.module.Module):
i += block
total += read_block_size
self.footer()
return True
......@@ -69,5 +69,7 @@ class Signature(binwalk.module.Module):
def run(self):
for fp in self.config.target_files:
self.header()
self.scan_file(fp)
self.footer()
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