Commit f23e83b7 by devttys0

Initial code for signature.py plugin added.

parent 27a8a4d6
...@@ -100,9 +100,9 @@ class Error(Result): ...@@ -100,9 +100,9 @@ class Error(Result):
Result.__init__(self, **kwargs) Result.__init__(self, **kwargs)
if self.exception: if self.exception:
sys.stderr.write(str(self.exception) + "\n") sys.stderr.write("Exception: " + str(self.exception) + "\n")
elif self.description: elif self.description:
sys.stderr.write(self.description + "\n") sys.stderr.write("Error: " + self.description + "\n")
class Module(object): class Module(object):
''' '''
...@@ -137,8 +137,22 @@ class Module(object): ...@@ -137,8 +137,22 @@ class Module(object):
def __init__(self, **kwargs): def __init__(self, **kwargs):
# TODO: Instantiate plugins object # TODO: Instantiate plugins object
# self.plugins = x # self.plugins = x
self.errors = []
self.results = [] self.results = []
process_kwargs(self, kwargs) process_kwargs(self, kwargs)
try:
self.load()
except KeyboardInterrupt as e:
raise e
except Exception as e:
self.error(exception=e)
def load(self):
'''
Invoked at module load time.
May be overridden by the module sub-class.
'''
return None
def init(self): def init(self):
''' '''
...@@ -225,8 +239,16 @@ class Module(object): ...@@ -225,8 +239,16 @@ class Module(object):
''' '''
e = Error(**kwargs) e = Error(**kwargs)
self.errors.append(e) self.errors.append(e)
if e.exception:
raise e.exception def header(self):
self.config.display.format_strings(self.HEADER_FORMAT, self.RESULT_FORMAT)
if type(self.HEADER) == type([]):
self.config.display.header(*self.HEADER)
elif self.HEADER:
self.config.display.header(self.HEADER)
def footer(self):
self.config.display.footer()
def main(self): def main(self):
''' '''
...@@ -242,12 +264,7 @@ class Module(object): ...@@ -242,12 +264,7 @@ class Module(object):
self.error(exception=e) self.error(exception=e)
return False return False
self.config.display.format_strings(self.HEADER_FORMAT, self.RESULT_FORMAT) self.header()
if type(self.HEADER) == type([]):
self.config.display.header(*self.HEADER)
elif self.HEADER:
self.config.display.header(self.HEADER)
self._plugins_pre_scan() self._plugins_pre_scan()
try: try:
...@@ -259,8 +276,8 @@ class Module(object): ...@@ -259,8 +276,8 @@ class Module(object):
return False return False
self._plugins_post_scan() self._plugins_post_scan()
self.footer()
self.config.display.footer()
return retval return retval
class Modules(object): class Modules(object):
...@@ -277,13 +294,18 @@ class Modules(object): ...@@ -277,13 +294,18 @@ class Modules(object):
Returns None. Returns None.
''' '''
self.ok = True
self.config = None self.config = None
self.argv = argv self.arguments = argv
self.dependency_results = {} self.dependency_results = {}
if not dummy: if not dummy:
from binwalk.modules.configuration import Configuration from binwalk.modules.configuration import Configuration
self.config = self.load(Configuration) self.config = self.load(Configuration)
for e in self.config.errors:
if e.exception:
self.ok = False
break
def list(self, attribute="run"): def list(self, attribute="run"):
''' '''
...@@ -337,26 +359,31 @@ class Modules(object): ...@@ -337,26 +359,31 @@ class Modules(object):
return run_modules return run_modules
def run(self, module): def run(self, module):
retval = False
obj = self.load(module) obj = self.load(module)
if obj.enabled: if isinstance(obj, Module) and obj.enabled:
try: try:
retval = obj.main() obj.main()
except AttributeError as e: except AttributeError as e:
print("WARNING:", e) sys.stderr.write("WARNING: " + str(e) + "\n")
obj = None
else:
obj = None
return retval return obj
def load(self, module): def load(self, module):
kwargs = self.argv(module, argv=self.argv) if self.ok:
kwargs = self.argv(module, argv=self.arguments)
kwargs.update(self.dependencies(module)) kwargs.update(self.dependencies(module))
return module(**kwargs) return module(**kwargs)
else:
return None
def dependencies(self, module): def dependencies(self, module):
kwargs = {} kwargs = {}
if hasattr(module, "DEPENDS"): if self.ok and hasattr(module, "DEPENDS"):
# Disable output when modules are loaded as dependencies # Disable output when modules are loaded as dependencies
orig_log = self.config.display.log orig_log = self.config.display.log
orig_quiet = self.config.display.quiet orig_quiet = self.config.display.quiet
...@@ -365,8 +392,7 @@ class Modules(object): ...@@ -365,8 +392,7 @@ class Modules(object):
for (kwarg, mod) in iterator(module.DEPENDS): for (kwarg, mod) in iterator(module.DEPENDS):
if not has_key(self.dependency_results, mod): if not has_key(self.dependency_results, mod):
self.dependency_results[mod] = self.load(mod) self.dependency_results[mod] = self.run(mod)
self.dependency_results[mod].main()
kwargs[kwarg] = self.dependency_results[mod] kwargs[kwarg] = self.dependency_results[mod]
self.config.display.log = orig_log self.config.display.log = orig_log
...@@ -449,6 +475,8 @@ class Modules(object): ...@@ -449,6 +475,8 @@ class Modules(object):
if self.config is not None and not has_key(kwargs, 'config'): if self.config is not None and not has_key(kwargs, 'config'):
kwargs['config'] = self.config kwargs['config'] = self.config
if not has_key(kwargs, 'enabled'):
kwargs['enabled'] = False
return kwargs return kwargs
...@@ -473,9 +501,6 @@ class Modules(object): ...@@ -473,9 +501,6 @@ class Modules(object):
for (k, v) in iterator(kwargs): for (k, v) in iterator(kwargs):
if not hasattr(module, k): if not hasattr(module, k):
setattr(module, k, v) setattr(module, k, v)
if not hasattr(module, 'enabled'):
setattr(module, 'enabled', False)
else: else:
raise Exception("binwalk.module.Modules.process_kwargs: %s has no attribute 'KWARGS'" % str(module)) raise Exception("binwalk.module.Modules.process_kwargs: %s has no attribute 'KWARGS'" % str(module))
...@@ -489,7 +514,7 @@ def process_kwargs(obj, kwargs): ...@@ -489,7 +514,7 @@ def process_kwargs(obj, kwargs):
Returns None. Returns None.
''' '''
return Modules(dummy=True).kwargs(module, kwargs) return Modules(dummy=True).kwargs(obj, kwargs)
def show_help(fd=sys.stdout): def show_help(fd=sys.stdout):
''' '''
......
...@@ -2,3 +2,4 @@ from configuration import Configuration ...@@ -2,3 +2,4 @@ from configuration import Configuration
from hashmatch import HashMatch from hashmatch import HashMatch
from binvis import Plotter from binvis import Plotter
from hexdiff import HexDiff from hexdiff import HexDiff
from signature import Signature
...@@ -8,6 +8,7 @@ from binwalk.compat import * ...@@ -8,6 +8,7 @@ from binwalk.compat import *
class Configuration(binwalk.module.Module): class Configuration(binwalk.module.Module):
RUN = False
NAME = "General" NAME = "General"
CLI = [ CLI = [
binwalk.module.ModuleOption(long='length', binwalk.module.ModuleOption(long='length',
...@@ -83,10 +84,14 @@ class Configuration(binwalk.module.Module): ...@@ -83,10 +84,14 @@ class Configuration(binwalk.module.Module):
binwalk.module.ModuleKwarg(name='do_update', default=False), binwalk.module.ModuleKwarg(name='do_update', default=False),
] ]
def __init__(self, **kwargs): def load(self):
self.target_files = [] self.target_files = []
binwalk.module.process_kwargs(self, kwargs) 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)
if self.show_help: if self.show_help:
binwalk.module.show_help() binwalk.module.show_help()
...@@ -99,12 +104,6 @@ class Configuration(binwalk.module.Module): ...@@ -99,12 +104,6 @@ class Configuration(binwalk.module.Module):
self._open_target_files() self._open_target_files()
self._set_verbosity() self._set_verbosity()
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)
def __del__(self): def __del__(self):
self._cleanup() self._cleanup()
...@@ -145,7 +144,7 @@ class Configuration(binwalk.module.Module): ...@@ -145,7 +144,7 @@ class Configuration(binwalk.module.Module):
except KeyboardInterrupt as e: except KeyboardInterrupt as e:
raise e raise e
except Exception as e: except Exception as e:
self.error(description="Cannot open file : %s\n" % str(e)) self.error(description="Cannot open file : %s" % str(e))
# Unless -O was specified, don't run the scan unless we are able to scan all specified files # Unless -O was specified, don't run the scan unless we are able to scan all specified files
if len(self.target_files) != len(self.files) and not self.skip_unopened: if len(self.target_files) != len(self.files) and not self.skip_unopened:
......
import magic
import binwalk.config
import binwalk.module
import binwalk.parser
import binwalk.filter
import binwalk.smartsignature
from binwalk.compat import *
class Signature(binwalk.module.Module):
CLI = [
binwalk.module.ModuleOption(short='B',
long='signature',
kwargs={'enabled' : True}),
]
KWARGS = [
binwalk.module.ModuleKwarg(name='enabled', default=False),
binwalk.module.ModuleKwarg(name='magic_files', default=[]),
]
HEADER="BINWALK"
HEADER_FORMAT="%s\n"
RESULT=["offset", "offset", "description"]
RESULT_FORMAT="%d 0x%X %s\n"
MAGIC_FLAGS = magic.MAGIC_NO_CHECK_TEXT | magic.MAGIC_NO_CHECK_ENCODING | magic.MAGIC_NO_CHECK_APPTYPE | magic.MAGIC_NO_CHECK_TOKENS
def init(self):
# Instantiate the config class so we can access file/directory paths
self.conf = binwalk.config.Config()
# 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=False)
self.parser = binwalk.parser.MagicParser(self.filter, self.smart)
# Use the system default magic file if no other was specified
if not self.magic_files or self.magic_files is None:
# Append the user's magic file first so that those signatures take precedence
self.magic_files = [
self.conf.paths['user'][self.conf.BINWALK_MAGIC_FILE],
self.conf.paths['system'][self.conf.BINWALK_MAGIC_FILE],
]
# Parse the magic file(s) and initialize libmagic
self.mfile = self.parser.parse(self.magic_files)
self.magic = magic.open(self.MAGIC_FLAGS)
self.magic.load(str2bytes(self.mfile))
# Once the temporary magic file is loaded into libmagic, we don't need it anymore; delete the temp file
self.parser.rm_magic_file()
def scan_file(self, fp):
data = fp.read()
for candidate in self.parser.find_signature_candidates(data, len(data)):
# In python3 we need a bytes object to pass to magic.buffer
candidate_data = str2bytes(data[candidate:candidate+fp.MAX_TRAILING_SIZE])
# Pass the data to libmagic, and split out multiple results into a list
for magic_result in self.parser.split(self.magic.buffer(candidate_data)):
if not self.filter.invalid(magic_result):
# The smart filter parser returns a dictionary of keyword values and the signature description.
smart = self.smart.parse(magic_result)
self.result(description=smart['description'], offset=candidate)
def run(self):
for fp in self.config.target_files:
self.scan_file(fp)
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