Commit e929bb00 by devttys0

Fixed --term and logging bugs.

parent 5475c714
import sys import sys
import csv as pycsv import csv as pycsv
import binwalk.common
class Display(object): class Display(object):
BUFFER_WIDTH = 0 SCREEN_WIDTH = 0
HEADER_WIDTH = 115 HEADER_WIDTH = 150
MAX_LINE_LEN = 0
DEFAULT_FORMAT = "%s\n" DEFAULT_FORMAT = "%s\n"
def __init__(self, quiet=False, verbose=0, log=None, csv=False, fit_to_screen=False): def __init__(self, quiet=False, verbose=0, log=None, csv=False, fit_to_screen=False):
...@@ -15,17 +13,21 @@ class Display(object): ...@@ -15,17 +13,21 @@ class Display(object):
self.fit_to_screen = fit_to_screen self.fit_to_screen = fit_to_screen
self.fp = None self.fp = None
self.csv = None self.csv = None
self.num_columns = 0
self._configure_formatting() self._configure_formatting()
if log: if log:
self.fp = binwalk.common.BlockFile(log, mode="w") self.fp = open(log, "w")
if self.csv: if csv:
self.csv = pycsv.writer(self.fp) self.csv = pycsv.writer(self.fp)
def format_strings(self, header, result): def format_strings(self, header, result):
self.result_format = result self.result_format = result
self.header_format = header self.header_format = header
if self.num_columns == 0:
self.num_columns = len(header.split())
def log(self, fmt, columns): def log(self, fmt, columns):
if self.fp: if self.fp:
...@@ -35,6 +37,8 @@ class Display(object): ...@@ -35,6 +37,8 @@ class Display(object):
self.fp.write(fmt % tuple(columns)) self.fp.write(fmt % tuple(columns))
def header(self, *args): def header(self, *args):
self.num_columns = len(args)
self._fprint("%s", "\n", csv=False)
self._fprint(self.header_format, args) self._fprint(self.header_format, args)
self._fprint("%s", ["-" * self.HEADER_WIDTH + "\n"], csv=False) self._fprint("%s", ["-" * self.HEADER_WIDTH + "\n"], csv=False)
...@@ -49,7 +53,7 @@ class Display(object): ...@@ -49,7 +53,7 @@ class Display(object):
line = fmt % tuple(columns) line = fmt % tuple(columns)
sys.stdout.write(self._format_line(line.strip()) + "\n") sys.stdout.write(self._format_line(line.strip()) + "\n")
if not (self.csv and not csv): if self.fp and not (self.csv and not csv):
self.log(fmt, columns) self.log(fmt, columns)
def _append_to_data_parts(self, data, start, end): def _append_to_data_parts(self, data, start, end):
...@@ -81,17 +85,22 @@ class Display(object): ...@@ -81,17 +85,22 @@ class Display(object):
offset = 0 offset = 0
space_offset = 0 space_offset = 0
self.string_parts = [] self.string_parts = []
delim = '\n' + ' ' * self.BUFFER_WIDTH delim = '\n'
if self.fit_to_screen: if self.fit_to_screen and len(line) > self.SCREEN_WIDTH:
while len(line[offset:]) > self.MAX_LINE_LEN: line_columns = line.split(None, self.num_columns-1)
space_offset = line[offset:offset+self.MAX_LINE_LEN].rfind(' ')
if space_offset == -1 or space_offset == 0:
space_offset = self.MAX_LINE_LEN
self._append_to_data_parts(line, offset, offset+space_offset) if line_columns:
delim = '\n' + ' ' * line.rfind(line_columns[-1])
offset += space_offset while len(line[offset:]) > self.SCREEN_WIDTH:
space_offset = line[offset:offset+self.HEADER_WIDTH].rfind(' ')
if space_offset == -1 or space_offset == 0:
space_offset = self.SCREEN_WIDTH
self._append_to_data_parts(line, offset, offset+space_offset)
offset += space_offset
self._append_to_data_parts(line, offset, offset+len(line[offset:])) self._append_to_data_parts(line, offset, offset+len(line[offset:]))
...@@ -113,9 +122,7 @@ class Display(object): ...@@ -113,9 +122,7 @@ class Display(object):
# Get the terminal window width # Get the terminal window width
hw = struct.unpack('hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234')) hw = struct.unpack('hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234'))
self.HEADER_WIDTH = hw[1] self.SCREEN_WIDTH = self.HEADER_WIDTH = hw[1]
except Exception as e: except Exception as e:
pass pass
self.MAX_LINE_LEN = self.HEADER_WIDTH - self.BUFFER_WIDTH
import io import io
import os
import sys import sys
import inspect import inspect
import argparse import argparse
...@@ -103,9 +104,12 @@ class Module(object): ...@@ -103,9 +104,12 @@ class Module(object):
''' '''
All module classes must be subclassed from this. All module classes must be subclassed from this.
''' '''
# The module name, as displayed in help output # The module name, automatically populated.
NAME = "" NAME = ""
# The module title, as displayed in help output
TITLE = ""
# A list of binwalk.module.ModuleOption command line options # A list of binwalk.module.ModuleOption command line options
CLI = [] CLI = []
...@@ -113,7 +117,7 @@ class Module(object): ...@@ -113,7 +117,7 @@ class Module(object):
KWARGS = [] KWARGS = []
# A dictionary of module dependencies; all modules depend on binwalk.modules.configuration.Configuration # A dictionary of module dependencies; all modules depend on binwalk.modules.configuration.Configuration
DEPENDS = {} DEPENDS = {'config' : 'Configuration'}
# Format string for printing the header during a scan # Format string for printing the header during a scan
HEADER_FORMAT = "%s\n" HEADER_FORMAT = "%s\n"
...@@ -136,6 +140,7 @@ class Module(object): ...@@ -136,6 +140,7 @@ class Module(object):
# self.plugins = x # self.plugins = x
self.errors = [] self.errors = []
self.results = [] self.results = []
self.NAME = self.__class__.__name__
process_kwargs(self, kwargs) process_kwargs(self, kwargs)
...@@ -302,17 +307,41 @@ class Modules(object): ...@@ -302,17 +307,41 @@ class Modules(object):
Main class used for running and managing modules. Main class used for running and managing modules.
''' '''
def __init__(self, argv=sys.argv[1:]): def __init__(self, *argv, **kargv):
''' '''
Class constructor. Class constructor.
@argv - List of command line options. Must not include the program name (sys.argv[0]). @argv - List of command line options. Must not include the program name (e.g., sys.argv[1:]).
@kargv - Keyword dictionary of command line options.
Returns None. Returns None.
''' '''
argv = list(argv)
for (k,v) in iterator(kargv):
k = self._parse_api_opt(k)
if v not in [True, False, None]:
argv.append("%s %s" % (k, v))
else:
argv.append(k)
if not argv:
argv = sys.argv[1:]
self.arguments = argv self.arguments = argv
self.loaded_modules = {} self.loaded_modules = {}
def _parse_api_opt(self, opt):
# If the argument already starts with a hyphen, don't add hyphens in front of it
if opt.startswith('-'):
return opt
# Short options are only 1 character
elif len(opt) == 1:
return '-' + opt
else:
return '--' + opt
def list(self, attribute="run"): def list(self, attribute="run"):
''' '''
Finds all modules with the specified attribute. Finds all modules with the specified attribute.
...@@ -334,7 +363,7 @@ class Modules(object): ...@@ -334,7 +363,7 @@ class Modules(object):
for obj in self.list(attribute="CLI"): for obj in self.list(attribute="CLI"):
if obj.CLI: if obj.CLI:
help_string += "\n%s Options:\n" % obj.NAME help_string += "\n%s Options:\n" % obj.TITLE
for module_option in obj.CLI: for module_option in obj.CLI:
if module_option.long: if module_option.long:
...@@ -384,6 +413,14 @@ class Modules(object): ...@@ -384,6 +413,14 @@ class Modules(object):
if hasattr(module, "DEPENDS"): if hasattr(module, "DEPENDS"):
for (kwarg, dependency) in iterator(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)
else:
sys.stderr.write("WARNING: %s depends on %s which was not found in binwalk.modules.__init__.py\n" % (str(module), dependency))
continue
# No recursive dependencies, thanks # No recursive dependencies, thanks
if dependency == module: if dependency == module:
continue continue
......
from configuration import Configuration from signature import Signature
from hashmatch import HashMatch
from binvis import Plotter from binvis import Plotter
from hexdiff import HexDiff from hexdiff import HexDiff
from signature import Signature from hashmatch import HashMatch
from configuration import Configuration
...@@ -2,7 +2,6 @@ import os ...@@ -2,7 +2,6 @@ import os
import binwalk.module import binwalk.module
from binwalk.compat import * from binwalk.compat import *
from binwalk.common import BlockFile from binwalk.common import BlockFile
from binwalk.modules.configuration import Configuration
class Plotter(binwalk.module.Module): class Plotter(binwalk.module.Module):
''' '''
...@@ -13,9 +12,7 @@ class Plotter(binwalk.module.Module): ...@@ -13,9 +12,7 @@ class Plotter(binwalk.module.Module):
MAX_2D_PLOT_POINTS = 12500 MAX_2D_PLOT_POINTS = 12500
MAX_3D_PLOT_POINTS = 25000 MAX_3D_PLOT_POINTS = 25000
NAME = "Binary Visualization" TITLE = "Binary Visualization"
DEPENDS = {'config' : Configuration}
CLI = [ CLI = [
binwalk.module.ModuleOption(short='3', binwalk.module.ModuleOption(short='3',
......
...@@ -8,8 +8,8 @@ from binwalk.compat import * ...@@ -8,8 +8,8 @@ from binwalk.compat import *
class Configuration(binwalk.module.Module): class Configuration(binwalk.module.Module):
RUN = False TITLE = "General"
NAME = "General"
CLI = [ CLI = [
binwalk.module.ModuleOption(long='length', binwalk.module.ModuleOption(long='length',
short='l', short='l',
......
...@@ -8,7 +8,6 @@ import binwalk.common ...@@ -8,7 +8,6 @@ import binwalk.common
import binwalk.module import binwalk.module
import binwalk.smartstrings import binwalk.smartstrings
from binwalk.compat import * from binwalk.compat import *
from binwalk.modules.configuration import Configuration
class HashResult(object): class HashResult(object):
''' '''
...@@ -28,15 +27,14 @@ class HashMatch(binwalk.module.Module): ...@@ -28,15 +27,14 @@ class HashMatch(binwalk.module.Module):
DEFAULT_CUTOFF = 0 DEFAULT_CUTOFF = 0
CONSERVATIVE_CUTOFF = 90 CONSERVATIVE_CUTOFF = 90
DEPENDS = {'config' : Configuration } TITLE = "Fuzzy Hash"
NAME = "Fuzzy Hash"
CLI = [ CLI = [
binwalk.module.ModuleOption(short='F', binwalk.module.ModuleOption(short='F',
long='fuzzy', long='fuzzy',
kwargs={'enabled' : True}, kwargs={'enabled' : True},
description='Perform fuzzy hash matching on files/directories'), description='Perform fuzzy hash matching on files/directories'),
binwalk.module.ModuleOption(short='c', binwalk.module.ModuleOption(short='t',
long='cutoff', long='cutoff',
nargs=1, nargs=1,
priority=100, priority=100,
......
...@@ -5,7 +5,6 @@ import platform ...@@ -5,7 +5,6 @@ import platform
import binwalk.module import binwalk.module
import binwalk.common as common import binwalk.common as common
from binwalk.compat import * from binwalk.compat import *
from binwalk.modules.configuration import Configuration
# TODO: This code is an effing mess. # TODO: This code is an effing mess.
class HexDiff(binwalk.module.Module): class HexDiff(binwalk.module.Module):
...@@ -23,9 +22,8 @@ class HexDiff(binwalk.module.Module): ...@@ -23,9 +22,8 @@ class HexDiff(binwalk.module.Module):
'blue' : '34', 'blue' : '34',
} }
DEPENDS = {'config' : Configuration} TITLE = "Binary Diffing"
NAME = "Binary Diffing"
CLI = [ CLI = [
binwalk.module.ModuleOption(short='W', binwalk.module.ModuleOption(short='W',
long='hexdump', long='hexdump',
......
...@@ -5,13 +5,10 @@ import binwalk.parser ...@@ -5,13 +5,10 @@ import binwalk.parser
import binwalk.filter import binwalk.filter
import binwalk.smartsignature import binwalk.smartsignature
from binwalk.compat import * from binwalk.compat import *
from binwalk.modules.configuration import Configuration
class Signature(binwalk.module.Module): class Signature(binwalk.module.Module):
DEPENDS = {'config' : Configuration} TITLE = "Signature Scan"
NAME = "Signature Scan"
CLI = [ CLI = [
binwalk.module.ModuleOption(short='B', binwalk.module.ModuleOption(short='B',
...@@ -32,8 +29,8 @@ class Signature(binwalk.module.Module): ...@@ -32,8 +29,8 @@ class Signature(binwalk.module.Module):
binwalk.module.ModuleKwarg(name='magic_files', default=[]), binwalk.module.ModuleKwarg(name='magic_files', default=[]),
] ]
HEADER = "BINWALK" HEADER = ["DECIMAL", "HEX", "DESCRIPTION"]
HEADER_FORMAT = "%s\n" HEADER_FORMAT = "%-12s %-12s %s\n"
RESULT = ["offset", "offset", "description"] RESULT = ["offset", "offset", "description"]
RESULT_FORMAT = "%-12d 0x%-12X %s\n" RESULT_FORMAT = "%-12d 0x%-12X %s\n"
......
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