Files
suanli-juzhen/04_暴力破解/scripts/scan_to_brute.py

208 lines
6.7 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
扫描结果 暴力破解 桥接工具
================================
01_扫描模块 的输出结果中提取 SSH 开放端口的 IP
生成暴力破解器可用的目标列表
支持的输入格式
- 01_扫描模块 mumayi_full_scan.py 输出的 JSON
- nmap XML 输出
- masscan JSON 输出
- 纯文本 IP 列表
用法:
# 从扫描JSON导入
python3 scan_to_brute.py --input ../01_扫描模块/results/scan_results.json --output targets.txt
# 从nmap XML导入
python3 scan_to_brute.py --input scan.xml --format nmap --output targets.txt
# 从CSV导入指定IP列和端口列
python3 scan_to_brute.py --input hosts.csv --format csv --ip-col ip --port-col port --output targets.txt
# 直接对接暴力破解
python3 scan_to_brute.py --input scan.json --pipe | python3 ssh_bruter.py --targets /dev/stdin
"""
import json
import csv
import sys
import argparse
import xml.etree.ElementTree as ET
from pathlib import Path
# SSH 相关端口
SSH_PORTS = {22, 2222, 22222, 10022, 20022, 222, 2022}
def extract_from_json(filepath):
"""从JSON扫描结果提取SSH目标"""
targets = []
with open(filepath, "r", encoding="utf-8") as f:
data = json.load(f)
if isinstance(data, list):
for item in data:
ip = item.get("ip") or item.get("host") or item.get("address")
if not ip:
continue
# 查找SSH端口
open_ports = item.get("open_ports") or item.get("ports") or []
ssh_ports = []
for p in open_ports:
if isinstance(p, dict):
port_num = p.get("port", 0)
service = p.get("service", "").lower()
if port_num in SSH_PORTS or "ssh" in service:
ssh_ports.append(port_num)
elif isinstance(p, int):
if p in SSH_PORTS:
ssh_ports.append(p)
if ssh_ports:
for port in ssh_ports:
targets.append(f"{ip}:{port}")
# 如果没发现SSH端口但有该IP默认加22
elif item.get("ssh") or item.get("has_ssh"):
targets.append(f"{ip}:22")
elif isinstance(data, dict):
# 键值对格式 {ip: {ports: [...]}}
for ip, info in data.items():
if isinstance(info, dict):
ports = info.get("ports") or info.get("open_ports") or []
for p in ports:
port_num = p if isinstance(p, int) else p.get("port", 0)
if port_num in SSH_PORTS:
targets.append(f"{ip}:{port_num}")
return targets
def extract_from_nmap_xml(filepath):
"""从nmap XML输出提取SSH目标"""
targets = []
tree = ET.parse(filepath)
root = tree.getroot()
for host in root.findall(".//host"):
addr_elem = host.find("address[@addrtype='ipv4']")
if addr_elem is None:
continue
ip = addr_elem.get("addr")
for port in host.findall(".//port"):
portid = int(port.get("portid", 0))
state = port.find("state")
service = port.find("service")
if state is not None and state.get("state") == "open":
svc_name = service.get("name", "") if service is not None else ""
if portid in SSH_PORTS or "ssh" in svc_name.lower():
targets.append(f"{ip}:{portid}")
return targets
def extract_from_masscan(filepath):
"""从masscan JSON输出提取SSH目标"""
targets = []
with open(filepath, "r") as f:
# masscan JSON格式可能不完全标准
content = f.read().strip()
if content.endswith(","):
content = content[:-1]
if not content.startswith("["):
content = "[" + content + "]"
data = json.loads(content)
for item in data:
ip = item.get("ip")
ports = item.get("ports", [])
for p in ports:
port_num = p.get("port", 0)
if port_num in SSH_PORTS:
targets.append(f"{ip}:{port_num}")
return targets
def extract_from_csv(filepath, ip_col="ip", port_col="port"):
"""从CSV提取SSH目标"""
targets = []
with open(filepath, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
ip = row.get(ip_col, "").strip()
port = row.get(port_col, "22").strip()
if ip:
port_num = int(port) if port.isdigit() else 22
if port_num in SSH_PORTS:
targets.append(f"{ip}:{port_num}")
return targets
def extract_from_text(filepath):
"""从纯文本提取每行一个IP或IP:port"""
targets = []
with open(filepath, "r") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
if ":" in line:
targets.append(line)
else:
targets.append(f"{line}:22")
return targets
def main():
parser = argparse.ArgumentParser(description="扫描结果转暴力破解目标列表")
parser.add_argument("--input", "-i", required=True, help="输入文件路径")
parser.add_argument("--format", "-f", choices=["json", "nmap", "masscan", "csv", "text"],
default="json", help="输入格式 (默认 json)")
parser.add_argument("--output", "-o", help="输出文件路径")
parser.add_argument("--ip-col", default="ip", help="CSV中IP列名")
parser.add_argument("--port-col", default="port", help="CSV中端口列名")
parser.add_argument("--pipe", action="store_true", help="输出到stdout管道模式")
args = parser.parse_args()
# 提取目标
fmt = args.format
if fmt == "json":
targets = extract_from_json(args.input)
elif fmt == "nmap":
targets = extract_from_nmap_xml(args.input)
elif fmt == "masscan":
targets = extract_from_masscan(args.input)
elif fmt == "csv":
targets = extract_from_csv(args.input, args.ip_col, args.port_col)
elif fmt == "text":
targets = extract_from_text(args.input)
else:
targets = extract_from_json(args.input)
# 去重
targets = list(dict.fromkeys(targets))
print(f"[*] 提取到 {len(targets)} 个SSH目标", file=sys.stderr)
# 输出
if args.pipe or not args.output:
for t in targets:
print(t)
else:
with open(args.output, "w") as f:
for t in targets:
f.write(t + "\n")
print(f"[+] 已保存到 {args.output}", file=sys.stderr)
if __name__ == "__main__":
main()