imrooting/WatchTower

GitHub: imrooting/WatchTower

WatchTower 是一个将 nmap、nuclei、subfinder 等主流安全工具封装到统一 CLI 的 Python 自动化侦察与 OSINT 框架,支持本地和云端集群两种运行模式。

Stars: 0 | Forks: 0

# 🗼 WatchTower **自动化侦察与 OSINT 框架** WatchTower 是一个模块化 Python 框架,将行业标准的安全工具封装到统一的 CLI 中。运行网络扫描、子域名枚举、SSL 分析、密钥发现、CVE 查询等 —— 所有输出均为结构化、带时间戳、自文档化的格式。 ## 目录 - [工作原理](#how-it-works) - [环境要求](#requirements) - [安装](#installation) - [使用方法](#usage) - [模块](#modules) - [输出结构](#output-structure) - [添加新模块](#adding-a-new-module) - [技巧与提示](#tips--tricks) - [故障排除](#troubleshooting) ## 工作原理 WatchTower 有两种类型的模块: - **Fleet 模块** —— 使用 [axiom](https://github.com/pry0cc/axiom) 将工作分发到云端实例集群。适用于重量级扫描任务(nmap、nuclei、爬虫等),需要跨多个目标快速运行。需要指定 `-f fleet_name`。 - **独立模块** —— 在本地机器上运行。无需云端。适用于 DNS 侦察、OSINT、请求头抓取等。 两种类型产生相同的结构化输出格式。 ## 环境要求 **始终需要:** - Python 3.10 或更高版本 - `curl` —— 大多数 Linux/macOS 系统预装 - `git` —— 用于克隆某些模块使用的仓库 **独立模块** —— 只安装你实际需要的工具: | 工具 | 使用模块 | 安装方式 | |---|---|---| | `dnsrecon` | `dnsrecon` 模块 | `sudo apt install dnsrecon` | | `spiderfoot` | `spiderfoot`、`formfinder`、`github` | `pip install spiderfoot` | | `gitleaks` | `gitleaks` 模块 | [下载二进制文件](https://github.com/gitleaks/gitleaks/releases) | | `jq` | `spidering` 模块 | `sudo apt install jq` | | `qsreplace` | `spidering` 模块 | `go install github.com/tomnomnom/qsreplace@latest` | | `asn` | `asn`、`cve` 模块 | 首次运行时自动安装 | **Fleet 模块** —— 你需要先设置好 axiom。以下工具运行在你的云端集群节点上,而非本地机器。WatchTower 在运行每个模块时会自动在集群上安装它们: | 工具 | 使用模块 | |---|---| | `nmap` | `nmap` | | `hakrawler` + `gospider` | `spidering` | | `httpx` | `spidering`、`subdomains`、`httpx` | | `assetfinder` + `amass` | `subdomains` | | `nuclei` | `nuclei` | | `wafw00f` | `waf` | | `waybackurls` | `waybackurls` | | `sslscan` | `sslscan`(在集群上从源码构建,自动) | | `whatweb` | `whatweb`(在集群上通过 apt 安装,自动) | | `SecretFinder` | `secretfinder`(在集群上克隆,自动) | | `ffuf` | `ffuf`(在集群上通过 go 安装,自动) | ## 安装 ``` # 1. 克隆仓库 git clone https://github.com/yourorg/watchtower.git cd watchtower # 2. 创建 Python 虚拟环境 python3 -m venv venv # 3. 激活它 source venv/bin/activate # Linux / macOS # venv\Scripts\activate # Windows # 4. 安装 Python 依赖 pip install xlsxwriter openpyxl # 5. 使脚本可执行 chmod +x watchtower.py ``` **然后仅从上面的独立模块需求表中安装你需要的工具。** 无需预先安装所有工具。 **Fleet 模块**,安装并配置 axiom: ``` bash <(curl -fsSL https://raw.githubusercontent.com/pry0cc/axiom/master/interact/axiom-configure) # 启动一个 fleet(5 个节点) axiom-fleet spawn myfleet -i 5 # 检查它是否正在运行 axiom-ls ``` ## 使用方法 ``` python3 watchtower.py -m -i [OPTIONS] ``` | 参数 | 描述 | |---|---| | `-m` / `--module` | 要运行的模块 **(必填)** | | `-i` / `--input` | 输入文件 —— 每行一个域名或 URL **(必填)** | | `-f` / `--fleet` | Axiom 集群名称(Fleet 模块必填) | | `-e` / `--extension` | `finddocs` 的文件扩展名(如 `pdf`) | | `-v` / `--verbose` | 打印每条执行的命令 | | `--version` | 显示版本信息 | **示例:** ``` # Fleet 模块(需要 -f) python3 watchtower.py -m nmap -i targets.txt -f myfleet python3 watchtower.py -m spidering -i domains.txt -f myfleet python3 watchtower.py -m nuclei -i urls.txt -f myfleet python3 watchtower.py -m ffuf -i urls.txt -f myfleet # 独立模块(不需要 -f) python3 watchtower.py -m dnsrecon -i domains.txt python3 watchtower.py -m getheaders -i urls.txt python3 watchtower.py -m asn -i ips.txt python3 watchtower.py -m finddocs -i urls.txt -e pdf # 常用标志 python3 watchtower.py -m httpx -i domains.txt -f myfleet -v # verbose DEBUG=1 python3 watchtower.py -m sslscan -i domains.txt -f myfleet # full traceback NO_COLOR=1 python3 watchtower.py -m dnsrecon -i domains.txt # no colour ``` ## 模块 ### Fleet 模块 | 模块 | 功能 | 关键输出 | |---|---|---| | `nmap` | 网络扫描,支持交互式选项(TCP/UDP、端口、速度、脚本) | Excel 文件,包含开放端口、主机摘要、漏洞等工作表 | | `spidering` | 使用 hakrawler + gospider 爬取目标,用 httpx 探测存活 URL | `Final-URL-List.txt`、`Final-JavaScript-URL-List.txt` | | `sslscan` | 扫描 SSL/TLS —— 发现弱密码套件、协议状态、证书备用名称 | `ssl-tls-status.txt`、`weak-ciphers.txt`、`domains-from-ssl-cert.txt` | | `secretfinder` | 在 JavaScript 文件中搜索 API 密钥、令牌、机密信息 | `javascript-secrets.txt` | | `subdomains` | 通过 assetfinder 和/或 amass 枚举子域名,用 httpx 确认存活 | `live-subdomains.txt`、`subdomains-by-domain.txt`、Excel 报告 | | `whatweb` | Web 技术指纹识别(CMS、框架、服务器版本) | `whatweb-results.txt` | | `waf` | 通过 wafw00f 检测目标上的 WAF 防护 | `waf-results.txt` | | `waybackurls` | 从 Wayback Machine 获取历史 URL | `waybackurls.txt` | | `httpx` | 探测主机列表,仅返回存活的 HTTP/HTTPS 主机 | `httpx-live-hosts.txt` | | `nuclei` | 对目标运行 Nuclei 漏洞模板 | `nuclei-findings.txt` | | `ffuf` | 目录/端点暴力破解,支持交互式字典和模式选择 | Excel(按状态码颜色编码)+ 纯文本 | ### 独立模块 | 模块 | 功能 | 关键输出 | |---|---|---| | `dnsrecon` | 完整 DNS 侦察 —— A、MX、NS、TXT、SPF、DMARC 记录 | `dnsrecon-all-records.csv`、`spf-records.csv`、`dmarc-records.csv` | | `getheaders` | 通过 curl 从 URL 列表获取 HTTP 响应头 | `response-headers.xlsx`、`response-headers.txt` | | `getbody` | 通过 curl 从 URL 列表获取 HTTP 响应体 | `response-bodies.txt` | | `spiderfoot` | OSINT 收集 —— 邮箱、姓名、电话号码 | `spiderfoot-osint.txt` | | `formfinder` | 发现目标站点上的 Web 表单 | `forms-found.txt` | | `asn` | ASN 查询、IP 段信息、每个目标的地理位置 | `asn-results.xlsx` | | `cve` | 通过 Shodan 获取目标的 CVE/漏洞数据 | `cve-results.xlsx` | | `github` | 发现与目标关联的公开 GitHub 仓库 | `github-repos.txt`、`github-repos-for-gitleaks.txt` | | `finddocs` | 按文件扩展名过滤 URL 列表(pdf、docx、xlsx 等) | `-file-urls.txt`、`-files-by-domain.txt` | | `gitleaks` | 克隆 GitHub 仓库并扫描泄露的密钥 | 每个仓库的 JSON 报告 + `gitleaks-summary.txt` | ## 输出结构 所有输出都存放在 `watchtower-results/` 中。不会写入到你的工作目录。 ``` watchtower-results/ ├── MANIFEST.txt ← index of every file produced, with timestamps ├── final/ │ ├── nmap/ │ │ ├── nmap-results-20250516T143022.xlsx │ │ └── nmap-open-ports-20250516T143022.txt │ ├── ffuf/ │ │ ├── ffuf-findings-20250516T150012.xlsx │ │ └── ffuf-findings-20250516T150012.txt │ └── /... └── debug/ └── / ← raw tool output and temp files ``` **每个输出文件都是自文档化的。** 纯文本文件顶部有一个头部信息块: ``` # ════════════════════════════════════════════════════════════════ # WatchTower Reconnaissance Report # ──────────────────────────────────────────────────────────────── # Module : nmap # Description : 通过 Nmap 进行全面的网络扫描 # Generated : 2025-05-16 14:30:22 # Operator : alice @ kali # Input File : /home/alice/targets.txt # Fleet : myfleet # Targets (3): # 192.168.1.1 # 192.168.1.2 # 10.0.0.1 # ════════════════════════════════════════════════════════════════ ``` Excel 文件的第一个工作表是 **Report Info**,包含相同的信息。 ## 添加新模块 添加模块始终需要在 `watchtower.py` 中做 **3 处修改**。其他不需要改动 —— 一旦这 3 项就位,模块会自动出现在 `--help`、Tab 补全和模块列表中。 以下是每部分的作用: ``` MODULE_REGISTRY → tells WatchTower the module exists and what flags it needs run_() → the actual logic: install tools, run the scan, write outputs DISPATCH → connects the module name string to the function ``` ### 模式 A —— 独立模块 当工具**在你的本地机器上运行**时使用。不需要 axiom。 **1. 添加到 `MODULE_REGISTRY`:** ``` MODULE_REGISTRY: dict[str, dict] = { # ... existing entries ... "mymodule": { "desc": "One-line description shown in --help", "fleet": False, # standalone — no -f flag needed "ext": False, # set True only if it needs -e like finddocs }, } ``` **2. 编写函数:** ``` # ══════════════════════════════════════════════ # mymodule # ══════════════════════════════════════════════ def run_mymodule(input_file: str, verbose: bool = False) -> None: MODULE = "mymodule" require_file(input_file) fin = final_dir(MODULE) # watchtower-results/final/mymodule/ ← analyst outputs go here dbg = debug_dir(MODULE) # watchtower-results/debug/mymodule/ ← raw/temp files go here # Check the tool is installed before trying to use it if not shutil.which("mytool"): error("mytool not found. Install with: sudo apt install mytool") sys.exit(1) # Run the tool — save raw output into debug/ so it doesn't pollute final/ raw_out = str(dbg / "mytool-raw.txt") run_cmd(f'mytool -i "{input_file}" -o "{raw_out}"', verbose=verbose) # Write the final clean output to final/ with a metadata header out_txt = fin / f"mymodule-results-{_SESSION['timestamp']}.txt" header = _write_text_header(MODULE, "Description of what this file contains") content = open(raw_out, encoding="utf-8", errors="replace").read() with open(out_txt, "w", encoding="utf-8") as f: f.write(header) f.write(content) # Register the file in MANIFEST.txt so it shows up in the session index write_manifest_entry(MODULE, str(out_txt), "Short description for the manifest") success(f"mymodule complete → {out_txt}") ``` **3. 添加到 `DISPATCH`:** ``` DISPATCH: dict[str, callable] = { # ... existing entries ... "mymodule": lambda a: run_mymodule(a.input, a.verbose), } ``` **运行:** ``` python3 watchtower.py -m mymodule -i targets.txt ``` ### 模式 B —— Fleet 模块(axiom-scan) 当工具**有原生 axiom 模块**且可以通过 `axiom-scan -m ` 分发时使用。这是最常见的 Fleet 模式。 **1. 添加到 `MODULE_REGISTRY`:** ``` "mymodule": { "desc": "One-line description", "fleet": True, # fleet required — user must pass -f "ext": False, }, ``` **2. 编写函数:** ``` def run_mymodule(input_file: str, fleet: str, verbose: bool = False) -> None: MODULE = "mymodule" require_file(input_file) require_fleet(fleet, MODULE) # exits cleanly with a message if -f was not passed fin = final_dir(MODULE) dbg = debug_dir(MODULE) # Install the tool on all fleet nodes before scanning. # The if ! command -v check makes this safe to run every time — # it skips silently if the tool is already installed. info(f"Ensuring mytool is on fleet '{fleet}' …") run_cmd( "axiom-exec '" "if ! command -v mytool &>/dev/null; then " " echo \"[fleet] installing mytool …\" && " " go install github.com/example/mytool@latest; " # ← your install command "else " " echo \"[fleet] mytool already present\"; " "fi'", verbose=verbose, ) # axiom-scan splits your input file across fleet nodes and runs the tool in parallel raw_out = str(dbg / "mytool-raw.txt") axiom_scan(input_file, fleet, "mytool-axiom-flag", raw_out, verbose=verbose) # ↑ # this is the -m flag used by axiom-scan # check axiom's module list for the exact name # Write the final output out_txt = fin / f"mymodule-results-{_SESSION['timestamp']}.txt" header = _write_text_header(MODULE, "Description of what this file contains") content = open(raw_out, encoding="utf-8", errors="replace").read() \ if os.path.isfile(raw_out) else "" with open(out_txt, "w", encoding="utf-8") as f: f.write(header) f.write(content) write_manifest_entry(MODULE, str(out_txt), "mytool findings") success(f"mymodule complete → {fin}/") ``` **3. 添加到 `DISPATCH`:** ``` "mymodule": lambda a: run_mymodule(a.input, a.fleet, a.verbose), ``` **运行:** ``` python3 watchtower.py -m mymodule -i targets.txt -f myfleet ``` ### 模式 C —— Fleet 模块(axiom-exec) 当工具**没有原生 axiom 模块**时使用。你需要构建一个 shell 脚本,推送到集群节点,远程运行,然后拉回结果。`ffuf` 模块使用此模式。 **2. 编写函数**(步骤 1 和 3 与模式 B 相同): ``` def run_mymodule(input_file: str, fleet: str, verbose: bool = False) -> None: MODULE = "mymodule" require_file(input_file) require_fleet(fleet, MODULE) fin = final_dir(MODULE) dbg = debug_dir(MODULE) # Install on fleet nodes (same idempotent pattern as Pattern B) run_cmd( "axiom-exec 'if ! command -v mytool &>/dev/null; then " "; fi'", verbose=verbose, ) # Build a shell script that runs the tool against each target tmp_script = dbg / "run-mytool.sh" raw_out = dbg / "raw-results" raw_out.mkdir(parents=True, exist_ok=True) with open(tmp_script, "w") as sh: sh.write("#!/usr/bin/env bash\nset -euo pipefail\n\n") for target in read_lines(input_file): safe = re.sub(r"[^\w._-]", "", target)[:100] sh.write(f"mytool -target '{target}' -o ~/recon/mytool-{safe}.json\n") # Push script → run it on fleet → pull results back locally run_cmd("axiom-exec 'mkdir -p ~/recon'", verbose=verbose) run_cmd(f'axiom-scp "{tmp_script}" "~/recon/run-mytool.sh"', verbose=verbose) run_cmd("axiom-exec 'bash ~/recon/run-mytool.sh'", verbose=verbose) run_cmd(f'axiom-scp "~/recon/mytool-*.json" "{raw_out}/"', verbose=verbose) # Parse raw_out/*.json and write final outputs # ... your parsing logic here ... success(f"mymodule complete → {fin}/") ``` ### 辅助脚本 如果你的模块需要辅助 Python 脚本来解析或合并结果,将其放在 `modules/` 目录中,像这样调用: ``` run_module_script("my-helper.py", arg1, arg2) ``` 无论 WatchTower 从哪里运行,它都会被自动找到。 ### 快速参考 | 模式 | 使用场景 | 注册表中的 `fleet` | 函数签名 | |---|---|---|---| | A —— 独立模块 | 工具在本地运行 | `False` | `(input_file, verbose)` | | B —— axiom-scan | 工具有原生 axiom 模块 | `True` | `(input_file, fleet, verbose)` | | C —— axiom-exec | 工具没有 axiom 模块 | `True` | `(input_file, fleet, verbose)` | ## 项目结构 ``` watchtower/ ├── watchtower.py ← Main script — edit this to add modules ├── requirements.txt ← Python package list (xlsxwriter, openpyxl) ├── README.md └── modules/ ← Helper scripts — do NOT move or rename these ├── capture-headers.py ├── capture-osint.py ├── clone-repos.py ├── convert-nmap-to-xml.py ├── dnsrecon-merge.py ├── parse_domains_subdomains.py └── pretty_parse_ssl_alt_names.py ``` ## 技巧与提示 - **只安装你需要的工具。** 如果你只使用 `dnsrecon` 和 `getheaders`,只需安装 `dnsrecon`。如果缺少必需的工具,WatchTower 会清晰地报错。 - **Tab 补全** —— 在 `-m` 后按 `Tab` 键循环切换模块名称。 - **输入文件格式** —— 每行一个域名或 URL。运行前删除空行和注释。 - **详细模式**(`-v`)在运行每条 shell 命令前打印出来 —— 有助于了解正在发生的事情。 - **调试模式**(`DEBUG=1`)在意外错误时打印完整的 Python 回溯信息。 - **无颜色模式**(`NO_COLOR=1`)去除所有颜色 —— 适用于记录到文件或 CI 流水线。 - **运行后检查 MANIFEST.txt** —— 它列出了所有生成的文件及其时间戳和描述,涵盖所有会话。 - **调试文件夹**(`watchtower-results/debug//`)包含工具的原始输出,如果你需要检查工具实际返回了什么。 ## 故障排除 | 问题 | 解决方案 | |---|---| | `Module helper 'X' not found` | 检查 `modules/` 目录是否完好且与 `watchtower.py` 在同一位置 | | `axiom-scan: command not found` | 安装并配置 axiom,或改用独立模块 | | `dnsrecon: command not found` | `sudo apt install dnsrecon` | | `gitleaks: command not found` | 从 [gitleaks releases](https://github.com/gitleaks/gitleaks/releases) 下载 | | `jq: command not found` | `sudo apt install jq` | | 输出文件为空 | 使用 `-v` 运行以查看具体命令和任何错误 | | `Permission denied` | `chmod +x watchtower.py` | | Python 版本错误 | 升级到 Python 3.10+:使用 `python3 --version` 检查 | | venv 未激活 | 运行 WatchTower 前先执行 `source venv/bin/activate` | ## 许可证 MIT —— 自由使用,欢迎贡献。
标签:ASN查询, axiom, CISA项目, CVE查询, dnsrecon, DNS侦察, ESC4, GitHub, GitHub信息收集, gitleaks, Go工具链, IP 地址批量处理, LIDS, nuclei, OSINT, Python框架, spiderfoot, Spidering, SSL分析, timestamped输出, TIP, 云存储安全, 云扫描集群, 后渗透, 威胁情报, 子域名枚举, 安全工具集成, 开发者工具, 持续安全扫描, 插件系统, 数据统计, 无线安全, 模块化扫描, 端口扫描, 系统安全, 结构化输出, 网络安全, 网络安全审计, 网络扫描, 自动化侦察, 表单发现, 运行时操纵, 防御绕过, 隐私保护