├── README.md
├── netscan.py
├── requirements.txt
├── scantastic.py
├── showRange.py
├── urls
└── .gitkeep
├── words
├── ASP
├── ASPX
├── HTML
├── PHP
└── blank
├── xml
└── .gitkeep
└── xmltourl.py
/README.md:
--------------------------------------------------------------------------------
1 | # scantastic-tool
2 |
3 | ## It's bloody scantastic
4 |
5 | If you like this and are feeling a bit(coin) generous - 1JdSGqg2zGTbpFMJPLbWoXg7Nng3z1Qp58
6 |
7 | It works for me: http://makthepla.net/scantastichax.png
8 |
9 | - Dependencies: (DIY - I ain't supportin shit)
10 | - Masscan - https://github.com/robertdavidgraham/masscan
11 | - Nmap - https://nmap.org/download.html
12 | - ElasticSearch - http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/_installing_elasticsearch.html
13 | - Kibana - http://www.elasticsearch.org/overview/kibana/installation/
14 |
15 |
16 | This tool can be used to store masscan or nmap data in elasticsearch,
17 | (the scantastic plugin in the image is not here)
18 |
19 | It allows performs distributed directory brute-forcing.
20 |
21 | All your base are belong to us. I might maintain or improve this over time. MIGHT.
22 |
23 | ## Quickstart
24 |
25 | ### Example usage
26 |
27 | Run and import a scan of home /24 network
28 |
29 | ```
30 | ./scantastic.py -s -H 192.168.1.0/24 -p 80,443 -x homescan.xml (with masscan)
31 | ./scantastic.py -ns -H 192.168.1.0/24 -p 80,443 -x homescan.xml (with nmap)
32 | ```
33 |
34 | Export homescan to a list of urls
35 |
36 | ```
37 | ./scantastic.py -eurl -x homescan.xml > urlist (with masscan)
38 | ./scantastic.py -nurl -x homescan.xml > urlist (with nmap)
39 | ```
40 |
41 | Brute force the url list using wordlist and put results into index homescan
42 | using 10 threads (By default it uses 1 thread)
43 |
44 | ```
45 | ./scantastic.py -d -u urlist -w some_wordlist -i homescan -t 10
46 | ```
47 |
48 | ```
49 | root@ubuntu:~/scantastic-tool# ./scantastic.py -h
50 | usage: scantastic.py [-h] [-v] [-d] [-s] [-noes] [-sl] [-in] [-e] [-eurl]
51 | [-del] [-H HOST] [-p PORTS] [-x XML] [-w WORDS] [-u URLS]
52 | [-t THREADS] [-esh ESHOST] [-esp PORT] [-i INDEX]
53 | [-a AGENT]
54 |
55 | optional arguments:
56 | -h, --help show this help message and exit
57 | -v, --version Version information
58 | -d, --dirb Run directory brute force. Requires --urls & --words
59 | -s, --scan Run masscan on single range. Specify --host & --ports
60 | & --xml
61 | -ns, --nmap Run Nmap on a single range specify -H & -p
62 | -noes, --noelastics Run scan without elasticsearch insertion
63 | -sl, --scanlist Run masscan on a list of ranges. Requires --host &
64 | --ports & --xml
65 | -nsl, --nmaplist Run Nmap on a list of ranges -H & -p & -x
66 | -in, --noinsert Perform a scan without inserting to elasticsearch
67 | -e, --export Export a scan XML into elasticsearch. Requires --xml
68 | -eurl, --exporturl Export urls to scan from XML file. Requires --xml
69 | -nurl, --exportnmap Export urls from nmap XML, requires -x
70 | -del, --delete Specify an index to delete.
71 | -H HOST, --host HOST Scan this host or list of hosts
72 | -p PORTS, --ports PORTS
73 | Specify ports in masscan format. (ie.0-1000 or
74 | 80,443...)
75 | -x XML, --xml XML Specify an XML file to store output in
76 | -w WORDS, --words WORDS
77 | Wordlist to be used with --dirb
78 | -u URLS, --urls URLS List of Urls to be used with --dirb
79 | -t THREADS, --threads THREADS
80 | Specify the number of threads to use.
81 | -esh ESHOST, --eshost ESHOST
82 | Specify the elasticsearch host
83 | -esp PORT, --port PORT
84 | Specify ElasticSearch port
85 | -i INDEX, --index INDEX
86 | Specify the ElasticSearch index
87 | -a AGENT, --agent AGENT
88 | Specify a User Agent for requests
89 | ```
90 |
91 | Use -noes and -in scans to not import scans by default upon completion of a scan
92 |
--------------------------------------------------------------------------------
/netscan.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # A class to run masscan and import the results to ES
3 |
4 | import subprocess
5 | import socket
6 | import xmltodict
7 | from elasticsearch import Elasticsearch
8 | from datetime import datetime
9 |
10 |
11 | class Masscan:
12 | # Initialize with range, output, ports
13 |
14 | def __init__(self, ip_r, xml_o, ps):
15 | self.ip_range = ip_r
16 | self.xml_output = xml_o
17 | self.ports = ps
18 |
19 | def run(self):
20 | self.args = ("masscan", "-sS", "-Pn", self.ip_range,
21 | "-oX", self.xml_output, "--rate=15000", "-p",
22 | self.ports, "--open")
23 | popen = subprocess.Popen(self.args, stdout=subprocess.PIPE)
24 | popen.wait()
25 | self.output = popen.stdout.read()
26 | print "Scan completed!"
27 |
28 | def runfile(self):
29 | self.args = ("masscan", "-sS", "-Pn", "-iL", self.ip_range,
30 | "-oX", self.xml_output, "--rate=15000", "-p", self.ports,
31 | "--open")
32 | popen = subprocess.Popen(self.args, stdout=subprocess.PIPE)
33 | popen.wait()
34 | self.output = popen.stdout.read()
35 | print "Scan completed!"
36 |
37 | def import_es(self, es_index, host, port):
38 | es = Elasticsearch([{u'host': host, u'port': port}])
39 | try:
40 | with open(self.xml_output, "r") as xmlfile:
41 | data = xmlfile.read().replace('\n', '')
42 | xml = xmltodict.parse(data)
43 | nmaprun = xml['nmaprun']
44 | host = nmaprun['host']
45 | except:
46 | print "IO Error"
47 | for entry in host:
48 | port = entry['ports']['port']
49 | try:
50 | name, alias, addrlist = socket.gethostbyaddr(entry['address']['@addr'])
51 | except socket.herror:
52 | name = entry['address']['@addr']
53 | dataentry = {
54 | 'timestamp': datetime.now(),
55 | 'ip': entry['address']['@addr'],
56 | 'port': port['@portid'],
57 | 'name': name,
58 | 'link': 'http://' + name + '/'
59 | }
60 | result = es.index(index=es_index, doc_type='hax', body=dataentry)
61 |
62 |
63 | class Nmap:
64 | # Initialize with range, output, ports
65 |
66 | def __init__(self, ip_r, xml_o, ps):
67 | self.ip_range = ip_r
68 | self.xml_output = xml_o
69 | self.ports = ps
70 |
71 | def run(self):
72 | self.args = ("nmap", "-sS", "-Pn", self.ip_range,
73 | "-oX", self.xml_output, "-p", self.ports, "--open")
74 | popen = subprocess.Popen(self.args, stdout=subprocess.PIPE)
75 | popen.wait()
76 | self.output = popen.stdout.read()
77 | print "Scan completed!"
78 |
79 | def runfile(self):
80 | self.args = ("nmap", "-sS", "-Pn", "-iL", self.ip_range,
81 | "-oX", self.xml_output, "-p", self.ports, "--open")
82 | popen = subprocess.Popen(self.args, stdout=subprocess.PIPE)
83 | popen.wait()
84 | self.output = popen.stdout.read()
85 | print "Scan completed!"
86 |
87 | def toES(address, ports, es_index, host, port):
88 | es = Elasticsearch([{u'host': host, u'port': port}])
89 | try:
90 | name, alias, addrlist = socket.gethostbyaddr(address)
91 |
92 | except socket.herror:
93 | name = address
94 | dataentry = {
95 | 'timestamp': datetime.now(),
96 | 'ip': address,
97 | 'port': ports,
98 | 'name': name,
99 | 'link': 'http://' + name + '/'
100 | }
101 | print dataentry
102 |
103 | def import_es(self, es_index, host, port):
104 | try:
105 | with open(self.xml_output, "r") as xmlfile:
106 | data = xmlfile.read().replace('\n', '')
107 | xml = xmltodict.parse(data)
108 | nmaprun = xml['nmaprun']
109 | scanhost = nmaprun['host']
110 | for i in scanhost:
111 | address = i['address'][0]['@addr']
112 | port1 = dict(i)
113 | try: #if one result
114 | if int(port1['ports']['port']['@portid']) > 0:
115 | port2 = port1['ports']['port']['@portid']
116 | toES(address, str(port2), es_index, host, port)
117 | except: #if multiple
118 | port2 = i['ports']['port']#[0]['@portid']
119 | for z in port2:
120 | x = z['@portid']
121 | toES(address, str(x), es_index, host, port)
122 | except IOError, e:
123 | print e
124 |
125 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | elasticsearch==1.3.0
2 | requests==2.20.0
3 | netaddr==0.7.13
4 | xmltodict==0.9.2
5 | numpy==1.9.1
6 |
--------------------------------------------------------------------------------
/scantastic.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import multiprocessing
4 | import argparse
5 | import sys
6 | import requests
7 | import string
8 | from datetime import datetime
9 | from time import sleep
10 | from elasticsearch import Elasticsearch
11 | from netscan import Masscan
12 | from netscan import Nmap
13 | from xmltourl import Xml2urls
14 | from xmltourl import Xml2urls2
15 | from numpy import array_split
16 |
17 | requests.packages.urllib3.disable_warnings()
18 |
19 | def version_info():
20 | VERSION_INFO = 'Scantastic v2.0'
21 | AUTHOR_INFO = 'Author: Ciaran McNally - https://makthepla.net'
22 | print ' _ _ _'
23 | print ' ___ ___ ___ ___| |_ ___ ___| |_|_|___'
24 | print '|_ -| _| .\'| | _| .\'|_ -| _| | _|'
25 | print '|___|___|__,|_|_|_| |__,|___|_| |_|___|'
26 | print '======================================='
27 | print VERSION_INFO
28 | print AUTHOR_INFO
29 |
30 |
31 | # Split the list of urls into chunks for threading
32 | def split_urls(u, t):
33 | print 'Number of URLS: ' + str(len(u))
34 | print 'Threads: ' + str(t)
35 | print 'URLS in each split: ' + str(len(u) / t)
36 | print '========================='
37 | sleep(1)
38 | return array_split(u, t)
39 |
40 |
41 | def returnIPaddr(u):
42 | ip = ""
43 | if u.startswith('http://'):
44 | remainhttp = u[7:]
45 | ip = string.split(remainhttp, '/')[0]
46 | if u.startswith('https://'):
47 | remainhttps = u[8:]
48 | ip = string.split(remainhttps, '/')[0]
49 | return ip
50 |
51 |
52 | def returnTitle(content):
53 | t1 = ''
54 | t2 = ''
55 | if '
' in content:
56 | t1 = string.split(content, '')[1]
57 | t2 = string.split(t1, '')[0]
58 | return t2
59 |
60 |
61 | # Make requests
62 | def requestor(urls, dirb, host, port, agent, esindex, usees):
63 | data = {}
64 | es = Elasticsearch([{u'host': host, u'port': port}])
65 | user_agent = {'User-agent': agent}
66 | for url in urls:
67 | urld = url + dirb
68 | try:
69 | r = requests.get(urld, timeout=10, headers=user_agent, verify=False)
70 | stat = r.status_code
71 | time = datetime.utcnow()
72 | cont_len = len(r.content)
73 | title = returnTitle(r.content)
74 | if len(r.content) >= 500:
75 | content = r.content[0:500]
76 | else:
77 | content = r.content
78 | ip = returnIPaddr(url)
79 | if 'image' in r.headers['content-type']:
80 | content = 'image'
81 | if r.status_code == 200:
82 | print urld + ' - ' + str(r.status_code) + ':' + str(len(r.content))
83 | except requests.exceptions.Timeout:
84 | # print urld+' - Timeout'
85 | stat = -1
86 | except requests.exceptions.ConnectionError:
87 | # print url+dirb+' - Connection Error!'
88 | stat = -2
89 | except requests.exceptions.TooManyRedirects:
90 | # print urld+' - Too many redirects!'
91 | stat = -3
92 | except:
93 | stat = 0
94 |
95 | if stat > 0:
96 | data = {
97 | 'timestamp': time,
98 | 'ip': ip,
99 | 'status': stat,
100 | 'content-length': cont_len,
101 | 'content': content,
102 | 'title': title,
103 | 'link': url + dirb,
104 | 'directory': dirb
105 | }
106 | try:
107 | if data['status'] == 200:
108 | if usees == False:
109 | result = es.index(index=esindex, doc_type='hax',
110 | body=data)
111 | else:
112 | pass
113 | else:
114 | pass
115 | except:
116 | data['title'] = 'Unicode Error'
117 | data['content'] = 'Unicode Error'
118 | if data['status'] == 200:
119 | if usees == False:
120 | result = es.index(index=esindex, doc_type='hax',
121 | body=data)
122 | else:
123 | pass
124 | else:
125 | pass
126 |
127 |
128 | # Run regular masscan on specified range
129 | def scan(host, ports, xml, index, eshost, esport, noin):
130 | ms = Masscan(host, 'xml/' + xml, ports)
131 | ms.run()
132 | if noin == False:
133 | ms.import_es(index, eshost, esport)
134 | print ms.output
135 |
136 |
137 | # Run masscan on file of ranges
138 | def scanlst(hostfile, ports, xml, index, eshost, esport, noin):
139 | ms = Masscan(hostfile, 'xml/' + xml, ports)
140 | ms.runfile()
141 | if noin == False:
142 | ms.import_es(index, eshost, esport)
143 | print ms.output
144 |
145 | # Run regular masscan on specified range
146 | def nscan(host, ports, xml, index, eshost, esport, noin):
147 | ms = Nmap(host, 'xml/' + xml, ports)
148 | ms.run()
149 | if noin == False:
150 | ms.import_es(index, eshost, esport)
151 | print ms.output
152 |
153 |
154 | # Run masscan on file of ranges
155 | def nscanlst(hostfile, ports, xml, index, eshost, esport, noin):
156 | ms = Nmap(hostfile, 'xml/' + xml, ports)
157 | ms.runfile()
158 | if noin == False:
159 | ms.import_es(index, eshost, esport)
160 | print ms.output
161 |
162 | def export_xml(xml, index, eshost, esport):
163 | ms = Masscan('x', 'xml/' + xml, 'y')
164 | ms.import_es(index, eshost, esport)
165 |
166 | def nexport_xml(xml, index, eshost, esport):
167 | ms = Nmap('x', 'xml/' + xml, 'y')
168 | ms.import_es(index, eshost, esport)
169 |
170 | def delete_index(dindex, eshost, esport):
171 | url = 'http://' + eshost + ':' + str(esport) + '/' + dindex
172 | print 'deleting index: ' + url
173 | r = requests.delete(url)
174 | print r.content
175 |
176 |
177 | def export_urls(xml):
178 | x = Xml2urls(xml)
179 | x.run()
180 |
181 | def nexport_urls(xml):
182 | x = Xml2urls2(xml)
183 | x.run()
184 |
185 | if __name__ == '__main__':
186 | parse = argparse.ArgumentParser()
187 | parse.add_argument('-v', '--version', action='store_true', default=False,
188 | help='Version information')
189 | parse.add_argument('-d', '--dirb', action='store_true', default=False,
190 | help='Run directory brute force. Requires --urls & --words')
191 | parse.add_argument('-s', '--scan', action='store_true', default=False,
192 | help='Run masscan on single range. Specify --host & --ports & --xml')
193 | parse.add_argument('-ns', '--nmap', action='store_true', default=False,
194 | help='Run Nmap on a single range specify -H & -p')
195 | parse.add_argument('-noes', '--noelastics', action='store_true', default=False,
196 | help='Run scan without elasticsearch insertion')
197 | parse.add_argument('-sl', '--scanlist', action='store_true', default=False,
198 | help='Run masscan on a list of ranges. Requires --host & --ports & --xml')
199 | parse.add_argument('-nsl', '--nmaplist', action='store_true', default=False,
200 | help='Run Nmap on a list of ranges -H & -p & -x')
201 | parse.add_argument('-in', '--noinsert', action='store_true', default=False,
202 | help='Perform a scan without inserting to elasticsearch')
203 | parse.add_argument('-e', '--export', action='store_true', default=False,
204 | help='Export a scan XML into elasticsearch. Requires --xml')
205 | parse.add_argument('-eurl', '--exporturl', action='store_true', default=False,
206 | help='Export urls to scan from XML file. Requires --xml')
207 | parse.add_argument('-nurl', '--exportnmap', action='store_true', default=False,
208 | help='Export urls from nmap XML, requires -x')
209 | parse.add_argument('-del', '--delete', action='store_true', default=False,
210 | help='Specify an index to delete.')
211 | parse.add_argument('-H', '--host', type=str, help='Scan this host or list of hosts')
212 | parse.add_argument('-p', '--ports', type=str,
213 | default='21,22,80,443,8000,8080,8443,2080,2443,9090,6000,8888,50080,50443,5900',
214 | help='Specify ports in masscan format. (ie.0-1000 or 80,443...)')
215 | parse.add_argument('-x', '--xml', type=str, default='scan.xml',
216 | help='Specify an XML file to store output in')
217 | parse.add_argument('-w', '--words', type=str, default='words',
218 | help='Wordlist to be used with --dirb')
219 | parse.add_argument('-u', '--urls', type=str, default='urls',
220 | help='List of Urls to be used with --dirb')
221 | parse.add_argument('-t', '--threads', type=int, default=1,
222 | help='Specify the number of threads to use.')
223 | parse.add_argument('-esh', '--eshost', type=str, default=u'127.0.0.1',
224 | help='Specify the elasticsearch host')
225 | parse.add_argument('-esp', '--port', type=int, default=5900,
226 | help='Specify ElasticSearch port')
227 | parse.add_argument('-i', '--index', type=str, default='scantastic',
228 | help='Specify the ElasticSearch index')
229 | parse.add_argument('-a', '--agent', type=str, default='Scantastic O_o',
230 | help='Specify a User Agent for requests')
231 | args = parse.parse_args()
232 |
233 | if len(sys.argv) <= 1:
234 | parse.print_help()
235 | sys.exit(0)
236 |
237 | if args.version:
238 | version_info()
239 |
240 | if args.scan and (args.host is not None):
241 | scan(args.host, args.ports, args.xml, args.index, args.eshost,
242 | args.port, args.noinsert)
243 | elif args.nmap and (args.host is not None):
244 | nscan(args.host, args.ports, args.xml, args.index, args.eshost,
245 | args.port, args.noinsert)
246 |
247 | if args.scanlist and (args.host is not None):
248 | scanlst(args.host, args.ports, args.xml, args.index, args.eshost,
249 | args.port, args.noinsert)
250 | elif args.nmaplist and (args.host is not None):
251 | nscanlst(args.host, args.ports, args.xml, args.index, args.eshost,
252 | args.port, args.noinsert)
253 |
254 | if args.export:
255 | export_xml(args.xml, args.index, args.eshost, args.port)
256 |
257 | if args.delete:
258 | delete_index(args.index, args.eshost, args.port)
259 |
260 | if args.exporturl:
261 | export_urls(args.xml)
262 | elif args.exportnmap:
263 | nexport_urls(args.xml)
264 |
265 | if args.dirb:
266 | try:
267 | with open(args.urls) as f:
268 | urls = f.read().splitlines()
269 | with open(args.words) as f:
270 | words = f.read().splitlines()
271 | except IOError:
272 | print 'File not found!'
273 | threads = []
274 | splitlist = list(split_urls(urls, args.threads))
275 |
276 | for word in words:
277 | print 'Word: ' + word
278 | for i in range(0, len(splitlist)):
279 | p = multiprocessing.Process(target=requestor,
280 | args=(
281 | list(splitlist[i]), word, args.eshost, args.port, args.agent,
282 | args.index,
283 | args.noelastics))
284 | threads.append(p)
285 | try:
286 | for p in threads:
287 | p.start()
288 | for p in threads:
289 | p.join()
290 | except KeyboardInterrupt:
291 | print 'Killing Threads...'
292 | for p in threads:
293 | p.terminate()
294 | sys.exit(0)
295 | threads = []
296 |
--------------------------------------------------------------------------------
/showRange.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #./showRange.py [127.0.0.0/RANGE]
3 | import sys
4 | from netaddr import *
5 |
6 | addr=sys.argv[1]
7 |
8 | ip = IPNetwork(addr)
9 | print "from: ",str(ip.network)
10 | print "to: ",str(ip.broadcast)
11 |
12 |
--------------------------------------------------------------------------------
/urls/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/urls/.gitkeep
--------------------------------------------------------------------------------
/words/ASP:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/words/ASP
--------------------------------------------------------------------------------
/words/ASPX:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/words/ASPX
--------------------------------------------------------------------------------
/words/HTML:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/words/HTML
--------------------------------------------------------------------------------
/words/PHP:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/words/PHP
--------------------------------------------------------------------------------
/words/blank:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/xml/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maK-/scantastic-tool/37dc863e9285cf156a42847d61f884434f42ad91/xml/.gitkeep
--------------------------------------------------------------------------------
/xmltourl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # Generate URLS from scanfile
3 | # ===============================
4 |
5 | import xmltodict
6 |
7 |
8 | class Xml2urls:
9 | def __init__(self, xmlfile):
10 | self.xmlf = xmlfile
11 | self.data = ''
12 | try:
13 | with open('xml/' + self.xmlf) as myf:
14 | self.data = myf.read().replace('\n', '')
15 | except IOError:
16 | print 'File IO Error'
17 | self.xml = xmltodict.parse(self.data)
18 |
19 |
20 | def run(self):
21 | nmaprun = self.xml['nmaprun']
22 | host = nmaprun['host']
23 |
24 | for entry in host:
25 | port = entry['ports']['port']
26 | if int(port['@portid']) == 80:
27 | name = entry['address']['@addr']
28 | print 'http://' + name + '/'
29 | elif int(port['@portid']) == 443:
30 | name = entry['address']['@addr']
31 | print 'https://' + name + '/'
32 | elif int(port['@portid']) == 21:
33 | name = entry['address']['@addr']
34 | print 'ftp://' + name + '/'
35 | else:
36 | name = entry['address']['@addr']
37 | print 'http://' + name + ':' + str(port['@portid']) + '/'
38 |
39 | class Xml2urls2:
40 | def __init__(self, xmlfile):
41 | self.xmlf = xmlfile
42 | self.data = ''
43 | try:
44 | with open('xml/' + self.xmlf) as myf:
45 | self.data = myf.read().replace('\n', '')
46 | except IOError:
47 | print 'File IO Error'
48 | self.xml = xmltodict.parse(self.data)
49 |
50 | def run(self):
51 | nmaprun = self.xml['nmaprun']
52 | scanhost = nmaprun['host']
53 | for i in scanhost:
54 | address = i['address'][0]['@addr']
55 | port1 = dict(i)
56 | try:
57 | if int(port1['ports']['port']['@portid']) > 0:
58 | port2 = port1['ports']['port']['@portid']
59 | if port2 == '80':
60 | print 'http://'+address+'/'
61 | elif port2 == '443':
62 | print 'https://'+address+'/'
63 | else:
64 | print 'http://'+address+':'+port2+'/'
65 | except:
66 | port2 = i['ports']['port']
67 | for z in port2:
68 | x = z['@portid']
69 | if x == '80':
70 | print 'http://'+address+'/'
71 | elif x == '443':
72 | print 'https://'+address+'/'
73 | else:
74 | print 'http://'+address+':'+x+'/'
75 |
76 |
--------------------------------------------------------------------------------