#!/usr/bin/env python
import sys, time, getopt, \
httplib, logging, threading
from urlparse import urlparse
def usage(mess=""):
print \
"""wscan usage:
Files/dirs scan mode:
wscan.py http[s]://site.com[:port][/path/] [-t] [-g] [-p pattern] [-f list.txt] [-l log.txt] [-h headers.txt] [-n 10]
SubDomains scan mode:
wscan.py http[s]://site.com[:port] -s [-t] [-g] [-p pattern] [-f subdomains.txt] [-l log.txt] [-h headers.txt] [-n 10]
Opts:
-t Test mode
-s Subdomains scan mode
-g GET scan mode with pattern
-f File with dirs, files or subdomains for scan.
list.txt by default (or subdomains.txt in subdomain-scan mode)
-l Log file (scanlog.txt by default)
-n Number of threads (10 by default)
-h File with headers
-p Headers filter pattern
"""
sys.exit(mess)
def head_scan(thrnum):
while True:
lock.acquire()
path = listFH.readline().rstrip()
lock.release()
if not len(path): return
if path[0:1] == "/": path = path[1:]
tryes = tryes_to_reconn
while tryes:
try:
conn = Connect(url.netloc)
conn.request(method, mypath+path, headers=headers)
resp = conn.getresponse()
#print "[~] "+mypath+path+"\t\t\t\r",
break
except:
tryes-=1
time.sleep(sleep_reconn_time)
conn.close()
continue
if not tryes:
say("[!] Can't get response from "+url.netloc+mypath+path)
conn.close()
continue
if resp.status not in bad_status:
if len(pattern):
hdr = get_headers_str(resp.getheaders())
if method == "GET":
html = resp.read(get_len)
hdr += html
if not hdr.find(pattern)==-1:
conn.close()
continue
if test_mode:
hdr = get_headers_str(resp.getheaders())
say("\n[~] Test request: %s%s\n%s %s\n\n%s\n" \
% (url.netloc, mypath+path, resp.status, resp.reason, hdr))
if not len(pattern) and method=="GET":
html = resp.read(get_len)
say(html+"\n")
say("[+] %s\t\t[%i] %s" % (mypath+path, resp.status, resp.reason))
conn.close()
def subdomain_scan(thrnum):
while True:
lock.acquire()
sd = listFH.readline().rstrip()
lock.release()
if not len(sd): return
sd += "."
try:
conn = Connect(sd+url.netloc)
#print "[~] "+sd+url.netloc+"\t\t\t\r",
except:
continue
try:
conn.request(method, "/", headers=headers)
resp = conn.getresponse()
if resp.status in bad_status:
raise error
except:
conn.close()
continue
if len(pattern):
hdr = get_headers_str(resp.getheaders())
if method == "GET":
html = resp.read(get_len)
hdr += html
if not hdr.find(pattern)==-1:
conn.close()
continue
if test_mode:
hdr = get_headers_str(resp.getheaders())
say("\n[~] Test request: %s%s\n%s %s\n\n%s\n" \
% (sd, url.netloc, resp.status, resp.reason, hdr))
if not len(pattern) and method=="GET":
html = resp.read(get_len)
say(html+"\n")
say("[+] %s%s\t\t[%i] %s" % (sd, url.netloc, resp.status, resp.reason))
conn.close()
def get_headers_str(data):
hdr = ""
for header, param in data: hdr += header+": "+param+"\n"
return hdr
# Defaults:
list_file = "list.txt"
log_file = "scanlog.txt"
threads_num = 10
bad_status = (404,)
tryes_to_reconn = 2
sleep_reconn_time = 2
get_len = 512
test_mode_bads = ("/", "dirtest9834592")
test_mode_bads_sd = ("www", "sdtest9834592")
pattern = ""
get_pattern = ""
headers_file = ""
headers = {}
method = "HEAD"
thread_func = head_scan
test_mode = False
try:
url = urlparse(sys.argv[1])
if url.scheme == "http": Connect = httplib.HTTPConnection
elif url.scheme == "https": Connect = httplib.HTTPSConnection
else: raise error
mypath = url.path if len(url.path) else "/"
except: usage("[!] Error: wrong URL")
try: opts, args = getopt.getopt(sys.argv[2:], "stf:l:n:h:p:g")
except getopt.GetoptError, err:
usage("[!] Error: "+str(err))
for opt, arg in opts:
if opt == '-s':
list_file = "subdomains.txt"
thread_func = subdomain_scan
test_mode_bads = test_mode_bads_sd
elif opt == '-t': test_mode = True
elif opt == '-f': list_file = arg
elif opt == '-l': log_file = arg
elif opt == '-n': threads_num = int(arg)
elif opt == '-h': headers_file = arg
elif opt == '-p': pattern = arg
elif opt == '-g': method = "GET"
else: usage("[!] Error: wrong params")
try: listFH = open(list_file, 'r')
except: sys.exit("[!] Error: can't open "+list_file)
if len(headers_file):
try: headers = dict([line.rstrip().split(": ", 1) for line in open(headers_file) if len(line)>3])
except: sys.exit("[!] Error: can't work with "+headers_file)
logging.basicConfig(level=logging.INFO, format='%(message)s', filename=log_file, filemode='w')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logging.getLogger('').addHandler(console)
say = logging.info
if test_mode:
listFH.close()
try: listFH = open("test_mode_list.txt", 'w')
except: sys.exit("[!] Error: can't open test_mode_list.txt")
[listFH.write(bads+"\n") for bads in test_mode_bads]
listFH.close()
listFH = open("test_mode_list.txt", 'r')
threads = []
lock = threading.Lock()
for thrnum in xrange(threads_num):
thread = threading.Thread(target=thread_func, name="thread %i" % thrnum, args=[thrnum])
thread.start()
threads.append(thread)
[thread.join() for thread in threads]
if test_mode: say("\n[~] End of test")
# by cr0w
# http://cr0w-at.blogspot.com