<s> import os <EOL> import re <EOL> import ctypes <EOL> import fnmatch <EOL> import binwalk . core . C <EOL> import binwalk . core . common <EOL> from binwalk . core . compat import * <EOL> from binwalk . core . module import Module , Option , Kwarg <EOL> class HashResult ( object ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , name , hash = None , strings = None ) : <EOL> self . name = name <EOL> self . hash = hash <EOL> self . strings = strings <EOL> class HashMatch ( Module ) : <EOL> '''<STR_LIT>''' <EOL> DEFAULT_CUTOFF = <NUM_LIT:0> <EOL> CONSERVATIVE_CUTOFF = <NUM_LIT> <EOL> TITLE = "<STR_LIT>" <EOL> CLI = [ <EOL> Option ( short = '<STR_LIT:F>' , <EOL> long = '<STR_LIT>' , <EOL> kwargs = { '<STR_LIT>' : True } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:u>' , <EOL> long = '<STR_LIT>' , <EOL> priority = <NUM_LIT:100> , <EOL> type = int , <EOL> kwargs = { '<STR_LIT>' : DEFAULT_CUTOFF } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:S>' , <EOL> long = '<STR_LIT>' , <EOL> kwargs = { '<STR_LIT>' : True } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:s>' , <EOL> long = '<STR_LIT>' , <EOL> kwargs = { '<STR_LIT>' : True , '<STR_LIT>' : CONSERVATIVE_CUTOFF } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:p>' , <EOL> long = '<STR_LIT>' , <EOL> kwargs = { '<STR_LIT>' : False , '<STR_LIT>' : CONSERVATIVE_CUTOFF } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:n>' , <EOL> long = '<STR_LIT:name>' , <EOL> kwargs = { '<STR_LIT>' : True } , <EOL> description = '<STR_LIT>' ) , <EOL> Option ( short = '<STR_LIT:L>' , <EOL> long = '<STR_LIT>' , <EOL> kwargs = { '<STR_LIT>' : True } , <EOL> description = "<STR_LIT>" ) , <EOL> ] <EOL> KWARGS = [ <EOL> Kwarg ( name = '<STR_LIT>' , default = DEFAULT_CUTOFF ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = True ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = None ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> Kwarg ( name = '<STR_LIT>' , default = False ) , <EOL> ] <EOL> LIBRARY_NAME = "<STR_LIT>" <EOL> LIBRARY_FUNCTIONS = [ <EOL> binwalk . core . C . Function ( name = "<STR_LIT>" , type = int ) , <EOL> binwalk . core . C . Function ( name = "<STR_LIT>" , type = int ) , <EOL> binwalk . core . C . Function ( name = "<STR_LIT>" , type = int ) , <EOL> ] <EOL> FUZZY_MAX_RESULT = <NUM_LIT> <EOL> FUZZY_MIN_FILE_SIZE = <NUM_LIT> <EOL> HEADER_FORMAT = "<STR_LIT>" + "<STR_LIT:U+0020>" * <NUM_LIT:11> + "<STR_LIT>" <EOL> RESULT_FORMAT = "<STR_LIT>" + "<STR_LIT:U+0020>" * <NUM_LIT> + "<STR_LIT>" <EOL> HEADER = [ "<STR_LIT>" , "<STR_LIT>" ] <EOL> RESULT = [ "<STR_LIT>" , "<STR_LIT:description>" ] <EOL> def init ( self ) : <EOL> self . total = <NUM_LIT:0> <EOL> self . last_file1 = HashResult ( None ) <EOL> self . last_file2 = HashResult ( None ) <EOL> self . lib = binwalk . core . C . Library ( self . LIBRARY_NAME , self . LIBRARY_FUNCTIONS ) <EOL> def _get_strings ( self , fname ) : <EOL> return '<STR_LIT>' . join ( list ( binwalk . core . common . strings ( fname , minimum = <NUM_LIT:10> ) ) ) <EOL> def _show_result ( self , match , fname ) : <EOL> if self . abspath : <EOL> fname = os . path . abspath ( fname ) <EOL> if match < <NUM_LIT:100> : <EOL> fname = '<STR_LIT:U+0020>' + fname <EOL> if match < <NUM_LIT:10> : <EOL> fname = '<STR_LIT:U+0020>' + fname <EOL> self . result ( percentage = match , description = fname , plot = False ) <EOL> def _compare_files ( self , file1 , file2 ) : <EOL> '''<STR_LIT>''' <EOL> status = <NUM_LIT:0> <EOL> file1_dup = False <EOL> file2_dup = False <EOL> if not self . filter_by_name or os . path . basename ( file1 ) == os . path . basename ( file2 ) : <EOL> if os . path . exists ( file1 ) and os . path . exists ( file2 ) : <EOL> hash1 = ctypes . create_string_buffer ( self . FUZZY_MAX_RESULT ) <EOL> hash2 = ctypes . create_string_buffer ( self . FUZZY_MAX_RESULT ) <EOL> if file1 == self . last_file1 . name and self . last_file1 . hash : <EOL> file1_dup = True <EOL> else : <EOL> self . last_file1 . name = file1 <EOL> if file2 == self . last_file2 . name and self . last_file2 . hash : <EOL> file2_dup = True <EOL> else : <EOL> self . last_file2 . name = file2 <EOL> try : <EOL> if self . strings : <EOL> if file1_dup : <EOL> file1_strings = self . last_file1 . strings <EOL> else : <EOL> self . last_file1 . strings = file1_strings = self . _get_strings ( file1 ) <EOL> if file2_dup : <EOL> file2_strings = self . last_file2 . strings <EOL> else : <EOL> self . last_file2 . strings = file2_strings = self . _get_strings ( file2 ) <EOL> if file1_strings == file2_strings : <EOL> return <NUM_LIT:100> <EOL> else : <EOL> if file1_dup : <EOL> hash1 = self . last_file1 . hash <EOL> else : <EOL> status |= self . lib . fuzzy_hash_buf ( file1_strings , len ( file1_strings ) , hash1 ) <EOL> if file2_dup : <EOL> hash2 = self . last_file2 . hash <EOL> else : <EOL> status |= self . lib . fuzzy_hash_buf ( file2_strings , len ( file2_strings ) , hash2 ) <EOL> else : <EOL> if file1_dup : <EOL> hash1 = self . last_file1 . hash <EOL> else : <EOL> status |= self . lib . fuzzy_hash_filename ( file1 , hash1 ) <EOL> if file2_dup : <EOL> hash2 = self . last_file2 . hash <EOL> else : <EOL> status |= self . lib . fuzzy_hash_filename ( file2 , hash2 ) <EOL> if status == <NUM_LIT:0> : <EOL> if not file1_dup : <EOL> self . last_file1 . hash = hash1 <EOL> if not file2_dup : <EOL> self . last_file2 . hash = hash2 <EOL> if hash1 . raw == hash2 . raw : <EOL> return <NUM_LIT:100> <EOL> else : <EOL> return self . lib . fuzzy_compare ( hash1 , hash2 ) <EOL> except Exception as e : <EOL> binwalk . core . common . warning ( "<STR_LIT>" % str ( e ) ) <EOL> return None <EOL> def is_match ( self , match ) : <EOL> '''<STR_LIT>''' <EOL> return ( match is not None and ( ( match >= self . cutoff and self . same ) or ( match < self . cutoff and not self . same ) ) ) <EOL> def _get_file_list ( self , directory ) : <EOL> '''<STR_LIT>''' <EOL> file_list = [ ] <EOL> directory = os . path . abspath ( directory ) + os . path . sep <EOL> for ( root , dirs , files ) in os . walk ( directory ) : <EOL> root = '<STR_LIT>' . join ( root . split ( directory , <NUM_LIT:1> ) [ <NUM_LIT:1> : ] ) <EOL> files = [ os . path . join ( root , f ) for f in files if self . symlinks or not os . path . islink ( f ) ] <EOL> file_list += files <EOL> return set ( file_list ) <EOL> def hash_files ( self , needle , haystack ) : <EOL> '''<STR_LIT>''' <EOL> self . total = <NUM_LIT:0> <EOL> for f in haystack : <EOL> m = self . _compare_files ( needle , f ) <EOL> if m is not None and self . is_match ( m ) : <EOL> self . _show_result ( m , f ) <EOL> self . total += <NUM_LIT:1> <EOL> if self . max_results and self . total >= self . max_results : <EOL> break <EOL> def hash_file ( self , needle , haystack ) : <EOL> '''<STR_LIT>''' <EOL> matching_files = [ ] <EOL> self . total = <NUM_LIT:0> <EOL> done = False <EOL> for directory in haystack : <EOL> for f in self . _get_file_list ( directory ) : <EOL> f = os . path . join ( directory , f ) <EOL> m = self . _compare_files ( needle , f ) <EOL> if m is not None and self . is_match ( m ) : <EOL> self . _show_result ( m , f ) <EOL> matching_files . append ( ( m , f ) ) <EOL> self . total += <NUM_LIT:1> <EOL> if self . max_results and self . total >= self . max_results : <EOL> done = True <EOL> break <EOL> if done : <EOL> break <EOL> return matching_files <EOL> def hash_directories ( self , needle , haystack ) : <EOL> '''<STR_LIT>''' <EOL> done = False <EOL> self . total = <NUM_LIT:0> <EOL> source_files = self . _get_file_list ( needle ) <EOL> for directory in haystack : <EOL> dir_files = self . _get_file_list ( directory ) <EOL> for source_file in source_files : <EOL> for dir_file in dir_files : <EOL> file1 = os . path . join ( needle , source_file ) <EOL> file2 = os . path . join ( directory , dir_file ) <EOL> m = self . _compare_files ( file1 , file2 ) <EOL> if m is not None and self . is_match ( m ) : <EOL> self . _show_result ( m , "<STR_LIT>" % ( file1 , file2 ) ) <EOL> self . total += <NUM_LIT:1> <EOL> if self . max_results and self . total >= self . max_results : <EOL> done = True <EOL> break <EOL> if done : <EOL> break <EOL> def run ( self ) : <EOL> '''<STR_LIT>''' <EOL> needle = self . config . files [ <NUM_LIT:0> ] <EOL> haystack = self . config . files [ <NUM_LIT:1> : ] <EOL> self . header ( ) <EOL> if os . path . isfile ( needle ) : <EOL> if os . path . isfile ( haystack [ <NUM_LIT:0> ] ) : <EOL> self . hash_files ( needle , haystack ) <EOL> else : <EOL> self . hash_file ( needle , haystack ) <EOL> else : <EOL> self . hash_directories ( needle , haystack ) <EOL> self . footer ( ) <EOL> return True </s>
