From 3fbfa3e9e1e659144e026fb80f93eadc9b37f727 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 30 May 2015 11:39:19 +0200 Subject: [PATCH] release --- README | 52 ++++ fudge.py | 188 ++++++++++++++ lib/CHANGELOG | 21 ++ lib/FUDGEanalyse.py | 253 +++++++++++++++++++ lib/FUDGEanalyse.pyc | Bin 0 -> 8156 bytes lib/FUDGEheader.py | 575 +++++++++++++++++++++++++++++++++++++++++++ lib/FUDGEheader.pyc | Bin 0 -> 11730 bytes lib/MANGLEheader.pyc | Bin 0 -> 11634 bytes lib/__init__.py | 4 + lib/__init__.pyc | Bin 0 -> 185 bytes 10 files changed, 1093 insertions(+) create mode 100755 README create mode 100755 fudge.py create mode 100755 lib/CHANGELOG create mode 100755 lib/FUDGEanalyse.py create mode 100644 lib/FUDGEanalyse.pyc create mode 100755 lib/FUDGEheader.py create mode 100644 lib/FUDGEheader.pyc create mode 100755 lib/MANGLEheader.pyc create mode 100755 lib/__init__.py create mode 100644 lib/__init__.pyc diff --git a/README b/README new file mode 100755 index 0000000..a909082 --- /dev/null +++ b/README @@ -0,0 +1,52 @@ +Disclaimer: +=========== + +None :) + +Intro: +====== + +This code is for automated analysis of files you may find around the internet. Primarily it was coded for the investigation of firmwares of devices. But you can use it generally for pattern recognition. + +Currently it supports by 80plugins, this means by 80 different patterns that may match on a current file. There are still some interesting, exotic or important plugins missing. However i hope it may help you out on some point. If you got interesting patterns please let me know, and i'am happy to add them. + +How to use the tool: +==================== + +List all plugins: + +%python fudge.py -l + +Searching for just one patterntype: + +%python fudge.py -f /bin/ls -o test/ -p ELF + +Searching for a class of patterns: + +%python fudge.py -f /bin/ls -o test/ -P FS + +Searching through all patterns and extract findings: + +%python fudge.py -f /bin/ls -o test/ -x + +Searching through all patterns, extract findings and generate report with the tool file: + +%python fudge.py -f /bin/ls -o test/ -x -r + +Bugs: +===== + +- slow on big files +- suffix recognition isn't working + +Todo: +===== + +- verbose mode not implemented +- add logfile function +- complete rewrite + +Outro: +====== + +That's it guys'n'girls. I hope you can use it for some good. For any further questions on the code you can contact me via email diff --git a/fudge.py b/fudge.py new file mode 100755 index 0000000..b5b563f --- /dev/null +++ b/fudge.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python2 +# +# by dash@hack4.org in 2008 +############################ + +from lib.FUDGEanalyse import * +from lib.FUDGEheader import * +import getopt,sys,os + +#maybe put that later somewhere else +extractit=0 +fileReport=0 + +def fudge_banner(): + inst2=ANALYSE() + print "[+] FirmareFudger %s by dash@hack4.org" % inst2.version + print "[+] tool for firmware analyses written in August 2008" + print "[+] " + inst2=[] + +def fudge_usage(): + inst2=ANALYSE() + print "[+] FirmareFudger %s by dash@hack4.org" % inst2.version + print "[+] tool for firmware analyses written in August 2008" + print "[+] " + print "[+]\t-f " + print "[+]\t-o " + print "[+]\t-n " + print "[+]\t-x extract found files" + print "[+]\t-P " + print "[+]\t-p " + print "[+]\t-r do an investigation on extracted files with file" + print "[+]\t-l list all available plugins" + print "[+]\t-v verbose mode on" + print "[+]\t-V Version" + print "[+]" + print "[+] Example:" + print "[+] python %s -f input.img -o outdir -n outname -x" % sys.argv[0] + print "" + inst2=[] + +def generateFilereport(instance): + + if fileReport==1: + print "[+] Generating file Report" + instance.generateReport() + else: + print "[-] Don't enabled file Report mode" + +def extractdata(instance, extractit): + instance.extractcount() + + if extractit==1: + print "[+] Extracting found files" + instance.extractfile() + else: + print "[-] Don't enabled extraction mode" + + instance.closefile() + +try: + opts, args = getopt.getopt(sys.argv[1:], "n:o:P:p:lvf:xVr") + +#let's check if we got some arguments, dont we?! + if len(opts)==0: + fudge_usage() + sys.exit(1) + +except getopt.GetoptError, err: + fudge_usage() + print "[!] %s" % str(err) + sys.exit(1) + +for option, arg in opts: + if option == "-f": + file=arg + inst2=ANALYSE() + inst2.file=file + elif option == "-o": + inst2.dir=arg + inst2.create_dir() + elif option == "-n": + inst2.outname=arg + elif option == "-r": + fileReport=1 + elif option == "-p": + lonelyplugin=arg + inst2.lonelyplugin=lonelyplugin + elif option == "-P": + plugin=arg + inst2.plugin=plugin + elif option == "-l": + fudge_banner() + inst2=ANALYSE() + inst2.showplugins() + inst2=[] + sys.exit(1) + elif option == "-v": + print "verbose" + elif option == "-V": + fudge_banner() + sys.exit(0) + elif option == "-x": + extractit=1 + else: + print "unknown option" + fudge_usage() + sys.exit(1) + +#print the banner :D +fudge_banner() +inst2.openfile() +inst2.printargs() + +#check for named plugin(VAX is currently 2) +true=0 +if inst2.lonelyplugin!=None: + lonely=inst2.lonelyplugin + for type in range(len(TYPES)): + for plugin in range(len(TYPES[type])): + inst2.type=TYPES[type][plugin][3] + compare=inst2.type.split(" ") + compare=compare[0] + compare.strip(" ") +# print "-%s-" % lonely +# print "-%s-" % compare + if lonely==compare: + true=1 + print "[+] Checking for %s" % inst2.type + inst2.fd.seek(0,0) + inst2.search=TYPES[type][plugin][1] + inst2.checkheader() + + extractdata(inst2,extractit) + generateFilereport(inst2) + + if true!=1: + print "[-] Sorry couldn't find %s " % inst2.lonelyplugin + + sys.exit(0) + +if inst2.plugin!=None: + KIND=inst2.plugin + if KIND=="FS": + type=0 + elif KIND=="EXEC": + type=1 + elif KIND=="PACKERS": + type=2 + elif KIND=="DOCS": + type=3 + elif KIND=="BOOT": + type=4 + elif KIND=="ASM": + type=5 + elif KIND=="PICTURES": + type=6 + elif KIND=="DEVICES": + type=7 + elif KIND=="ROUTERS": + type=8 + else: + print "[-] Unkown plugin class %s !" % inst2.plugin + sys.exit(1) + +#only check for the asked TYPE + print "[+] Testing only for %s plugins" % (KIND) + for plugin in range(len(TYPES[type])): + inst2.type=TYPES[type][plugin][3] + print "[+] Checking for %s" % inst2.type + inst2.fd.seek(0,0) + inst2.search=TYPES[type][plugin][1] + inst2.checkheader() +else: + +#check for all TYPES + for type in range(len(TYPES)): + for plugin in range(len(TYPES[type])): + inst2.type=TYPES[type][plugin][3] + print "[+] Checking for %s" % inst2.type + inst2.fd.seek(0,0) + inst2.search=TYPES[type][plugin][1] + inst2.checkheader() + + + +extractdata(inst2,extractit) +generateFilereport(inst2) diff --git a/lib/CHANGELOG b/lib/CHANGELOG new file mode 100755 index 0000000..f1c5f58 --- /dev/null +++ b/lib/CHANGELOG @@ -0,0 +1,21 @@ +Tue Mar 10 16:03:24 CET 2009 +============================ + +- added plugin support (choose between categories) +- added report mode with file + + +Tue Mar 10 00:47:18 CET 2009 +============================ + +- added jffs/jffs2 support +- added pluginlist +- added little corrections +- added version output + +long long before(last year august) +================================== + +- initial PoC +- addition of a lot of patterns +- extract mode diff --git a/lib/FUDGEanalyse.py b/lib/FUDGEanalyse.py new file mode 100755 index 0000000..c11edb6 --- /dev/null +++ b/lib/FUDGEanalyse.py @@ -0,0 +1,253 @@ +import FUDGEheader +import os,sys,time,struct,binascii + +def dbgprint(): + print "nothing" + +class ANALYSE(object): + + def __init__(self): + + """ file - the file to analyse + stat - os.stat results of self.file + type - 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 - number of the found files in file + cut - dict for offsets for the extractfile method + dir - output directory for putting files + outname - name of the output files part + reportfile - name of the status report + files - list with paths of extracte files + """ + + + self.file=None + self.stat=None + self.type=None + self.plugin=None + self.lonelyplugin=None + self.reportfile=None + self.files=[] + self.fd=None + self.search=None + self.string="" + self.data=[] + self.offset=0 + self.extract=0 + self.cut={} + self.set_offset=0 + self.set_string=0 + self.debug=0 + self.dir="" + self.outname="Extract" + self.length=0 + self.version="0.3" + + def privileges(self): + if self.stat.st_uid != os.getuid(): + print "[!] Attention file owner is %d" % self.stat.st_uid + + def printargs(self): + + size=self.stat.st_size + Kilo=1024.0 + Mega=1048576.0 + + print "[+] Fudger Version %s - Fileinformation" % self.version + print "[+] Filename %s" % self.file + + 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.stat.st_uid + print "[+] Group %d" % self.stat.st_gid + #print "[+] Search for %s" % self.search + + + def openfile(self): + + self.stat=os.stat(self.file) + print "[+] Open %s" % (self.file) + self.fd=open(self.file,"r") + + def closefile(self): + + print "[+] Close %s" % self.file + self.fd.close() + + def create_dir(self): + + try: + print "[+] Creating directory %s" % (self.dir) + os.mkdir(self.dir) + return(0) + except OSError, 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 checkheader(self): + self.data=[] + offset=0 +# print "[+] Checking for FS Type Headers" + try: + for byte in self.fd.read(self.stat.st_size): +# print "[+] Bytes in %s" % self.stat.st_size + self.data.append(byte) + #print "[+] data %s" % self.data + #print "in for loop" + if len(self.data) == len(self.search): + #print "set o =0" + o=0 + #print "[+] Datalen is %d" % len(self.data) + for i in range(len(self.data)): + if self.data[i]==self.search[i]: +# print self.data[i] +# print self.search[i] + o+=1 + # i+=1 + if o==len(self.search): + offlen=offset-len(self.data)+1 + print "[+] FOUND at Offset %d to %d" % (offlen,offset) + # print "FIELD " + str(self.data) + self.cut[self.extract]=offlen +# print "%s" % str(self.cut) +# print "%d" % self.cut[self.extract] + o=0 + self.data.pop(0) + self.extract+=1 + else: + # print "Nope" +# print self.data + self.data.pop(0) + o=0 + #print "set i=0" + i=0 + + offset+=1 + + except KeyboardInterrupt: + print "\n[!] KeyboardInterrupt at check %s" % self.type + sys.exit(1) + + def extractcount(self): + + print "[+] Found %d possible types" % (self.extract) + + + def seekinto(self): + allbytes="" + self.fd=open(self.file,"r") + 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.file,"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 "readed %s " % readbytes + mangle_file.close() + mangle_file=open(self.file,"r+") + mangle_file.seek(0,0) + mangle_file.seek(self.cut[part],0) + mangle_file.write(self.set_string) + mangle_file.close() + + + def extractfile(self): + """ its working just need some cleanups, and small fixes """ + + exo_file=open(self.file,"r") + + for part in range(self.extract): + # dbgprint "part %d" % part + exo_file.seek(0,0) + exo_file.seek(self.cut[part],0) + + suffix=self.type + suffix=suffix.split(" ") + suffix=suffix[0] + FILENAME=self.dir+"/"+self.outname+"-"+str(self.extract)+"-"+str(self.cut[part])+"." + suffix + print "[+] FILENAME: %s" % FILENAME + exw_file=open(FILENAME,"w") + + TOWRITE=(self.stat.st_size)-self.cut[part] + for byte in exo_file.read(TOWRITE): + #for byte in exo_file.read(self.stat.st_size): + exw_file.write(byte) + + exw_file.close() +#complicated + # print "written %d" % self.cut[self.extract] + exo_file.close() + +#lets add it to files if reportfile shall be written + # if self.reportfile!=None: + self.files.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 showplugins(self): + """ ok this method is not part of the CLASS ANALYSE + maybe i change this later""" + i=0 + print "[+] Plugins:" + for type in range(len(FUDGEheader.TYPES)): + if type==0: + stringtype="FS" + elif type==1: + stringtype="EXEC" + elif type==2: + stringtype="PACKERS" + elif type==3: + stringtype="DOCS" + elif type==4: + stringtype="BOOT" + elif type==5: + stringtype="ASM" + elif type==6: + stringtype="PICTURES" + elif type==7: + stringtype="DEVICES" + elif type==8: + stringtype="ROUTER" + print "%s:" % stringtype + for plugin in range(len(FUDGEheader.TYPES[type])): + print "\t\t- %s" % FUDGEheader.TYPES[type][plugin][3] + i+=1 + + print "\n[+] Found %d plugins." % i + print "[+] Done" + diff --git a/lib/FUDGEanalyse.pyc b/lib/FUDGEanalyse.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f99190bef18a746f06f35133961d454a9e951423 GIT binary patch literal 8156 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'),\ + HEADER2: None,\ + DESC: "archive",\ + CHANCE: 2}, + ARCHIVEFILE:{ \ + HEADER1: ('21','3c','61','72'),\ + HEADER2: None,\ + DESC: "archive file",\ + CHANCE: 2}, + HRB:{ \ + HEADER1: ('\xc0','H','R','B'),\ + HEADER2: None,\ + DESC: "Harbour HRB file",\ + CHANCE: 2}, + RISCOS:{ \ + HEADER1: ('A','r','c','h','i','v','e'),\ + HEADER2: None,\ + DESC: "RISC OS archive (ArcFS format)",\ + CHANCE: 2}, + HAP:{ \ + HEADER1: ('\x91','\x33','H','F'),\ + HEADER2: None,\ + DESC: "HAP archive data",\ + CHANCE: 2}, + LIM:{ \ + HEADER1: ('L','I','M','\x1a'),\ + HEADER2: None,\ + DESC: "LIM archive data",\ + CHANCE: 2}, + FREEZE:{ \ + HEADER1: ('\x1f','\x9f','\x4a','\x10','\x0a'),\ + HEADER2: None,\ + DESC: "Freeze archive data",\ + CHANCE: 2}, + ZOO:{ \ + HEADER1: ('\xfd','\xc4','\xa7','\xdc'),\ + HEADER2: None,\ + DESC: "Zoo archive data",\ + CHANCE: 2}, + RAR:{ \ + HEADER1: ('R','a','r','!'),\ + HEADER2: None,\ + DESC: "RAR archive data",\ + CHANCE: 2}, + EET:{ \ + HEADER1: ('\x1e','\xe7','\xff','\x00'),\ + HEADER2: None,\ + DESC: "EET archive",\ + CHANCE: 2}, + RZIP:{ \ + HEADER1: ('R','Z','I','P'),\ + HEADER2: None,\ + DESC: "rzip compressed data",\ + CHANCE: 2}, + SQSH:{ \ + HEADER1: ('S','Q','S','H'),\ + HEADER2: None,\ + DESC: "squished archive data (Acorn RISCOS)",\ + CHANCE: 2}, + ISC:{ \ + HEADER1: ('I','S','c','('),\ + HEADER2: None,\ + DESC: "InstallShield CAB",\ + CHANCE: 2}, + NWFILE:{ \ + HEADER1: ('P','a','c','k','e','d','\\',' ','F','i','l','e','\\'),\ + HEADER2: None,\ + DESC: "Personal NetWare Packed File",\ + CHANCE: 2}, + DSIGDCC:{ \ + HEADER1: ('D','S','I','G','D','C','C'),\ + HEADER2: None,\ + DESC: "CrossePAC archive data",\ + CHANCE: 2}, + ARJ:{ \ + HEADER1: ('\x60','\xea'),\ + HEADER2: None,\ + DESC: "ARJ",\ + CHANCE: 2} + }, + + DOCS: { \ + PDF:{ \ + HEADER1: ('\x25','\x50','\x44','\x46','\x2e'),\ + HEADER2: None,\ + DESC: "PDF - Portable Document Format",\ + CHANCE: 2}, + DOC:{ \ + HEADER1: ('\xd0','\xcf','\x11','\xe0','\xa1','\xb1','\x1a','\xe1'),\ + HEADER2: None,\ + DESC: "DOC - Microsoft Document Format",\ + CHANCE: 2}, + RTF:{ \ + HEADER1: ('{','\\','\\','r','t','f'),\ + HEADER2: None,\ + DESC: "RTF - Rich Text Format data",\ + CHANCE: 2} + }, + + BOOT: { \ + UBOOT:{ \ + HEADER1: ('\x27','\x05','\x19','\x56'),\ + HEADER2: None,\ + DESC: "UBOOT - PPCBoot Image - maybe bootloader",\ + CHANCE: 2} + +}, + ASM: { \ + AVR:{ \ + HEADER1: ('a','v','a','o','b','j'),\ + HEADER2: None,\ + DESC: "AVR assembler object code",\ + CHANCE: 2} +}, + PICTURES: { \ + GIMPXCF:{ \ + HEADER1: ('g','i','m','p','\\',' ','x','c','f'),\ + HEADER2: None,\ + DESC: "GIMP XCF image data",\ + CHANCE: 2} +}, + + DEVICES: { \ + LTRX1:{ \ + HEADER1: ('D','S','T','-','L','T','R','X'),\ + HEADER2: None,\ + DESC: "LTRX1 - Lantronics Firmware Part detected",\ + CHANCE: 2}, + + LTRX2:{ \ + HEADER1: ('L','T','R','X'),\ + HEADER2: None,\ + DESC: "LTRX2 - Lantronics Firmware Part detected",\ + CHANCE: 2}, + + WGR614BOOT:{ \ + HEADER1: ('*','#','$','^'),\ + HEADER2: None,\ + DESC: "NETGEAR WGR614v9 Bootware - unknown bootloader maybe",\ + CHANCE: 2}, + + WGR614:{ \ + HEADER1: ('@','U','1','2','H','0','9','4','T'),\ + HEADER2: None,\ + DESC: "NETGEAR WGR614v9 Firmware",\ + CHANCE: 2} + +} +} diff --git a/lib/FUDGEheader.pyc b/lib/FUDGEheader.pyc new file mode 100644 index 0000000000000000000000000000000000000000..816f2b098cadd21601eacf05ef62d60d2e3ac943 GIT binary patch literal 11730 zcmdU!Ym8h+R>x~Re#MXY{eE4)+mCsV$B)>K`*C}w?e6KGdwV?N8)uWAzSo|P`{DGx zV>>~R)uNSH?Fxv5_y9=JLKd{Z2jB|=A;>Bqw1^e^1tefUY*wsR+ApwLgn%rBbN;8h z?;LwJ>ksgOL^)kk^{Z2-PMtcps?z_%%^Uu7<97;G)A?ry{obJe!e7{IjBku5vd{Q^ z##?3lRmST#e!uZn8-KO&));?{@zxrDt?||wf1UBx8-Km=UNHU(#@hf58_{1 z@m@Cm9^>6G{$ArHjla)$DdX=qUfTEvjF&O~LF3uRKV-bD@edns()dS=H)VXwcsb)A zHQr6*A2Z%9;~zI(-uNesS1|rb<4qg?l<|s~Zwd3A!F(OmxR7PYS;*U9=D^IuCwEZq zq2?9T+=Z83g_k~qIlhKouY;+8SpZW7^dt&pT3{erwG$Qp%Y)IeJVS*s9RAzKAm zr;wWp*(S((g-k1CyC5$pq@<7?f^1MoSs^3pc+TkK_Pc2vau3*NXVUv ze7F*MSjb(9d~+r82*q|E(X_9*0$LXHZuS0PUna!inY3i)Y; z92aE2Lf%ox2|*4hyPrvI_Ypg%m0M_7m2R^gF4@?AwBAhM64vJ?X8Me&@kNb1L}C?-eio})tYNX1 z#X1)2S-ikv1B;C;HnE_KovFRZVhf9{EVi-O&Vnz1wVf<>vDnRG4~xAl_OaN{;sA?- zEDo_a%;E?Oi^WkE$5 zXDefk{d zoy=sZE!n8uuRNn{BUFAD@~a`Qtvi_`nx$V0A6WIuLQuC7k6QJmMqn)l6+dX7f%19C z6c&*2dCdG?Z^bRY5>=ph2jmYRev7PwCdP?Mle8O4^-9!gTW+)RFkEa!7<>*g2RRKniOzGiW)2DmtX?tMt}fOd1!C1% z8X?_Ejga2I@9tR6y(0)W?$1{Q9`@#|GG@Es~(=7AZN*KYRmaLBT z%A=82twbFwJP=^{#Z@!V@G)$gu?w@TVkT%TS+MfFmBqZTSTohuV@%^R1UZP@HJrHf&4m5b4#vkm0E4l z$L7QC6EF>pF47xjhNhd4Z$Tb~lqIc(oJeH@!7xO4DQ%VP>@u6t;}$Gf4aa%85{FA^ zu~xTkRid{ow5{s4afVpd#yL4fU8uHVE!11p2LmBlUu)h+JY&akf^D^-<_P2$vE-A| zEgv)<2K522_K0AgJ0|kp#fuWiXF(>@ye7dwBWTm6oop;j(VvfN%}O;Gq%DmpEJ4aP ztstM3lMZ1~F=t!vk; zC?N9OQ>MzdW7g%lrrS&5Vs{pjQFxC|<=q*Nn%y^-g5d4I%0-&tT!ZX)Zl!a^pUSxMo~LCL>Bp2p{? z;PyVe+AbddOCg^Ja?LQR)a&kIEvWmX)$4(oZkGRTXuN@Se+}i&VGEU#Gb@>KAml^D zO$v%c(z$85t$WeqN;^1j<(k#OGd=Z~4j*pZXzAWP@@OZIV}MUWZn>SDx5fsCyIs(7 z74mwo{X*OxanN<#AMv?sbOb+RRs2lIUl&J1K4Ep22_FM?#|PN?Qx<%ZrY+FP`7`A%%%h`AGk9x?p@K8EcGDFm2+M`SJ0I_@_XpDRn7)&1Xx!) zIx_QLVE!EPw;;cTQM^`5E96le^8GU!4x`uiLOx^KcDW1SoY8)}hFDXf#%G4`&81qn zNQbuN>S$f7t#;F5R}|edNLV_I(#aHD_5fqvMY)dPF41SM)vVO5=^&b;sF3aJ%kc$C zyxpQxVkwzcLqgB%kl&B^G)<9(zfM99Vrfb^4)t<+rd6er4IM$`BMk7HkbeWY4f5NN zUxxgB$d8Z;GsQFoccE4#dnkgfr?g>8KNa!;+bQ!0(5Y1yt#a_BJ6wE7S_Aer(%o#T zSmZBasgzE&T9F(R=p-r8!mqL>eO> zhx|-9PUB45XE=EKv%wRIeg!8I5{|c-*WiA*}>uamyFAo zFo&~I0veziYGT!V405)!V69>^Cu-5pABSZP7`RvGFqeQT9tb8RA>zmj~m}Xh3)Wh1$K!sr@Mcm0gTMR;iHiBft0eu z1uA~zuqRPeXJbUp%EbGq{xCM`Yp9Sj@P{aWUCiQLFWzH&(K4FAF5ugggWx>JrSmMX z3$SMp@ersR=(P?~NmTddB?n*e;_4OK`Y`Y+1QUuW+49&Ryzf!jIoHZw9Oe;OpeY%L zpp9CHc;^^rgn8`0Q7(DMHJ=q9 zaN3L)e;yu|o%5--TF@b~lRdC?uxQZ9TV71Z@*!^`8hg252JV&Av#hcgXSTFMFS_^E zQu5QS1P1{O`GN#GGBhVnREpHcTP8Nh%&85Lm>B0VpB0_~m2$2MPm zD$cIQ!^=nOSpYu2NFz9xSX^dtr8^)-`2cGhhiNJf^Q3&_cn{*^;=IJAt1Q^m*syn@ zX-qV6zL)tRN-#&NlG*H!O%`{)2fv~JR!CV?6jwN@iedz3&(#v@JX7@Qo=!PJI*we{ z3y}qzI0&U-Sf=Kj|*6Zl{{n(2q<2|3jPyhzwV1Ax+>V9wVzG1gT16BrMf)dgOK3FO44=<&uB;kZHIqO4D*J&AUhi5TnFSUxN zfR-H`pg71nfA>=9ysX}*G$G&HJjfXqSrTy)y5S)4^*;EcalV!#lAHkKgI`YEr_K>i zvV5mxySO0It2D=>J#VLRm846^E!&Ywx(-Nz5AbpWaSIX8u#`)eXB|?(?#S4;bLmdm zDbAL;JNqi_+$oid7!NP#faSq@WLbF>u)Ir0?DFpW@`(Ct6pHYSEZXr*ELLT*_@#GS zG|?|T-(p_;G>f)$N-UqtP3H>9Nn0w5DNy_l3iWu-M2X)Q^Sx3Edbw^i9~V7`&w-~mIWF?L^E+Fq=#-PGydCj}nJYSv@a#6aCeb4rRPt+Cw=gP$ zP!$UNzJ=lG`3k@E=7R>l_jC)=ho75(&?6FzkryINF74185K4INK?#pKP{FS_DDd+P z3j7QMqYFHr5`};pahAzVyX9m)?@s0Hd`TtKq8NEzEncTjmDk<})*9A0X9ozPV_KHOyG%$YY=8vJAuJha( znlvBa=`xSb({mUK(d_0XGwHPRGBtyt8#aDvH{h49zHk$+wWy)nDrUfUQM!tv75C3x zX%s$_J0dm{FSPuL@m+T+<0iXBCoYy|W#VaCW~VH>h6;`?&Mi%r3hpGTr|e|Lc4T8o zSyn$|(;Ttqi^aTbOqZ8ILLohsoTdQc6fjNy?}EP-CKe%ofQOdC_RwOh5l|s$4^@Z# zVCdmn(PFDPRKibo$-hqx_1eNvb~ZC<%d7ApF`O!{Hd_8tJ-Ch!!@rZ$*Y>aNd*Yk;z=4tZjzgO<{{I#O5pT^;TrQe!m_IB&IW!>7o{=RkicVk>y)vNozE3GtIT=%J^ zb$uIqcK!JBmj3=v)v|29&&mDoYkY1Sdh?BE{@i_^b9Vn9_5Gw3S>CS7hiul{D!`lnv{$z)kH|Lv0BEAoHnJtTxDgsWti@VbQC zExc~w_6V;>xV^&b749nGtrG5P;jI?#8sV)G?pook74ACdu7}nJXl;bnCTMMj)tsDV=6#Oyp$H6}g{sj00_fKzlv_ZD8_re z-^s)*CHiGzjuPE6F)zlu{q^z}DR}?J;6Vm&(D1)AcwED4Wdb#C)bM{W_=<*mG`vZ} z|HzK8N5})|Ha^G25-~w+YELXyj{bh>%kG6 zWAF|QcQM#y@Jbv5oxyz+)Ll&t z1oj%HRbg8DbQ5bCe3QZZHN1|&H3lEh@OlO}7<^E}8yFlh_>hJ-GWafo4GnK%@O=g! z*6?NqKg-}F6Uu_>zWCG59qGU)Jzx27i;mk7;;-!LKv;iiQUn{A~uC z8XjWscNv`2@GyhF$KaHPM;QEl2B$SV%HSU`*wXMAga3xX84aId@DCY0q2aR({t<&G zHGGc2f6L%3?QuO#4eW8}nbzMit*g3;M;QDw24B>;t2L?4NLB=(ayK;j^YLnI6mhe;eEag@X{ z633;8$nZR*3pp85t9d6q?HB__rc(98dtv0)P-umOUxNH=$V5mMq--;vAwCtzK7*^e@lyc5Zm2UXP^`KEJMWG>yLU6}#80XGNDkY^=TdtO(pkX-m z(yeeQh|u^vWEOG?astZpm3kHx4j8SZ*(fhnZu`orld^?WkQ|YZNYmKL(eP0eG&z(lVxBE#a>W%23n486 z1*@|NHNOe@TgXpCzOJUA3~v9fUtW$%i?Ss-5=Pz`kh2)fDy8Z796 z?1lT>Y=PWeSgKTwYo+MEfwFF0Ml-Cf>|xnbQmV+@lCf9~$~Ol>*@sH~2I2t`OAA!c zKsARTKN8YHIib{Ye(jcD9dIkRCG3%6BIlkzuL9vDNHawv;}6vQh79_N+Tx`Ad8bk@ zmHk0ECD4&&NEPNKtOrHYmRMA}yppFHo5H6el5; zjESjPZCt~+bjgT(NuGMZRJHcbI@H%xV>w*Xy-+ifJUE$iW?Wh9JhSZk_kAN9buzTp zIWzMXF-;dJWm+yL3+A;4^J%wv9&XqKxgN4Fq-`$ePSYq??+3SNR2zEV!Ky_S=F_S4 zN)>(xmHad02`uk(QN3!#{0g>*c}zR`uu(oeP|3`TBL~(dIgc2Hp;- zWX@bL#s-JA3QEQyFSp9i#^n(OUDN#$9a%<4@EI%Pb58v_KN`~EL=O`dQ*y^^nE#Wd z#$vGCFedFJ<`p_!fxHcW*;yxL$RmW-Pe`-n{-QRBei-+ns>v+0AoP`1zFaonnMp0b z46Q9{Z*3sJbnQ?i<}EPag8VGxkI{-71f3O9E4K7KtKlHDei72~%(99az&_o$UqP&O zgc|L+;WNvXa7i9|+N+b}S`Hd@gIqD~^kc#545O5pgv)NC%_oqqBDf2FBMj=Lsxjq9 z^D-*b^!3#CkEOg3$WvCqOm#GgdX7U5Vi*cII{vU>P4z-K4<=K_;l2P>U>gM7D#VW9KSlVWj z)6=vE77D3k5JYNAmA`AHdyBrYD6^^o9a^CBH1;}kP7a*xeod}m4I@~5+Al}6SgRfC z2FSaJlZkA;U@W9E&GQN3q+c4CYc9IE=Ha0nO4l}OGy$cn8<8RFl9l>isA*c3-<3wo zMdu%k`V};7+}*i>l91zW{j#-DQ<%Q>PNW z%_QnHFeOKWz$a1!%aHXA_q|Rn!nnFd>VOW00e0 z8_6!4`h{c~a#%^5j8H`Eo3!c&S&t%R8n+%=UIR|XMe3;hDzcjg<^7WunP~RYKCF|La$0N1RIBJy+;p>hDBBBJj0KBq7=Twa2%ET+kemyqo8^}=S(btjw zjxvjmHmWaVFG@xeh{+RFf>5ColT8y>MKvNA@dtr8r3-{AJtb4B>Q=ux4xuZSb)n&I z3@wsLH31Q>Gz*d0JYA}pF+eSnK#>^-goRv)IF5xqNIYi45T%AmP|!fVEmDUuBaxeq z=RQ)+O!5wr!?Ax?)&ix@oy~TT^Q`g#-JjyYUx0^I9KWNj2I^3VFOIi-&vF|ug#x7P%!IM}|(Z~yM7Lv`gBGOOU6pTo!fKj*k=a920o-}v$1%kExny6;}O1w4kptOZBQRHeI>( zW%v*JTOifoBDuo3QB{l}ZMj^9JbFygq0fqxZaTD03lRpJC>T{iTkK-U$Zx6yAo9ow zFe;J2HcQ%SSm2(E^b<=OMIpc^APu!F!gG&mNR`KqPGhfDd(L64pT=SY5j*X8Jk`^v z8C4C&G5lT*j(t%2X#z)#aowJ>_X#!T6r4C6zz^V0K(2yRJK3D70Rw@kKnknHG19** z1*W+D82y9~TE`mHqkVLR%Hc?wByn$)V}KUzEd;gpmtq{U3u>_5p$N;oN&48SlGI3R z)?Kl&-nGsmqwz95Y^O*mErl{7@wiMz)WzcC1v$m{)cD}SVmrXU(_VjF#)Tt4?_<~RmtRrpd(Fnf8J8DFo z(eI%n9lu6V5uQDvpq@3ADd`Np@|_Vy@++Sk(HVM5L|H1S%$?6pW%K5Qr81|Jpy=HW z)#LdMMeIrZK%)6{hW?nao)cZLE~hd4G{Sh17p-X3%ZfABL!-ns#b3J7-0-oHWz)N{-6p{T`L6JFLnwRsZE39Yq=2vRp;G)6+m? z!}!YkGn%rs^PCykX$nnwC5H0UJeopaI@yVIDurTsZN*o{G`{ja2@m0}h#YwZgzIHQ0*1eEs<#;Xd zmaG0{+5*B)NvEvtS>5%(AJ2I=;@veKtl^!0tJ->`W%Q@WRn703wOzek>+rWZPIb5P z{_j#NwHD{CklNnUyFzZ8)xUS?|9*|{*_xI7`g_~|o?H8WUh}(+Lwk8gT6$4OYJ2|X JmAu=^`)|aq#T5Vm literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8f79f8f5a04fbabe619cae1d3bf206b75830fbc6 GIT binary patch literal 185 zcmZSn%*(Zp`;l)l0~9akEP6*BWOOB8Z4 zlZq0HD!KeLK-x;!fkb?KN`7*DyatfTfFO#^fn5F4;v)Tw{M=L^Beh6B*&roVzo4=t sBR@|+08D{RF46~@svjQ@vLHTQ52%0xsMjVpKczG$)s7j+E(T%-0FM4Dg8%>k literal 0 HcmV?d00001