├── ip.txt ├── result.png ├── ok.txt ├── dic.txt ├── README.md ├── ihoneyInfoDisclosure.py ├── ihoneyPortScan.py └── ihoneyBakFileScan.py /ip.txt: -------------------------------------------------------------------------------- 1 | 192.168.0.105 2 | 192.168.0.26 3 | 192.168.0.222 4 | 192.168.0.250 -------------------------------------------------------------------------------- /result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scanfsec/ihoneyPortScan/HEAD/result.png -------------------------------------------------------------------------------- /ok.txt: -------------------------------------------------------------------------------- 1 | 207.148.23.27:22 2 | 207.148.23.27:80 3 | 207.148.23.27:111 4 | 207.148.23.27:8989 5 | -------------------------------------------------------------------------------- /dic.txt: -------------------------------------------------------------------------------- 1 | bak.rar 2 | bak.zip 3 | backup.rar 4 | backup.zip 5 | www.zip 6 | www.rar 7 | web.rar 8 | web.zip 9 | wwwroot.rar 10 | wwwroot.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ihoneyPortScan v1.2 端口扫描器 2 | [![Python3](https://img.shields.io/badge/python-3.5-green.svg?style=plastic)](https://www.python.org/) 3 | 4 | 5 | ## 简介: 6 | * 如nmap等传统的扫描太慢且有些信息没必要扫描,本程序其实和masscan效果一样,但效果不一定有masscan好。 7 | * 本程序特点是使用python的telnet库来扫描端口,而不是常规的socket探测方式,现在已经有很多防火墙会拦截socket方式探测,但大多部分对telnet还是不拦截的。 8 | * ip地址和域名都可以扫描,请尽量扫描ip地址,除非此域名确认没有waf、CDN。 9 | * 扫描结果将保存在ok.txt文件中 10 | * 请使用python3.5版本运行 11 | 12 | result:
13 | ![result](result.png) 14 | 15 | ## 安装依赖模块: 16 | 多线程、队列、telnet库等 17 | pip3.5 install queue threading telnetlib base64 argparse ipaddress 18 | 19 | ## 可选参数: 20 | -h,--help 查看使用帮助 21 | -t 可选参数:指定线程数,默认是一个线程 22 | --port 指定扫描端口,支持三种格式:(1)80 (2)80,443,3306,3389 (3)1-65535 23 | 24 | ## 如果端口未指定,将默认扫描以下端口: 25 | [21, 22, 23, 53, 80, 111, 139, 161, 389, 443, 445, 512, 513, 514, 26 | 873, 1025, 1433, 1521, 3128, 3306, 3311, 3312, 3389, 5432, 5900, 27 | 5984, 6082, 6379, 7001, 7002, 8000, 8080, 8081, 8090, 9000, 9090, 28 | 8888, 9200, 9300, 10000, 11211, 27017, 27018, 50000, 50030, 50070] 29 | 30 | ## 必选参数(二选一): 31 | -f 指定存放ip的文件,每一行一个ip或域名 32 | --ip 可以指定ip地址或者域名 33 | 34 | ## 使用样例: 35 | python3.5 ihoneyPortScan.py --ip 192.168.0.105 --port 20-3390 -t 100 36 | python3.5 ihoneyPortScan.py --ip www.xxx.top --port 80,443,3306,3389,8080 37 | python3.5 ihoneyPortScan.py -f ip.txt -t 100 38 | 39 | -------------------------------------------------------------------------------- /ihoneyInfoDisclosure.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import requests 3 | import logging 4 | from queue import Queue 5 | from threading import Thread 6 | from argparse import ArgumentParser 7 | 8 | logging.basicConfig(level=logging.WARNING, format="%(message)s") 9 | 10 | """ 11 | 可能存在信息泄露的文件: 12 | /.git/config 未完成检测代码 13 | /.svn/entries 未完成检测代码 14 | /WEB-INF/web.xml 已完成 15 | 16 | 1.重写线程类 17 | 全局请求超时时间 18 | auth函数(主要验证功能块) 19 | run函数调用auth函数 20 | 21 | 2.分发函数 22 | 创建队列 23 | 实例化线程类并启动线程 24 | 25 | 3.主函数内容 26 | 3.1 扫描文件字典: 27 | .git/config 关键词: 28 | .svn/entries 关键词: 29 | WEB-INF/web.xml 关键词: 30 | 3.2 定义线程数 31 | 3.3 从文件去除url组合加上字典,文件每行不需要添加http(加了也会给你去掉) 32 | """ 33 | 34 | 35 | class PortScan(Thread): 36 | def __init__(self, queue): 37 | Thread.__init__(self) 38 | self.queue = queue 39 | self.headers = { 40 | 'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", 41 | 'Connection': 'close' 42 | } 43 | self.timeout = 5 44 | self.webinfkey = "" 45 | 46 | def _auth(self, url): 47 | try: 48 | r = requests.get(url=url, headers=self.headers, timeout=self.timeout, allow_redirects=False) 49 | content = r.text 50 | 51 | if self.webinfkey in content and r.status_code == 200: 52 | logging.warning("[*] {}".format(url)) 53 | with open('info.txt', 'a') as f: 54 | try: 55 | f.write(str(url) + '\n') 56 | except: 57 | pass 58 | except Exception: 59 | pass 60 | 61 | def run(self): 62 | while not self.queue.empty(): 63 | url = self.queue.get() 64 | try: 65 | self._auth(url) 66 | except: 67 | continue 68 | 69 | 70 | def dispatcher(url_file=None, url=None, max_thread=100, info_dic=None): 71 | urllist = [] 72 | if url_file is not None and url is None: 73 | with open(str(url_file)) as f: 74 | while True: 75 | line = str(f.readline()).strip() 76 | if line: 77 | urllist.append(line) 78 | else: 79 | break 80 | elif url is not None and url_file is None: 81 | urllist.append(url) 82 | else: 83 | pass 84 | 85 | with open('info.txt', 'w'): 86 | pass 87 | 88 | q = Queue() 89 | for url in urllist: 90 | url = url.strip('http://').strip('https://').strip('/') 91 | for info in info_dic: 92 | url = 'http://' + str(url) + '/' + str(info) # url:www.xx.com info:WEB-INF/web.xml 93 | q.put(url) 94 | 95 | # print(q.__dict__['queue']) 96 | qsize = q.qsize() 97 | print('队列大小:' + str(qsize)) 98 | 99 | threadl = [PortScan(q) for _ in range(max_thread)] 100 | for t in threadl: 101 | t.start() 102 | 103 | for t in threadl: 104 | t.join() 105 | 106 | 107 | if __name__ == '__main__': 108 | parser = ArgumentParser(add_help=True, description='Information disclosure scanning tools..') 109 | parser.add_argument('-f', dest="url_file", help="Set ip file") 110 | parser.add_argument('-t', dest="max_threads", nargs='?', type=int, default=1, help="Set max threads") 111 | parser.add_argument('-u', '--url', dest='url', nargs='?', type=str, help="Example: www.xxx.top") 112 | 113 | args = parser.parse_args() 114 | info_dic = ['WEB-INF/web.xml'] 115 | 116 | try: 117 | if args.url: 118 | dispatcher(url=args.url, max_thread=args.max_threads, info_dic=info_dic) 119 | elif args.url_file: 120 | dispatcher(url_file=args.url_file, max_thread=args.max_threads, info_dic=info_dic) 121 | else: 122 | print("Domain name? urlfile?") 123 | except Exception as e: 124 | print(e) -------------------------------------------------------------------------------- /ihoneyPortScan.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from queue import Queue 3 | from threading import Thread 4 | from telnetlib import Telnet 5 | from base64 import b64decode 6 | from argparse import ArgumentParser 7 | from ipaddress import ip_address 8 | 9 | 10 | class PortScan(Thread): 11 | TIMEOUT = 5 # 默认扫描超时时间 12 | 13 | def __init__(self, queue): 14 | Thread.__init__(self) 15 | self.queue = queue 16 | 17 | def auth(self, url): 18 | host = url.split(':')[0] 19 | port = url.split(':')[-1] 20 | 21 | try: 22 | tn = Telnet(host=host, port=port, timeout=self.TIMEOUT) 23 | # 越高,得到的调试输出就越多(sys.stdout)。 24 | tn.set_debuglevel(3) 25 | print('[*] ' + url + ' -- ok') 26 | 27 | with open('ok.txt', 'a') as f: 28 | try: 29 | f.write(str(url) + '\n') 30 | except: 31 | pass 32 | except Exception as e: 33 | # print('[ ] ' + url + ' -- ' + str(e)) 34 | pass 35 | finally: 36 | tn.close() 37 | 38 | def run(self): # 非空 39 | while not self.queue.empty(): 40 | url = self.queue.get() 41 | try: 42 | self.auth(url) 43 | except: 44 | continue 45 | 46 | 47 | def dispatcher(ip_file=None, ip=None, max_thread=100, portlist=None): 48 | iplist = [] 49 | if ip_file is not None and ip is None: 50 | with open(str(ip_file)) as f: 51 | while True: 52 | line = str(f.readline()).strip() 53 | if line: 54 | iplist.append(line) 55 | else: 56 | break 57 | elif ip is not None and ip_file is None: 58 | iplist.append(ip) 59 | else: 60 | pass 61 | 62 | with open('ok.txt', 'w'): 63 | pass 64 | 65 | q = Queue() 66 | for ip in iplist: 67 | for port in portlist: 68 | url = str(ip) + ':' + str(port) 69 | q.put(url) 70 | 71 | # print(q.__dict__['queue']) 72 | print('队列大小:' + str(q.qsize())) 73 | 74 | threadl = [PortScan(q) for _ in range(max_thread)] 75 | for t in threadl: 76 | t.start() 77 | 78 | for t in threadl: 79 | t.join() 80 | 81 | 82 | if __name__ == '__main__': 83 | parser = ArgumentParser(add_help=True, description='Port scan tool..') 84 | parser.add_argument('-f', dest="ip_file", help="Set ip file") 85 | parser.add_argument('-t', dest="max_threads", nargs='?', type=int, default=1, help="Set max threads") 86 | parser.add_argument('--ip', dest='ip', nargs='?', type=str, help="Example: 192.168.0.105, www.xxx.top") 87 | parser.add_argument('--port', dest='port', nargs='?', type=str, help="Example: 80 80-89 80,443,3306,8080") 88 | 89 | args = parser.parse_args() 90 | logo_code = 'IF8gXyAgICAgICAgICAgICAgICAgICAgICAgICAgICBfX19fICAgICAgICAgICAgXyAgIF9fX18gICAgICAgICAgICAgICAgICAKKF8pIHxfXyAgIF9fXyAgXyBfXyAgIF9fXyBfICAgX3wgIF8gXCBfX18gIF8gX198IHxfLyBfX198ICBfX18gX18gXyBfIF9fICAKfCB8ICdfIFwgLyBfIFx8ICdfIFwgLyBfIFwgfCB8IHwgfF8pIC8gXyBcfCAnX198IF9fXF9fXyBcIC8gX18vIF9gIHwgJ18gXCAKfCB8IHwgfCB8IChfKSB8IHwgfCB8ICBfXy8gfF98IHwgIF9fLyAoXykgfCB8ICB8IHxfIF9fXykgfCAoX3wgKF98IHwgfCB8IHwKfF98X3wgfF98XF9fXy98X3wgfF98XF9fX3xcX18sIHxffCAgIFxfX18vfF98ICAgXF9ffF9fX18vIFxfX19cX18sX3xffCB8X3wKICAgICAgICAgICAgICAgICAgICAgICAgICB8X19fLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK' 91 | print(b64decode(logo_code).decode()) 92 | print("Example:\npython3.5 portScan.py --ip 192.168.0.105 --port 20-3390 -t 100\npython3.5 portScan.py --ip www.xxx.top --port 80,443,3306,3389,8080 \npython3.5 xingyuPortScan1.2.py -f ip.txt -t 100") 93 | print('-' * 64) 94 | 95 | portlist1 = args.port 96 | if portlist1: 97 | if ',' in portlist1: 98 | portlist = portlist1.split(',') 99 | elif '-' in portlist1: 100 | portlist = portlist1.split('-') 101 | tmpportlist = [] 102 | [tmpportlist.append(i) for i in range(int(portlist[0]), int(portlist[1]) + 1)] 103 | portlist = tmpportlist 104 | else: 105 | portlist = [portlist1] 106 | else: 107 | portlist = [21, 22, 23, 53, 80, 111, 139, 161, 389, 443, 445, 512, 513, 514, 108 | 873, 1025, 1433, 1521, 3128, 3306, 3311, 3312, 3389, 5432, 5900, 109 | 5984, 6082, 6379, 7001, 7002, 8000, 8080, 8081, 8090, 9000, 9090, 110 | 8888, 9200, 9300, 10000, 11211, 27017, 27018, 50000, 50030, 50070] 111 | print('You do not specify a port, will only scan has set the default port') 112 | 113 | if args.ip: 114 | try: 115 | # ip_address(args.ip) 116 | dispatcher(ip=args.ip, max_thread=args.max_threads, portlist=portlist) 117 | except Exception as e: 118 | print(e) 119 | elif args.ip_file: 120 | dispatcher(ip_file=args.ip_file, max_thread=args.max_threads, portlist=portlist) 121 | else: 122 | print("Please specify the IP address or domain name and the port scanning") 123 | -------------------------------------------------------------------------------- /ihoneyBakFileScan.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # 2018.04.20 T00ls.net 3 | # __author__: ihoneysec 4 | import requests 5 | import logging 6 | from binascii import b2a_hex 7 | from queue import Queue 8 | from threading import Thread 9 | from argparse import ArgumentParser 10 | from copy import deepcopy 11 | 12 | logging.basicConfig(level=logging.WARNING, format="%(message)s") 13 | 14 | 15 | class BakScan(Thread): 16 | def __init__(self, queue): 17 | Thread.__init__(self) 18 | self.queue = queue 19 | self.headers = { 20 | 'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36", 21 | } 22 | self.timeout = 5 # 3秒测试有漏报 23 | 24 | def _auth(self, url): 25 | try: 26 | r = requests.get(url=url, headers=self.headers, timeout=self.timeout, allow_redirects=False, stream=True, verify=False) 27 | # 验证压缩包文件头10个字节,rar固定头16进制为:526172211a0700cf9073 zip为:504b0304140000000800 28 | content = b2a_hex(r.raw.read(10)).decode() 29 | if r.status_code == 200: 30 | rarsize = int(r.headers.get('Content-Length')) // 1024 // 1024 31 | if content.startswith('526172') or content.startswith('504b03'): 32 | logging.warning('[*] {} size:{}M'.format(url, rarsize)) 33 | with open('success.txt', 'a') as f: 34 | try: 35 | f.write(str(url) + '\n') 36 | except: 37 | pass 38 | else: # 如果你只想看扫描成功的备份地址就注释这行和下一行 39 | logging.warning('[ ] {}'.format(url)) 40 | except Exception as e: 41 | pass 42 | 43 | def run(self): 44 | while not self.queue.empty(): 45 | url = self.queue.get() 46 | try: 47 | self._auth(url) 48 | except: 49 | continue 50 | 51 | 52 | def dispatcher(url_file=None, url=None, max_thread=1, dic=None): 53 | urllist = [] 54 | if url_file is not None and url is None: 55 | with open(str(url_file)) as f: 56 | while True: 57 | line = str(f.readline()).strip() 58 | if line: 59 | urllist.append(line) 60 | else: 61 | break 62 | elif url is not None and url_file is None: 63 | urllist.append(url) 64 | else: 65 | pass 66 | 67 | with open('success.txt', 'w'): 68 | pass 69 | 70 | q = Queue() 71 | 72 | for u in urllist: 73 | # 假设url为www.test.gov.cn,自动根据域名生成一些备份文件名,如下: 74 | # www.test.gov.cn.rar www.test.gov.cn.zip 75 | # wwwtestgovcn.rar wwwtestgovcn.zip 76 | # testgovcn.rar testgovcn.zip 77 | # test.gov.cn.rar test.gov.cn.zip 78 | # www.rar www.zip 79 | www1 = u.split('.') 80 | wwwlen = len(www1) 81 | wwwhost = '' 82 | for i in range(1, wwwlen): 83 | wwwhost += www1[i] 84 | 85 | current_info_dic = deepcopy(dic) # 深拷贝 86 | current_info_dic.extend([u + '.rar', u + '.zip']) 87 | current_info_dic.extend([u.replace('.', '') + '.rar', u.replace('.', '') + '.zip']) 88 | current_info_dic.extend([wwwhost + '.rar', wwwhost + '.zip']) 89 | current_info_dic.extend([u.split('.', 1)[-1] + '.rar', u.split('.', 1)[-1] + '.zip']) 90 | # print(current_info_dic) 91 | """ 最终每个url对应可以扫描的字典部分如下 92 | ['web.rar', 'web.zip', 'backup.rar', 'www.rar', 'bak.rar', 'wwwroot.zip', 'bak.zip', 'www.zip', 'wwwroot.rar', 'backup.zip', 'www.test.gov.cn.rar', 'www.test.gov.cn.zip', 'wwwtestgovcn.rar', 'wwwtestgovcn.zip', 'testgovcn.rar', 'testgovcn.zip', 'test.gov.cn.rar', 'test.gov.cn.zip'] 93 | ['web.rar', 'web.zip', 'backup.rar', 'www.rar', 'bak.rar', 'wwwroot.zip', 'bak.zip', 'www.zip', 'wwwroot.rar', 'backup.zip', 'www.baidu.com.rar', 'www.baidu.com.zip', 'wwwbaiducom.rar', 'wwwbaiducom.zip', 'baiducom.rar', 'baiducom.zip', 'baidu.com.rar', 'baidu.com.zip'] 94 | """ 95 | 96 | for info in current_info_dic: 97 | if u.startswith('http://') or u.startswith('https://'): 98 | url = str(u) + '/' + str(info) 99 | else: 100 | url = 'http://' + str(u) + '/' + str(info) 101 | q.put(url) 102 | 103 | # print(q.__dict__['queue']) # 注释掉或删掉这行,如果url批量太多,会满屏幕打印队列中待扫描的地址 104 | print('队列大小:' + str(q.qsize())) 105 | threadl = [BakScan(q) for _ in range(max_thread)] 106 | for t in threadl: 107 | t.start() 108 | 109 | for t in threadl: 110 | t.join() 111 | 112 | 113 | if __name__ == '__main__': 114 | parser = ArgumentParser(add_help=True, description='Information disclosure scanning tools..') 115 | parser.add_argument('-f', dest="url_file", help="Set ip file") 116 | parser.add_argument('-t', dest="max_threads", nargs='?', type=int, default=1, help="Set max threads") 117 | parser.add_argument('-u', '--url', dest='url', nargs='?', type=str, help="Example: www.xxx.top") 118 | 119 | """ 120 | 参数: 121 | -f 批量时指定存放url的文件 122 | -t 指定线程 123 | -u 单个url扫描时指定url 124 | 使用: 125 | 批量url扫描 python3.5 ihoneyBakFileScan.py -t 100 -f url.txt 126 | 单个url扫描 python3.5 ihoneyBakFileScan.py -u www.ihoneysec.top 127 | """ 128 | 129 | args = parser.parse_args() 130 | # 如果想使用这个脚本的默认扫描字典,请取消注释下一行注释 131 | info_dic = ['bak.rar', 'bak.zip', 'backup.rar', 'backup.zip', 'www.zip', 'www.rar', 'web.rar', 'web.zip', 'wwwroot.rar', 'wwwroot.zip', ] 132 | # 如果想从文件中自定义字典请取消下一行注释并注释上一行 133 | # info_dic = list(set([i.replace("\n", "") for i in open("dic.txt", "r").readlines()])) 134 | 135 | try: 136 | if args.url: 137 | dispatcher(url=args.url, max_thread=args.max_threads, dic=info_dic) 138 | elif args.url_file: 139 | dispatcher(url_file=args.url_file, max_thread=args.max_threads, dic=info_dic) 140 | else: 141 | print("Domain name? urlfile?") 142 | except Exception as e: 143 | pass 144 | --------------------------------------------------------------------------------