#!/usr/bin/env python
#coding:utf-8
# Author: Zeroh
import os
import re
import sys
import json
import Queue
import traceback
import threading
import optparse
import requests
from IPy import IP
reload(sys)
sys.setdefaultencoding('utf-8')
printLock = threading.Semaphore(1) #lock Screen print
TimeOut = 3 #request timeout
#User-Agent
header = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36','Connection':'close'}
class scan():
def __init__(self,cidr,threads_num, ports, ipfile):
self.threads_num = threads_num
self.ipfile = ipfile
#build ip queue
self.IPs = Queue.Queue()
if self.ipfile != "":
assets = self.readFile()
for ip, ports in assets:
for port in ports:
self.IPs.put('%s:%d' % (ip, port))
else:
for ip in IP(cidr):
ip = str(ip)
for port in ports:
self.IPs.put('%s:%d' % (ip, port))
def readFile(self):
assets = []
if os.path.exists(self.ipfile):
with open(self.ipfile) as f:
contents = f.read()
if ':' in contents: # ip:port格式
for line in contents.split('\n'):
if line :
ip_port = line.split(':')
ip = ip_port[0]
port = [int(ip_port[1])]
assets.append((ip, port))
else: # json格式
for line in contents.split('\n'):
try:
jsline = json.loads(line)
except:
continue
assets.append((jsline['ipaddr'], jsline['ports']))
else:
print 'file not exists'
return assets
def request(self):
with threading.Lock():
while self.IPs.qsize() > 0:
ip = self.IPs.get()
try:
r = requests.Session().get('http://'+str(ip),headers=header,timeout=TimeOut)
status = r.status_code
title = re.search(r'
(.*)', r.content) #get the title
if title:
title = title.group(1).strip().strip("\r").strip("\n")[:30]
else:
title = "None"
banner = ''
try:
banner += r.headers['Server'][:20] #get the server banner
except:pass
printLock.acquire()
try:
print "|%-21s|%-6s|%-20s|%-30s|" % (ip,status,banner,title.decode('utf-8'))
print "+---------------------+------+--------------------+------------------------------+"
#Save log
with open("./log/result.log",'a') as f:
f.write("%s %s %s %s\n" % (ip,status,banner,title))
except:
traceback.print_exc()
pass
except:
printLock.acquire()
finally:
printLock.release()
#Multi thread
def run(self):
for i in range(self.threads_num):
t = threading.Thread(target=self.request)
t.start()
if __name__ == "__main__":
parser = optparse.OptionParser("Usage: %prog [options] target")
parser.add_option("-t", "--thread", dest = "threads_num",
default = 10, type = "int",
help = "[optional]number of theads,default=10")
parser.add_option("-p", "--port", dest = "ports",
default = "80", type = "str",
help = "[optional]e.g. 80,443 or 80-443, default 80")
parser.add_option("-f", "--file", dest = "file",
default = "", type = "str",
help = "[optional]e.g. conf/ip.txt")
(options, args) = parser.parse_args()
# options.file = ".\conf\ip.txt"
if len(args) < 1 and options.file == "":
parser.print_help()
sys.exit(0)
elif len(args) == 1:
try:
IP(args[0])
except:
parser.print_help()
sys.exit(0)
cidr = '' if options.file != "" else args[0]
print "+---------------------+------+--------------------+------------------------------+"
print "| IP |Status| Server | Title |"
print "+---------------------+------+--------------------+------------------------------+"
ports = []
if ',' in options.ports:
ports = [int(port) for port in options.ports.split(',')]
elif '-' in options.ports:
start, end = options.ports.split('-')
ports = [port for port in range(int(start), int(end)+1)]
else:
ports.append(int(options.ports))
s = scan(cidr=cidr,threads_num=options.threads_num, ports=ports, ipfile=options.file)
s.run()