diff --git a/README.md b/README.md index 194e3ca..df5c021 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This code is for automated analysis of files you may find around the internet. P The original version had been built in 2007. In the last weeks, i had started to fix a lot of code, add features or clean some parts up. -FirmwareFudger is far from what it's goal is, but it is already handy :) +FirmwareFudger is far from what it's in my head, but it is already handy :) ## How to use the tool: diff --git a/ReleaseNotes_0.5.2.txt b/ReleaseNotes_0.5.2.txt new file mode 100644 index 0000000..abe7be0 --- /dev/null +++ b/ReleaseNotes_0.5.2.txt @@ -0,0 +1,24 @@ +Release Notes 0.5.2 +=================== + +After quite some time, i decided to spend some dedication to this old tool i had written. There +lies over a decade between v0.3 and the current version 0.5.2. + +Improvements: + +* FF has been ported to python3 +* speed, 0.3 had a naive approach of parsing files, with a lot of extra requests, + this had been changed, the speed improovements are over 300 times, so analysis of a firmware + currently takes some seconds +* bugs been fixed, one long term bug, was the always wrong suffix of a file type, this is + normally no problem, however tools like gzip do not like it if .gz is missing, so i fixed + the issue +* code cleanups and refactory, had been done a lot, and there is still a lot to add +* using argparse over getopt, as argparse is simply the better and more supportive alternative +* there is an experimental method called strings, while the normal version is known to + everyone, this version also does an analysis to dig up some more information about the file + more code and explanations will come +* FF is now working with threads, which has some extra time improvements during analysis +* FF is now using Queues at several stages + + diff --git a/ffudger.py b/ffudger.py new file mode 100755 index 0000000..0732d4b --- /dev/null +++ b/ffudger.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +# +# by dash in 2019 +############################ + + +import os +import sys +import argparse +import threading + +from lib.FUDGEanalyse import * +from lib.FUDGEheader import * + +#maybe put that later somewhere else +extractit=0 +fileReport=0 + +def fudge_banner(): + ff=ANALYSE() + print ("[+] FirmareFudger %s by dash" % ff.__version__) + print ("[+] tool for firmware analyses, May 2019") + print ("[+] ") + print ("[+] contact: d4shmail@gmail.com") + print + ff=[] + +def ff_fudge_routine(ff): + ''' the classic ffudger routine + patched and fixed up a bit :) + ''' + #print the banner :D + #fudge_banner() + + + # print some basic information + ff.printargs() + + true=0 + # check if only one plugin shall be tested + if ff.lonelyplugin!=None: + lonely=ff.lonelyplugin + for category in FUDGEheader.TYPES.keys(): + for plugin in FUDGEheader.TYPES[category].keys(): + if ff.lonelyplugin == FUDGEheader.TYPES[category][plugin][FUDGEheader.NAME]: + print ('[+] Analyzing for %s' % ff.lonelyplugin) + # checkheader etc.pp. + ff.fftype=lonely + + # fill the targetqueue + ff.ff_fill_targetqueue(category,plugin) + + # run the check routine + ff.checkheader() + + # check if only a group shall be tested + elif ff.ff_cat!=None: + + if ff.ff_cat in FUDGEheader.TYPES_DEF: + #print (ff.ff_cat) + category=FUDGEheader.TYPES_DEF[ff.ff_cat] + + #only check for the asked TYPE + print ("[+] Testing only for %s plugins" % (ff.ff_cat)) + for plugin in range(len(TYPES[category])): + # fill the targetqueue + ff.ff_fill_targetqueue(category,plugin) + + # check the file + ff.checkheader() + + else: + print ("[-] Unkown plugin class %s !" % ff.plugin) + sys.exit(1) + + + # if not one_plugin is choosen and also not the ff_cat + # we do check for all FF plugins + elif ff.ff_cat == None and ff.lonelyplugin==None: + print ('[+] Checking for all FF plugins') + + #check for all TYPES + for category in range(len(TYPES)): + #print (len(TYPES)) + + #print (TYPES[category]) + for plugin in range(len(TYPES[category])): + #print (len(TYPES[testtype])) + + # set the fftype + ff.fftype=TYPES[category][plugin][3] + + # fill the targetqueue + ff.ff_fill_targetqueue(category,plugin) + + # call the check_routine + #ff_check_routine(ff) + ff.checkheader() + + # ok, something went wrong + else: + + # was not able to find the named plugin + print ('[-] Sorry, something went wrong.\n[?] Execute tool with -Fl to see a complete fudger plugin list.') + return 1; + + # If a report needs to be created, create it now + #generateFilereport(ff) + + #print (ff.result_queue.qsize()) + + # hm, should work :> + while True: + if len(ff.thread_list)>0: + # print ('[.] Waiting for threads to finish %d' % (len(ff.thread_list))) + time.sleep (0.1); + for entry in ff.thread_list: + if (entry.isAlive())==False: + entry.join() + ff.thread_list.remove(entry) + else: + break + + # If extract data has been choosen, extract it now + ff.extractdata() + + # do strings analysis + if ff.str_analysis: + ff.strings_search() + + return 0; + + +def run(args): + ''' main run function, let the fun begin''' + + # instanciate FUDGEanalysis Class + ff=ANALYSE() + + # Preparations before we can analyse a file + + # set threads if given + if args.threads: + ff.thread_cnt=args.threads + + # show FirmwareFudgers Plugin Database, and return + if args.fudgelist: + ff.showplugins() + return 0; + + # show FirmwareFudgers Plugin Database, and return + #print (args.fudgelist_cat) + if args.fudgelist_cat: + ff.showplugins(cat=args.fudgelist_cat) + return 0; + + # set the file to analyse + if args.infile: + ff.infile=args.infile + + + # set the prefix for every extracted file + # default: FF-Extract + if args.outprefix: + ff.outprefix=args.outprefix + + # set the output directory + if args.outdir: + ff.outdir=args.outdir + # check if directory exists, if not create it + # if an error comes along, we abort the complete operation + if not ff.create_dir(): + print ('[-] Abort.') + + # create a report + if args.create_report: + ff.create_report=args.create_report + + # use only one specific plugin + ff.lonelyplugin=args.lonelyplugin + + # use only specific plugin group + ff.ff_cat=args.ff_cat + + # set extract to true + if args.extract: + ff.extract=True + ff.create_dir() + + + # set verbose mode + if args.verbose: + ff.verbose=True + + # set debug mode + if args.debug: + ff.debug=True + + # show version + #print (args.version) + if args.version==True: + fudge_banner() + return 0; + + # add flag if strings analysis is wanted + if args.strings == True: + ff.str_analysis=True + ff.str_minlen=args.str_minlen + ff.str_filter=args.str_filter + + # try to open our target file + if ff.openfile()==-1: + sys.exit(1) + + # use ff method + if args.fudge: + ff_fudge_routine(ff) + + +def main(): + ''' yay, we got a main :)''' + + ff=ANALYSE() + __tool__ = ff.__tool__ + __version__ = ff.__version__ + __author__ = ff.__author__ + __date__ = ff.__date__ + + parser_desc = 'FirmwareFudger, written to do better firmware analysis' + prog_desc = __tool__ + ' v' + __version__ + ' by ' + __author__ + ' (' + __date__ + ')' + parser = argparse.ArgumentParser(prog = prog_desc, description=parser_desc) + parser.add_argument('-f','--input-file',action="store",dest='infile',required=False,help='define the file to analyze') + parser.add_argument('-o','--outdir',action="store",dest='outdir',required=False,help='define the directory to save extracted files and logs to') + parser.add_argument('-O','--output-prefix',action="store",dest='outprefix',required=False,help='define the prefix for the extracted name (default: FF-Extract)') + parser.add_argument('-x','--extract',action="store_true",dest='extract',required=False,help='flag if you want to extract found files', default=False) + parser.add_argument('-F','--fudge',action="store_true",dest='fudge',required=False,help='use fudge mode (FirmwareFudgers own database)',default=True) + parser.add_argument('-S','--strings',action="store_true",dest='strings',required=False,help='run strings on file and conduct analysis',default=False) + parser.add_argument('-Sl','--strings-len',action="store",dest='str_minlen',required=False,help='the minimum length for string check',default=4, type=int) + parser.add_argument('-Sf','--strings-filter',action="store",dest='str_filter',required=False,help='the strings check filter, use regular expressions',default="([a-zA-Z0-9 \.\-]{7,})") + parser.add_argument('-M','--magic',action="store_true",dest='magic',required=False,help='use magic mode (libmagic database)',default=True) + parser.add_argument('-Fp','--fudge-plugin',action="store",dest='lonelyplugin',required=False,help='run only one specified plugin test',default=None) + parser.add_argument('-Fc','--fudge-category',action="store",dest='ff_cat',required=False,help='run only a section of possible plugins (e.g. EXEC)',default=None) + parser.add_argument('-Fl','--fudge-list',action="store_true",dest='fudgelist',required=False,help='show plugins of FirmwareFudger',default=False) + parser.add_argument('-Flc','--fudge-list-cat',action="store",dest='fudgelist_cat',required=False,help='show plugins of defined group',default=False) + parser.add_argument('--threads',action="store",dest='threads',required=False,help='define the value of maximum threads used, default is 20',default=None,type=int) + parser.add_argument('-v','--verbose',action="store_true",dest='verbose',required=False,help='run in verbose mode',default=False) + parser.add_argument('--debug',action="store_true",dest='debug',required=False,help='run in debug mode',default=False) + parser.add_argument('-r','--report',action="store_true",dest='create_report',required=False,help='create a report for the session',default=False) + parser.add_argument('-V','--version',action="store_true",dest='version',required=False,help='show version and tool information',default=False) + + args = parser.parse_args() + + # if no argument is given help is printed + if len(sys.argv)<2: + parser.print_help() + sys.exit(1) + + run(args) + +if __name__ == "__main__": + main() diff --git a/lib/FUDGEanalyse.py b/lib/FUDGEanalyse.py new file mode 100755 index 0000000..ea0388b --- /dev/null +++ b/lib/FUDGEanalyse.py @@ -0,0 +1,596 @@ + +import re +import os +import sys +import queue +import time +import struct +import binascii +import threading + +import lib.FUDGEheader as FUDGEheader +from lib.FUDGEheader import TYPES + +nor=0x1 +ver=0x2 +dbg=0x3 + +def dbgprint(): + print ("nothing") + +class ANALYSE(object): + + def __init__(self): + + """ + infile - the file to analyse + stat - os.stat results of self.infile + fftype - the current type of pattern test + plugin - choosen pluginclass to test for + lonelyplugin- choosen lonely plugin for test + fd - the filedescriptor of open and close + search - the search string/bytes + string - for convert2hex + data - the binary data field, where the bytes are filled in + offset - the offset delivered back for writing to self.cut + extract_cnt - number of the found files in file + extract - shall we extract anything? + cut - dict for offsets for the extractfile method + outdir - output directory for putting files + outname - name of the output files part + reportfile - name of the status report + files - list with paths of extracted files + """ + + # not in use yet + # self.threads = [] # list of overall threads + # self.thread_cnt = 20 # amount of threads + + # erm, check what those are used for :> + self.string="" + self.data=[] + + # ff magic search variables + # FIXME must get cleaned up + self.target_queue=queue.Queue() # all plugins to test + self.result_queue=queue.Queue() # all results from the test + self.offset=0 # offset for self.cut, does not need to be global + self.cut={} # this will be replaced with result_queue + self.set_offset=0 # ?? + self.set_string=0 # ?? + self.length=0 # does not need to be global, can also migrate to local + + # category and plugin variables + # what a MESS, this *must* get cleaned up + # FIXME + self.fftype=None # type of the pattern test, see header files + self.ff_cat=None # category to test for + self.plugin=None # pluginclass to test for + self.lonelyplugin=None # one plugin test only, named lonely plugin + self.search=None + + # threading variables + self.thread_cnt=20 # default value of concurrent threads is 20 + self.thread_alive=0 # variable for actually running threads + self.thread_list=[] # list for all active threads, not active gets removed + + # file variables + self.fd=None # filedescriptor of target file + self.instat=None # results of os.stat against infile + self.infile=None # the file to analyze + + # output variables + self.outdir=None # output directory + self.outprefix="FF-Extract" # prefix of every file written to output directory + + # reporting variables + self.report=False # generate report if variable is True + self.reportname=None # name of the status report file + self.reportfiles=[] # list of files extracted files, for reporting + + # logging options + self.debug=False + self.verbose=False + + # extraction variables + self.extract=False # extract found files if variable is True + self.extract_cnt=0 # number of files found + + + # variables for strings search mechanism + self.str_analysis=False + self.str_minlen=4 + self.str_filter="([a-zA-Z0-9 \.\-]{"+str(self.str_minlen)+",})" + self.str_resdict={} + self.str_anadict={} + + # misc tool variables + self.__author__="dash" + self.__version__="0.5.2" + self.__tool__="FirmwareFudger" + self.__date__="May of 2019" + + + def privileges(self): + if self.stat.st_uid != os.getuid(): + print ("[!] Attention file owner is %d" % self.stat.st_uid) + return False; + else: + return True; + + def ffprint(self,data,level): + ''' printing wrapper for: + * normal + * verbose + * debug + output + ''' + + if self.verbose==True and level==ver: + print (data) + elif self.debug==True and level==dbg: + print (data) + elif level==nor: + print (data) + + return 0; + + def printargs(self): + ''' output information about the file + ''' + + size=self.instat.st_size + Kilo=1024.0 + Mega=1048576.0 + + print ("[+] Fudger Version %s - Fileinformation" % self.__version__) + print ("[+] Filename %s" % self.infile) + + if size<=Mega: + sizeK=size/Kilo + print ("[+] Size %.2fK - %dB" % (sizeK,size)) + + elif size>=Mega: + sizeM=size/Mega + sizeK=size/Kilo + print ("[+] Size %.2fM - %.2fK - %dB" % (sizeM,sizeK,size)) + else: + print ("[+] Size %d" % size) + + print ("[+] User %d" % self.instat.st_uid) + print ("[+] Group %d" % self.instat.st_gid) + #print "[+] Search for %s" % self.search + + def openfile_fd(self): + ''' simple open file operation and return fd + ''' + + try: + self.instat=os.stat(self.infile) + #print ("[+] Open %s" % (self.infile)) + fd=open(self.infile,"rb") + except PermissionError as e: + print ('[-]',e) + return -1 + except IsADirectoryError as e: + print ('[-]',e) + return -1 + except FileNotFoundError as e: + print ('[-]',e) + return -1 + + return fd; + + def openfile(self): + ''' simple open file operation + ''' + + try: + self.instat=os.stat(self.infile) + print ("[+] Open %s" % (self.infile)) + self.fd=open(self.infile,"rb") + except PermissionError as e: + print ('[-]',e) + return -1 + except IsADirectoryError as e: + print ('[-]',e) + return -1 + except FileNotFoundError as e: + print ('[-]',e) + return -1 + + def closefile(self): + ''' simple closefile operaiton''' + + print ("[+] Close %s" % self.infile) + self.fd.close() + + def create_dir(self): + ''' method for checking outdir and properties + and order creation + ''' + if self.outdir != None: + try: + result=os.stat(self.outdir) + return 0; + + except FileNotFoundError as e: + self.__create_dir() + elif self.outdir==None and self.extract==True: + # self.outdir is not specified, but it has been asked to extract data + # let us generate a directory for that usecase + dirname = self.infile.replace('/','_') + dirname = dirname.replace('..','_') + dirname = dirname.replace('.','_') + dirname = dirname.replace('!','_') + dirname = dirname.replace('-','_') + dirname = dirname.lower() + self.outdir=dirname + try: + result=os.stat(self.outdir) + return 0; + + except FileNotFoundError as e: + self.__create_dir() + return 0; + + + + + + + def __create_dir(self): + ''' this function tests if the output directory does exist, if not a new + one is created. if the name exists but it is not a directory + an error is thrown and the process is aborted. + ''' + + try: + print ("[+] Creating directory %s" % (self.outdir)) + os.mkdir(self.outdir) + return(0) + except OSError as e: + print ("[-] Error %d %s" % (e.args[0], e.args[1])) + return(1) + + def convert2array(self): + + for byte in range(len(self.string)): + print ("\'%c\'," % self.string[byte],) + + def ff_fill_targetqueue(self,category,plugin): + ''' here starts the calls for the magic behind the scenes + category and plugin type are delivered and the target queue is build up + + self.target_queue - consists of all information necessary for finding magic and + later extraction + ''' + # print (TYPES[testtype][plugin]) + header1=TYPES[category][plugin][1] + header2=TYPES[category][plugin][2] + name=TYPES[category][plugin][3] + desc=TYPES[category][plugin][4] + suffix=TYPES[category][plugin][5] + + # now fill up the target queue + self.target_queue.put({ 'category':category,\ + 'plugin':plugin,\ + 'Header1':header1,\ + 'Header2':header2,\ + 'name':name,\ + 'desc':desc,\ + 'suffix':suffix}) + + #print (self.target_queue.qsize()) + return 0; + + + def __checkheader(self,target): + ''' new version of checkheader, that time with impressive speed + as a simpler search algorithm is used and an awesome class: re + and not working :( + ''' + + fd=self.openfile_fd() + + #print ('[d] __checkheader') + + header1=target['Header1'] + category=target['category'] + plugin=target['plugin'] + suffix=target['suffix'] + name=target['name'] + hh='' + cut={} + + # due a not sooo good design of ff database this has to be done + # obviously ff database needs a redesign :) + for i in header1: + hh = hh+i + + # lets create our re pattern + hh = re.escape(hh) + hh=bytes(hh,'latin-1') + re_comp=re.compile(hh) + + #print ('[v] Checking %s' % target['name']) + #print ('[d] Header1:',header1) + #print ('[d] HH:',hh) + + for match in re.finditer(re_comp, fd.read()): + #print('match', match.span()) + #print('match.group',match.group()) + + offstart, offend = match.span() + print ("[+] FOUND %s at Offset %d to %d" % (target['name'],offstart,offend)) + #print(match.span(), match.group()) + dataend=self.instat.st_size + cut={'offstart':offstart,'offend':offend,'dataend':dataend,'category':category,'plugin':plugin,'suffix':suffix} + #print ('checkheader:',cut) + self.result_queue.put(cut) +# self.str_resdict[match.span()]=match.group() + + cut={} + self.extract_cnt+=1 + + fd.close() + + def checkheader(self): + ''' threaded checkheader wrapper + ''' + + while self.target_queue.qsize()>0: + # set current thread count + self.thread_alive=len(self.thread_list) + # check if we have crossed the limit of maximum threads + if self.thread_alive0: + + # place result in target variable + target = self.result_queue.get() + + #cut[self.extract_cnt]=(offstart,offend,dataend,category,plugin,suffix) + +# print (target) +# print (len(target)) + + offstart=target['offstart'] + suffix=target['suffix'] + if suffix==None: + suffix='' + + # go to start of file + exo_file.seek(0,0) + exo_file.seek(offstart,0) + + #print (self.cut) + #print (self.cut[part]) + + FILENAME=self.outdir+"/"+self.outprefix+"-"+str(self.extract)+"-"+str(offstart)+"." + suffix + print ("[+] FILENAME: %s" % FILENAME) + try: + exw_file=open(FILENAME,"wb") + + except PermissionError as e: + print ('[-] ',e) + return -1; + + # data to write to the extracted file + # please note that currently the end of the + # original file is the end - for reasons ;) + TOWRITE=(self.instat.st_size)-offstart + + # depending on the file size this might get problematic + buf = exo_file.read() + exw_file.write(buf) + + # close the file + exw_file.close() + + #lets add it to files if reportfile shall be written + self.reportfiles.append(FILENAME) + + def generateReport(self): + print ("[+] Found %d extracted files" % len(self.files)) + print + print ("file Report") + print ("="*11) + for extracted in self.files: + #print "[+] %s " % extracted + os.spawnl(os.P_WAIT,"/usr/bin/file","file",extracted) + + def __print_categories(self): + ''' sub-method for printing all categories + ''' + print ('[+] Categories') + for cat in FUDGEheader.TYPES_DEF: + print ('\t%s' % cat) + + return 0; + + def showplugins(self,cat=None): + """ all plugins currently supported by FF own database + + """ + i=0 + if cat!=None: + if cat in FUDGEheader.TYPES_DEF: + print ("[+] Plugins:") +# print ('[v] FOUND %s' % cat) + catid = FUDGEheader.TYPES_DEF[cat] + + print ("[+] %s:" % cat) + for plugin in range(len(FUDGEheader.TYPES[catid])): + print ("\t\t- %s - %s" % (FUDGEheader.TYPES[catid][plugin][FUDGEheader.NAME],FUDGEheader.TYPES[catid][plugin][FUDGEheader.DESC])) + i+=1 + + else: + print ('[-] Category "%s" does not exist' % cat); + self.__print_categories() + return -1; + + # show all plugins supported + else: + for fftype in range(len(FUDGEheader.TYPES)): + if fftype==0: + stringtype="FS" + elif fftype==1: + stringtype="EXEC" + elif fftype==2: + stringtype="PACKERS" + elif fftype==3: + stringtype="DOCS" + elif fftype==4: + stringtype="BOOT" + elif fftype==5: + stringtype="ASM" + elif fftype==6: + stringtype="PICTURES" + elif fftype==7: + stringtype="DEVICES" + elif fftype==8: + stringtype="CRYPTO" + # elif fftype==9: + # stringtype="CRYPTO" + print ("%s:" % stringtype) + for plugin in range(len(FUDGEheader.TYPES[fftype])): + print ("\t\t- %s - %s" % (FUDGEheader.TYPES[fftype][plugin][FUDGEheader.NAME],FUDGEheader.TYPES[fftype][plugin][FUDGEheader.DESC])) + i+=1 + + print ("\n[+] Found %d plugins." % i) + print ("[+] Done") + +##################################### +# # +# strings analysis section # +# # +##################################### + + def strings_analysis(self): + ''' method for analysing and giving hints to the analyst + + self.str_resdict, the result dictionary of self.string_search method + self.str_anadict, the reuslt dictionary for self.string_analysis method + ''' + + ana = open('supply/strings.txt','r') + # read strings supply file + for line in ana.readlines(): + # is it a comment, no? then proceed + if not line.startswith('#'): + a = line.split(';') + needle=a[0] + desc=a[1] + tools=a[2] + for k in self.str_resdict.keys(): + if self.str_resdict[k].find(needle)!=-1: + self.str_anadict[needle]=(needle,desc,tools) + print ('[+] %s - %s - %s' % (needle,desc,tools)) + + print ('[+] Found %d interesting string(s) during analysis.' % len(self.str_anadict)) + + ana.close() + return 0; + + def strings_output(self): + ''' method for writing results of strings search + self.str_resdict, the result dictionary of self.string_search method + ''' + + return 0; + + def strings_search(self): + ''' this method does the work of the unix userland tool "strings" + it searches a binary for possible strings, for later manual + analysis. in this particular case an automatic analysis is added + as well to hint the analyst on something interesting found + + self.str_minlen, the default is 4 + self.str_filter, the regular expression filter + self.str_resdict, the result dictionary with string, start/end position + ''' + # variables for strings search mechanism + + self.openfile() + # print (re.findall(re_filter, str(self.fd.read()))) + + for match in re.finditer(self.str_filter, str(self.fd.read())): + #print('match', match.span()) + #print('match.group',match.group()) +# print(match.span(), match.group()) + self.str_resdict[match.span()]=match.group() + + # place this somewhere else later + self.strings_analysis() diff --git a/lib/FUDGEanalyse.pyc b/lib/FUDGEanalyse.pyc new file mode 100644 index 0000000..a72bf4a Binary files /dev/null and b/lib/FUDGEanalyse.pyc differ diff --git a/lib/FUDGEheader.py b/lib/FUDGEheader.py new file mode 100755 index 0000000..8ff60c3 --- /dev/null +++ b/lib/FUDGEheader.py @@ -0,0 +1,813 @@ +#complete list +TYPES = 0x00 + +#categories +FS = 0x00 +EXEC = 0x01 +PACKERS = 0x02 +DOCS = 0x03 +BOOT = 0x04 +ASM = 0x05 +PICTURES = 0x06 +DEVICES = 0x07 +#ROUTERS = 0x08 +CRYPTO = 0x08 + +#Filesystem Type Definitions +MSDOS = 0x00 +CRAMFS1 = 0x01 +CRAMFS2 = 0x02 #difference is another searchstring +ROM1FS = 0x03 +SQUASHFS1 = 0x04 #difference is another searchstring +SQUASHFS2 = 0x05 +FAT32 = 0x06 +CDUNIX = 0x07 +ADF = 0x08 +SGI = 0x09 +SGIXFS = 0x0a +ST40 = 0x0b +CBM = 0x0c +WINIMAGE = 0x0d +COB = 0x0e +UFS1 = 0x0f +QEMU1 = 0x10 +JFFSL = 0x11 +JFFSB = 0x12 +JFFS2L = 0x13 +JFFS2B = 0x14 +FAT12 = 0x15 +FAT16 = 0x16 + +#Executeable File Definitions +ELF = 0x00 +BFLT = 0x01 +PE = 0x02 +MSDOSCOM = 0x03 +DOSCOM = 0x04 +SPSSPORTABLE= 0x05 +SPSSSYSTEM = 0x06 +PPCPEF = 0x07 + +#Packing Specific definitions +ZIP1 = 0x00 +ZIP2 = 0x01 +BZIP = 0x02 +GZIP = 0x03 +ACE = 0x04 +TAR = 0x05 +TRX1 = 0x06 +TRX2 = 0x07 +LZMA = 0x08 +UPX = 0x09 +GNUTAR = 0x0A +CRUSH = 0x0B +HLSQZ = 0x0B +SQWEZ = 0x0C +HPAK = 0x0D +LZOP = 0x0E +MDCD = 0x0F +MSCOMPRESS = 0x10 +INSTALLSHIELD = 0x11 +PAQ = 0x12 +JARARJ = 0x13 +STUFFIT = 0x14 +VAX3 = 0x15 +VAX5 = 0x16 +ARCHIVE = 0x17 +ARCHIVEFILE = 0x18 +HRB = 0x19 +RISCOS = 0x1a +HAP = 0x1b +LIM = 0x1c +FREEZE = 0x1d +ZOO = 0x1e +RAR = 0x1f +EET = 0x20 +RZIP = 0x21 +SQSH = 0x22 +ISC = 0x23 +NWFILE = 0x24 +DSIGDCC = 0x25 +ARJ = 0x26 + +#Document Fileformats +PDF = 0x00 +DOC = 0x01 +RTF = 0x02 + +#Bootloader Definitions +UBOOT = 0x00 + +#Assembler object codes +AVR = 0x00 + +#Image Files(pictures etc.) +GIMPXCF = 0x00 + +#Devices Specific Firmware characteristics +LTRX1 = 0x00 +LTRX2 = 0x01 +WGR614BOOT = 0x02 +WGR614 = 0x03 + +#Router Specific Firmware characteristics specifications + +#Crypto stuff, certificates, keys, typical indications of crypto +DSAPRIV = 0x00 #-----BEGIN DSA PRIVATE KEY----- -----END DSA PRIVATE KEY----- +RSAPRIV = 0x01 #-----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY----- +SSHPUB = 0x02 # ssh-dss +CACERT = 0x03 #-----BEGIN CERTIFICATE----- -----END CERTIFICATE----- +CERTREQ = 0x04 #-----BEGIN CERTIFICATE REQUEST----- -----END CERTIFICATE REQUEST----- +PGPMSG = 0x05 #-----BEGIN PGP MESSAGE----- -----END PGP MESSAGE----- + +#Header definitions +HEADER1 = 0x01 #start header +HEADER2 = 0x02 #stop trailer/header +NAME = 0x03 #the format name +DESC = 0x04 #teh description +SUFFIX = 0x05 #the ending of the file, some tools want to have a proper ending, gzip for instance +CHANCE = 0x06 #chance calculator, if at least "chance" bytes are correct print out possibility... +TOOLS = 0x07 #tools of trade to work with that kind of files + + +#Filesystem Specifications +# +#still much too add +########################################### +TYPES = { FS: { \ + MSDOS:{ \ + HEADER1: ('M','Z','H','H'),\ + HEADER2: None,\ + NAME: 'MSDOS',\ + DESC: "MSDOS - Filesystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + CRAMFS1:{ \ + HEADER1: ('\x45','\x3d','\xcd','\x28'),\ + HEADER2: None,\ + NAME: 'CRAMFS1',\ + DESC: "CRAMFS - Compressed ROMFS",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + CRAMFS2:{ \ + HEADER1: ('C','o','m','p','r','e','s','s','e','d','\x20','R','O','M','F','S'),\ + HEADER2: None,\ + NAME: 'CRAMFS2',\ + DESC: "CRAMFS2 - Compressed ROMFS",\ + SUFFIX: 'img',\ + CHANCE: 8}, + + ROM1FS:{ \ + HEADER1: ('-','r','o','m','1','f','s'),\ + HEADER2: None,\ + NAME: 'ROM1FS',\ + DESC: "ROM1FS - ROM FILE SYSTEM",\ + SUFFIX: 'img',\ + CHANCE: 3}, + + SQUASHFS1:{ \ + HEADER1: ('h','s','q','s'),\ + HEADER2: None,\ + NAME: 'SQUASHFS',\ + DESC: "SQUASHFS - Big Endian",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + SQUASHFS2:{ \ + HEADER1: ('s','q','s','h'),\ + HEADER2: None,\ + NAME: 'SQUASHFS2',\ + DESC: "SQUASHFS - Little Endian",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + FAT32:{ \ + HEADER1: ('\x46','\x41','\x54','\x33','\x32'),\ + HEADER2: None,\ + NAME: 'FAT32',\ + DESC: "FAT32 - Filessystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + FAT12:{ \ + HEADER1: ('\x46','\x41','\x54','\x31','\x32'),\ + HEADER2: None,\ + DESC: "FAT12 - Filessystem",\ + NAME: 'FAT12',\ + SUFFIX: 'img',\ + CHANCE: 2}, + + FAT16:{ \ + HEADER1: ('\x46','\x41','\x54','\x31','\x36'),\ + HEADER2: None,\ + NAME: 'FAT16',\ + DESC: "FAT16 - Filessystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + CDUNIX:{ \ + HEADER1: ('\x01','\x43','\x44','\x30','\x30','\x31','\x01'),\ + HEADER2: None,\ + NAME: 'CDUNIX',\ + DESC: "CDUNIX - Filessystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + ADF:{ \ + HEADER1: ('D','O','S','\x00'),\ + HEADER2: None,\ + NAME: 'ADF',\ + DESC: "ADF - Amiga Filessystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + SGI:{ \ + HEADER1: ('\x0B','\xE5','\xA9','\x41'),\ + HEADER2: None,\ + NAME: 'SGI',\ + DESC: "SGI - SGI disk label (volume header)",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + SGIXFS:{ \ + HEADER1: ('\x58','\x46','\x53','\x42'),\ + HEADER2: None,\ + NAME: 'SGIXFS',\ + DESC: "SGI XFS - filesystem data",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + ST40:{ \ + HEADER1: ('\x13','\xa9','\xf1','\x7e'),\ + HEADER2: None,\ + NAME: 'ST40',\ + DESC: "ST40 - component image format",\ + SUFFIX: 'img',\ + CHANCE: 2}, + CBM:{ \ + HEADER1: ('C','B','M'),\ + HEADER2: None,\ + NAME: 'POWER64',\ + DESC: "Power 64 - C64 Emulator Snapshot",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + WINIMAGE:{ \ + HEADER1: ('W','I','N','I','M','A','G','E'),\ + HEADER2: None,\ + NAME: 'WinImage',\ + DESC: "WinImage - WinImage Archive data",\ + SUFFIX: 'img',\ + CHANCE: 2}, + COB:{ \ + HEADER1: ('C','o','B','1'),\ + HEADER2: None,\ + NAME: 'COB1',\ + DESC: "CoB1 - lantronix html/webserver filesystem",\ + SUFFIX: 'img',\ + CHANCE: 2}, + UFS1:{ \ + HEADER1: ('\x00','\x01','\x19','\x54'),\ + HEADER2: None,\ + NAME: 'UFS1',\ + DESC: "UFS1 - Unix Fast File system [v1] (little-endian)",\ + SUFFIX: 'img',\ + CHANCE: 2}, + QEMU1:{ \ + HEADER1: ('\x51','\x46','\x49','\xfb'),\ + HEADER2: None,\ + NAME: 'QEMU1',\ + DESC: "QEMU1 - Qemu Image, Format: Qcow",\ + SUFFIX: 'img',\ + CHANCE: 2}, + JFFSL:{ \ + HEADER1: ('\x31','\x39','\x38','\x34'),\ + HEADER2: None,\ + NAME: 'JFFS1_LE',\ + DESC: "JFFS1 - version 1, little endian",\ + TOOLS: "mtd-tools, mkfs.jffs etc.",\ + SUFFIX: 'img',\ + CHANCE: 2}, + + JFFSB:{ \ + HEADER1: ('\x34','\x38','\x39','\x31'),\ + HEADER2: None,\ + NAME: 'JFFS1_BE',\ + DESC: "JFFS1 - version 1, big endian",\ + SUFFIX: 'img',\ + TOOLS: "mtd-tools, mkfs.jffs etc.",\ + CHANCE: 2}, + + JFFS2L:{ \ + HEADER1: ('\x85','\x19','\x03','\x20'),\ + HEADER2: None,\ + NAME: 'JFFS2_LE',\ + DESC: "JFFS2 - version 2, little endian",\ + SUFFIX: 'img',\ + TOOLS: "mtd-tools, mkfs.jffs etc.",\ + CHANCE: 2}, + + JFFS2B:{ \ + HEADER1: ('\x19','\x85','\x20','\x03'),\ + HEADER2: None,\ + NAME: 'JFFS2_BE',\ + DESC: "JFFS2 - version 2, big endian",\ + SUFFIX: 'img',\ + TOOLS: "mtd-tools, mkfs.jffs etc.",\ + CHANCE: 2} + }, + + EXEC: { + ELF:{ \ + HEADER1: ('\x7f','E','L','F'),\ + HEADER2: None,\ + NAME: 'ELF',\ + DESC: "ELF - File Format",\ + SUFFIX: 'elf',\ + CHANCE: 2}, + BFLT:{ \ + HEADER1: ('b','F','L','T'),\ + HEADER2: None,\ + NAME: 'BFLT',\ + DESC: "bFLT - File Format",\ + SUFFIX: 'bflf',\ + CHANCE: 2}, + PE:{ \ + HEADER1: ('P','E','\x00','\x00'),\ + HEADER2: None,\ + NAME: 'PE',\ + DESC: "PE - File Format",\ + SUFFIX: 'exe',\ + CHANCE: 2}, + MSDOSCOM:{ \ + HEADER1: ('\xfc','\x57','\xf3','\xa5','\xc3'),\ + HEADER2: None,\ + NAME: 'COM',\ + DESC: "COM executable for MS-DOS",\ + SUFFIX: 'com',\ + CHANCE: 2}, + DOSCOM:{ \ + HEADER1: ('\xfc','\x57','\xf3','\xa4','\xc3'),\ + HEADER2: None,\ + NAME: 'COMDOS',\ + DESC: "COM executable for DOS",\ + SUFFIX: 'com',\ + CHANCE: 2}, + SPSSPORTABLE:{ \ + HEADER1: ('\xc1','\xe2','\xc3','\xc9'),\ + HEADER2: None,\ + NAME: 'SPSS',\ + DESC: "SPSS Portable File",\ + SUFFIX: None,\ + CHANCE: 2}, + SPSSSYSTEM:{ \ + HEADER1: ('$','F','L','2'),\ + HEADER2: None,\ + NAME: 'SPSS2',\ + DESC: "SPSS System File",\ + SUFFIX: None,\ + CHANCE: 2}, + PPCPEF:{ \ + HEADER1: ('J','o','y','!','p','e','f','f','p','w','p','c'),\ + HEADER2: None,\ + NAME: 'PPC_PEF',\ + DESC: "header for PowerPC PEF executable",\ + SUFFIX: None,\ + CHANCE: 2} + }, + + PACKERS: { + ZIP1:{ \ + HEADER1: ('\x50','\x4b','\x03','\x04'),\ + HEADER2: None,\ + NAME: 'ZIP1',\ + DESC: "ZIP1 - Phil Katz ",\ + SUFFIX: 'zip',\ + CHANCE: 2}, + ZIP2:{ \ + HEADER1: ('\x50','\x4b','\x01','\x02'),\ + HEADER2: None,\ + NAME: 'ZIP2',\ + DESC: "ZIP2 - Phil Katz ",\ + SUFFIX: 'zip',\ + CHANCE: 2}, + BZIP:{ \ + HEADER1: ('\x42','\x5a','\x68'),\ + HEADER2: None,\ + NAME: 'BZIP',\ + DESC: "BZIP - a block-sorting file compressor",\ + SUFFIX: 'bz2',\ + CHANCE: 2}, + GZIP:{ \ + HEADER1: ('\x1f','\x8b'),\ + HEADER2: None,\ + NAME: 'GZIP',\ + DESC: "GZIP - Lempel-Ziv coding (LZ77)",\ + SUFFIX: 'gz',\ + CHANCE: 2}, + ACE:{ \ + HEADER1: ('*','*','A','C','E','*','*'),\ + HEADER2: None,\ + NAME: 'ACE',\ + DESC: "ACE - e-merge GmbH - winace.com",\ + SUFFIX: 'ace',\ + CHANCE: 2}, + TAR:{ \ + HEADER1: ('\x00','u','s','t','a','r','\x00'),\ + HEADER2: None,\ + NAME: 'TAR',\ + DESC: "TAR - tape archiver",\ + SUFFIX: 'tar',\ + CHANCE: 2}, + TRX1:{ \ + HEADER1: ('\x30','\x52','\x44','\x48'),\ + HEADER2: None,\ + NAME: 'TRX1',\ + DESC: "TRX1 - ",\ + SUFFIX: None,\ + CHANCE: 2}, + TRX2:{ \ + HEADER1: ('H','D','R','0'),\ + HEADER2: ('0','R','D','H'),\ + NAME: 'TRX2',\ + DESC: "TRX2 - ",\ + SUFFIX: None,\ + CHANCE: 2}, + LZMA:{ \ + HEADER1: ('\x5d','\x00','\x00','\x80'),\ + HEADER2: None,\ + NAME: 'LZMA',\ + DESC: "LZMA - Lempel-Ziv-Markov chain-Algorithm",\ + SUFFIX: 'lzma',\ + CHANCE: 2}, + UPX:{ \ + HEADER1: ('U','P','X','!'),\ + HEADER2: None,\ + NAME: 'UPX',\ + DESC: "UPX - Ultimate Packer for eXecuteables",\ + SUFFIX: 'upx',\ + CHANCE: 2}, + GNUTAR:{ \ + HEADER1: ('u','s','t','a','r','\x20','\x20','\x00'),\ + HEADER2: None,\ + NAME: 'GNUTAR',\ + DESC: "GNUTAR - tar == teer + tape archiver",\ + SUFFIX: 'tar',\ + CHANCE: 2}, + CRUSH:{ \ + HEADER1: ('C', 'R', 'U', 'S', 'H'),\ + HEADER2: None,\ + NAME: 'CRUSH',\ + DESC: "CRUSH - Crush archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + + HLSQZ:{ \ + HEADER1: ('H', 'L', 'S', 'Q', 'Z'),\ + HEADER2: None,\ + NAME: 'HLSQZ',\ + DESC: "HLSQZ - Squeeze It archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + + SQWEZ:{ \ + HEADER1: ('S', 'Q', 'W', 'E', 'Z'),\ + HEADER2: None,\ + NAME: 'SQWEZ',\ + DESC: "SQWEZ - archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + HPAK:{ \ + HEADER1: ('H', 'P', 'A', 'K'),\ + HEADER2: None,\ + NAME: 'HPAK',\ + DESC: "HPAK - archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + LZOP:{ \ + HEADER1: ('\x89','\x4c','\x5a','\x4f','\x00','\x0d','\x0a','\x1a','\x0a'),\ + HEADER2: None,\ + NAME: 'LZOP',\ + DESC: "LZOP - lzop comrpressed data",\ + SUFFIX: None,\ + CHANCE: 2}, + MDCD:{ \ + HEADER1: ('M', 'D', 'm', 'd'),\ + HEADER2: None,\ + NAME: 'MDCD',\ + DESC: "MDCD - archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + MSCOMPRESS:{ \ + HEADER1: ('\x88','\xf0','\x27'),\ + HEADER2: None,\ + NAME: 'MS',\ + DESC: "MS Compress archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + INSTALLSHIELD:{ \ + HEADER1: ('\x13','\x5d','\x65','\x8c'),\ + HEADER2: None,\ + NAME: 'MSIS',\ + DESC: "InstallShield - Z archive Data",\ + SUFFIX: None,\ + CHANCE: 2}, + PAQ:{ \ + HEADER1: ('\xaa','\x40','\x5f','\x77','\x1f','\xe5','\x82','\x0d'),\ + HEADER2: None,\ + NAME: 'PAQ',\ + DESC: "PAQ - archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + JARARJ:{ \ + HEADER1: ('\x1a','J','a','r','\x1b'),\ + HEADER2: None,\ + NAME: 'JAR',\ + DESC: "JAR (ARJ Software, Inc.) archive data",\ + SUFFIX: 'arj',\ + CHANCE: 2}, + STUFFIT:{ \ + HEADER1: ('S','t','u','f','f','I','t'),\ + HEADER2: None,\ + NAME: 'STUFFIT',\ + DESC: "StuffIt Archive",\ + SUFFIX: 'stuffit',\ + CHANCE: 2}, + VAX3:{ \ + HEADER1: ('\x65','\xff','\x00','\x00'),\ + HEADER2: None,\ + NAME: 'VAX3',\ + DESC: "VAX 3.0 archive",\ + SUFFIX: None,\ + CHANCE: 2}, + VAX5:{ \ + HEADER1: ('\x3c','\x61','\x72','\x3e'),\ + HEADER2: None,\ + NAME: 'VAX5',\ + DESC: "VAX 5.0 archive",\ + SUFFIX: None,\ + CHANCE: 2}, + ARCHIVE:{ \ + HEADER1: ('=','<','a','r','>'),\ + HEADER2: None,\ + NAME: 'AR',\ + DESC: "archive",\ + SUFFIX: 'ar',\ + CHANCE: 2}, + ARCHIVEFILE:{ \ + HEADER1: ('21','3c','61','72'),\ + HEADER2: None,\ + NAME: 'ARfile',\ + DESC: "archive file",\ + SUFFIX: 'ar',\ + CHANCE: 2}, + HRB:{ \ + HEADER1: ('\xc0','H','R','B'),\ + HEADER2: None,\ + NAME: 'HRB',\ + DESC: "Harbour HRB file",\ + SUFFIX: 'hrb',\ + CHANCE: 2}, + RISCOS:{ \ + HEADER1: ('A','r','c','h','i','v','e'),\ + HEADER2: None,\ + NAME: 'RISCOS',\ + DESC: "RISC OS archive (ArcFS format)",\ + SUFFIX: None,\ + CHANCE: 2}, + HAP:{ \ + HEADER1: ('\x91','\x33','H','F'),\ + HEADER2: None,\ + NAME: 'HAP',\ + DESC: "HAP archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + LIM:{ \ + HEADER1: ('L','I','M','\x1a'),\ + HEADER2: None,\ + NAME: 'LIM',\ + DESC: "LIM archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + FREEZE:{ \ + HEADER1: ('\x1f','\x9f','\x4a','\x10','\x0a'),\ + HEADER2: None,\ + NAME: 'FREEZE',\ + DESC: "Freeze archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + ZOO:{ \ + HEADER1: ('\xfd','\xc4','\xa7','\xdc'),\ + HEADER2: None,\ + NAME: 'ZOO',\ + DESC: "Zoo archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + RAR:{ \ + HEADER1: ('R','a','r','!'),\ + HEADER2: None,\ + NAME: 'RAR',\ + DESC: "RAR archive data",\ + SUFFIX: 'rar',\ + CHANCE: 2}, + EET:{ \ + HEADER1: ('\x1e','\xe7','\xff','\x00'),\ + HEADER2: None,\ + NAME: 'EET',\ + DESC: "EET archive",\ + SUFFIX: None,\ + CHANCE: 2}, + RZIP:{ \ + HEADER1: ('R','Z','I','P'),\ + HEADER2: None,\ + NAME: 'RZIP',\ + DESC: "rzip compressed data",\ + SUFFIX: None,\ + CHANCE: 2}, + SQSH:{ \ + HEADER1: ('S','Q','S','H'),\ + HEADER2: None,\ + NAME: 'SQUISH',\ + DESC: "squished archive data (Acorn RISCOS)",\ + SUFFIX: None,\ + CHANCE: 2}, + ISC:{ \ + HEADER1: ('I','S','c','('),\ + HEADER2: None,\ + NAME: 'CAB',\ + DESC: "InstallShield CAB",\ + SUFFIX: None,\ + CHANCE: 2}, + NWFILE:{ \ + HEADER1: ('P','a','c','k','e','d','\\',' ','F','i','l','e','\\'),\ + HEADER2: None,\ + NAME: 'NETWARE',\ + DESC: "Personal NetWare Packed File",\ + SUFFIX: None,\ + CHANCE: 2}, + DSIGDCC:{ \ + HEADER1: ('D','S','I','G','D','C','C'),\ + HEADER2: None,\ + NAME: 'CROSSEPAC',\ + DESC: "CrossePAC archive data",\ + SUFFIX: None,\ + CHANCE: 2}, + ARJ:{ \ + HEADER1: ('\x60','\xea'),\ + HEADER2: None,\ + NAME: 'ARJ',\ + DESC: "ARJ",\ + SUFFIX: 'arj',\ + CHANCE: 2} + }, + + DOCS: { \ + PDF:{ \ + HEADER1: ('\x25','\x50','\x44','\x46','\x2e'),\ + HEADER2: None,\ + NAME: 'PDF',\ + DESC: "PDF - Portable Document Format",\ + SUFFIX: 'pdf',\ + CHANCE: 2}, + DOC:{ \ + HEADER1: ('\xd0','\xcf','\x11','\xe0','\xa1','\xb1','\x1a','\xe1'),\ + HEADER2: None,\ + NAME: 'DOC',\ + DESC: "DOC - Microsoft Document Format",\ + SUFFIX: 'doc',\ + CHANCE: 2}, + RTF:{ \ + HEADER1: ('{','\\','\\','r','t','f'),\ + HEADER2: None,\ + NAME: 'RTF',\ + DESC: "RTF - Rich Text Format data",\ + SUFFIX: 'rtf',\ + CHANCE: 2} + }, + + BOOT: { \ + UBOOT:{ \ + HEADER1: ('\x27','\x05','\x19','\x56'),\ + HEADER2: None,\ + NAME: 'UBOOT',\ + DESC: "UBOOT - PPCBoot Image - maybe bootloader",\ + SUFFIX: 'uboot',\ + CHANCE: 2} + +}, + ASM: { \ + AVR:{ \ + HEADER1: ('a','v','a','o','b','j'),\ + HEADER2: None,\ + NAME: 'AVR',\ + DESC: "AVR assembler object code",\ + SUFFIX: 'avr',\ + CHANCE: 2} +}, + PICTURES: { \ + GIMPXCF:{ \ + HEADER1: ('g','i','m','p','\\',' ','x','c','f'),\ + HEADER2: None,\ + NAME: 'GIMP_XCF',\ + DESC: "GIMP XCF image data",\ + SUFFIX: 'xcf',\ + CHANCE: 2} +}, + + DEVICES: { \ + LTRX1:{ \ + HEADER1: ('D','S','T','-','L','T','R','X'),\ + HEADER2: None,\ + NAME: 'LTRX1',\ + DESC: "LTRX1 - Lantronics Firmware Part detected",\ + SUFFIX: None,\ + CHANCE: 2}, + + LTRX2:{ \ + HEADER1: ('L','T','R','X'),\ + HEADER2: None,\ + NAME: 'LTRX2',\ + DESC: "LTRX2 - Lantronics Firmware Part detected",\ + SUFFIX: None,\ + CHANCE: 2}, + + WGR614BOOT:{ \ + HEADER1: ('*','#','$','^'),\ + HEADER2: None,\ + NAME: 'NETGEAR_BOOT',\ + DESC: "NETGEAR WGR614v9 Bootware - unknown bootloader maybe",\ + SUFFIX: None,\ + CHANCE: 2}, + + WGR614:{ \ + HEADER1: ('@','U','1','2','H','0','9','4','T'),\ + HEADER2: None,\ + NAME: 'NETGEAR_FW',\ + DESC: "NETGEAR WGR614v9 Firmware",\ + SUFFIX: None,\ + CHANCE: 2} + + }, + + CRYPTO: { + DSAPRIV:{ \ + HEADER1: ('-----BEGIN DSA PRIVATE KEY-----'),\ + HEADER2: ('-----END DSA PRIVATE KEY-----'),\ + NAME: 'DSAPRIV',\ + DESC: "DSAPRIV - Private Key in DSA Format",\ + SUFFIX: None,\ + CHANCE: 2}, + + RSAPRIV:{ \ + HEADER1: ('-----BEGIN RSA PRIVATE KEY-----'),\ + HEADER2: ('-----END RSA PRIVATE KEY-----'),\ + NAME: 'RSAPRIV',\ + DESC: "RSAPRIV - Private Key in RSA Format",\ + SUFFIX: None,\ + CHANCE: 2}, + + SSHPUB:{ \ + HEADER1: ('ssh-dss'),\ + HEADER2: None,\ + NAME: 'SSHDSS',\ + DESC: "SSHDSS - Public ssh key",\ + SUFFIX: None,\ + CHANCE: 2}, + + CACERT:{ \ + HEADER1: ('-----BEGIN CERTIFICATE-----'),\ + HEADER2: ('-----END CERTIFICATE-----'),\ + NAME: 'CACERT',\ + DESC: "CACERT - Certificate Format",\ + SUFFIX: None,\ + CHANCE: 2}, + + CERTREQ:{ \ + HEADER1: ('-----BEGIN CERTIFICATE REQUEST-----'),\ + HEADER2: ('-----END CERTIFICATE REQUEST-----'),\ + NAME: 'CERTREQ',\ + DESC: "CERTREQ - Certificate Request Format",\ + SUFFIX: None,\ + CHANCE: 2}, + + PGPMSG:{ \ + HEADER1: ('-----BEGIN PGP MESSAGE-----'),\ + HEADER2: ('-----END PGP MESSAGE-----'),\ + NAME: 'PGPMSG',\ + DESC: "PGPMSG - Pretty Good Privacy Message Format",\ + SUFFIX: None,\ + CHANCE: 2}, +} +} + +TYPES_DEF = { 'FS':FS,\ + 'EXEC':EXEC,\ + 'PACKERS':PACKERS,\ + 'DOCS':DOCS,\ + 'BOOT':BOOT,\ + 'ASM':ASM,\ + 'PICTURES':PICTURES,\ + 'DEVICES':DEVICES,\ + 'CRYPTO':CRYPTO + } diff --git a/lib/FUDGEheader.pyc b/lib/FUDGEheader.pyc new file mode 100644 index 0000000..20a4f59 Binary files /dev/null and b/lib/FUDGEheader.pyc differ diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100755 index 0000000..c291675 --- /dev/null +++ b/lib/__init__.py @@ -0,0 +1,4 @@ +""" +Fudge init library +""" + diff --git a/lib/__init__.pyc b/lib/__init__.pyc new file mode 100644 index 0000000..6609b46 Binary files /dev/null and b/lib/__init__.pyc differ diff --git a/lib/__pycache__/FUDGEanalyse.cpython-37.pyc b/lib/__pycache__/FUDGEanalyse.cpython-37.pyc new file mode 100644 index 0000000..ac32424 Binary files /dev/null and b/lib/__pycache__/FUDGEanalyse.cpython-37.pyc differ diff --git a/lib/__pycache__/FUDGEheader.cpython-37.pyc b/lib/__pycache__/FUDGEheader.cpython-37.pyc new file mode 100644 index 0000000..e1a209a Binary files /dev/null and b/lib/__pycache__/FUDGEheader.cpython-37.pyc differ diff --git a/lib/__pycache__/__init__.cpython-37.pyc b/lib/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..a3e8b10 Binary files /dev/null and b/lib/__pycache__/__init__.cpython-37.pyc differ diff --git a/supply/strings.txt b/supply/strings.txt new file mode 100644 index 0000000..06254b3 --- /dev/null +++ b/supply/strings.txt @@ -0,0 +1,30 @@ +# this is a header file for the strings analysis function +# it is kept in simple csv style; so it can easily edited +# the idea is to add strings possibly found in firmwares +# hints on what it is and a description +# +# it is *not* made to repeat magic strings already existing in +# fudge database or libmagic/magic.mgc database +# +# needle: +# all search strings(needle) are written in lower case; however FF will check +# for lower and capital letters +# +# shortdesc: +# add a short description +# +# tools: +# possible tools or url? +# +# format +# needle;shortdesc;tools +linux;Linux string has been found; possibly linux OS or file;http://www.kernel.org +kernel;Kernel strings has been found; sneak around and check if more information is existing;hexdump -C +supertask;Supertask(RTOS) found;google +trontask;Trontask(RTOS) found;google +ILC 150 GSM Upgrade;inline gsm modem;https://www.phoenixcontact.com/online/portal/de?uri=pxc-oc-itemdetail:pid=2916545&library=dede&tab=1 +SPI Flash Image; SPI access available;http://linux-sunxi.org/Bootable_SPI_flash +/etc;linux etc directory;google +/mnt;linux mnt directory;google +/etc/shadow;shadow file;shadow +/etc/passwd;passwd file;passwd