#!/usr/bin/env python
#coding:utf-8
# Author: Zeroh
import re
import sys
import Queue
import codecs
import logging
import optparse
import requests
import threading
from IPy import IP
from os.path import basename
# from urllib3.exceptions import ConnectTimeoutError
printLock = threading.Semaphore(1) #lock Screen print
TimeOut = 5 #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):
self.threads_num = threads_num
self.log_handler = None
self.cidr, self.logfilename = self.load_target(cidr)
self.cur_position = 1
self.total = len(self.cidr)
self.running = True
#build ip queue
self.IPs = Queue.Queue()
self.msg_queue = Queue.Queue()
for ip in self.cidr:
self.IPs.put(ip)
def load_target(self, target):
targets = []
logfilename = ''
try:
# try to open as file
with open(target, 'r') as handle:
for line in handle:
if line.strip():
targets.append(line.strip())
logfilename = basename(target)
except IOError, e:
# treat as range of ip
ips = IP(target)
logfilename = ips.strNormal(3)
targets = map(lambda x: str(x), ips)
return (targets, './log/{}.log'.format(logfilename))
def __record(self, log):
if self.log_handler:
self.log_handler.write(log + '\n')
print log
def request(self, log_handler):
while self.IPs.qsize() > 0:
ip = self.IPs.get()
self.msg_queue.put('Current target: ' + ip)
try:
r = requests.Session().get('http://' + ip,headers=header,timeout=TimeOut)
status = r.status_code
title = re.search(r'
(.*)', r.text) #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
self.msg_queue.put("|%-16s|%-6s|%-20s|%-30s|" % (ip,status,banner,title))
self.msg_queue.put("+----------------+------+--------------------+------------------------------+")
except Exception:
# timeout, nothing to do
pass
def __print_log_message(self):
while self.running:
try:
msg = self.msg_queue.get(timeout=0.1)
except:
continue
with printLock:
if msg[0] in ('|', '+'):
self.__record(msg)
else:
sys.stdout.write(' ' * 100 + '\r')
sys.stdout.flush()
if msg[:7] == 'Current':
msg = '%s (%d/%d)' % (msg, self.cur_position, self.total)
if self.cur_position < self.total:
self.cur_position += 1
sys.stdout.write(msg + '\r')
sys.stdout.flush()
#Multi thread
def run(self):
threads = []
with codecs.open(self.logfilename, 'w+', 'utf-8') as handle:
try:
self.log_handler = handle
log_thread = threading.Thread(target=self.__print_log_message)
log_thread.start()
self.msg_queue.put("+----------------+------+--------------------+------------------------------+")
self.msg_queue.put("| IP |Status| Server | Title |")
self.msg_queue.put("+----------------+------+--------------------+------------------------------+")
for i in range(self.threads_num):
threads.append(threading.Thread(target=self.request, args=(handle,)))
threads[i].setDaemon(True)
threads[i].start()
for thread in threads:
thread.join(20000)
except KeyboardInterrupt:
self.msg_queue.put('[+] User aborted')
finally:
self.running = False
self.msg_queue.put('done.')
if __name__ == "__main__":
parser = optparse.OptionParser("Usage: %prog [options] ")
parser.add_option("-t", "--thread", dest = "threads_num",
default = 10, type = "int",
help = "[optional]number of theads,default=10")
(options, args) = parser.parse_args()
if len(args) < 1:
parser.print_help()
sys.exit(0)
s = scan(cidr = args[0], threads_num = options.threads_num)
s.run()