From aa960e034de928ab3a5be4c534bafc4e48f67911 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 11:31:13 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E7=AB=AF=E5=8F=A3=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/httpscan.py b/httpscan.py index d0276a6..4999c88 100644 --- a/httpscan.py +++ b/httpscan.py @@ -18,19 +18,23 @@ class scan(): - def __init__(self,cidr,threads_num): + def __init__(self,cidr,threads_num, ports): self.threads_num = threads_num self.cidr = IP(cidr) - #build ip queue + self.ports = ports + #build ip queue self.IPs = Queue.Queue() for ip in self.cidr: ip = str(ip) - self.IPs.put(ip) + for port in self.ports: + self.IPs.put('%s:%d' % (ip, port)) + 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 @@ -67,6 +71,9 @@ def run(self): 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]80,443 or 80-443, default 80") (options, args) = parser.parse_args() if len(args) < 1: parser.print_help() @@ -76,5 +83,16 @@ def run(self): print "| IP |Status| Server | Title |" print "+----------------+------+--------------------+------------------------------+" - s = scan(cidr=args[0],threads_num=options.threads_num) + + ports = [] + if ',' in options.ports: + ports = 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)) + + print ports + s = scan(cidr=args[0],threads_num=options.threads_num, ports=ports) s.run() From f6e9036f82f2721dafccd8897b66ff05bd1edac1 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 11:42:54 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E7=AB=AF=E5=8F=A3=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 1 - 1 file changed, 1 deletion(-) diff --git a/httpscan.py b/httpscan.py index 4999c88..f91d50a 100644 --- a/httpscan.py +++ b/httpscan.py @@ -93,6 +93,5 @@ def run(self): else: ports.append(int(options.ports)) - print ports s = scan(cidr=args[0],threads_num=options.threads_num, ports=ports) s.run() From 85dc7a2bd46321e9020ecfd7f9d53a937e732ac9 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 11:47:08 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E7=AB=AF=E5=8F=A3=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/httpscan.py b/httpscan.py index f91d50a..afd007a 100644 --- a/httpscan.py +++ b/httpscan.py @@ -48,8 +48,8 @@ def request(self): banner += r.headers['Server'][:20] #get the server banner except:pass printLock.acquire() - print "|%-16s|%-6s|%-20s|%-30s|" % (ip,status,banner,title) - print "+----------------+------+--------------------+------------------------------+" + print "|%-21s|%-6s|%-20s|%-30s|" % (ip,status,banner,title) + print "+---------------------+------+--------------------+------------------------------+" #Save log with open("./log/"+self.cidr.strNormal(3)+".log",'a') as f: @@ -79,14 +79,14 @@ def run(self): parser.print_help() sys.exit(0) - print "+----------------+------+--------------------+------------------------------+" - print "| IP |Status| Server | Title |" - print "+----------------+------+--------------------+------------------------------+" + print "+---------------------+------+--------------------+------------------------------+" + print "| IP |Status| Server | Title |" + print "+---------------------+------+--------------------+------------------------------+" ports = [] if ',' in options.ports: - ports = options.ports.split(',') + 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)] From 33d6d39080f8014c5e7a6baa2e8f2759fa54938e Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 11:47:43 +0800 Subject: [PATCH 04/10] Update README.md --- README.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a21c6ad..d09e450 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@ -# httpscan -httpscan是一个扫描指定CIDR网段的Web主机的小工具。和端口扫描器不一样,httpscan是以爬虫的方式进行Web主机发现,因此相对来说不容易被防火墙拦截。 +# httpscan V1.1 -httpscan会返回IP http状态码 Web容器版本 以及网站标题。 -![demo][1] +**Usage**:`python httpscan.py IP/CIDR –t threads -p portrange` -**Usage**:`./httpscan IP/CIDR –t threads` +Example:`python httpscan.py 10.20.30.0/24 –t 10 -p 80,443` -Example:`./httpscan.py 10.20.30.0/24 –t 10` +`python httpscan.py 10.20.30.0/24 –t 10 -p 8000-8080` +``` +httpscan> python .\httpscan.py 192.168.62.201 -p 80,8080 ++---------------------+------+--------------------+------------------------------+ +| IP |Status| Server | Title | ++---------------------+------+--------------------+------------------------------+ +|192.168.62.201:8080 |401 |Oracle XML DB/Oracle|None | ++---------------------+------+--------------------+------------------------------+ +|192.168.62.201:80 |200 |Apache/2.4.39 (Win64|None | ++---------------------+------+--------------------+------------------------------+ +``` - [1]: https://raw.githubusercontent.com/zer0h/httpscan/master/log/demo.png From 0662cd47fa99ead42a972d8241acdfe3eb8d2df2 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 11:48:54 +0800 Subject: [PATCH 05/10] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d09e450..1c8a470 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # httpscan V1.1 +增加支持指定端口范围扫描。 + **Usage**:`python httpscan.py IP/CIDR –t threads -p portrange` Example:`python httpscan.py 10.20.30.0/24 –t 10 -p 80,443` From 1d9e293536bbfdc793620c3cace57baa644b5131 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 17:19:22 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=89=AB=E6=8F=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 83 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/httpscan.py b/httpscan.py index afd007a..3f5aa27 100644 --- a/httpscan.py +++ b/httpscan.py @@ -1,44 +1,66 @@ #!/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 = 5 #request timeout +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): + def __init__(self,cidr,threads_num, ports, ipfile): self.threads_num = threads_num - self.cidr = IP(cidr) - self.ports = ports + self.ipfile = ipfile #build ip queue self.IPs = Queue.Queue() - for ip in self.cidr: - ip = str(ip) - for port in self.ports: - self.IPs.put('%s:%d' % (ip, port)) + + 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().split('\n') + for line in contents: + jsline = json.loads(line) + 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.text) #get the title + title = re.search(r'(.*)', r.content) #get the title if title: title = title.group(1).strip().strip("\r").strip("\n")[:30] else: @@ -48,14 +70,16 @@ def request(self): banner += r.headers['Server'][:20] #get the server banner except:pass printLock.acquire() - print "|%-21s|%-6s|%-20s|%-30s|" % (ip,status,banner,title) - print "+---------------------+------+--------------------+------------------------------+" - - #Save log - with open("./log/"+self.cidr.strNormal(3)+".log",'a') as f: - f.write(ip+"\n") - - except Exception,e: + 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() @@ -66,6 +90,7 @@ def run(self): 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", @@ -73,17 +98,29 @@ def run(self): help = "[optional]number of theads,default=10") parser.add_option("-p", "--port", dest = "ports", default = "80", type = "str", - help = "[optional]80,443 or 80-443, default 80") + 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() - if len(args) < 1: + + # 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(',')] @@ -93,5 +130,5 @@ def run(self): else: ports.append(int(options.ports)) - s = scan(cidr=args[0],threads_num=options.threads_num, ports=ports) + s = scan(cidr=cidr,threads_num=options.threads_num, ports=ports, ipfile=options.file) s.run() From b0e121fedc7fec0f0c6a62a3bb99155331b8730f Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 17:19:42 +0800 Subject: [PATCH 07/10] Update README.md --- README.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1c8a470..2903f41 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,35 @@ # httpscan V1.1 -增加支持指定端口范围扫描。 +### Update log -**Usage**:`python httpscan.py IP/CIDR –t threads -p portrange` +1. 增加支持指定端口范围扫描。 -Example:`python httpscan.py 10.20.30.0/24 –t 10 -p 80,443` +2. 增加指定文件扫描。文件格式为: + + ``` + {"ipaddr":"192.168.62.201","ports":[80,8080]} + {"ipaddr":"192.168.62.202","ports":[80,8080]} + ... + ``` + + 每行是一个`json`字符串,包含`ipaddr`和`ports`字段。其中`ports`的值为数组。 + +## Usage + +`python httpscan.py IP/CIDR –t threads -p portrange` + +或 + + `python httpscan.py -f xxx.txt` + +Example: + +`python httpscan.py 10.20.30.0/24 –t 10 -p 80,443` `python httpscan.py 10.20.30.0/24 –t 10 -p 8000-8080` +`python .\httpscan.py -f .\conf\ip.txt` + ``` httpscan> python .\httpscan.py 192.168.62.201 -p 80,8080 +---------------------+------+--------------------+------------------------------+ @@ -17,5 +39,13 @@ httpscan> python .\httpscan.py 192.168.62.201 -p 80,8080 +---------------------+------+--------------------+------------------------------+ |192.168.62.201:80 |200 |Apache/2.4.39 (Win64|None | +---------------------+------+--------------------+------------------------------+ +httpscan> python .\httpscan.py -f .\conf\ip.txt ++---------------------+------+--------------------+------------------------------+ +| IP |Status| Server | Title | ++---------------------+------+--------------------+------------------------------+ +|192.168.62.201:8080 |401 |Oracle XML DB/Oracle|None | ++---------------------+------+--------------------+------------------------------+ +|192.168.62.201:80 |200 |Apache/2.4.39 (Win64|None | ++---------------------+------+--------------------+------------------------------+ ``` From 5388776c6b54754938506ead159970e56b86b6d7 Mon Sep 17 00:00:00 2001 From: xinhaiyucheng <1726401743@qq.com> Date: Tue, 27 Oct 2020 17:48:13 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E5=A4=84=E7=90=86json.loads=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/httpscan.py b/httpscan.py index 3f5aa27..9e8e19b 100644 --- a/httpscan.py +++ b/httpscan.py @@ -45,7 +45,10 @@ def readFile(self): with open(self.ipfile) as f: contents = f.read().split('\n') for line in contents: - jsline = json.loads(line) + try: + jsline = json.loads(line) + except: + continue assets.append((jsline['ipaddr'], jsline['ports'])) else: From 8b0c5d97cb40e47b7543a82aa4a033c41555600d Mon Sep 17 00:00:00 2001 From: V1cent-1227 <1726401743@qq.com> Date: Sat, 7 Nov 2020 23:08:25 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81ip:po?= =?UTF-8?q?rt=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/httpscan.py b/httpscan.py index 9e8e19b..dc23559 100644 --- a/httpscan.py +++ b/httpscan.py @@ -43,13 +43,18 @@ def readFile(self): assets = [] if os.path.exists(self.ipfile): with open(self.ipfile) as f: - contents = f.read().split('\n') - for line in contents: - try: - jsline = json.loads(line) - except: - continue - assets.append((jsline['ipaddr'], jsline['ports'])) + contents = f.read() + if ':' in contents: # ip:port格式 + for line in contents.split('\n'): + ip,port = line.split(':') + 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' From 9486ab72a4b15c7e855a533e9e831902947620df Mon Sep 17 00:00:00 2001 From: V1cent-1227 <1726401743@qq.com> Date: Sat, 7 Nov 2020 23:20:34 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=94=AF=E6=8C=81ip:po?= =?UTF-8?q?rt=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpscan.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/httpscan.py b/httpscan.py index dc23559..3ec51fc 100644 --- a/httpscan.py +++ b/httpscan.py @@ -46,8 +46,11 @@ def readFile(self): contents = f.read() if ':' in contents: # ip:port格式 for line in contents.split('\n'): - ip,port = line.split(':') - assets.append((ip, port)) + 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: