Skip to content

Commit 9227fc9

Browse files
committed
new
1 parent 3a5677c commit 9227fc9

File tree

1 file changed

+298
-0
lines changed

1 file changed

+298
-0
lines changed

bannerscan.py

+298
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
#coding=utf-8
2+
3+
import threading
4+
import requests
5+
import argparse
6+
import time
7+
import re
8+
9+
10+
PORTS = (80,81,82,83,84,85,86,87,88,89,90,443,801,873,881,1900,2601,2604,3128,4440,4848,5001,5275,6379,7001,7002,7003,7005,7008,7033,7080,7090,7778,7901,8000,8001,8002,8003,8010,8011,8020,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8199,8443,8886,8888,9000,9043,9060,9080,9090,9200,9437,9440,9956,11211,16082,16907,18100,20000,27017,28017,41080,50000)
11+
PATHS = ('/robots.txt',
12+
'/admin/',
13+
'/console/',
14+
'/uddiexplorer/',
15+
'/manager/html/',
16+
'/jmx-console/',
17+
'/web-console/',
18+
'/jonasAdmin/',
19+
'/manager/',
20+
'/install/',
21+
'/ibm/console/logon.jsp',
22+
'/axis2/axis2-admin/',
23+
'/CFIDE/administrator/index.cfm',
24+
'/FCKeditor/',
25+
'/fckeditor/',
26+
'/fck/',
27+
'/FCK/',
28+
'/HFM/',
29+
'/WEB-INF/',
30+
'/ckeditor/',
31+
'/phpMyAdmin/',
32+
'/Struts2/index.action',
33+
'/index.action',
34+
'/phpinfo.php',
35+
'/info.php',
36+
'/1.php',
37+
'/CHANGELOG.txt',
38+
'/LICENSE.txt',
39+
'/readme.html',
40+
'/cgi-bin/',
41+
'/invoker/',
42+
'/.svn/',
43+
'/test/',
44+
'/CFIDE/',
45+
'/.htaccess',
46+
'/.git/'
47+
)
48+
49+
HTML_LOG_TEMPLATE="""
50+
<!DOCTYPE html>
51+
<html>
52+
<head>
53+
<meta charset="UTF-8">
54+
<title>Bannerscan Report</title>
55+
<style type="text/css">
56+
%s
57+
</style>
58+
</head>
59+
<body>
60+
<center><h2>%s</h2></center>
61+
<div class="report-content">
62+
%s
63+
</div>
64+
</body>
65+
</html>
66+
"""
67+
css = """
68+
body{background-color:#FFF;color:#444;font-family:"Droid Serif",Georgia,"Times New Roman",STHeiti,serif;font-size:100%;}
69+
a{color:#3354AA;text-decoration:none;}
70+
a:hover,a:active{color:#444;}
71+
pre,code{background:#F3F3F0;font-family:Menlo,Monaco,Consolas,"Lucida Console","Courier New",monospace;font-size:.92857em;padding:2px 4px;}
72+
code{color:#B94A48;}
73+
pre{overflow:auto;max-height:400px;padding:8px;}
74+
pre code{color:#444;padding:0;}
75+
h1,h2,h3{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;}
76+
textarea{resize:vertical;}.report-meta a,.report-content a,.widget a,a{border-bottom:1px solid#EEE;}.report-meta a:hover,.report-content a:hover,.widget a:hover,a{border-bottom-color:transparent;}#header{padding-top:35px;border-bottom:1px solid#EEE;}#logo{color:#333;font-size:2.5em;}.description{color:#999;font-style:italic;margin:.5em 0 0;}.report{border-bottom:1px solid#EEE;padding:15px 0 20px;}.report-title{font-size:1.4em;margin:.83em 0;}.report-meta{margin-top:-.5em;color:#999;font-size:.92857em;padding:0;}.report-meta li{display:inline-block;padding-left:12px;border-left:1px solid#EEE;margin:0 8px 0 0;}.report-meta li:first-child{margin-left:0;padding-left:0;border:none;}.report-content{line-height:1.5;}.report-content hr,hr{margin:2em auto;width:100px;border:1px solid#E9E9E9;border-width:2px 0 0 0;}
77+
"""
78+
79+
ipPattern = "^([1]?\d\d?|2[0-4]\d|25[0-5])\." \
80+
"([1]?\d\d?|2[0-4]\d|25[0-5])\." \
81+
"([1]?\d\d?|2[0-4]\d|25[0-5])\." \
82+
"([1]?\d\d?|2[0-4]\d|25[0-5])$"
83+
84+
iprangePattern = "^([1]?\d\d?|2[0-4]\d|25[0-5])\." \
85+
"([1]?\d\d?|2[0-4]\d|25[0-5])\." \
86+
"([1]?\d\d?|2[0-4]\d|25[0-5])\." \
87+
"([1]?\d\d?|2[0-4]\d|25[0-5])-([1]?\d\d?|2[0-4]\d|25[0-5])$"
88+
89+
ua = "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6"
90+
91+
headers = dict()
92+
result = dict()
93+
94+
95+
class bannerscan(threading.Thread):
96+
def __init__(self, ip, timeout, headers):
97+
self.ip = ip
98+
self.req = requests
99+
self.timeout = timeout
100+
self.headers = headers
101+
self.per = 0
102+
threading.Thread.__init__(self)
103+
104+
def run(self):
105+
result[self.ip] = dict()
106+
for port in PORTS:
107+
url_pre = "https://" if port == 443 else "http://"
108+
site = url_pre + self.ip + ":" + str(port)
109+
try:
110+
print ("[*] %s\r" % (site[0:60].ljust(60, " "))),
111+
resp = requests.head(site,
112+
allow_redirects = False,
113+
timeout=self.timeout,
114+
headers=self.headers
115+
)
116+
result[self.ip][port] = dict()
117+
118+
except Exception, e:
119+
pass
120+
121+
else:
122+
result[self.ip][port]["headers"] = resp.headers
123+
result[self.ip][port]["available"] = list()
124+
125+
for path in PATHS:
126+
try:
127+
url = site + path
128+
print ("[*] %s\r" % (url[0:60].ljust(60, " "))),
129+
resp = self.req.get(url,
130+
allow_redirects = False,
131+
timeout=self.timeout,
132+
headers=self.headers
133+
)
134+
135+
except Exception, e:
136+
pass
137+
else:
138+
if resp.status_code in [200, 406, 401, 403, 500]:
139+
r = re.findall("<title>([\s\S]+?)</title>", resp.content)
140+
title = lambda r : r and r[0] or ""
141+
result[self.ip][port]["available"].append((title(r), url, resp.status_code))
142+
143+
def getiplst(host, start=1, end=255):
144+
iplst = []
145+
ip_pre = ""
146+
for pre in host.split('.')[0:3]:
147+
ip_pre = ip_pre + pre + '.'
148+
for i in range(start, end):
149+
iplst.append(ip_pre + str(i))
150+
return iplst
151+
152+
def retiplst(ip):
153+
iplst = []
154+
if ip:
155+
if re.match(ipPattern, ip):
156+
print "[*] job: %s \r" % ip
157+
iplst = getiplst(ip)
158+
return iplst
159+
else:
160+
print "[!] not a valid ip given."
161+
exit()
162+
163+
def retiprangelst(iprange):
164+
iplst = []
165+
if re.match(iprangePattern, iprange):
166+
ips = re.findall(iprangePattern, iprange)[0]
167+
ip = ips[0] + "." + ips[1] + "." + ips[2] + "." + "1"
168+
ipstart = int(ips[3])
169+
ipend = int(ips[4]) + 1
170+
print "[*] job: %s.%s - %s" % (ips[0] + "." + ips[1] + "." + ips[2], ipstart, ipend)
171+
iplst = getiplst(ip, ipstart, ipend)
172+
return iplst
173+
else:
174+
print "[!] not a valid ip range given."
175+
exit()
176+
177+
def ip2int(s):
178+
l = [int(i) for i in s.split('.')]
179+
return (l[0] << 24) | (l[1] << 16) | (l[2] << 8) | l[3]
180+
181+
def log(out, path):
182+
logcnt = ""
183+
centerhtml = lambda ips: len(ips)>1 and str(ips[0]) + " - " + str(ips[-1]) or str(ips[0])
184+
titlehtml = lambda x : x and "<strong>" + str(x) + "</strong><br />" or ""
185+
ips = out.keys()
186+
ips.sort(lambda x, y: cmp(ip2int(x), ip2int(y)))
187+
for ip in ips:
188+
titled = False
189+
if type(out[ip]) == type(dict()):
190+
for port in out[ip].keys():
191+
if not titled:
192+
if len(out[ip][port]['headers']):
193+
logcnt += "<center><h2>%s</h2></center>" % ip
194+
logcnt += "<hr />"
195+
titled = True
196+
logcnt += "PORT: %s <br />" % port
197+
logcnt += "Response Headers:<pre>"
198+
for key in out[ip][port]["headers"].keys():
199+
logcnt += key + ":" + out[ip][port]["headers"][key] + "\n"
200+
logcnt += "</pre>"
201+
for title, url, status_code in out[ip][port]["available"]:
202+
logcnt += titlehtml(title) + \
203+
"<a href=\"" + url + "\">" + url + " </a> "+ \
204+
"Status Code:<code>" + str(status_code) + "</code><br />"
205+
logcnt += "<br />"
206+
center = centerhtml(ips)
207+
logcnt = HTML_LOG_TEMPLATE % ( css, center, logcnt)
208+
outfile = open(path, "a")
209+
outfile.write(logcnt)
210+
outfile.close()
211+
212+
def scan(iplst, timeout, headers, savepath):
213+
global result
214+
start = time.time()
215+
threads = []
216+
217+
for ip in iplst:
218+
t = bannerscan(ip,timeout,headers)
219+
threads.append(t)
220+
221+
for t in threads:
222+
t.start()
223+
224+
for t in threads:
225+
t.join()
226+
227+
log(result, savepath)
228+
result = dict()
229+
print
230+
231+
def main():
232+
parser = argparse.ArgumentParser(description='banner scanner. by DM_ http://x0day.me')
233+
group = parser.add_mutually_exclusive_group()
234+
235+
group.add_argument('-i',
236+
action="store",
237+
dest="ip",
238+
)
239+
group.add_argument('-r',
240+
action="store",
241+
dest="iprange",
242+
type=str,
243+
)
244+
group.add_argument('-f',
245+
action="store",
246+
dest="ipfile",
247+
type=argparse.FileType('r')
248+
)
249+
parser.add_argument('-s',
250+
action="store",
251+
required=True,
252+
dest="savepath",
253+
type=str,
254+
)
255+
parser.add_argument('-t',
256+
action="store",
257+
required=False,
258+
type = int,
259+
dest="timeout",
260+
default=5
261+
)
262+
263+
args = parser.parse_args()
264+
savepath = args.savepath
265+
timeout = args.timeout
266+
iprange = args.iprange
267+
ipfile = args.ipfile
268+
ip = args.ip
269+
270+
headers['user-agent'] = ua
271+
272+
print "[*] starting at %s" % time.ctime()
273+
274+
if ip:
275+
iplst = retiplst(ip)
276+
scan(iplst, timeout, headers, savepath)
277+
278+
elif iprange:
279+
iplst = retiprangelst(iprange)
280+
scan(iplst, timeout, headers, savepath)
281+
282+
elif ipfile:
283+
lines = ipfile.readlines()
284+
for line in lines:
285+
if re.match(ipPattern, line):
286+
iplst = retiplst(line)
287+
scan(iplst, timeout, headers, savepath)
288+
elif re.match(iprangePattern, line):
289+
iplst = retiprangelst(line)
290+
scan(iplst, timeout, headers, savepath)
291+
292+
else:
293+
parser.print_help()
294+
exit()
295+
296+
if __name__ == '__main__':
297+
main()
298+

0 commit comments

Comments
 (0)