# 导入必要的模块 import os # 用于操作系统路径 import sys # 用于操作系统相关的功能 sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../') # 将父级目录添加到模块搜索路径中 import time # 用于时间操作,例如延时 # 从client.portscan模块导入ShodanScan和NmapScan类,用于进行端口扫描 from client.portscan.ShodanScan import Scan from client.portscan.NmapScan import Nmap_Portscan # 从client.database模块导入数据库会话和数据表模型 from client.database import session, SrcAssets, SrcPorts # 定义PortScan类,用于执行端口扫描操作 class PortScan: def __init__(self, ip): # 初始化方法,接收IP地址 self.ip = ip def run(self): # 执行端口扫描 # 1. 使用Shodan扫描IP的端口和漏洞 port_list, vulns_list = Scan(ip=self.ip) # 2. 使用Nmap扫描获取更详细的端口信息 port_dict = Nmap_Portscan(ip=self.ip, port_info_list=port_list) # 返回端口扫描结果和漏洞信息 return port_dict, vulns_list # 定义读取资产数据的函数 def ReadAssets(): '''读取资产数据''' # 查询数据库,获取未进行端口扫描的资产(资产表中asset_port_flag为False) assets_sql = session.query(SrcAssets).filter(SrcAssets.asset_port_flag == False).first() # 提交数据库事务 session.commit() if assets_sql: # 获取该资产的IP地址 ip = assets_sql.asset_ip # 查询所有具有相同IP地址的资产 assets_sql1 = session.query(SrcAssets).filter(SrcAssets.asset_ip == ip).all() # 遍历所有相同IP的资产,将其端口扫描状态更新为True for sql in assets_sql1: sql.asset_port_flag = True # 修改资产的端口扫描状态为True session.add(sql) # 将修改的资产添加到会话中 try: # 提交事务,将修改保存到数据库 session.commit() except Exception as error: # 如果提交失败,打印异常信息并回滚事务 print(f'[-]端口扫描-修改IP扫描状态异常{error}') session.rollback() # 返回读取到的资产数据 return assets_sql # 定义将扫描结果写入数据库的函数 def WritePosts(port_dict, assets_sql): '''端口扫描入库''' # 遍历扫描到的端口信息 for info in port_dict: # 构造要插入到数据库的端口数据 port_sql = SrcPorts( port_name=assets_sql.asset_name, # 资产名称 port_host=assets_sql.asset_host, # 资产主机 port_ip=assets_sql.asset_ip, # 资产IP地址 port_port=port_dict[info]['port'], # 端口号 port_service=port_dict[info]['name'], # 服务名称 port_product=port_dict[info]['product'], # 产品名称 port_version=port_dict[info]['version'] # 产品版本 ) # 将端口信息添加到数据库会话中 session.add(port_sql) try: # 提交事务,将端口信息保存到数据库 session.commit() except Exception as error: # 如果提交失败,回滚事务并打印错误信息 session.rollback() print(f'[-]端口入库异常{error}') # 打印扫描结果已入库完成的提示 print(f'[+]端口[{assets_sql.asset_ip}]入库完成') # 主函数,启动端口扫描和入库操作 def main(): print('[+]端口扫描启动') while True: # 读取资产数据 assets_sql = ReadAssets() # 如果没有可处理的资产,等待30秒后继续尝试 if not assets_sql: time.sleep(30) else: # 创建PortScan实例,传入要扫描的IP地址 portscan = PortScan(assets_sql.asset_ip) # 运行端口扫描,获取端口信息和漏洞信息 port_dict, vulns_list = portscan.run() # 如果扫描结果不为空,写入数据库 if port_dict: WritePosts(port_dict, assets_sql) # 如果该脚本作为主程序执行,启动端口扫描程序 if __name__ == '__main__': main()