def get_filename2(mode='load', title=None): while True: bancls() if title: fpr('%s' % title) print fpr('Please provide a file name:') fn = raw_input(' []> ') print if fn: if mode == 'save': if os.path.isfile(fn): if get_yesno_input (' File already exist. Overwrite it [y/N]: '): return fn #else: # return None else: return fn if mode == 'load': if os.path.exists(fn): return fn else: fpr.fail('File not found') print if get_yesno_input(' Return to menu [y/N]> '): break
def logs_save(logs, thread_name, logpfx): from core.data import cfgs, smtp, fpr, tc, DEBUG from core.func import dbginfo from datetime import datetime logfile = logpfx + datetime.now().strftime('%Y%m%d%H%M%S') import os, errno import logging logger = logging.getLogger('threadslogs') fn = cfgs['log_path'] + '/' + logfile try: print with open(fn, "w") as text_file: text_file.write("{0}".format(logs)) fpr.ok('Saving logs in %s' % logfile) logger.info('[%s]: Successful saving logs in file: %s' % (thread_name, logfile)) except IOError as ioex: fpr.fail('Saving logs in %s' % logfile) #fpr.fail('Err: Logs not saved with %s' % logfile ) print fpr.err('Errno: %s' % ioex.errno) fpr.err('Err code: %s' % errno.errorcode[ioex.errno]) fpr.err('Err message: %s' % os.strerror(ioex.errno)) logger.info('[%s]: Saving logs in file: %s failed: %s: %s' % (thread_name, logfile, errno.errorcode[ioex.errno], os.strerror(ioex.errno)))
def get_cpt_no(): # set_dval(q=' Set CPT', dd=smtp['dha']['threads'], key='cpt', val=None) info('info','Note: CPT defines a number of commands sent per single thread where each \n' \ ' thread is a a new SMTP connection which need to be established.\n\n' \ ' * CPT = NOR / NOT\n' \ ' * CPT can not be greater than number of recipients (NOR) \n' \ ' * CPT is recounted when NOT is changed.\n' \ ' * CPT is equal NOR by default ', adj='l' ) print n = raw_input(' [%s]> ' % smtp['dha']['threads'].get('cpt',None)) \ or smtp['dha']['threads'].get('cpt',None) if n == None: return MAX_COMMANDS = 1000 if type(n) is int or n.isdigit(): print if 0 < int(n) < MAX_COMMANDS: # smtp['dha']['threads']['cpt'] = int(n) # fpr.ok('%s'%n) if chDHAThrDep(cpt=int(n)): fpr.ok('%s'%n) else: fpr.fail('Setting CPT as %s' % n)
def get_rcpt_no(): # from core.data import smtp,fpr,tc,tr # from core.data import MAX_RCPT_PER_MSG # from core.func import info info('info','Note: RPM defines a number of recipients used with a single message.\n' \ ' It\'s a number of RCPT TO commands send with corresponding addresses.\n\n' \ ' * RPM value can not be greater than number of recipients (NOR) when \n' \ ' NOR is greater than one.\n' \ ' * Settinng RPM does not make sense for single recipient. ', adj='l' ) #fpr('RpM can not be greater than number of recipients when NoR > 1') #fpr('Settinng RpM does not make sense for single recipient') print n = raw_input(' [%s]> ' % smtp['replay']['threads'].get('rpm',None)) \ or smtp['replay']['threads'].get('rpm',None) if n == None: return if type(n) is int or n.isdigit(): print if 0 < int(n) < MAX_RCPT_PER_MSG: print #ret = chThrDep(rpm=int(n)) #if ret > True: # smtp['replay']['threads']['rpm']=int(ret) if chThrDep(rpm=int(n)): fpr.ok('%s' % n) else: print fpr.fail('%s' % n)
def get_msgs_no(): # from core.data import smtp,fpr,tc,tr # from core.data import MAX_MSG_PER_TH # from core.func import info info('info','Note: MPT defines a number of messages sent per single thread where each \n' \ ' thread is a a new SMTP connection which need to be established.\n\n' \ ' * MPT can not be greater than number of recipients (NOR) when \n' \ ' NOR is greater than one.\n' \ ' * Settinng MPT also does not make sense for single recipient. ', adj='l' ) print n = raw_input(' [%s]> ' % smtp['replay']['threads'].get('mpt',None)) \ or smtp['replay']['threads'].get('mpt',None) if n == None: return if type(n) is int or n.isdigit(): print if 1 <= int(n) <= MAX_MSG_PER_TH: print #ret = chThrDep(mpt=int(n)) #if ret > True: # smtp['replay']['threads']['mpt']=int(ret) if chThrDep(mpt=int(n)): fpr.ok('%s' % n) else: print fpr.fail('%s' % n)
def iworkspace(): SECMODE=0700 fpr('Initialiazing workspace ..') # Directory check if os_type() == 'posix': # fpr('+ POSIX system found') # fpr('+ Directory check') for k in cfgs: #print k if re.match('.*_path$',k): #print k,cfgs[k] _dir = cfgs[k] #if not os.path.exists(_dir): if not os.path.isdir(_dir): try: os.makedirs(_dir) fpr.ok('* Creating workspace directory: %s' % _dir ) except OSError as exception: fpr.fail('* Creating workspace directory: %s' % _dir ) if exception.errno != errno.EEXIST: raise if exception.errno != errno.EACCES: raise if os.path.isdir(_dir): if os.path.basename(_dir) in ['keys','logs']: try: os.chmod(_dir,SECMODE) except OSError, e: pass
def get_threads_no(): info('info','Note: NOT defines the number of threads where each thread is a new separate' \ ' and simultaneous connection. \n' \ ' * NOT = NOR / CPT \n' \ ' * NOT is 1 by default \n' \ ' * NOT value should be keep between 1 - %s \n' \ ' * NOT is recounted when CPT is changed' % MAX_THREADS, adj='l' ) print n = raw_input(' [%s]> ' % smtp['dha']['threads'].get('not',None)) \ or smtp['dha']['threads'].get('not',None) if n == None: return if type(n) is int or n.isdigit(): print if 0 < int(n) < MAX_THREADS: # smtp['dha']['threads']['not'] = int(n) # fpr.ok('%s'%n) if chDHAThrDep(t=int(n)): fpr.ok('%s'%n) else: fpr.fail('Setting NoT as %s' % n)
def runDHAThreads(): viewDHAThreadsSummary() print if smtp['addrlist']['r_reject'].keys() or smtp['addrlist']['r_valid'].keys(): fpr('Flushing currently found results (valid/refused recipients) ..') del smtp['dha']['threads']['ok'][:] del smtp['dha']['threads']['fail'][:] smtp['addrlist']['r_reject'].clear() smtp['addrlist']['r_valid'].clear() from pprint import pprint if smtp['dha'].get('cmd') != 'RCPT TO': #chek if sysem support EXPN/VRFY command before threading print if get_yesno_input(' Would you like to test an SMTP server for %s method before threading [y/N]: ' % smtp['dha'].get('cmd')): sc = enumSMTPcmd(v=False,dhost=smtp['connect']['hosts'][0]) # enumSMTPcmd(v=True,dhost=smtp['connect']['hosts'][0]): #pprint(sc) #if smtp['connect']['hosts'][0]['tls_mode'] == 'TLS': #print smtp['dha'].get('cmd') if smtp['dha'].get('cmd') in sc['method']: fpr.ok('Method %s is supported' % smtp['dha'].get('cmd')) else: fpr.fail('Method %s is unsupported' % smtp['dha'].get('cmd')) print fpr('Consider to change an SMTP method!') print t = srThread() t.daemon = True t.delay = smtp['dha']['threads'].get('delay',1) t.threads = smtp['dha']['threads']['reals'].get( 'not',smtp['dha']['threads'].get('not',1) ) t.cpt = smtp['dha']['threads']['reals'].get( 'cpt',smtp['dha']['threads'].get('cpt',get_rcpts('NoR')) ) t.method = smtp['dha'].get('cmd') t.rcpts = smtp['addrlist']['rcpts'] #print get_rcpts('NoR') if get_rcpts('NoR'): if raw_input(' Confirm threading [y/N]:> ') in ['y','Y']: # enable logging from core.msg.sender import Logger logger = Logger() t.run() logger.close() else: print fpr.err('Threading were Cancaled!') else: print fpr.err('Err. No recipients defined!')
def loadSession(): print if not get_yesno_input(' Would you like to load saved session: [y/N]> '): return print fpr('Session files are stored under the session subdirectory by default.\n' \ 'Please provide a full path if you would like to load a session file from different location.') # get the latest file as default: print latest = max(glob.iglob(os.path.join(cfgs['sess_path'], '*.session')), key=os.path.getctime) if latest: fpr('Latest saved session is %s' % os.path.basename(latest)) print sf = raw_input(' [%s]> ' % os.path.basename(latest)) or latest print # if filename does not include path than search file in session dir if not os.path.dirname(sf): sf = cfgs['sess_path'] + '/' + sf if os.path.exists(sf): # import json try: f = open(sf, 'r') # json loads tmp = json.load(f) #from pprint import pprint #pprint(tmp) #TODO: test tmpe dict x = 0 for k in tmp.keys(): if k in [ 'connection', 'signatures', 'replay', 'content', 'headers' ]: x += 1 if x: fpr.ok('Session file seems to be proper') else: fpr.fail('Session file is not proper') return # overwrite main SMTP dict print '=====' #smtp = {k:v for k,v in tmp.items()} for k, v in inSMTPdict(tmp).items(): print k, v smtp[k] = v print '=====' fpr.ok('Session load successful') except IOError as e: fpr.err('Loding session failed: %s' % e) else: fpr.err('Session file does not exist')
def get_timeout(): info('info','Note: Time waiting for server reply', adj='l' ) print n = raw_input(' [%s]> ' % smtp['dha']['threads'].get('timeout',TH_TIMEOUT)) \ or smtp['dha']['threads'].get('timeout',TH_TIMEOUT) if n and (type(n) is int or n.isdigit()): if 0 <= int(n): print smtp['dha']['threads']['timeout']=int(n) fpr.ok('%s'%n) else: print fpr.fail('%s'%n)
def dumpSession(): info('info','Saved session allows to save current connection and message setting to be \n' \ 'useful with further tests, as a proof of successful test or used as template\n\n'\ 'Note: Session file can store sensitive data like SMTP authentication\n' \ ' credential or private keys and certificate.',adj='l') print if not get_yesno_input( ' Would you like to save your current session: [y/N]> '): return print fpr('Session files are stored under the session subdirectory by default.\n' \ 'Please provide a full path if you would like to store you session somehere else.') sessfile = 'minja-' + datetime.now().strftime('%Y%m%d%H%M%S') + '.session' print sf = raw_input(' [%s]> ' % sessfile) or sessfile print if sf == sessfile or not os.path.dirname(sf): sf = cfgs['sess_path'] + '/' + sf if os.path.exists(sf): fpr('Session file already exist') else: if os.access(os.path.dirname(sf), os.W_OK): #the file does not exists but write privileges are given fpr('Saving under %s\n' % sf) #import json dd = outSMTPdict(smtp) try: #f = codecs.open(sf, 'w', encoding='utf-8') f = open(sf, 'w') json.dump(dd, f, indent=3) fpr.ok('Session saving') except IOError as e: fpr.err('Saving file failed: %s' % e) else: fpr.fail('Missing write permission')
def save_content_asfile(content, fn, mode='w'): # if os.path.isfile(fn): # if not get_yesno_input (' File already exist. Overwrite it [y/N]: '): # return False try: with open(fn, mode) as fo: fo.write(content) fpr.ok('Saving content in %s' % fn) except IOError as ioex: fpr.fail('Saving content in %s' % fn ) #fpr.fail('Err: Logs not saved with %s' % logfile ) print fpr.err('Errno: %s' % ioex.errno) fpr.err('Err code: %s' % errno.errorcode[ioex.errno]) fpr.err('Err message: %s' % os.strerror(ioex.errno) )
def get_filename(): #import os.path while True: bancls() fpr('Load attachment from file') print fpr('Please provide a full path: ') fn = raw_input(' > ') if fn: #content.att_load_file(smtp['content']['att'],attfn) if os.path.exists(fn): return fn else: fpr.fail('File not found') print if raw_input(' Return to menu [y/N]> ') in ['y','Y']: break
def get_delay(): info('info','Note: Delay is number of miliseconds between starting new threads, \n' \ ' where each new thread is a new SMTP connection.', adj='l' ) print n = raw_input(' [%s]> ' % smtp['dha']['threads'].get('delay',TH_DELAY)) \ or smtp['dha']['threads'].get('delay',TH_DELAY) if n and (type(n) is int or n.isdigit()): if 0 <= int(n): print smtp['dha']['threads']['delay']=int(n) fpr.ok('%s'%n) else: print fpr.fail('%s'%n)
def get_threads_no(): # from core.data import smtp,fpr,tc,tr # from core.data import MAX_THREADS # fpr.info('Threads are treated as seperate connections.') # print # fpr('Try to keep number of Threads between <1-100>') # fpr('NoT can not be greater than number of recipients when NoR > 1') # print info('info','Note: NOT defines the number of threads where each thread is a new seperate' \ ' and simultaneous connection. \n' \ ' * NOT can not be greater then number of recipients (NOR) when \n' \ ' NOR is greater than one.\n' \ ' * NOT value should be kept between 1 - %s \n\n' \ ' ** NOT can be greater than 1 when there is only 1 recipient but\n' \ ' ** this raise a special case when the same message is sent multiple \n' \ ' ** times (NOT times) to single recipient using a seperate connection \n' \ ' ** and bombarding recipient with the same message' % MAX_THREADS, adj='l' ) print n = raw_input(' [%s]> ' % smtp['replay']['threads'].get('not',None)) \ or smtp['replay']['threads'].get('not',None) if n == None: return if type(n) is int or n.isdigit(): print if 0 < int(n) < MAX_THREADS: #smtp['replay']['threads']['not']=int(n) #fpr.ok('%s'%n) #ret = chThrDep(t=int(n)) #if ret > True: # #smtp['replay']['threads']['not']=int(n) # smtp['replay']['threads']['not']=ret if chThrDep(t=int(n)): pass #fpr.ok('%s'%n) else: fpr.fail('Setting NoT as %s' % n)
def run_wizzard_host(d): # WHAT CAN BE DONE MORE: # - use get)single and get_yesno fun # - modify to support multiple hosts ? fpr('Welcome in Wizzard') print fpr('Please follow .. ') print t = dict() t['host'] = get_single_input('SMTP Host', d.get('host',''),nl='') t['port'] = get_single_input('SMTP Port', d.get('port',''),nl='') t['helo'] = get_single_input('SMTP HELO', d.get('helo',''),nl='') t['smtp_auth_user'] = get_single_input('SMTP AUTH Username ', d.get('smtp_auth_user',''),nl='') t['smtp_auth_pass'] = get_single_input('SMTP AUTH Password ', d.get('smtp_auth_pass',''),nl='') # t['tls_mode'] = get_single_input('SMTP TLS', d.get('tls_mode','NoTLS'),nl='') if d.get('tls_mode') == 'NoTLS': fpr('TLS Mode: Disabled') if get_yesno_input(' > Enable TLS mode [y/N]> '): t['tls_mode'] = 'TLS' fpr('TLS Mode: Enabled') elif d.get('tls_mode') == 'TLS': fpr('TLS Mode: Enabled') if get_yesno_input(' > Disable TLS mode [y/N]> '): t['tls_mode'] = 'NoTLS' fpr('TLS Mode: Disabled') print if raw_input(' Save [Y/n]> ') in ['y', 'Y', '']: print fpr.ok('Settings saved') for k in t.keys(): d[k] = t[k] else: print fpr.fail('Settings not saved!')
def get_msgs_delay(): # from core.data import smtp,fpr,tc,tr # from core.data import MAX_MSG_PER_TH # from core.func import info info('info','Note: Delay is number of miliseconds between starting new threads, \n' \ ' where each new thread is a new SMTP connection.', adj='l' ) #fpr('Specify Delay between running new thread/connection') print n = raw_input(' [%s]> ' % smtp['replay']['threads'].get('delay',TH_DELAY)) \ or smtp['replay']['threads'].get('delay',TH_DELAY) if n and (type(n) is int or n.isdigit()): if 0 <= int(n): print smtp['replay']['threads']['delay'] = int(n) fpr.ok('%s' % n) else: print fpr.fail('%s' % n)
def get_sample(sample): #import os #import hashlib #from urllib2 import Request, urlopen, URLError, HTTPError #from core.func import dbginfo fpr('Fetching sample .. ') fn = sample['filename']+'.tmp' url = sample['url'] req = Request(url) try: r = urlopen(req) print except HTTPError as e: dbginfo('error', 'Err: The server couldn\'t fulfill the request.\n' \ 'Code: %s ' % e.code ) except URLError as e: dbginfo('error', 'Err: Server can not be reached!\n' \ 'Reason: %s ' % e.reason ) else: # everything is fine data = r.read() fpr.ok('Data fetching') with open(fn,"wb") as f: if data: try: f.write(data) except IOError: fpr.fail('Temporary file saving') return else: f.close() fpr.ok('Temporary file saving') if os.path.isfile(fn): md5tmpfn = hashlib.md5(open(fn, 'rb').read()).hexdigest() #print sample['md5'] #print hashlib.md5(open(fn, 'rb').read()).hexdigest() if sample['md5'] == md5tmpfn: fpr.ok('Hash testing') try: os.rename(fn, sample['filename']) except IOError: fpr.fail('File saving') return else: fpr.ok('File saving') else: fpr.fail('Hash testing') else: fpr.err('No data') return
def smtp_dha(cpt=1, rate=None, rcpts=[], method='RCPT TO',relays={} ,name='DHA-T-Single',v=False): dhar = dict() from pprint import pprint from core.data import cfgs,smtp,fpr,tc,DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid dbginfo('DEBUG','name=%s, cpt=%s, method=%s, rate=%s, rcpts=%s' % (name,cpt,method,rate,rcpts) ) #verbnose dhost=smtp['connect']['hosts'][0] try: import sys import smtplib # # log debuglevel output from smtplib # # redirect stderr from smtplib to string # # # # - from smtplib import stderr # if cfgs['conv_logs'] and cl: # ostderr = smtplib.stderr # smtplib.stderr = StderrLogger() # run smtp session if v: fpr.white('Establishing the session ..') s = smtplib.SMTP(dhost['host'],dhost['port']) # if cfgs['conv_logs'] and cl: # s.set_debuglevel('debug') # HELO - introduce yourself if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) #r = s.helo(smtp['connect']['hosts'][0]['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # STAARTTLS if 'starttls' in s.esmtp_features.keys(): if dhost['tls_mode'] == 'TLS': if v: fpr.white('TLS supported and requested') fpr.white('Establishing TLS session ..') fpr.cyan('>>> %s' % ('STARTTLS')) (c,m) = s.starttls() if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) # HELO - introducing yourself on encrypted session should be done as well if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.white('TLS supported but not requested') fpr.white('Unencrypted session established') # SMTP AUTH if 'auth' in s.esmtp_features.keys(): if dhost['smtp_auth_user'] != '': if v: fpr.cyan('>>> %s %s' % ('AUTH PLAIN','*********')) (c,m) = s.login(dhost['smtp_auth_user'],dhost['smtp_auth_pass']) if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif dhost['smtp_auth_user'] != '': if v: fpr.white('Authentication SET but not available (AUTH not supported)') fpr.white('Trying without AUTH') if method.lower() == 'rcpt to': # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] if v: fpr.cyan('>>> %s %s' % ('MAIL FROM:',sender)) (c,m) = s.docmd('MAIL FROM:',sender) if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # number of recipients to test # rpt - rcpt/thread # cpt - command/thread if cpt == None: cpt = 1 rpt = len(rcpts) cpt = rpt if v: fpr.white('Enumerating recipients ..') fpr.white(' * %s recipients to test with this thread' % len(rcpts)) fpr.white(' * method in use: %s' % method.lower()) #print rcpts for r in rcpts: if method.lower() == 'rcpt to': if v: fpr.cyan('>>> %s: <%s>' % (method,r)) (c,m) = s.docmd('%s:' % method,'<%s>' % r) else: # treat results returned from vrfy and expn similar # expn should have a separate condition as it could return # a list of recipients in case of mailing list but # in modern networks you should be really lucky to find such an SMTP server # supporting - good luck with that # - it should be implemented just as proof of concept rather than for real use if v: fpr.cyan('>>> %s <%s>' % (method,r)) (c,m) = s.docmd('%s' % method,'<%s>' % r) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': True, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) elif 500 <= c <= 599: if v: fpr.err('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': False, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) else: if v: fpr.err('<<< %s %s' %(c,m)) dhar.setdefault(r, { 'valid': False, 'code': c, 'msg': m, 'method': method.lower(), 'host': dhost['host'], 'thread': name } ) # query timeout - wait before next command #sleep(1) # pprint(dhar) # quit smtp session if v: fpr.cyan('>>> %s' % ('QUIT:')) (c,m) = s.quit() if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) fpr.white('Session closed successfully') elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) if v: print fpr('To check valid recipients back to the main submenu') #pprint(dhar) # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)
def smtp_sender(message, rpm=None, mpt=None, rate=None, rcpts=[], relays={}, name='T-Single'): #from core.data import smtp,fpr,tc from core.data import cfgs, smtp, fpr, tc, DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid # TODO: allow conv logs use with threads # for now: use conv logs only with single thread # for 3.1 inject message cl = 0 if name == 'T-Single': cl = 1 # ---------------------------------------------------- # # log thread session import logging # create logger logger = logging.getLogger('threadslogs') logger.info('Starting thread: [%s]' % name) logger.debug('[%s]: Pid=%d' % (name, get_tid())) logger.debug('[%s]: rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) # host logger.info('[%s]: H=%s:%s, smtp_auth=(%s,%s)' % (name, smtp['connect']['hosts'][0].get('host'), smtp['connect']['hosts'][0].get('port'), smtp['connect']['hosts'][0].get('smtp_auth_user'), smtp['connect']['hosts'][0].get('smtp_auth_pass'))) print # ---------------------------------------------------- # dbginfo( 'DEBUG', 'name=%s, rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) #return 0 # ---------------------------------------------------- # from StringIO import StringIO class StderrLogger(object): def __init__(self): #self.logger = logging.getLogger('threadslogs') self.sio = StringIO() def write(self, message): #self.logger.debug(message) self.sio.write(message) # ---------------------------------------------------- # try: import sys import smtplib # log debuglevel output from smtplib # redirect stderr from smtplib to string # # - from smtplib import stderr if cfgs['conv_logs'] and cl: ostderr = smtplib.stderr smtplib.stderr = StderrLogger() # run smtp session s = smtplib.SMTP(smtp['connect']['hosts'][0]['host'], smtp['connect']['hosts'][0]['port']) if cfgs['conv_logs'] and cl: s.set_debuglevel('debug') # HELO - introduce yourself s.ehlo(smtp['connect']['hosts'][0]['helo']) # STAARTTLS if smtp['connect']['hosts'][0]['tls_mode'] == 'TLS': s.starttls() # SMTP AUTH if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': s.login(smtp['connect']['hosts'][0]['smtp_auth_user'], smtp['connect']['hosts'][0]['smtp_auth_pass']) # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] # for single injection or when mpt value unknown use single message per connection if mpt == None: mpt = 1 rpm = len(rcpts) # split messages per connection for m in range(mpt): # m strt from 0 to mpt-1 # split rcpts per message si = m * rpm ei = m * rpm + rpm m_rcpts = rcpts[si:ei] #print (m,si,ei,m_rcpts) if m_rcpts: logger.debug('[%s]: F=%s, MPT=%s/%s R=%s' % (name, sender, (m + 1), mpt, m_rcpts)) # SEND # https://docs.python.org/2/library/email.message.html#email.message.Message # as_string([unixfrom]) # Return the entire message flattened as a string. When optional unixfrom is True, the envelope header is included in the returned string. unixfrom defaults to False. Flattening the message may trigger changes to the Message if defaults need to be filled in to complete the transformation to a string (for example, MIME boundaries may be generated or modified). response = s.sendmail(sender, m_rcpts, message.as_string(unixfrom=False)) if response: smtp['addrlist']['r_reject'].update(response) # dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) # The response returns a dictionary, with one entry for each recipient that # was refused. Each entry contains a tuple of the SMTP error code and the # accompanying error message sent by the server. # 'r_reject': {'': (501, '#5.1.1 bad address'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # "'*****@*****.**'": (550,'#5.1.0 Address rejected.'), # to be compatibile with other features build a r_valid dict # m_rcpts - all rcpts per tread for r in m_rcpts: if not r in response.keys(): # recipient is valid if not refused smtp['addrlist']['r_valid'].setdefault(r, (250, 'OK')) # s.sendmail(sender, rcpt, message.as_string(unixfrom=False)) # quit smtp session s.quit() #FIXME: # message sent success : nto true when threads with more than one message in it # fix this print info if name == 'T-Single': fpr.ok('Message was sent successfuly') smtp['replay']['threads']['ok'].append(name) # when only part of recipients/sender failed it looks like than # exception for recipientsRefused is not triggered # remember: to clear refu recipient list before you call out this function if response: smtp['addrlist']['r_reject'].update(response) dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) #from core.msg.viewers import viewRecipientsRefused # All recipients were refused. Nobody got the mail. The recipients attribute of # the exception object is a dictionary with information about the refused # recipients (like the one returned when at least one recipient was accepted). # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)
def enumSMTPcmd(v=None,dhost=smtp['connect']['hosts'][0]): #TODO: if no EHLO , use HELO from pprint import pprint # secure extn - list of extn received after successfull STARTTLS commands scmds = { 'extn' : [], 'secure_extn': [], 'cmds': '', 'method': [], } #pprint(dhost) #pprint(scmds) print try: import sys import smtplib # run smtp session if v: fpr.white('Establishing the session with %s on port %s' % (dhost['host'],dhost['port'])) s = smtplib.SMTP(dhost['host'],dhost['port']) if v: fpr.cyan('>>> %s' % 'HELP') r = s.help() scmds['scmds'] = r if v: fpr.green('<<< %s' % r) # if cfgs['conv_logs'] and cl: # s.set_debuglevel('debug') # HELO - introduce yourself if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) #r = s.helo(smtp['connect']['hosts'][0]['helo']) #print (c,m) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: if v: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): if v: fpr.white(' * %s %s' % (scmd,sarg)) scmds['extn'].append((scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) # STAARTTLS if 'starttls' in s.esmtp_features.keys(): if dhost['tls_mode'] == 'TLS': if v: fpr.white('TLS supported and requested') fpr.white('Establishing TLS session ..') fpr.cyan('>>> %s' % ('STARTTLS')) (c,m) = s.starttls() if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) # HELO - introducing yourself on encrypted session should be done as well if v: fpr.cyan('>>> %s %s' % ('EHLO',dhost['helo'])) (c,m) = s.ehlo(dhost['helo']) if v: #print (c,m) if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) if s.does_esmtp: fpr.white('ESMTP supported and have extn:') #print s.does_esmtp #print s.esmtp_features for (scmd,sarg) in s.esmtp_features.items(): fpr.white(' * %s %s' % (scmd,sarg)) scmds['secure_extn'].append((scmd,sarg)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.white('TLS supported but not requested') fpr.white('Unencrypted session established') # # SMTP AUTH # if 'auth' in s.esmtp_features.keys(): # if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': # if v: # fpr.cyan('>>> %s %s' % ('AUTH PLAIN','*********')) # (c,m) = s.login(smtp['connect']['hosts'][0]['smtp_auth_user'],smtp['connect']['hosts'][0]['smtp_auth_pass']) # if v: # if 200 <= c <= 299: # fpr.green('<<< %s %s' %(c,m)) # elif 500 <= c <= 599: # fpr.err('<<< %s %s' %(c,m)) # else: # if smtp['connect']['hosts'][0]['smtp_auth_user'] != '': # if v: # fpr.white('Authentication SET but not available (AUTH not supported)') # fpr.white('Trying without AUTH') # else: # if v: # fpr.white('Authentication not available (AUTH not supported)') # fpr.white('Trying without AUTH') #print rcpts r = 'postmaster' for sm in ['EXPN','VRFY']: if v: fpr.cyan('>>> %s <%s>' % (sm,r)) (c,m) = s.docmd('%s' % sm,'<%s>' % r) if 200 <= c <= 299: if v: fpr.green('<<< %s %s' %(c,m)) scmds['method'].append(sm) elif 500 <= c <= 599: if v: fpr.err('<<< %s %s' %(c,m)) else: if v: fpr.err('<<< %s %s' %(c,m)) if 'rcpt' in scmds['scmds'].lower(): scmds['method'].append('RCPT') # pprint(dhar) # quit smtp session if v: fpr.cyan('>>> %s' % ('QUIT:')) (c,m) = s.quit() if v: if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) fpr.white('Session closed successfully') elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) #pprint(scmds) return scmds # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') fpr.warn(str(e))
try: os.chmod(_dir,SECMODE) except OSError, e: pass if not DEBUG: return 0 # Modules: fpr('+ Module checks') MODULES=['dkim',] for m in MODULES: if modexists(m): fpr.ok('* module: %s ' % m) else: fpr.fail('* module: %s ' % m) # Sessions: # DKIM/S/MIME Keys # Certificates if DEBUG: fpr('Running .. (debug on)') else: fpr('Running .. ') #time.sleep(1)
def run(self): dbginfo( 'debug', 'Run: NoT=%s,RpM=%s,MpT=%s,' % (self.threads, self.rpm, self.mpt)) dbginfo('debug', 'Run: Rcpts: %s' % self.rcpts) #return if self.msg == None: fpr.fail('Message is not defined') return 0 # count number of recipients per threads rpt = 0 if self.rpm and self.mpt: rpt = self.rpm * self.mpt thr = [] for i in range(self.threads): # i - thread number - count from zero # split rcpts list per threads si = i * rpt ei = i * rpt + rpt t_rcpts = self.rcpts[si:ei] dbginfo('debug', 'Thread: Rcpts: %s' % t_rcpts) #return 0 # special case when rpm/mpt/.. = 1 and rcpt = 1 and not > 1 if len(self.rcpts) == 1 and (self.rpm and self.mpt) == 1: t_rcpts = self.rcpts dbginfo( 'debug', 'Raise Special Case: Thread: Rcpts: %s - %d' % (t_rcpts, len(self.rcpts))) # declare thread t = threading.Thread( target=smtp_sender_new, kwargs=dict( message=self.msg, rpm=self.rpm, mpt=self.mpt, rate=self.rate, rcpts=t_rcpts, name='T-%d' % i, ), name='T-%d' % i, verbose=None, ) t.setDaemon(self.daemon) #t.setName('t-%d'%i) thr.append(t) t.start() bancls2(thr, i, opt='replay') # delay between starting new connection (threads) time.sleep(self.delay / 1000.0) bancls2(thr, 0, 'replay') while threading.activeCount() > 1: i = 1 for j in thr: j.join(self.interval) i = i + 1 bancls2(thr, i, 'replay')
if 200 <= c <= 299: fpr.green('<<< %s %s' %(c,m)) fpr.white('Session closed successfully') elif 500 <= c <= 599: fpr.err('<<< %s %s' %(c,m)) #pprint(scmds) return scmds # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: unable to sent message. All recipients refused.') fpr.warn(str(e)) except smtplib.SMTPResponseException, e: fpr.fail('Error: unable to sent message') fpr.err('%s %s',(e.smtp_code,e.smtp_error)) except smtplib.SMTPException: fpr.fail('Error: unable to sent message') # for all other errors like socket, io, rtc errors except Exception,error: fpr.err('%s' % str(error) ) # --------------------------------------------------------------------------- # # # --------------------------------------------------------------------------- #
def dkim_vrfy(message): PYDNS_AVAILABLE = False DNSPYTHON_AVAILABLE = False # check dns libraries try: import dns DNSPYTHON_AVAILABLE = True except ImportError: pass try: import DNS PYDNS_AVAILABLE = True except ImportError: pass try: from dkim import DKIM, verify, DKIMException if not (PYDNS_AVAILABLE or DNSPYTHON_AVAILABLE): raise Exception("no supported dns library available") except: pass try: import dkim if True: d = dkim.DKIM(message) #print 'dir:',dir(d) #print 'sel:',d.selector #print 'dom:',d.domain #print 'h:',d.headers #print 'sh:',d.signed_headers #print 'sa:',d.signature_algorithm #print 'sf:',d.signature_fields #print 'ks:',d.keysize r = d.verify() fpr('Signature details') fpr('_' * (tc - 4)) print fpr(' selector (s): %s' % d.selector) fpr(' domain (d): %s' % d.domain) fpr(' headers : %s' % d.headers) fpr(' signed heads: %s' % d.signed_headers) fpr(' key algo (a): %s' % d.signature_algorithm) fpr(' key size : %s' % d.keysize) print fpr(' DKIM-Signature: %s' % d.signature_fields) fpr('_' * (tc - 4)) print else: r = dkim.verify(message) if r: fpr.ok("DKIM signature verification successful") else: fpr.fail("DKIM signature verification failed") except DKIMException, e: fpr("Verification result:") print fpr('%s' % e) print fpr.fail("DKIM signature verification failed")
print fpr.err( 'SPF record not found or more than one record found') fpr('_' * (tc - 4)) if dd.get('ip'): res, code, expl = q.check() valid = True else: print fpr.warn( 'Verification skipped. Missing client IP address!') except spf.TempError, e: fpr.err('Error: %s' % e) print if not valid: fpr.fail('SPF policy validation') return fpr.ok('SPF policy validation') print fpr('SPF Verification result') fpr('_' * (tc - 4) + '\n\n') fpr.info('%s,%s,%s' % (res, code, expl)) print fpr('SPF status : %s' % res) fpr.info('SPF code : %s ' % code) fpr('SPF info : %s' % expl) fpr('_' * (tc - 4) + '\n\n') """
def e_base64(op): # load from file if op == '1': fn = '' while True: bancls() fpr('Diagnostics: Base64 encoder') print fpr('Please provide a file name:') fn = raw_input(' []> ') print inputs = get_file_content(fn) print if inputs: #inputs = f.readlines() # include \n #inputs = f.read().splitlines() # exclude \n dbginfo('debug', inputs) print encb64 = coders.encode_attch(inputs) if isinstance(encb64, dict): fpr.ok('File content was encoded successful') else: fpr.fail('File content was not encoded') waitin() return encb64 elif raw_input(' Return to menu [y/N]> ') in ['y', 'Y']: break waitin() # load from input - paste it if op == '2': bancls() fpr('Diagnostics: Base64 encoder') print if raw_input(' Would you like to encode some content [y/N]> ') in [ 'y', 'Y' ]: print fpr('Please provide some plain content') fpr('Use Ctrl-D with new line to continue.') print fpr.blue('_' * (tc - 4)) print inputs = get_inputs() fpr.blue('_' * (tc - 4)) if inputs: dbglog(inputs) print encb64 = coders.encode_attch('\n'.join(inputs)) if isinstance(encb64, dict): fpr.ok('Input content was encoded successful') else: fpr.fail('Input content was not encoded') waitin() return encb64 #print inputs waitin()
def mpart_saver(part, op): if op == 1: #save as it is, no decoding #pprint(part) part['encext'] = None for (h, hv) in part['mheaders']: #fpr('%s: %s' % (h,hv)) if h.lower() == 'content-transfer-encoding': part['encext'] = '.' + hv.lower() print if not get_yesno_input(' Would you like to save this part: [y/N]> '): return print if part['filename']: fn = part['filename'] + part['encext'] else: fn = 'minja-' + part['type'].replace( '/', '_') + '-' + datetime.now().strftime( '%Y%m%d%H%M%S') + part['encext'] print fn = raw_input(' [%s]> ' % fn) or fn print #if sf == sessfile or not os.path.dirname(sf): # sf = cfgs['sess_path']+'/'+sf if not os.path.dirname(fn): fn = cfgs['mparts_path'] + '/' + fn if os.path.exists(fn): fpr('File already exist') else: if os.access(os.path.dirname(fn), os.W_OK): #the file does not exists but write privileges are given fpr('Saving under %s\n' % fn) try: #f = codecs.open(fn, 'w', encoding='utf-8') f = open(fn, 'w') f.write(part['payload']) f.close() fpr.ok('Session saving') except IOError as e: fpr.err('Saving file failed: %s' % e) else: fpr.fail('Missing write permission') if op == 2: #decode base64 first print if not get_yesno_input(' Would you like to save this part: [y/N]> '): return print if part['filename']: fn = part['filename'] else: fn = 'minja-' + part['type'].replace( '/', '_') + '-' + datetime.now().strftime('%Y%m%d%H%M%S') print fn = raw_input(' [%s]> ' % fn) or fn print #if sf == sessfile or not os.path.dirname(sf): # sf = cfgs['sess_path']+'/'+sf if not os.path.dirname(fn): fn = cfgs['mparts_path'] + '/' + fn if os.path.exists(fn): fpr('File already exist') else: if os.access(os.path.dirname(fn), os.W_OK): #the file does not exists but write privileges are given fpr('Saving under %s\n' % fn) try: #f = codecs.open(fn, 'w', encoding='utf-8') f = open(fn, 'wb') d = decode_attch(part['payload']) #pprint(d) f.write(d['raw']) f.close() fpr.ok('Session saving') except IOError as e: fpr.err('Saving file failed: %s' % e) else: fpr.fail('Missing write permission')
def smtp_sender_new(message, rpm=None, mpt=None, rate=None, rcpts=[], relays={}, name='T-Single'): #from core.data import smtp,fpr,tc from core.data import cfgs, smtp, fpr, tc, DEBUG from core.func import dbginfo from core.msg.viewers import viewSmtpConv from core.msg.threads import get_tid dhost = smtp['connect']['hosts'][0] # name of Thread define if this function is run as part of single connection or multithread connection # use convesation logs onlyin single thread # for 3.1 inject message # TODO: enable conv logs for threads cl = 0 if name == 'T-Single': cl = 1 # ---------------------------------------------------- # # log thread session import logging # create logger logger = logging.getLogger('threadslogs') logger.info('Starting thread: [%s]' % name) logger.debug('[%s]: Pid=%s' % (name, get_tid())) logger.debug('[%s]: rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) # host logger.info('[%s]: H=%s:%s, smtp_auth=(%s,%s)' % (name, dhost.get('host'), dhost.get('port'), dhost.get('smtp_auth_user'), dhost.get('smtp_auth_pass'))) print # ---------------------------------------------------- # dbginfo( 'DEBUG', 'name=%s, rpm=%s ,mpt=%s, rate=%s, rcpts=%s' % (name, rpm, mpt, rate, rcpts)) #return 0 # ---------------------------------------------------- # from StringIO import StringIO class StderrLogger(object): def __init__(self): #self.logger = logging.getLogger('threadslogs') self.sio = StringIO() def write(self, message): #self.logger.debug(message) self.sio.write(message) # ---------------------------------------------------- # try: import sys import smtplib # log debuglevel output from smtplib # redirect stderr from smtplib to string # # - from smtplib import stderr if cfgs['conv_logs'] and cl: ostderr = smtplib.stderr smtplib.stderr = StderrLogger() # run smtp session if name == 'T-Single': s = smtplib.SMTP(dhost['host'], dhost['port']) else: s = SMTPExt(dhost['host'], dhost['port']) if cfgs['conv_logs'] and cl: s.set_debuglevel('debug') # HELO - introduce yourself s.ehlo(dhost['helo']) #s.ehlo_or_helo_if_needed() # STAARTTLS fpr.warn(dhost['tls_mode']) if dhost['tls_mode'] == 'TLS': s.starttls() # HELO - introduce yourself s.ehlo(dhost['helo']) #s.ehlo_or_helo_if_needed() # SMTP AUTH if dhost.get('smtp_auth_user'): s.login(dhost.get('smtp_auth_user'), dhost.get('smtp_auth_pass')) # MAIL FROM sender = smtp['addrlist']['mail_from'] #rcpt = smtp['addrlist']['rcpt_to'] # for single injection or when mpt value unknown use single message per connection if mpt == None: mpt = 1 rpm = len(rcpts) # split messages per connection for m in range(mpt): # m strt from 0 to mpt-1 # split rcpts per message si = m * rpm ei = m * rpm + rpm m_rcpts = rcpts[si:ei] #print (m,si,ei,m_rcpts) if m_rcpts: logger.debug('[%s]: F=%s, MPT=%s/%s R=%s' % (name, sender, (m + 1), mpt, m_rcpts)) # SEND # https://docs.python.org/2/library/email.message.html#email.message.Message # as_string([unixfrom]) # Return the entire message flattened as a string. When optional unixfrom is True, # the envelope header is included in the returned string. unixfrom defaults to False. # Flattening the message may trigger changes to the Message if defaults need to be filled # in to complete the transformation to a string (for example, MIME boundaries may be # generated or modified). response = s.sendmail(sender, m_rcpts, message.as_string(unixfrom=False)) if response: smtp['addrlist']['r_reject'].update(response) #dbginfo('debug','Sendmail response list:',str(response)) #dbginfo('debug','Failed recipients:',str(smtp['addrlist']['r_reject'])) # s.sendmail(sender, rcpt, message.as_string(unixfrom=False)) #FIXME: # message sent success : nto true when threads with more than one message in it # fix this print info fpr.ok('Message was sent successfuly') smtp['replay']['threads']['ok'].append(name) # when only part of recipients/sender failed it looks like than # exception for recipientsRefused is not triggered # remember: to clear refu recipient list before you call out this function # when threds than this response is not fetchhe # it should be upper if response: smtp['addrlist']['r_reject'].update(response) # dbginfo('debug', 'Sendmail response list:', str(response)) dbginfo('debug', 'Failed recipients:', str(smtp['addrlist']['r_reject'])) # All recipients were refused. Nobody got the mail. The recipients attribute of # the exception object is a dictionary with information about the refused # recipients (like the one returned when at least one recipient was accepted). # the exception is triggered only when all recipoient failed :( except smtplib.SMTPRecipientsRefused, e: fpr.fail('Error: Message not sent. All recipients refused.') smtp['replay']['threads']['fail'].append(name) #print 'exception smtplib.SMTPRecipientsRefused',a fpr.warn(str(e)) smtp['addrlist']['r_reject'].update(e.recipients)