public 0.5.2 release :)
This commit is contained in:
@@ -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.
|
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:
|
## How to use the tool:
|
||||||
|
|||||||
24
ReleaseNotes_0.5.2.txt
Normal file
24
ReleaseNotes_0.5.2.txt
Normal file
@@ -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
|
||||||
|
|
||||||
|
|
||||||
261
ffudger.py
Executable file
261
ffudger.py
Executable file
@@ -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()
|
||||||
596
lib/FUDGEanalyse.py
Executable file
596
lib/FUDGEanalyse.py
Executable file
@@ -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_alive<self.thread_cnt:
|
||||||
|
|
||||||
|
# get a value from the target queue
|
||||||
|
target=self.target_queue.get()
|
||||||
|
# set variables for the thread, make it daemon and start it
|
||||||
|
thrd = threading.Thread(target=self.__checkheader,args=(target,))
|
||||||
|
thrd.daemon=True
|
||||||
|
thrd.start()
|
||||||
|
|
||||||
|
# add the thread to our list
|
||||||
|
self.thread_list.append(thrd)
|
||||||
|
#print ('thrd cnt: %d' % len(self.thread_list))
|
||||||
|
|
||||||
|
# this part watches that dead threads can join and it is removed from the list
|
||||||
|
for entry in self.thread_list:
|
||||||
|
if entry.isAlive()==False:
|
||||||
|
entry.join()
|
||||||
|
self.thread_list.remove(entry)
|
||||||
|
|
||||||
|
def seekinto(self):
|
||||||
|
allbytes=""
|
||||||
|
self.fd=open(self.infile,"rb")
|
||||||
|
self.fd.seek(0,0)
|
||||||
|
self.fd.seek(self.set_offset,0)
|
||||||
|
for byte in self.fd.read(self.length):
|
||||||
|
byte=binascii.hexlify(byte)
|
||||||
|
allbytes=allbytes + "\\x"+byte
|
||||||
|
print ("%s" % allbytes,)
|
||||||
|
|
||||||
|
|
||||||
|
def manglefile(self):
|
||||||
|
mangle_file=open(self.infile,"r")
|
||||||
|
for part in range(self.extract):
|
||||||
|
mangle_file.seek(0,0)
|
||||||
|
mangle_file.seek(self.cut[part],0)
|
||||||
|
readbytes=mangle_file.read(8)
|
||||||
|
print ("read %s " % readbytes)
|
||||||
|
mangle_file.close()
|
||||||
|
mangle_file=open(self.infile,"r+")
|
||||||
|
mangle_file.seek(0,0)
|
||||||
|
mangle_file.seek(self.cut[part],0)
|
||||||
|
mangle_file.write(self.set_string)
|
||||||
|
mangle_file.close()
|
||||||
|
|
||||||
|
def extractcount(self):
|
||||||
|
''' let's print some information about the files to extract
|
||||||
|
'''
|
||||||
|
print ("[+] Found %d possible types" % (self.extract_cnt))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
def extractdata(self):
|
||||||
|
''' simple wrapper function, which gets called by program
|
||||||
|
'''
|
||||||
|
# ram some info
|
||||||
|
self.extractcount()
|
||||||
|
|
||||||
|
# lets go to file extraction
|
||||||
|
self.extractfile()
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
def extractfile(self):
|
||||||
|
""" its working just need some cleanups, and small fixes """
|
||||||
|
|
||||||
|
if self.extract_cnt == 0:
|
||||||
|
self.ffprint('[-] Sorry, nothing to extract. Counter is zer0.',nor)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if self.extract==False:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
exo_file=open(self.infile,"rb")
|
||||||
|
|
||||||
|
# as long as we have results in the queue
|
||||||
|
while self.result_queue.qsize()>0:
|
||||||
|
|
||||||
|
# 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()
|
||||||
BIN
lib/FUDGEanalyse.pyc
Normal file
BIN
lib/FUDGEanalyse.pyc
Normal file
Binary file not shown.
813
lib/FUDGEheader.py
Executable file
813
lib/FUDGEheader.py
Executable file
@@ -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
|
||||||
|
}
|
||||||
BIN
lib/FUDGEheader.pyc
Normal file
BIN
lib/FUDGEheader.pyc
Normal file
Binary file not shown.
4
lib/__init__.py
Executable file
4
lib/__init__.py
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
"""
|
||||||
|
Fudge init library
|
||||||
|
"""
|
||||||
|
|
||||||
BIN
lib/__init__.pyc
Normal file
BIN
lib/__init__.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/FUDGEanalyse.cpython-37.pyc
Normal file
BIN
lib/__pycache__/FUDGEanalyse.cpython-37.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/FUDGEheader.cpython-37.pyc
Normal file
BIN
lib/__pycache__/FUDGEheader.cpython-37.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
lib/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
30
supply/strings.txt
Normal file
30
supply/strings.txt
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user