Commit f9ed24d4 by devttys0

Re-wrote hexdiff plugin.

parent fd62df46
...@@ -45,11 +45,11 @@ class Filter(object): ...@@ -45,11 +45,11 @@ class Filter(object):
INVALID_RESULT = "invalid" INVALID_RESULT = "invalid"
NON_PRINTABLE_RESULT = "\\" NON_PRINTABLE_RESULT = "\\"
def __init__(self, show_invalid_results=False): def __init__(self, show_invalid_results=None):
''' '''
Class constructor. Class constructor.
@show_invalid_results - Set to True to display results marked as invalid. @show_invalid_results - A function to call that will return True to display results marked as invalid.
Returns None. Returns None.
''' '''
...@@ -144,7 +144,7 @@ class Filter(object): ...@@ -144,7 +144,7 @@ class Filter(object):
return False return False
# If showing invalid results, just return True without further checking. # If showing invalid results, just return True without further checking.
if self.show_invalid_results: if callable(self.show_invalid_results) and self.show_invalid_results():
return True return True
# Don't include quoted strings or keyword arguments in this search, as # Don't include quoted strings or keyword arguments in this search, as
......
...@@ -109,7 +109,7 @@ class General(Module): ...@@ -109,7 +109,7 @@ class General(Module):
self._open_target_files() self._open_target_files()
self._set_verbosity() self._set_verbosity()
self.filter = binwalk.core.filter.Filter(self.show_invalid) self.filter = binwalk.core.filter.Filter(self._display_invalid)
# Set any specified include/exclude filters # Set any specified include/exclude filters
for regex in self.exclude_filters: for regex in self.exclude_filters:
...@@ -184,3 +184,5 @@ class General(Module): ...@@ -184,3 +184,5 @@ class General(Module):
except Exception as e: except Exception as e:
self.error(description="Cannot open file : %s" % str(e)) self.error(description="Cannot open file : %s" % str(e))
def _display_invalid(self):
return self.show_invalid
import os import os
import sys import sys
import curses import curses
import string
import platform import platform
import binwalk.core.common as common import binwalk.core.common as common
from binwalk.core.compat import * from binwalk.core.compat import *
from binwalk.core.module import Module, Option, Kwarg from binwalk.core.module import Module, Option, Kwarg
# TODO: This code is an effing mess.
class HexDiff(Module): class HexDiff(Module):
ALL_SAME = 0 ALL_SAME = 0
...@@ -22,6 +22,8 @@ class HexDiff(Module): ...@@ -22,6 +22,8 @@ class HexDiff(Module):
'blue' : '34', 'blue' : '34',
} }
SEPERATORS = ['\\', '/']
TITLE = "Binary Diffing" TITLE = "Binary Diffing"
CLI = [ CLI = [
...@@ -55,9 +57,8 @@ class HexDiff(Module): ...@@ -55,9 +57,8 @@ class HexDiff(Module):
Kwarg(name='enabled', default=False), Kwarg(name='enabled', default=False),
] ]
HEADER_FORMAT = "\n%s\n" RESULT_FORMAT = "0x%.8X %s\n"
RESULT_FORMAT = "%s\n" RESULT = ['offset', 'description']
RESULT = ['description']
def _no_colorize(self, c, color="red", bold=True): def _no_colorize(self, c, color="red", bold=True):
return c return c
...@@ -78,31 +79,121 @@ class HexDiff(Module): ...@@ -78,31 +79,121 @@ class HexDiff(Module):
if self.show_blue and blue in data: if self.show_blue and blue in data:
return True return True
if self.show_green and green in data: elif self.show_green and green in data:
return True return True
if self.show_red and red in data: elif self.show_red and red in data:
return True return True
return False return False
def hexascii(self, target_data, byte, offset):
diff_count = 0
for (fp, data) in iterator(target_data):
try:
if data[offset] != byte:
diff_count += 1
except IndexError as e:
diff_count += 1
if diff_count == len(target_data)-1:
color = "red"
elif diff_count > 0:
color = "blue"
else:
color = "green"
hexbyte = self.colorize("%.2X" % ord(byte), color)
if byte not in string.printable or byte in string.whitespace:
byte = "."
asciibyte = self.colorize(byte, color)
return (hexbyte, asciibyte)
def diff_files(self, target_files):
loop_count = 0
while True:
line = ""
done_files = 0
block_data = {}
seperator = self.SEPERATORS[loop_count % 2]
for fp in target_files:
block_data[fp] = fp.read(self.block)
if not block_data[fp]:
done_files += 1
# No more data from any of the target files? Done.
if done_files == len(target_files):
break
for fp in target_files:
hexline = ""
asciiline = ""
for i in range(0, self.block):
if i >= len(block_data[fp]):
hexbyte = "XX"
asciibyte = "."
else:
(hexbyte, asciibyte) = self.hexascii(block_data, block_data[fp][i], i)
hexline += "%s " % hexbyte
asciiline += "%s" % asciibyte
line += "%s |%s|" % (hexline, asciiline)
if self.terse:
break
if fp != target_files[-1]:
line += " %s " % seperator
self.result(offset=(fp.offset + (self.block * loop_count)), description=line)
loop_count += 1
def init(self): def init(self):
block = self.config.block # Disable the invalid description auto-filtering feature.
if not block: # This will not affect our own validation.
block = self.DEFAULT_BLOCK_SIZE self.config.show_invalid = True
# Set the block size (aka, hexdump line size)
self.block = self.config.block
if not self.block:
self.block = self.DEFAULT_BLOCK_SIZE
# Build a list of files to hexdiff
self.hex_target_files = [x for x in iter(self.next_file, None)]
# Build the header format string
header_width = (self.block * 4) + 2
if self.terse: if self.terse:
header_files = self.config.target_files[:1] file_count = 1
else: else:
header_files = self.config.target_files file_count = len(self.hex_target_files)
self.HEADER_FORMAT = "OFFSET " + ("%%-%ds " % header_width) * file_count
self.HEADER = self._build_header(header_files, block) # Build the header argument list
self.HEADER = [fp.name for fp in self.hex_target_files]
if self.terse and len(self.HEADER) > 1:
self.HEADER = self.HEADER[0]
# Set up the tty for colorization, if it is supported
if hasattr(sys.stderr, 'isatty') and sys.stderr.isatty() and platform.system() != 'Windows': if hasattr(sys.stderr, 'isatty') and sys.stderr.isatty() and platform.system() != 'Windows':
curses.setupterm() curses.setupterm()
self.colorize = self._colorize self.colorize = self._colorize
else: else:
self.colorize = self._no_colorize self.colorize = self._no_colorize
def run(self): def validate(self, result):
result.valid = self._color_filter(result.description)
return True def run(self):
if self.hex_target_files:
self.header()
self.diff_files(self.hex_target_files)
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