def main(): usage = "usage: %prog [options] host1 host2 hostrange\r\n" usage += 'Scans for SIP devices on a given network\r\n\r\n' usage += "examples:\r\n\r\n" usage += "%prog 10.0.0.1-10.0.0.255 " usage += "172.16.131.1 sipvicious.org/22 10.0.1.1/24" usage += "1.1.1.1-20 1.1.2-20.* 4.1.*.*\r\n\r\n" usage += "%prog -s session1 --randomize 10.0.0.1/8\r\n\r\n" usage += "%prog --resume session1 -v\r\n\r\n" usage += "%prog -p5060-5062 10.0.0.3-20 -m INVITE\r\n\r\n" parser = OptionParser(usage, version="%prog v" + str(__version__) + __GPL__) parser.add_option( "-p", "--port", dest="port", default="5060", help= "Destination port or port ranges of the SIP device - eg -p5060,5061,8000-8100", metavar="PORT") parser = standardoptions(parser) parser = standardscanneroptions(parser) parser.add_option("--randomscan", dest="randomscan", action="store_true", default=False, help="Scan random IP addresses") parser.add_option( "-i", "--input", dest="input", help= "Scan IPs which were found in a previous scan. Pass the session name as the argument", metavar="scan1") parser.add_option( "-I", "--inputtext", dest="inputtext", help= "Scan IPs from a text file - use the same syntax as command line but with new lines instead of commas. Pass the file name as the argument", metavar="scan1") parser.add_option( "-m", "--method", dest="method", help="Specify the request method - by default this is OPTIONS.", default='OPTIONS') parser.add_option("-d", "--debug", dest="printdebug", help="Print SIP messages received", default=False, action="store_true") parser.add_option( "--first", dest="first", help= "Only send the first given number of messages (i.e. usually used to scan only X IPs)", type="long") parser.add_option("-e", "--extension", dest="extension", default='100', help="Specify an extension - by default this is not set") parser.add_option( "--randomize", dest="randomize", action="store_true", default=False, help="Randomize scanning instead of scanning consecutive ip addresses") parser.add_option("--srv", dest="srvscan", action="store_true", default=False, help="Scan the SRV records for SIP on the destination domain name." \ "The targets have to be domain names - example.org domain1.com") parser.add_option('--fromname', dest="fromname", default="sipvicious", help="specify a name for the from header") parser.add_option('-6', '--ipv6', dest="ipv6", action='store_true', help="scan an IPv6 address") (options, args) = parser.parse_args() exportpath = None if options.resume is not None: exportpath = os.path.join(os.path.expanduser('~'), '.sipvicious', __prog__, options.resume) if os.path.exists(os.path.join(exportpath, 'closed')): logging.error("Cannot resume a session that is complete") exit(1) if not os.path.exists(exportpath): logging.critical('A session with the name %s was not found' % options.resume) exit(1) optionssrc = os.path.join(exportpath, 'options.pkl') previousresume = options.resume previousverbose = options.verbose options, args = pickle.load(open(optionssrc, 'rb'), encoding='bytes') options.resume = previousresume options.verbose = previousverbose elif options.save is not None: exportpath = os.path.join(os.path.expanduser('~'), '.sipvicious', __prog__, options.save) logging.basicConfig(level=calcloglevel(options)) logging.debug('started logging') scanrandomstore = None if options.input is not None: db = os.path.join(os.path.expanduser('~'), '.sipvicious', __prog__, options.input, 'resultua') if dbexists(db): scaniter = scanfromdb(db, options.method.split(',')) else: logging.error( "the session name does not exist. Please use svreport to list existing scans" ) exit(1) elif options.randomscan: logging.debug('making use of random scan') logging.debug('parsing range of ports: %s' % options.port) portrange = getRange(options.port) internetranges = [[16777216, 167772159], [184549376, 234881023], [251658240, 2130706431], [2147549184, 2851995647], [2852061184, 2886729727], [2886795264, 3221159935], [3221226240, 3227017983], [3227018240, 3232235519], [3232301056, 3323068415], [3323199488, 3758096127]] scanrandomstore = '.sipviciousrandomtmp' resumescan = False if options.save is not None: scanrandomstore = os.path.join(exportpath, 'random') resumescan = True scaniter = scanrandom(internetranges, portrange, options.method.split(','), randomstore=scanrandomstore, resume=resumescan) elif options.inputtext: logging.debug('Using IP addresses from input text file') try: f = open(options.inputtext, 'r') args = f.readlines() f.close() except IOError: logging.critical('Could not open %s' % options.inputtext) exit(1) args = list(map(lambda x: x.strip(), args)) args = [x for x in args if len(x) > 0] logging.debug('ip addresses %s' % args) try: iprange = ip4range(*args) except ValueError as err: logging.error(err) exit(1) portrange = getRange(options.port) if options.randomize: scanrandomstore = '.sipviciousrandomtmp' resumescan = False if options.save is not None: scanrandomstore = os.path.join(exportpath, 'random') resumescan = True scaniter = scanrandom(list(map(getranges, args)), portrange, options.method.split(','), randomstore=scanrandomstore, resume=resumescan) else: scaniter = scanlist(iprange, portrange, options.method.split(',')) else: if len(args) < 1: parser.error('Provide at least one target') exit(1) logging.debug('parsing range of ports: %s' % options.port) portrange = getRange(options.port) if options.randomize: scanrandomstore = '.sipviciousrandomtmp' resumescan = False if options.save is not None: scanrandomstore = os.path.join(exportpath, 'random') resumescan = True scaniter = scanrandom(list(map(getranges, args)), portrange, options.method.split(','), randomstore=scanrandomstore, resume=resumescan) elif options.srvscan: logging.debug("making use of SRV records") scaniter = getTargetFromSRV(args, options.method.split(',')) else: if options.resume is not None: lastipsrc = os.path.join(exportpath, 'lastip.pkl') try: f = open(lastipsrc, 'rb') previousip = pickle.load(f, encoding='bytes') f.close() except IOError: logging.critical('Could not read from %s' % lastipsrc) exit(1) logging.debug('Previous args: %s' % args) args = resumeFromIP(previousip, args) logging.debug('New args: %s' % args) logging.info('Resuming from %s' % previousip) if options.ipv6: scaniter = scanlist(ip6range(*args), portrange, options.method.split(',')) else: # normal consecutive scan try: iprange = ip4range(*args) except ValueError as err: logging.error(err) exit(1) scaniter = scanlist(iprange, portrange, options.method.split(',')) if options.save is not None: if options.resume is None: exportpath = os.path.join(os.path.expanduser('~'), '.sipvicious', __prog__, options.save) if os.path.exists(exportpath): logging.warning( 'we found a previous scan with the same name. Please choose a new session name' ) exit(1) logging.debug('creating an export location %s' % exportpath) try: os.makedirs(exportpath, mode=0o700) except OSError: logging.critical('could not create the export location %s' % exportpath) exit(1) optionsdst = os.path.join(exportpath, 'options.pkl') logging.debug('saving options to %s' % optionsdst) pickle.dump([options, args], open(optionsdst, 'wb+')) try: options.extension except AttributeError: options.extension = None if options.autogetip: tmpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tmpsocket.connect(("msn.com", 80)) options.externalip = tmpsocket.getsockname()[0] tmpsocket.close() sipvicious = DrinkOrSip( scaniter, selecttime=options.selecttime, compact=options.enablecompact, localport=options.localport, externalip=options.externalip, bindingip=options.bindingip, sessionpath=exportpath, extension=options.extension, printdebug=options.printdebug, first=options.first, fromname=options.fromname, ipv6=options.ipv6, ) start_time = datetime.now() logging.info("start your engines") try: try: sipvicious.start() except AssertionError as err: logging.critical(err) exit(1) if exportpath is not None: open(os.path.join(exportpath, 'closed'), 'w').close() except KeyboardInterrupt: logging.warning('caught your control^c - quiting') pass except Exception as err: if options.reportBack: logging.critical( "Got unhandled exception : sending report to author") reportBugToAuthor(traceback.format_exc()) else: logging.critical( "Unhandled exception - please run same command with the -R option to send me an automated report" ) pass logging.exception("Exception") if options.save is not None and sipvicious.nextip is not None and options.randomize is False and options.randomscan is False: lastipdst = os.path.join(exportpath, 'lastip.pkl') logging.debug('saving state to %s' % lastipdst) try: f = open(lastipdst, 'wb+') pickle.dump(sipvicious.nextip, f) f.close() except OSError: logging.warning('Could not save state to %s' % lastipdst) elif options.save is None: if scanrandomstore is not None: #if options.randomize or options.randomscan: try: logging.debug('removing %s' % scanrandomstore) os.unlink(scanrandomstore) except OSError: logging.warning('could not remove %s' % scanrandomstore) pass # display results if not options.quiet: lenres = len(sipvicious.resultua) if lenres > 0: logging.info("we have %s devices" % lenres) if (lenres < 400 and options.save is not None) or options.save is None: width = 60 labels = ('SIP Device', 'User Agent', 'Fingerprint') rows = list() try: for k in sipvicious.resultua.keys(): rows.append( (k.decode(), sipvicious.resultua[k].decode(), sipvicious.resultfp[k].decode())) except AttributeError: for k in sipvicious.resultua.keys(): rows.append((k, sipvicious.resultua[k], sipvicious.resultfp[k])) print(to_string(rows, header=labels)) else: logging.warning("too many to print - use svreport for this") else: logging.warning("found nothing") end_time = datetime.now() total_time = end_time - start_time logging.info("Total time: %s" % total_time)
resume=resumescan) elif options.srvscan: logging.debug("making use of SRV records") scaniter = getTargetFromSRV(args, options.method.split(',')) else: if options.resume is not None: lastipsrc = os.path.join(exportpath, 'lastip.pkl') try: f = open(lastipsrc, 'r') previousip = pickle.load(f) f.close() except IOError: logging.critical('Could not read from %s' % lastipsrc) exit(1) logging.debug('Previous args: %s' % args) args = resumeFromIP(previousip, args) logging.debug('New args: %s' % args) logging.info('Resuming from %s' % previousip) # normal consecutive scan try: iprange = ip4range(*args) except ValueError, err: logging.error(err) exit(1) scaniter = scanlist(iprange, portrange, options.method.split(',')) if options.save is not None: if options.resume is None: exportpath = os.path.join('.sipvicious', __prog__, options.save) if os.path.exists(exportpath): logging.warn(
scaniter = scanrandom(map(getranges,args),portrange,options.method.split(','),randomstore=scanrandomstore,resume=resumescan) elif options.srvscan: logging.debug("making use of SRV records") scaniter = getTargetFromSRV(args,options.method.split(',')) else: if options.resume is not None: lastipsrc = os.path.join(exportpath,'lastip.pkl') try: f=open(lastipsrc,'r') previousip = pickle.load(f) f.close() except IOError: logging.critical('Could not read from %s' % lastipsrc) exit(1) logging.debug('Previous args: %s' % args) args = resumeFromIP(previousip,args) logging.debug('New args: %s' % args) logging.info('Resuming from %s' % previousip) # normal consecutive scan try: iprange = ip4range(*args) except ValueError,err: logging.error(err) exit(1) scaniter = scanlist(iprange,portrange,options.method.split(',')) if options.save is not None: if options.resume is None: exportpath = os.path.join('.sipvicious',__prog__,options.save) if os.path.exists(exportpath): logging.warn('we found a previous scan with the same name. Please choose a new session name')