├── README.assets └── image-20220529094733097.png ├── README.md ├── config.ini ├── inforgation.py ├── modules ├── Template.html ├── _0zero.py ├── __init__.py ├── domain.py ├── fofa.py ├── hunter.py ├── output.py ├── shodan.py ├── threatbook.py └── zoomeye.py ├── output └── google.html └── requirements.txt /README.assets/image-20220529094733097.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wrong-pixel/inforgation/48858a208a74a1112b83032c8f536b141bc86814/README.assets/image-20220529094733097.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # inforgation蓝队信息聚合查询工具 2 | 3 | # GUI版本已经开发完成,请移步[inforGUI](https://github.com/Wrong-pixel/inforGUI),命令行版本将不再进行功能更新,如果遇到bug可以提交issue 4 | 5 | ### 特别感谢[狼组安全团队的TIG 威胁情报收集](https://github.com/wgpsec/tig#tig--%E5%A8%81%E8%83%81%E6%83%85%E6%8A%A5%E6%94%B6%E9%9B%86-) ,本工具也是在TIG的基础上进行开发,加入了更多平台的查询,各位师傅如有比较好的平台开放API接口的,也可提交issue。 6 | 7 | ### ps:由于接入平台的增多,不同平台的API响应速度会影响到查询速度,请根据自身需求配置APIKEY,APIKEY为空则不会通过该平台进行情报检索,目前已知对查询速度影响较大的API有shodan和zoomeye 8 | 9 | # inforgarion支持的平台如下: 10 | 11 | ## 鹰图 12 | > [奇安信鹰图平台](https://hunter.qianxin.com/) 13 | > 14 | > [鹰图API获取地址](https://hunter.qianxin.com/home/userInfo) 15 | ## fofa 16 | > [fofa平台](https://fofa.info/) 17 | > 18 | > [fofa API获取地址](https://fofa.info/personalData) 19 | ## 微步 20 | > [微步社区](https://x.threatbook.cn/) 21 | > 22 | > [微步API获取地址](https://x.threatbook.cn/v5/myApi) 23 | ## shodan 24 | > [shodan平台](https://www.shodan.io/) 25 | > 26 | > [shodan API获取地址](https://account.shodan.io/) 27 | ## 0zero 28 | > [0zero平台](https://0.zone/) 29 | > 30 | > [0zero API获取地址](https://0.zone/applyParticulars?type=site) 31 | ## zoomeye 32 | 33 | >[zoomeye 平台](https://www.zoomeye.org/) 34 | > 35 | >[zoomeye apiley获取地址](https://www.zoomeye.org/profile) 36 | 37 | ### and more...... 38 | # 使用方法: 39 | 1、clone至本地后首先安装依赖 40 | 41 | `pip(3) install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ 42 | ` 43 | 44 | 2、接着配置config.ini,往里面添加自己的APIKEY,config.ini如下: 45 | ```editorconfig 46 | [鹰图/hunter] 47 | # 鹰图地址:https://hunter.qianxin.com/ 48 | # 鹰图APIKEY获取地址:https://hunter.qianxin.com/home/userInfo 49 | username = 50 | apikey = 51 | 52 | [fofa] 53 | # fofa地址:https://fofa.info/ 54 | # fofa APIKEY获取地址:https://fofa.info/personalData 55 | mail = 56 | apikey = 57 | 58 | [微步/weibu] 59 | # 微步社区地址:https://x.threatbook.cn/ 60 | # 微步APIKEY获取地址:https://x.threatbook.cn/v5/myApi 61 | apikey = 62 | 63 | [shodan] 64 | # shodan地址:https://www.shodan.io/ 65 | # shodan APIKEY获取地址:https://account.shodan.io/ 66 | apikey = 67 | 68 | [0zero] 69 | # 0zero地址:https://0.zone/ 70 | # 0zero APIKEY获取地址:https://0.zone/applyParticulars?type=site 71 | apikey = 72 | 73 | [zoomeye] 74 | # zoomeye地址:https://www.zoomeye.org/ 75 | # zoomeye APIKEY获取地址:https://www.zoomeye.org/profile 76 | apikey= 77 | ``` 78 | 3、运行:`python3 inforgation.py`,使用`-i`参数指定要查询的单个IP;使用-f指定批量查询的文件,IP存放在文件中,一行一个;使用`-o`参数指定输出的文件名,如: 79 | `python3 inforgation.py -i 129.211.129.109 -o gogole`,运行结果如下: 80 | 81 | ```shell 82 | _ __ _ _ 83 | (_)_ __ / _| ___ _ __ __ _ __ _| |_(_) ___ _ __ 84 | | | '_ \| |_ / _ \| '__/ _` |/ _` | __| |/ _ \| '_ \ 85 | | | | | | _| (_) | | | (_| | (_| | |_| | (_) | | | | 86 | |_|_| |_|_| \___/|_| \__, |\__,_|\__|_|\___/|_| |_| 87 | Powered by Wrong-pixel |___/ version 1.1 88 | 89 | ───────────────────────── [INFO] 正在鹰图上查询 129.211.129.109 的信息... ────────────────────────── 90 | [INFO] 消耗积分:0 91 | [INFO] 今日剩余积分:30622 92 | ┏━━━━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━┓ 93 | ┃ url ┃ 端口 ┃ 网页标题 ┃ 域名 ┃ 状态码 ┃ 操作系统 ┃ 归属地 ┃ 运营商 ┃ 94 | ┡━━━━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━┩ 95 | │ http://playaga… │ 80 │ 温馨提示 │ playagame.xyz │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 96 | │ http://www.44i… │ 80 │ 温馨提示 │ www.44iv.com │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 97 | │ http://www.623… │ 80 │ 温馨提示 │ www.62335.com │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 98 | │ http://li64.com │ 80 │ 温馨提示 │ li64.com │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 99 | │ https://playag… │ 443 │ N/A │ playagame.xyz │ 0 │ N/A │ 中国上海市上海… │ 腾讯 │ 100 | │ https://li64.c… │ 443 │ N/A │ li64.com │ 0 │ N/A │ 中国上海市上海… │ 腾讯 │ 101 | │ https://www.44… │ 443 │ N/A │ www.44iv.com │ 0 │ N/A │ 中国上海市上海… │ 腾讯 │ 102 | │ https://www.62… │ 443 │ N/A │ www.62335.com │ 0 │ N/A │ 中国上海市上海… │ 腾讯 │ 103 | │ http://pay.kgm… │ 80 │ 温馨提示 │ pay.kgml.cc │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 104 | │ http://by.kgml… │ 80 │ 温馨提示 │ by.kgml.cc │ 200 │ N/A │ 中国上海市上海… │ 腾讯 │ 105 | └─────────────────┴──────┴─────────┴───────────────┴────────┴──────────┴──────────────┴────────┘ 106 | ───────────────────────── [INFO] 正在FOFA上查询 129.211.129.109 的信息... ────────────────────────── 107 | ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━┓ 108 | ┃ host ┃ 标题 ┃ 地理位置 ┃ 服务名 ┃ 协议 ┃ 109 | ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━┩ 110 | │ 129.211.129.109:80 │ │ China │ nginx/1.14.0 │ http │ 111 | │ https://129.211.129.109:443 │ │ China │ nginx/1.14.0 │ https │ 112 | │ 129.211.129.109 │ 301 Moved Permanently │ China │ nginx/1.14.0 │ http │ 113 | │ www.4399.net │ 301 Moved Permanently │ China │ nginx/1.14.0 │ http │ 114 | │ 4399.com │ 301 Moved Permanently │ China │ nginx/1.14.0 │ http │ 115 | │ https://4399.com │ 301 Moved Permanently │ China │ nginx/1.14.0 │ https │ 116 | │ https://129.211.129.109 │ 301 Moved Permanently │ China │ nginx/1.14.0 │ https │ 117 | │ wwww.4399.com │ 301 Moved Permanently │ China │ nginx/1.14.0 │ http │ 118 | │ https://wwww.4399.com │ 301 Moved Permanently │ China │ nginx/1.14.0 │ https │ 119 | │ 129.211.129.109:80 │ │ China │ │ http │ 120 | │ https://129.211.129.109:443 │ │ China │ │ https │ 121 | │ ww.4399.com │ 301 Moved Permanently │ China │ nginx/1.14.0 │ http │ 122 | └─────────────────────────────┴───────────────────────┴──────────┴──────────────┴───────┘ 123 | ─────────────────────── [INFO] 正在微步上查询 129.211.129.109 的威胁情报... ──────────────────────── 124 | ┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━┓ 125 | ┃ 威胁等级 ┃ IP类型判断 ┃ 威胁类型 ┃ 运营商 ┃ 地理位置 ┃ 场景 ┃ 情报可信度 ┃ 126 | ┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━┩ 127 | │ 无威胁 │ 白名单,IDC服务器 │ 腾讯云主机 │ 腾讯 │ 中国 上海市上海市 │ 数据中心 │ 高 │ 128 | └──────────┴──────────────────┴────────────┴────────┴───────────────────┴──────────┴────────────┘ 129 | ──────────────────────── [INFO] 正在shodan上查询 129.211.129.109 的信息... ───────────────────────── 130 | ┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ 131 | ┃ IP ┃ 开放的端口 ┃ 域名 ┃ 子域名 ┃ 运营商 ┃ 132 | ┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ 133 | │ 129.211.129.109 │ 80、443 │ 4399.com、 │ 4399.com │ Shenzhen Tencent Computer Systems Company │ 134 | │ │ │ │ │ Limited │ 135 | └─────────────────┴────────────┴────────────┴──────────┴───────────────────────────────────────────┘ 136 | ─────────────────────── [INFO] 正在0zero上查询 129.211.129.109 的威胁情报... ─────────────────────── 137 | [WARNING] 没有在0zero平台查询到相关信息! 138 | 139 | ──────────────────────── [INFO] 正在zoomeye上查询 129.211.129.109 的信息... ──────────────────────── 140 | ┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ 141 | ┃ IP ┃ 应用 ┃ 端口 ┃ 服务 ┃ 服务标题 ┃ 142 | ┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ 143 | │ 129.211.129.109 │ nginx │ 443 │ https │ 301 Moved Permanently │ 144 | │ 129.211.129.109 │ nginx │ 80 │ http │ \xd0\xa1\xd3\xce\xcf\xb7,4399\xd0\xa1\xd3\x… │ 145 | │ │ │ │ │ - www.4399.com │ 146 | │ 129.211.129.109 │ nginx │ 10443 │ http │ │ 147 | │ 129.211.129.109 │ │ 3389 │ ms-wbt-server │ │ 148 | │ 129.211.129.109 │ OpenSSH │ 22 │ ssh │ │ 149 | └─────────────────┴─────────┴───────┴───────────────┴──────────────────────────────────────────────┘ 150 | ──────────────────────────────────────── [INFO]域名结果汇总 ──────────────────────────────────────── 151 | ┏━━━━━━━━━━━━━━━┓ 152 | ┃ IP绑定的域名 ┃ 153 | ┡━━━━━━━━━━━━━━━┩ 154 | │ www.4399.net │ 155 | │ wwww.4399.com │ 156 | │ www.44iv.com │ 157 | │ playagame.xyz │ 158 | │ www.62335.com │ 159 | │ pay.kgml.cc │ 160 | │ by.kgml.cc │ 161 | │ ww.4399.com │ 162 | │ li64.com │ 163 | │ 4399.com │ 164 | └───────────────┘ 165 | ``` 166 | 167 | 168 | 169 | 查询完毕后会在output目录中生成google.html的查询报告,如果使用`-o`指定文件名,则会在output目录下以IP跟时间为名生成报告,报告如下: 170 | 171 | ![image-20220529094733097](README.assets/image-20220529094733097.png) 172 | 173 | # TODO 174 | - [x] 批量查询 175 | - [x] 算法优化 176 | - [x] 情报聚合后的去重 177 | - [ ] 域名反查、whois查询 178 | - [x] 添加更多平台查询 179 | 180 | # 最后,欢迎各位师傅提issue!万分感谢🙏 181 | -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | [鹰图/hunter] 2 | # 鹰图地址:https://hunter.qianxin.com/ 3 | # 鹰图APIKEY获取地址:https://hunter.qianxin.com/home/userInfo 4 | # 鹰图用户名为注册手机号或邮箱 5 | username= 6 | apikey= 7 | 8 | [fofa] 9 | # fofa地址:https://fofa.info/ 10 | # fofa APIKEY获取地址:https://fofa.info/personalData 11 | mail= 12 | apikey= 13 | 14 | [微步/weibu] 15 | # 微步社区地址:https://x.threatbook.cn/ 16 | # 微步APIKEY获取地址:https://x.threatbook.cn/v5/myApi 17 | apikey= 18 | 19 | [shodan] 20 | # shodan地址:https://www.shodan.io/ 21 | # shodan APIKEY获取地址:https://account.shodan.io/ 22 | apikey= 23 | 24 | [0zero] 25 | # 0zero地址:https://0.zone/ 26 | # 0zero APIKEY获取地址:https://0.zone/applyParticulars?type=site 27 | apikey= 28 | 29 | [zoomeye] 30 | # zoomeye地址:https://www.zoomeye.org/ 31 | # zoomeye APIKEY获取地址:https://www.zoomeye.org/profile 32 | apikey= -------------------------------------------------------------------------------- /inforgation.py: -------------------------------------------------------------------------------- 1 | import modules 2 | from modules import hunter 3 | from modules import fofa 4 | from modules import threatbook 5 | from modules import shodan 6 | from modules import _0zero 7 | from modules import zoomeye 8 | from modules import domain 9 | from modules import output 10 | 11 | from rich.traceback import install 12 | from rich.table import Table 13 | from rich.progress import track, Progress 14 | from configparser import ConfigParser 15 | 16 | import argparse 17 | import time 18 | import sys 19 | 20 | cfg = ConfigParser() 21 | progress = Progress() 22 | install(show_locals=True) 23 | 24 | 25 | # 忘了为啥把打印table的过程抽象成方法了。。。但是不影响用就不改了 26 | def print_table(table: Table): 27 | progress.console.print(table if table is not None else "") 28 | 29 | 30 | # 为了实现批量查询,需要将查询单个IP的过程抽象为方法,之后只要将需要批量查询的ip转化为列表,对列表中的每个元素调用方法就可以了 31 | def get_single_ip(ip, file_name): 32 | progress.console.rule("[gray][INFO] 正在查询 %s 的情报" % ip) 33 | # 预先创建table对象,免得奇奇怪怪的报错 34 | hunter_table = fofa_table = threatbook_table = shodan_table = _0zero_table = zoomeye_table = None 35 | config_file = 'config.ini' 36 | cfg.read(config_file, encoding='utf-8') 37 | # 鹰图查询结果 38 | if cfg['鹰图/hunter']['username'] == "" or cfg['鹰图/hunter']['apikey'] == "": 39 | progress.console.print("[red][WRONG] 鹰图配置信息缺失!本次不予查询!") 40 | else: 41 | hunter = modules.hunter.hunter(cfg['鹰图/hunter']['username'], cfg['鹰图/hunter']['apikey']) 42 | hunter_table = hunter.get_result(ip) 43 | print_table(hunter_table) 44 | 45 | # fofa查询结果 46 | if cfg['fofa']['mail'] == "" or cfg['fofa']['apikey'] == "": 47 | progress.console.print("[red][WRONG] fofa配置信息缺失!本次不予查询!") 48 | else: 49 | fofa = modules.fofa.fofa(cfg['fofa']['mail'], cfg['fofa']['apikey']) 50 | fofa_table = fofa.get_result(ip) 51 | print_table(fofa_table) 52 | 53 | # 微步查询结果 54 | if cfg['微步/weibu']['apikey'] == "": 55 | progress.console.print("[red][WRONG] 微步配置信息缺失!本次不予查询!") 56 | else: 57 | threatbook = modules.threatbook.threatbook(cfg['微步/weibu']['apikey']) 58 | threatbook_table = threatbook.get_result(ip) 59 | print_table(threatbook_table) 60 | 61 | # shodan查询结果 62 | if cfg['shodan']['apikey'] == "": 63 | progress.console.print("[red][WRONG] shodan配置信息缺失!本次不予查询!") 64 | else: 65 | shodan = modules.shodan.shodan(cfg['shodan']['apikey']) 66 | shodan_table = shodan.get_result(ip) 67 | print_table(shodan_table) 68 | 69 | # 0zero查询结果 70 | if cfg['0zero']['apikey'] == "": 71 | progress.console.print("[red][WRONG] 0zero配置信息缺失!本次不予查询!") 72 | else: 73 | _0zero = modules._0zero._0zero(cfg['0zero']['apikey']) 74 | _0zero_table = _0zero.get_result(ip) 75 | print_table(_0zero_table) 76 | 77 | # zoomeye查询结果 78 | if cfg['zoomeye']['apikey'] == "": 79 | progress.console.print("[red][WRONG] zoomeye配置信息缺失!本次不予查询!") 80 | else: 81 | zoomeye = modules.zoomeye.zoomeye(cfg['zoomeye']['apikey']) 82 | zoomeye_table = zoomeye.get_result(ip) 83 | print_table(zoomeye_table) 84 | 85 | if file_name == "": 86 | file_name = ip + "-" + time.strftime('%Y-%m-%d-%H:%M:%S') 87 | 88 | table_list = [] 89 | domain_list = [] 90 | if threatbook_table is not None: 91 | table_list.append({"微步": threatbook_table}) 92 | 93 | if hunter_table is not None: 94 | table_list.append({"鹰图": hunter_table}) 95 | domain_list += hunter.get_domain() 96 | 97 | if fofa_table is not None: 98 | table_list.append({"FOFA": fofa_table}) 99 | domain_list += fofa.get_domain() 100 | 101 | if shodan_table is not None: 102 | table_list.append({"shodan": shodan_table}) 103 | domain_list += shodan.get_domain() 104 | 105 | if _0zero_table is not None: 106 | table_list.append({"0zero": _0zero_table}) 107 | 108 | if zoomeye_table is not None: 109 | table_list.append({"zoomeye": zoomeye_table}) 110 | 111 | # 处理域名结果,暂时不准备封装成类了,因为get_domain方法是在每个模块类中定义的,如果需要抽象成类的话需要传入类对象 112 | # 不封白不封,传列表 113 | if domain_list: 114 | domain = modules.domain.domain(list(set(domain_list))) 115 | domain_table = domain.get_result() 116 | if domain_table is not None: 117 | progress.console.print(domain_table) 118 | table_list.append({"域名结果": domain_table}) 119 | 120 | output = modules.output.output(ip, file_name, table_list) 121 | # 调用方法 122 | output.output_html() 123 | progress.console.print("[green][INFO] 信息查询完毕,报告保存为%s/output/%s.html" % (sys.path[0], file_name)) 124 | 125 | 126 | # 为了实现批量查询,需要将单个查询的方法进行封装 127 | 128 | 129 | # 按间距中的绿色按钮以运行脚本。 130 | if __name__ == '__main__': 131 | progress.console.print(r""" 132 | _ __ _ _ 133 | (_)_ __ / _| ___ _ __ __ _ __ _| |_(_) ___ _ __ 134 | | | '_ \| |_ / _ \| '__/ _` |/ _` | __| |/ _ \| '_ \ 135 | | | | | | _| (_) | | | (_| | (_| | |_| | (_) | | | | 136 | |_|_| |_|_| \___/|_| \__, |\__,_|\__|_|\___/|_| |_| 137 | Powered by Wrong-pixel |___/ version 1.1 138 | """) 139 | # 命令行参数解析 140 | parser = argparse.ArgumentParser(description="蓝队信息聚合查询工具") 141 | group = parser.add_mutually_exclusive_group() 142 | group.add_argument('-i', '--ip', dest='ip', help='指定目标 IP') 143 | group.add_argument('-f', '--file', dest='ip_file', help='批量查询,将IP存放在文件中,一行一个') 144 | parser.add_argument('-o', '--output', dest='filename', help='导出报告的名称,默认为.html,存放路径为output目录') 145 | args = parser.parse_args() 146 | # 单个IP的检测 147 | if args.ip: 148 | # 是否指定文件名 149 | filename = "" 150 | if args.filename: 151 | filename = args.filename 152 | # 调用方法实现单个IP的查询 153 | get_single_ip(args.ip, filename) 154 | 155 | # 这个我实在是没想好,是不是要用多线程,输出怎么显示,总之先试着写一写 156 | if args.ip_file: 157 | f = open(args.ip_file, 'r') 158 | # 去重,生成列表 159 | ip_list = list(set(f.read().split('\n'))) 160 | try: 161 | # 去除空内容 162 | ip_list.remove("") 163 | except ValueError: 164 | pass 165 | # 单线程查询,多线程。。后面再做吧 166 | for ip in track(ip_list, description="正在进行批量查询"): 167 | get_single_ip(ip, file_name=ip) 168 | -------------------------------------------------------------------------------- /modules/Template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1447 | 1448 |
1449 |

针对{{ IP }}的情报聚合报告

本报告基于{{ times }}发起的对{{ IP }}的情报查询结果生成

{% for table in tables %}

{% for table_name, table_html in table.items() %}

{{ table_name }}

{{ table_html }}

{% endfor %}

{% endfor %}

 

1450 | 1451 | -------------------------------------------------------------------------------- /modules/_0zero.py: -------------------------------------------------------------------------------- 1 | from rich.table import Table 2 | from rich.progress import Progress 3 | import requests 4 | 5 | progress = Progress() 6 | 7 | 8 | class _0zero: 9 | 10 | def __init__(self, apikey): 11 | self.apikey = apikey 12 | 13 | def get_result(self, ip, timeout=5): 14 | progress.console.rule('[green][INFO] 正在0zero上查询 %s 的威胁情报...' % ip) 15 | self.table = Table() 16 | self.table.add_column("IP", justify="left") 17 | self.table.add_column("端口", justify="left") 18 | self.table.add_column("url", justify="left") 19 | self.table.add_column("网页标题", justify="center") 20 | self.table.add_column("操作系统", justify="center") 21 | self.table.add_column("服务器", justify="center") 22 | self.table.add_column("运营商", justify="center") 23 | self.table.add_column("协议", justify="center") 24 | url = "https://0.zone/api/data/" 25 | query = { 26 | "title": "ip={}".format(ip), 27 | "title_type": "site", 28 | "page": 1, 29 | "pagesize": 10, 30 | "zone_key_id": "{}".format(self.apikey) 31 | } 32 | try: 33 | text = requests.request("POST", url, data=query, timeout=timeout).json() 34 | except BaseException as e: 35 | progress.console.print("[red][WRONG] 查询0zero信息超时,错误信息为%s" % e) 36 | return None 37 | if text['code'] == 1: 38 | progress.console.print("[red][WRONG] 查询出错,错误信息为: %s " % (text['message'])) 39 | return None 40 | if not text['data']: 41 | progress.console.print("[yellow][WARNING] 没有在0zero平台查询到相关信息!") 42 | return None 43 | for item in text['data']: 44 | target_ip = item["ip"] if item["ip"] else "N/A" 45 | target_port = item["port"] if item["port"] else "N/A" 46 | target_url = item["url"] if item["url"] else "N/A" 47 | target_title = item["title"] if item["title"] else "N/A" 48 | target_os = item["os"] if item["os"] else "N/A" 49 | target_component = item["component"] if item["component"] else "N/A" 50 | target_operator = item["operator"] if item["operator"] else "N/A" 51 | target_protocol = item["protocol"] if item["protocol"] else "N/A" 52 | self.table.add_row(target_ip, target_port, target_url, target_title, target_os, target_component, 53 | target_operator, target_protocol) 54 | return self.table 55 | -------------------------------------------------------------------------------- /modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wrong-pixel/inforgation/48858a208a74a1112b83032c8f536b141bc86814/modules/__init__.py -------------------------------------------------------------------------------- /modules/domain.py: -------------------------------------------------------------------------------- 1 | from rich.table import Table 2 | from rich.progress import Progress 3 | 4 | progress = Progress() 5 | 6 | 7 | class domain: 8 | 9 | def __init__(self, domain_list: list): 10 | self.domain_list = domain_list 11 | 12 | def get_result(self): 13 | # 如果不是空的,把多余的"N/A"除掉,实例化时已经对域名列表去重了,这里就不需要再去,但是考虑到列表的remove方法,得加一个try 14 | # 先试着把N/A去掉,不确定是不是列表里面只有一个N/A 15 | try: 16 | self.domain_list.remove("N/A") 17 | # 列表里面没有N/A这个元素,会报错,处理一下 18 | except ValueError: 19 | pass 20 | # 实例化的列表=可能是空的,表示没有域名信息,直接返回None,主函数就不会将空table传入output列表 21 | if not self.domain_list: 22 | return None 23 | # 打个横幅 24 | progress.console.rule('[green][INFO]域名结果汇总') 25 | # 实例化一个空table 26 | table = Table() 27 | # 列标题 28 | table.add_column("IP绑定的域名") 29 | for item in self.domain_list: 30 | # 添加列元素 31 | table.add_row(item) 32 | return table -------------------------------------------------------------------------------- /modules/fofa.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from base64 import b64encode 3 | from rich.table import Table 4 | from rich.progress import Progress 5 | import re 6 | 7 | progress = Progress() 8 | 9 | 10 | class fofa: 11 | 12 | def __init__(self, mail, apikey): 13 | self.mail = mail 14 | self.apikey = apikey 15 | 16 | def get_result(self, ip, timeout=5): 17 | self.table = Table() 18 | progress.console.rule('[green][INFO] 正在FOFA上查询 %s 的信息...' % ip) 19 | # base64编码查询语句 20 | words = b64encode(bytes('ip="{}"'.format(str(ip)).encode())).decode() 21 | # 拼接url 22 | self.url = 'https://fofa.info/api/v1/search/all?email={}&key={}&qbase64={}&fields=host,title,country_name,' \ 23 | 'province,city,server,protocol,banner,isp'.format( 24 | self.mail, self.apikey, words) 25 | try: 26 | self.data = requests.get(self.url, timeout=timeout).json() 27 | except requests.ReadTimeout: 28 | progress.console.print("[red][WRONG] 查询FOFA信息超时!") 29 | return None 30 | except BaseException: 31 | progress.console.print('[red][WRONG] 查询FOFA出错!(原因是在FOFA查询时,个别IP使用语法ip="*.*.*.*"会报错)') 32 | # api请求错误 33 | if self.data['error']: 34 | progress.console.print("[red][WRONG] FOFA查询 %s 失败!" % ip) 35 | return None 36 | if self.data['size'] == 0: 37 | progress.console.print("[yellow][WARNING] 没有在FOFA上查询到 %s 的相关信息!" % ip) 38 | return None 39 | self.table.add_column('host', justify="left") 40 | self.table.add_column('标题', justify="left") 41 | self.table.add_column('地理位置', justify="left") 42 | self.table.add_column('服务名', justify="left") 43 | self.table.add_column('协议', justify="left") 44 | for item in self.data['results']: 45 | self.table.add_row(item[0], item[1], item[2] + " " + item[3] + " " + item[4], item[5], item[6]) 46 | return self.table 47 | 48 | def get_domain(self): 49 | try: 50 | content = re.compile(r'[a-zA-Z]') 51 | domain_list = [] 52 | for item in self.table.columns[0]._cells: 53 | item = item.replace("https://", "").replace("http://", "") 54 | if re.match(content, item): 55 | domain_list.append(item) 56 | return domain_list 57 | except BaseException as e: 58 | return [] 59 | -------------------------------------------------------------------------------- /modules/hunter.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from base64 import b64encode 3 | from rich.table import Table 4 | from rich.progress import Progress 5 | 6 | progress = Progress() 7 | 8 | 9 | class hunter: 10 | 11 | def __init__(self, username, apikey): 12 | self.username = username 13 | self.apikey = apikey 14 | 15 | def get_result(self, ip, timeout=5): 16 | self.table = Table() 17 | progress.console.rule('[green][INFO] 正在鹰图上查询 %s 的信息...' % ip) 18 | # base64加密查询语句 19 | words = b64encode(bytes('ip="{}"'.format(ip).encode())).decode() 20 | # 拼接url 21 | self.url = "https://hunter.qianxin.com/openApi/search?username={}&api-key={}&search={}&page=1&page_size=10&is_web=1".format( 22 | self.username, self.apikey, words) 23 | # 解析json数据 24 | try: 25 | # 超时处理,默认为5秒 26 | self.data = requests.get(self.url, timeout=timeout).json() 27 | except BaseException as e: 28 | progress.console.print("[red][WRONG] 查询鹰图信息超时") 29 | return None 30 | if self.data['code'] != 200: 31 | progress.console.print("[red][WRONG] 查询鹰图信息失败!%s " % (self.data['message'])) 32 | return None 33 | # 消耗积分 34 | progress.console.print("[green][INFO] "+self.data['data']['consume_quota']) 35 | # 剩余积分 36 | progress.console.print("[green][INFO] "+self.data['data']['rest_quota']) 37 | # 创建输出表 38 | self.table.add_column('url', justify="left") 39 | self.table.add_column('端口', justify="left") 40 | self.table.add_column('网页标题', justify="left") 41 | self.table.add_column('域名', justify="left") 42 | self.table.add_column('状态码', justify="center") 43 | self.table.add_column('操作系统', justify="center") 44 | self.table.add_column('归属地', justify="center") 45 | self.table.add_column('运营商', justify="center") 46 | try: 47 | for data in self.data['data']['arr']: 48 | # 获取url 49 | target_url = data['url'] 50 | # 获取端口 51 | target_port = str(data['port']) 52 | # 获取网页标题 53 | target_web_title = str(data['web_title']) if data['web_title'] else "N/A" 54 | # 获取域名 55 | target_domain = data['domain'] if data['domain'] else "N/A" 56 | # 获取状态码 57 | target_status_code = str(data['status_code']) 58 | # 获取操作系统 59 | target_os = data['os'] if data['os'] else "N/A" 60 | # 获取地理位置 61 | target_localtion = data['country'] + data['province'] + data['city'] 62 | # 获取运营商 63 | target_isp = data['isp'] 64 | # 添加到表格中 65 | self.table.add_row(target_url, target_port, target_web_title, target_domain, target_status_code, 66 | target_os, target_localtion, target_isp) 67 | return self.table 68 | except TypeError: 69 | # 可能是没查到结果,也可能是查询速度过快 70 | progress.console.print('[yellow][WARNING] 没有在鹰图上查询到 %s 的相关信息' % ip) 71 | return None 72 | # 返回table对象 73 | 74 | def get_domain(self): 75 | try: 76 | return self.table.columns[3]._cells 77 | except BaseException as e: 78 | return [] -------------------------------------------------------------------------------- /modules/output.py: -------------------------------------------------------------------------------- 1 | import jinja2 2 | import pandas as pd 3 | import time 4 | 5 | import rich.table 6 | 7 | 8 | class output: 9 | 10 | def __init__(self, ip, file_name, table_list): 11 | # 报告中的IP字段 12 | self.ip = ip 13 | # 报告名 14 | self.file_name = file_name 15 | # 报告中用来生成表格的table列表,单个元素为字典,字典键为平台名,值为rich.table.Table 16 | self.table_list = table_list 17 | 18 | def output_html(self): 19 | # 创建jinjia2渲染模版 20 | env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath='')) 21 | template = env.get_template('./modules/Template.html') 22 | 23 | # 报告中的时间 24 | check_time = time.strftime('%Y-%m-%d-%H:%M:%S') 25 | # 创建一个空列表存放最终传给模版渲染的表格内容 26 | tables = [] 27 | # 首先遍历传入的列表 28 | for item in self.table_list: 29 | # 列表中的单个元素为字典类型,k表示取平台名,v表示取table对象 30 | for k, v in item.items(): 31 | # 将tables对象转化为html语言后重新生成一个字典并放入tables列表 32 | tables.append({k: self.get_html(v)}) 33 | html = template.render(times=check_time, tables=tables, IP=self.ip) 34 | with open("./output/{}.html".format(self.file_name), "w", encoding='utf-8') as f: 35 | f.write(html) 36 | f.close() 37 | 38 | # 此方法将table对象转化为html语言 39 | def get_html(self, table: rich.table.Table): 40 | # 为什么是字典,因为rich.table.Table的取值是按列来去的,分为列名(header属性)以及属性值列表(_cells属性),获取这两个内容才能通过pandas生成表格 41 | table_data = {} 42 | # 按列,转化为字典 43 | for item in table.columns: 44 | table_data.update({item.header: item._cells}) 45 | # pandas生成html语言,返回,注意每次调用只返回一个table的html语言, 46 | # 在上面的output方法中传入模版的是需要一个列表,列表的单个元素是字典,字典键为表格名(即平台名),字典值为对应表格的html代码 47 | return pd.DataFrame(table_data, ).to_html(justify="left", index=False, na_rep="N/A") 48 | -------------------------------------------------------------------------------- /modules/shodan.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from rich.table import Table 3 | from rich.progress import Progress 4 | 5 | progress = Progress() 6 | 7 | 8 | class shodan: 9 | 10 | def __init__(self, apikey): 11 | self.apikey = apikey 12 | 13 | def get_result(self, ip, timeout=5): 14 | self.table = Table() 15 | progress.console.rule('[green][INFO] 正在shodan上查询 %s 的信息...' % ip) 16 | self.url = "https://api.shodan.io/shodan/host/{}?key={}".format(ip, self.apikey) 17 | try: 18 | self.data = requests.get(self.url, timeout=timeout).json() 19 | except BaseException as e: 20 | progress.console.print("[red][WRONG] shodan查询失败!IP格式错误或请求超时! 错误信息为: %s " % e) 21 | return None 22 | 23 | if 'error' in self.data: 24 | progress.console.print('[yellow][WARNING] 没有在shodan上查询到 %s 的相关信息' % ip) 25 | return None 26 | else: 27 | try: 28 | target_ip = self.data['ip_str'] 29 | except TypeError: 30 | target_ip = "N/A" 31 | 32 | try: 33 | target_port = "" 34 | for item in self.data['ports']: 35 | target_port += str(item) + "、" 36 | except BaseException as e: 37 | progress.console.log(e) 38 | target_port = "" 39 | 40 | try: 41 | target_hostname = "" 42 | for item in self.data['hostnames']: 43 | target_hostname += item + "、" 44 | except TypeError: 45 | target_hostname = "" 46 | 47 | try: 48 | target_domain = "" 49 | for item in self.data['domains']: 50 | target_domain += item + "、" 51 | except TypeError: 52 | target_domain = "" 53 | 54 | try: 55 | target_isp = self.data['isp'] 56 | except TypeError: 57 | target_isp = "N/A" 58 | 59 | self.table.add_column("IP", justify="center") 60 | self.table.add_column("开放的端口", justify="left") 61 | self.table.add_column("域名", justify="left") 62 | self.table.add_column("子域名", justify="left") 63 | self.table.add_column("运营商", justify="left") 64 | 65 | self.table.add_row(target_ip, target_port[:-1], target_domain, target_hostname[:-1], target_isp) 66 | 67 | return self.table 68 | 69 | def get_domain(self): 70 | try: 71 | return self.table.columns[3]._cells[0].split("、") 72 | except BaseException: 73 | return [] -------------------------------------------------------------------------------- /modules/threatbook.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from rich.table import Table 3 | from rich.progress import Progress 4 | 5 | progress = Progress() 6 | 7 | 8 | class threatbook: 9 | def __init__(self, apikey): 10 | self.apikey = apikey 11 | 12 | def get_result(self, ip, timeout=5): 13 | self.table = Table() 14 | progress.console.rule('[green][INFO] 正在微步上查询 %s 的威胁情报...' % ip) 15 | self.url = "https://api.threatbook.cn/v3/scene/ip_reputation" 16 | query = { 17 | "apikey": self.apikey, 18 | "resource": ip, 19 | "lang": "zh" 20 | } 21 | try: 22 | self.data = requests.request("GET", self.url, params=query, timeout=timeout).json() 23 | except requests.ReadTimeout: 24 | progress.console.print("[red][WRONG] 查询微步信息超时") 25 | return None 26 | if self.data['response_code']: 27 | progress.console.print( 28 | "[red][WRONG]微步查询失败!错误码:%s ,错误信息: %s " % (self.data['response_code'], self.data['verbose_msg'])) 29 | return None 30 | self.data = self.data['data'][ip] 31 | self.table.add_column("威胁等级", justify="center") 32 | self.table.add_column("IP类型判断", justify="center") 33 | self.table.add_column("威胁类型", justify="center") 34 | self.table.add_column("运营商", justify="center") 35 | self.table.add_column("地理位置", justify="center") 36 | self.table.add_column("场景", justify="center") 37 | self.table.add_column("情报可信度", justify="center") 38 | target_severity = self.data['severity'] 39 | target_judgments = "" 40 | for item in self.data['judgments']: 41 | target_judgments += item + "," 42 | target_tags = "" 43 | for item in self.data['tags_classes']: 44 | for tag in item['tags']: 45 | target_tags += tag 46 | target_carrier = self.data['basic']['carrier'] 47 | target_location = self.data['basic']['location']['country'] + " " + self.data['basic']['location']['province'] + self.data['basic']['location']['city'] 48 | target_scene = self.data['scene'] 49 | target_confidence_level = self.data['confidence_level'] 50 | self.table.add_row(target_severity, target_judgments[:-1], target_tags, target_carrier, target_location, 51 | target_scene, target_confidence_level) 52 | return self.table 53 | 54 | def get_domain(self): 55 | return self.table 56 | -------------------------------------------------------------------------------- /modules/zoomeye.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from rich.progress import Progress 3 | from rich.table import Table 4 | 5 | progress = Progress() 6 | 7 | 8 | class zoomeye: 9 | 10 | def __init__(self, apikey): 11 | self.apikey = apikey 12 | 13 | def get_result(self, ip, timeout=10): 14 | self.table = Table() 15 | progress.console.rule('[green][INFO] 正在zoomeye上查询 %s 的信息...' % ip) 16 | url = "https://api.zoomeye.org/host/search?query=%s" % ip 17 | headers = { 18 | "API-KEY": self.apikey 19 | } 20 | try: 21 | data = requests.request("GET", url=url, headers=headers, timeout=timeout).json() 22 | except BaseException as e: 23 | progress.console.print("[red][WRONG] 查询zoomeye信息超时!") 24 | return None 25 | if data['total'] != 0: 26 | self.table.add_column("IP", justify="left") 27 | self.table.add_column("应用", justify="left") 28 | self.table.add_column("端口", justify="left") 29 | self.table.add_column("服务", justify="left") 30 | self.table.add_column("服务标题", justify="left") 31 | for item in data['matches']: 32 | target_ip = item['ip'] 33 | target_hostname = item['portinfo']['app'] if item['portinfo']['app'] else "" 34 | target_port = str(item['portinfo']['port']) if item['portinfo']['port'] else "" 35 | target_service = item['portinfo']['service'] if item['portinfo']['service'] else "" 36 | target_title = item['portinfo']['title'][0] if item['portinfo']['title'] is not None else "" 37 | self.table.add_row(target_ip, target_hostname, target_port, target_service, target_title) 38 | return self.table 39 | else: 40 | progress.console.print('[yellow][WARNING] 没有在zoomeye上查询到 %s 的相关信息' % ip) 41 | return None 42 | -------------------------------------------------------------------------------- /output/google.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1452 | 1453 |
1454 |

针对114.114.114.114的情报聚合报告

本报告基于2022-05-29-08:43:44发起的对114.114.114.114的情报查询结果生成

微步

1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 |
威胁等级IP类型判断威胁类型运营商地理位置场景情报可信度
无威胁白名单,IDC服务器美国Cogent通信公司中国Anycast

FOFA

1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | 1595 | 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | 1688 | 1689 | 1690 | 1691 | 1692 | 1693 | 1694 | 1695 | 1696 | 1697 | 1698 | 1699 |
host标题地理位置服务名协议
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
wiki.ministep.cnministepChinanginx/1.16.1http
114.114.114.114:53Chinadns
baipeng66.funChinahttp
114.114.114.114:53Chinadns
114.114.114.114:53Chinadns
illucidhome.comJiangyi Lighting Co. LTD – Mirror lampChinaApachehttp

shodan

1700 | 1701 | 1702 | 1703 | 1704 | 1705 | 1706 | 1707 | 1708 | 1709 | 1710 | 1711 | 1712 | 1713 | 1714 | 1715 | 1716 | 1717 | 1718 |
IP开放的端口域名子域名运营商
114.114.114.11453114dns.com\npublic1.114dns.comCogent Communications

0zero

1719 | 1720 | 1721 | 1722 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | 1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 |
IP端口url网页标题操作系统服务器运营商协议
114.114.114.11453N/AN/Aunknownunknown114DNSN/A

 

1744 | 1745 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.27.1 2 | rich~=12.4.4 3 | Jinja2~=3.0.3 4 | pandas~=1.4.2 --------------------------------------------------------------------------------