Exemplo n.º 1
0
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:
                labels = ('SIP Device','User Agent')
                rows = list()
                try:
                    for k in sipvicious.resultua.keys():
                        rows.append((k.decode(),sipvicious.resultua[k].decode()))
                except AttributeError:
                    for k in sipvicious.resultua.keys():
                        rows.append((k,sipvicious.resultua[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)
Exemplo n.º 2
0
def main():
    usage = "usage: %prog [options] target\r\n"
    usage += "examples:\r\n"
    usage += "%prog -e100-999 10.0.0.1\r\n"
    usage += "%prog -d dictionary.txt 10.0.0.2\r\n"
    parser = OptionParser(usage, version="%prog v" +
                          str(__version__) + __GPL__)
    parser.add_option("-p", "--port", dest="port", default="5060",
                      help="Destination port of the SIP device - eg -p 5060", metavar="PORT")
    parser = standardoptions(parser)
    parser = standardscanneroptions(parser)
    parser.add_option("-d", "--dictionary", dest="dictionary", type="string",
                      help="specify a dictionary file with possible extension names",
                      metavar="DICTIONARY")
    parser.add_option("-m", "--method", dest="method", type="string",
                      help="specify a request method. The default is REGISTER. Other possible methods are OPTIONS and INVITE",
                      default="REGISTER",
                      metavar="OPTIONS")
    parser.add_option("-e", "--extensions", dest="range", default='100-999',
                      help="specify an extension or extension range\r\nexample: -e 100-999,1000-1500,9999",
                      metavar="RANGE")
    parser.add_option("-z", "--zeropadding", dest="zeropadding", type="int",
                      help="""the number of zeros used to padd the username.
                  the options "-e 1-9999 -z 4" would give 0001 0002 0003 ... 9999""",
                      default=0,
                      metavar="PADDING")
    parser.add_option('--force', dest="force", action="store_true",
                      default=False,
                      help="Force scan, ignoring initial sanity checks.")
    parser.add_option('--template', '-T', action="store", dest="template",
                      help="""A format string which allows us to specify a template for the extensions
                      example svwar.py -e 1-999 --template="123%#04i999" would scan between 1230001999 to 1230999999"
                      """)
    parser.add_option('--enabledefaults', '-D', action="store_true", dest="defaults",
                      default=False, help="""Scan for default / typical extensions such as
                      1000,2000,3000 ... 1100, etc. This option is off by default.
                      Use --enabledefaults to enable this functionality""")
    parser.add_option('--maximumtime', action='store', dest='maximumtime', type="int",
                      default=10,
                      help="""Maximum time in seconds to keep sending requests without
                      receiving a response back""")
    parser.add_option('--domain', dest="domain",
                      help="force a specific domain name for the SIP message, eg. -d example.org")
    parser.add_option("--debug", dest="printdebug",
                      help="Print SIP messages received",
                      default=False, action="store_true"
                      )
    parser.add_option('-6', dest="ipv6", action="store_true", help="scan an IPv6 address")
    (options, args) = parser.parse_args()
    global exportpath
    exportpath = None
    logging.basicConfig(level=calcloglevel(options))
    logging.debug('started logging')
    if options.force:
        initialcheck = False
    else:
        initialcheck = True
    if options.template is not None:
        try:
            options.template % 1
        except TypeError:
            logging.critical(
                "The format string template is not correct. Please provide an appropiate one")
            exit(1)
    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)
    if len(args) != 1:
        parser.error("provide one hostname")
    else:
        host = args[0]
    if options.dictionary is not None:
        guessmode = 2
        try:
            dictionary = open(options.dictionary, 'r', encoding='utf-8', errors='ignore')
        except IOError:
            logging.error("could not open %s" % options.dictionary)
            exit(1)
        if options.resume is not None:
            lastextensionsrc = os.path.join(exportpath, 'lastextension.pkl')
            previousposition = pickle.load(open(lastextensionsrc, 'rb'), encoding='bytes')
            dictionary.seek(previousposition)
        guessargs = dictionary
    else:
        guessmode = 1
        if options.resume is not None:
            lastextensionsrc = os.path.join(exportpath, 'lastextension.pkl')
            try:
                previousextension = pickle.load(open(lastextensionsrc, 'rb'), encoding='bytes')
            except IOError:
                logging.critical('Could not read from %s' % lastextensionsrc)
                exit(1)
            logging.debug('Previous range: %s' % options.range)
            options.range = resumeFrom(previousextension, options.range)
            logging.debug('New range: %s' % options.range)
            logging.info('Resuming from %s' % previousextension)
        extensionstotry = getRange(options.range)
        guessargs = (extensionstotry, options.zeropadding,
                     options.template, options.defaults)
    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+'))
    if options.autogetip:
        tmpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tmpsocket.connect(("msn.com", 80))
        options.externalip = tmpsocket.getsockname()[0]
        tmpsocket.close()
    enableack = False
    if options.method.upper() == 'INVITE':
        enableack = True
    sipvicious = TakeASip(
        host,
        port=options.port,
        selecttime=options.selecttime,
        method=options.method,
        compact=options.enablecompact,
        guessmode=guessmode,
        guessargs=guessargs,
        sessionpath=exportpath,
        initialcheck=initialcheck,
        externalip=options.externalip,
        enableack=enableack,
        maxlastrecvtime=options.maximumtime,
        localport=options.localport,
        domain=options.domain,
        printdebug=options.printdebug,
        ipv6=options.ipv6,
    )
    start_time = datetime.now()
    #logging.info("scan started at %s" % str(start_time))
    logging.info("start your engines")
    try:
        sipvicious.start()
        if exportpath is not None:
            open(os.path.join(exportpath, 'closed'), 'w').close()
    except KeyboardInterrupt:
        logging.warning('caught your control^c - quiting')
    except Exception as err:
        if options.reportBack:
            logging.critical(
                "Got unhandled exception : %s\nSending report to author" % err.__str__())
            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.nextuser is not None:
        lastextensiondst = os.path.join(exportpath, 'lastextension.pkl')
        logging.debug('saving state to %s' % lastextensiondst)
        try:
            if guessmode == 1:
                pickle.dump(sipvicious.nextuser, open(
                    os.path.join(exportpath, 'lastextension.pkl'), 'wb'))
                logging.debug('logged last extension %s' % sipvicious.nextuser)
            elif guessmode == 2:
                pickle.dump(sipvicious.guessargs.tell(), open(
                    os.path.join(exportpath, 'lastextension.pkl'), 'wb'))
                logging.debug('logged last position %s' %
                              sipvicious.guessargs.tell())
        except IOError:
            logging.warning('could not log the last extension scanned')
    # display results
    if not options.quiet:
        lenres = len(sipvicious.resultauth)
        if lenres > 0:
            logging.info("we have %s extensions" % lenres)
            if (lenres < 400 and options.save is not None) or options.save is None:
                labels = ('Extension', 'Authentication')
                rows = list()
                try:
                    for k in sipvicious.resultauth.keys():
                        rows.append((k.decode(), sipvicious.resultauth[k].decode()))
                except AttributeError:
                    for k in sipvicious.resultauth.keys():
                        rows.append((k, sipvicious.resultauth[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)
Exemplo n.º 3
0
def main():
    usage = "usage: %prog -u username [options] target\r\n"
    usage += "examples:\r\n"
    usage += "%prog -u100 -d dictionary.txt 10.0.0.1\r\n"
    usage += "%prog -u100 -r1-9999 -z4 10.0.0.1\r\n"
    parser = OptionParser(usage, version="%prog v" +
                          str(__version__) + __GPL__)
    parser.add_option("-p", "--port", dest="port", default="5060",
                      help="Destination port of the SIP device - eg -p 5060", metavar="PORT")
    parser = standardoptions(parser)
    parser = standardscanneroptions(parser)
    parser.add_option("-u", "--username", dest="username",
                      help="username to try crack", metavar="USERNAME")
    parser.add_option("-d", "--dictionary", dest="dictionary", type="string",
                      help="specify a dictionary file with passwords",
                      metavar="DICTIONARY")
    parser.add_option("-r", "--range", dest="range", default="100-999",
                      help="specify a range of numbers. example: 100-200,300-310,400",
                      metavar="RANGE")
    parser.add_option("-e", "--extension", dest="extension",
                      help="Extension to crack. Only specify this when the extension is different from the username.",
                      metavar="EXTENSION")
    parser.add_option("-z", "--zeropadding", dest="zeropadding", type="int", default=0,
                      help="""the number of zeros used to padd the password.
                  the options "-r 1-9999 -z 4" would give 0001 0002 0003 ... 9999""",
                      metavar="PADDING")
    parser.add_option("-n", "--reusenonce", dest="reusenonce", default=False,
                      help="Reuse nonce. Some SIP devices don't mind you reusing the nonce (making them vulnerable to replay attacks). Speeds up the cracking.",
                      action="store_true",
                      )
    parser.add_option('--template', '-T', action="store", dest="template",
                      help="""A format string which allows us to specify a template for the extensions
                      example svwar.py -e 1-999 --template="123%#04i999" would scan between 1230001999 to 1230999999"
                      """)
    parser.add_option('--maximumtime', action='store', dest='maximumtime', type="int", default=10,
                      help="Maximum time in seconds to keep sending requests without receiving a response back")
    parser.add_option('--enabledefaults', '-D', action="store_true", dest="defaults",
                      default=False, help="""Scan for default / typical passwords such as
                      1000,2000,3000 ... 1100, etc. This option is off by default.
                      Use --enabledefaults to enable this functionality""")
    parser.add_option('--domain', dest="domain",
                      help="force a specific domain name for the SIP message, eg. example.org")
    parser.add_option('--requesturi', dest="requesturi",
                        help="force the first line URI to a specific value; e.g. sip:[email protected]")
    parser.add_option('-6', dest="ipv6", action="store_true", help="Scan an IPv6 address")
    parser.add_option('-m','--method', dest='method', default='REGISTER', help="Specify a SIP method to use")
    (options, args) = parser.parse_args()
    exportpath = None
    logging.basicConfig(level=calcloglevel(options))
    logging.debug('started logging')
    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.debug('Session path: %s' % exportpath)

    if options.resume is not None:
        exportpath = os.path.join(os.path.expanduser(
            '~'), '.sipvicious', __prog__, options.resume)
        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)
    if len(args) != 1:
        parser.error("provide one hostname")
    else:
        host = args[0]

    if options.username is None:
        parser.error("provide one username to crack")

    if options.dictionary is not None:
        crackmode = 2
        try:
            dictionary = open(options.dictionary, 'r', encoding='utf-8', errors='ignore')
        except IOError:
            logging.error("could not open %s" % options.dictionary)
        if options.resume is not None:
            lastpasswdsrc = os.path.join(exportpath, 'lastpasswd.pkl')
            previousposition = pickle.load(open(lastpasswdsrc, 'rb'), encoding='bytes')
            dictionary.seek(previousposition)
        crackargs = dictionary
    else:
        crackmode = 1
        if options.resume is not None:
            lastpasswdsrc = os.path.join(exportpath, 'lastpasswd.pkl')
            try:
                previouspasswd = pickle.load(open(lastpasswdsrc, 'rb'), encoding='bytes')
            except IOError:
                logging.critical('Could not read from %s' % lastpasswdsrc)
                exit(1)
            logging.debug('Previous range: %s' % options.range)
            options.range = resumeFrom(previouspasswd, options.range)
            logging.debug('New range: %s' % options.range)
            logging.info('Resuming from %s' % previouspasswd)
        rangelist = getRange(options.range)
        crackargs = (rangelist, options.zeropadding,
                     options.template, options.defaults, [options.username])
    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+'))
    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 = ASipOfRedWine(
        host,
        username=options.username,
        selecttime=options.selecttime,
        compact=options.enablecompact,
        crackmode=crackmode,
        crackargs=crackargs,
        reusenonce=options.reusenonce,
        extension=options.extension,
        sessionpath=exportpath,
        port=options.port,
        externalip=options.externalip,
        maxlastrecvtime=options.maximumtime,
        localport=options.localport,
        domain=options.domain,
        requesturi=options.requesturi,
        ipv6=options.ipv6,
        method=options.method,
    )

    start_time = datetime.now()
    logging.info("scan started at %s" % str(start_time))
    try:
        sipvicious.start()
        if exportpath is not None:
            open(os.path.join(exportpath, 'closed'), 'w').close()
    except KeyboardInterrupt:
        logging.warning('caught your control^c - quiting')
    except Exception as err:
        if options.reportBack:
            logging.critical(
                "Got unhandled exception : %s\nsending report to author" % err.__str__())
            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.previouspassword is not None:
        lastextensiondst = os.path.join(exportpath, 'lastpasswd.pkl')
        logging.debug('saving state to %s' % lastextensiondst)
        try:
            if crackmode == 1:
                pickle.dump(sipvicious.previouspassword, open(
                    os.path.join(exportpath, 'lastpasswd.pkl'), 'wb+'))
                logging.debug('logged last password %s' %
                              sipvicious.previouspassword)
            elif crackmode == 2:
                pickle.dump(sipvicious.crackargs.tell(), open(
                    os.path.join(exportpath, 'lastpasswd.pkl'), 'wb+'))
                logging.debug('logged last position %s' %
                              sipvicious.crackargs.tell())
        except IOError:
            logging.warning('could not log the last tried password')
    # display results
    if not options.quiet:
        lenres = len(sipvicious.resultpasswd)
        if lenres > 0:
            logging.info("we have %s cracked users" % lenres)
            if (lenres < 400 and options.save is not None) or options.save is None:
                labels = ('Extension', 'Password')
                rows = list()
                try:
                    for k in sipvicious.resultpasswd.keys():
                        rows.append((k.decode(), sipvicious.resultpasswd[k].decode()))
                except AttributeError:
                    for k in sipvicious.resultpasswd.keys():
                        rows.append((k, sipvicious.resultpasswd[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)