262 lines
7.8 KiB
Python
Executable File
262 lines
7.8 KiB
Python
Executable File
#!/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()
|