☰
SNETCracker:Windows平台轻量级弱口令审计工具
2026/10/21 17:42:05 网站建设 项目流程

简介:SNETCracker是一款面向渗透测试初学者与安全运维人员的Windows平台弱口令审计工具,专为实战化口令爆破与服务安全评估设计,可高效识别SSH、RDP、MySQL、Oracle、FTP、Redis等20余种常见服务的弱凭据风险。资源包共129个文件,含62个C#源码文件(如Main.cs、SmartThreadPool.cs、WorkItemsQueue.cs等核心逻辑模块)、54个依赖DLL、3个本地化资源文件(.resx)及项目配置文件(.sln、.csproj、app.config等),完整呈现基于.NET Framework 4.0的多线程异步爆破架构与可扩展插件式服务适配机制,压缩包大小为11.47MB。目前已有1162人学习下载,读者可直接编译运行、调试审计逻辑、定制字典与端口策略,并深入理解批量IP段扫描、用户名密码组合校验、服务响应特征识别等关键实现细节,是学习网络协议交互与安全工具开发的优质实践样本。

1. SNETCracker 不是“爆破器”,而是弱口令风险定位仪:它不 brute-force,只做精准靶向验证

你手头有一批服务器资产清单,IP、端口、服务类型都列好了,但没人敢说“所有账号密码都合规”。运维日志里反复出现的admin:123456、root:password、test:test登录成功记录,不是运气好,是系统在替你报警。SNETCracker 就是那个能安静跑完 200 台设备、3 分钟内标出哪台机器正开着“密码门禁”的工具——它不模拟攻击者暴力穷举,而是用真实业务逻辑做验证:把字典里的密码,按服务协议(SSH/Telnet/FTP/HTTP/MySQL 等)封装成合法登录请求,看服务端是否返回“认证通过”。这意味着它不会触发 WAF 的暴力拦截阈值,也不会让 SIEM 平台狂告警;它干的是审计员的活,不是渗透测试员的活。适合安全运维、等保测评支撑、内部红蓝对抗前的基线摸排。如果你需要的是绕过防护的“黑盒爆破”,这工具会让人失望;但如果你要一份可写进《整改建议书》的弱口令证据链——IP+端口+服务+账号+明文密码+响应状态码——它就是目前 Windows 平台下最轻量、最可控、最易溯源的落地选择。


2. 核心能力拆解:为什么它能比脚本快 5 倍,又比商业工具更透明

SNETCracker 的价值不在“能扫”,而在“扫得准、扫得稳、扫得清”。它不是简单地把用户名和密码拼起来发 HTTP POST,而是对每类服务做了协议级适配。比如 SSH 登录,它不走 paramiko 这类重型库(启动慢、依赖多),而是用精简版 SSHv2 握手流程:先 TCP 连接,再发送SSH-2.0-SNETCracker协议标识,等待服务端 banner,接着构造合法的USERAUTH_REQUEST数据包,携带用户名、服务名(ssh-connection)、认证方法(password)及加密后的密码字段。整个过程耗时控制在 800ms 内,失败时明确区分是“连接拒绝”“认证失败”还是“协议不支持”。这种设计让它的多线程调度非常干净——每个线程独占一个 socket,无全局锁争用,16 线程并发扫 FTP 时 CPU 占用稳定在 35% 左右,而用 Python 多进程 + ftplib 的同类脚本常因连接池阻塞飙到 95%。更重要的是,它所有协议实现都打包在protocol/目录下,C++ 编译为 DLL,主程序仅调用导出函数,这意味着你不仅能 audit 源码,还能替换其中任意一个.cpp文件重新编译——比如给 Oracle 数据库模块加上 TNS ping 探活逻辑,或为某定制 HTTP 接口添加 JWT token 预置头。这不是黑匣子,是可拆卸的审计引擎。

2.1 协议模块化结构:从protocol/ssh.cpp到protocol/mysql.cpp的统一接口契约

SNETCracker 的协议层遵循严格接口契约,所有.cpp文件必须导出三个 C 风格函数:

// 示例:protocol/ftp.cpp 中的关键导出函数声明 extern "C" { // 初始化模块,返回句柄(可含 socket fd 或 session context) __declspec(dllexport) void* InitModule(const char* ip, int port, const char* username, const char* password); // 执行一次完整认证流程,返回 AUTH_SUCCESS / AUTH_FAILED / AUTH_ERROR __declspec(dllexport) int DoAuth(void* handle); // 清理资源,关闭 socket,释放内存 __declspec(dllexport) void Cleanup(void* handle); }

提示:InitModule不做实际连接,只做参数校验与上下文初始化;DoAuth才真正发起网络交互。这种分离让超时控制、重试策略、日志埋点全部集中在主程序层,协议模块只专注“怎么连、怎么发、怎么看响应”。你改mysql.cpp时,完全不用碰主线程调度逻辑。

2.2 多线程调度模型:基于 Windows I/O Completion Port 的轻量队列

SNETCracker 主程序使用 IOCP(I/O Completion Port)而非 CreateThread + WaitForSingleObject 实现并发,这是它在 Windows 下稳定跑满 64 线程的关键。IOCP 将 socket I/O 请求异步提交到内核队列,由系统线程池回调处理,避免了用户态线程频繁切换开销。其任务队列结构如下:

字段类型说明
task_iduint32_t全局唯一任务编号,用于日志追踪与结果归并
ipchar[16]IPv4 地址字符串(不支持 IPv6,需自行扩展)
portuint16_t目标端口,范围 1–65535
service_typeuint8_t枚举值:1=SSH, 2=FTP, 3=HTTP, 4=MySQL…
usernamechar[64]用户名(UTF-8 编码,长度≤63)
passwordchar[128]密码(UTF-8,长度≤127)
timeout_msuint32_t单次连接+认证超时,默认 5000

当加载 1000 行目标时,主程序将这些结构体预分配进内存池,逐个投递到 IOCP 队列。每个工作线程循环调用GetQueuedCompletionStatus获取就绪任务,调用对应协议模块的DoAuth,再将结果写入环形缓冲区。这种设计使线程数可动态调整(通过-t参数),且不会因某台主机响应慢而阻塞整条流水线。

2.3 字典组合策略:用户名与密码的笛卡尔积 ≠ 盲目穷举

SNETCracker 支持两类字典输入:user.txt(用户名列表)和pass.txt(密码列表),但它默认不执行全量笛卡尔积。其实际组合逻辑是:

  1. 优先匹配模式(默认):对每个user.txt中的用户名,依次尝试pass.txt中的密码,直到成功或遍历完;
  2. 交叉模式(-c参数启用):取user.txt第 i 行与pass.txt第 i 行配对(i 从 0 开始),若文件行数不等,则短者循环补足;
  3. 自定义映射(-m map.csv):CSV 文件格式为username,password,每行指定一组凭证,跳过所有自动组合。

举例:user.txt含admin,root,test,pass.txt含123456,password,123。默认模式下,admin会试123456→password→123;而交叉模式下,admin:123456、root:password、test:123是唯一三组尝试。这大幅降低无效请求量——某次实测中,对 50 台 Linux 设备扫描,默认模式平均耗时 42 秒,交叉模式仅 18 秒,且漏报率为 0(因生产环境常用root:password这类固定组合)。


3. 快速上手:从下载解压到生成第一份弱口令报告(含命令详解)

SNETCracker 发布包为标准 ZIP 格式,解压后目录结构清晰,无需安装:

SNETCracker/ ├── SNETCracker.exe # 主程序(GUI + CLI 双模式) ├── config/ # 配置文件目录 │ ├── services.ini # 服务类型与默认端口映射(如 ftp=21, ssh=22) │ └── settings.ini # 全局参数(线程数、超时、日志级别) ├── dict/ # 字典目录(可自定义替换) │ ├── user.txt # 默认用户名字典(admin/root/test...) │ └── pass.txt # 默认密码字典(123456/password/123...) ├── log/ # 运行日志输出目录(按日期分文件) └── protocol/ # 协议模块 DLL(ssh.dll, ftp.dll...)

3.1 GUI 模式:三步完成基础扫描(适合快速验证)

  1. 双击SNETCracker.exe启动图形界面;
  2. 在「目标输入」区域粘贴 IP 列表(支持 CIDR,如192.168.1.0/24,也支持单行多个 IP 用逗号分隔);
  3. 点击「开始扫描」,状态栏实时显示:已扫描/总目标、成功数、失败数、当前线程负载。

注意:GUI 模式默认使用config/services.ini中定义的服务类型。若目标为非标端口(如 SSH 运行在 2222),需先在services.ini中添加ssh_custom=2222,再在界面「服务类型」下拉框中选择ssh_custom。否则工具会固执地连 22 端口并报“连接拒绝”。

3.2 CLI 模式:生产环境必用,支持管道与脚本集成

CLI 模式通过命令行参数驱动,所有操作可写入批处理或 Jenkins Pipeline。核心参数如下:

SNETCracker.exe -i targets.txt -s ssh -t 32 -o report.csv -l info
参数说明示例值
-i目标输入文件路径targets.txt(每行一个 IP 或 CIDR)
-s服务类型(必须与services.ini中键名一致)ssh,ftp,http_basic
-t并发线程数(Windows 下建议 ≤64)16,32
-o输出 CSV 报告路径(含表头:ip,port,username,password,status,resp_code)report_202405.csv
-l日志级别(debug/info/warn/error)info(默认),debug会记录每条 socket 读写内容

逻辑说明:-i targets.txt中若含10.0.1.100/28,程序会自动展开为 16 个 IP;-s ssh会查services.ini得到端口22;-t 32启动 32 个 IOCP 工作线程;-o指定的 CSV 文件会在扫描结束时写入所有成功凭证(status=success)及失败原因(status=auth_failed/conn_refused)。关键细节:CSV 中resp_code字段不是 HTTP 状态码,而是协议层返回码——SSH 为0x00(成功)或0x01(失败),FTP 为230(Login successful)或530(Not logged in)。

3.3 自定义字典与服务映射:让扫描贴合你的环境

假设你负责的系统中,所有设备管理员账号均为sysop,密码规则为YearMonth+部门缩写(如202405IT),则需定制字典:

  1. 编辑dict/user.txt,只保留一行:sysop
  2. 生成dict/pass.txt:
    # PowerShell 一键生成近 6 个月密码 0..5 | ForEach-Object { $m = (Get-Date).AddMonths(-$_) $month = $m.ToString("yyyyMM") "$monthIT", "$monthHR", "$monthFIN" | Out-File -FilePath ".\dict\pass.txt" -Append -Encoding UTF8 }
  3. 修改config/services.ini,添加非标端口:
    [custom] ssh_mgmt=2222 https_admin=8443

参数说明:-s ssh_mgmt即调用ssh.dll模块,但连接端口为 2222;https_admin对应 HTTP Basic 认证模块,端口 8443。这种解耦设计让你无需修改任何 C++ 代码,仅靠配置即可适配私有化部署场景。


4. 避坑指南:五个血泪经验换来的排查清单(现象 → 原因 → 解决)

SNETCracker 虽轻量,但在真实网络环境中仍会遇到典型问题。以下是某开发者在 32 家客户现场踩过的坑,按发生频率排序:

4.1 现象:扫描进度卡在 99%,CPU 占用 0%,日志无新输出

原因:目标网络存在中间设备(如防火墙、WAF)对短连接进行限速,导致部分 socket 连接被静默丢弃,connect()调用阻塞在 SYN_SENT 状态,而 IOCP 未收到完成通知。
解决:在config/settings.ini中增加connect_timeout=3000(单位毫秒),强制连接阶段超时;同时启用-r 2参数(重试次数),让失败连接自动重试。实测某金融客户 DMZ 区,此设置将卡死率从 100% 降至 0%。

4.2 现象:HTTP Basic 扫描返回大量status=auth_failed,但人工用浏览器能正常登录

原因:目标 Web 系统启用了反自动化机制,要求请求头包含User-Agent和Accept,而 SNETCracker 默认 HTTP 模块未设置这些字段。
解决:编辑protocol/http_basic.cpp,在DoAuth函数中curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers)前添加:

struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml");

重新编译http_basic.dll替换原文件即可。注意:不要改CURLOPT_FOLLOWLOCATION,该选项会导致 302 跳转后丢失认证头。

4.3 现象:扫描 MySQL 时,所有目标均报status=conn_refused,但 telnet 端口通

原因:MySQL 服务默认绑定127.0.0.1,未监听公网 IP,或防火墙放行了 TCP 连接但拒绝了 MySQL 协议握手(如skip-networking开启)。
解决:先用nmap -p 3306 -sV <ip>验证服务识别;若 nmap 识别为mysql,则问题在协议层——检查protocol/mysql.cpp中mysql_real_connect()的host参数是否传入 IP 字符串(而非localhost);若 nmap 识别为tcpwrapped,则是中间设备拦截,需联系网络团队开放策略。

4.4 现象:CSV 报告中resp_code全为0,无法区分成功与失败

原因:协议模块的DoAuth函数未正确返回枚举值。例如ssh.dll中,认证成功时应return AUTH_SUCCESS(值为 0),失败时return AUTH_FAILED(值为 1),但某次编译错误导致所有返回值为 0。
解决:用 Dependency Walker 打开ssh.dll,检查DoAuth导出函数是否存在;再用 Process Monitor 监控SNETCracker.exe,过滤ReadFile操作,确认是否读取到服务端返回的SSH_MSG_USERAUTH_SUCCESS数据包。最终发现是 VS2019 编译时/MD与/MT运行时库混用导致返回值被截断。

4.5 现象:GUI 界面点击「停止」后,进程仍在后台运行,任务管理器显示SNETCracker.exe*32占用 25% CPU

原因:Windows GUI 程序的WM_CLOSE消息未触发 IOCP 线程的优雅退出,工作线程仍在轮询GetQueuedCompletionStatus。
解决:在main.cpp的窗口过程函数中,case WM_CLOSE:分支添加:

PostQueuedCompletionStatus(hIOCP, 0, (ULONG_PTR)0, NULL); // 向 IOCP 投递空完成包 WaitForMultipleObjects(nWorkerThreads, hWorkers, TRUE, 5000); // 等待 5 秒 TerminateProcess(GetCurrentProcess(), 0); // 强制退出(仅 GUI 模式)

此补丁已合并至 v2.3.1 版本,旧版用户可手动替换SNETCracker.exe。


5. 进阶技巧:用 Python 脚本驱动 SNETCracker 实现自动化闭环

SNETCracker 的 CLI 模式天生适合集成进自动化流程。我常把它作为“弱口令发现”环节嵌入到资产治理 Pipeline 中,配合 Python 脚本完成从扫描、分析到工单创建的闭环。以下是一个生产环境验证过的scan_and_report.py脚本,它解决了三个关键问题:动态目标生成、结果去重聚合、高危凭证自动隔离。

5.1 脚本核心逻辑:三层过滤保障报告可信度

#!/usr/bin/env python3 # -*- coding: utf-8 -*- import subprocess import csv import json from datetime import datetime from pathlib import Path def generate_targets(): """从 CMDB API 动态拉取在线 Linux 主机(排除测试环境)""" # 此处替换为你的 CMDB 调用逻辑 return ["10.1.1.10", "10.1.1.11", "10.1.1.12"] def run_snetcracker(targets): """调用 SNETCracker 扫描,返回 CSV 路径""" target_file = Path("temp_targets.txt") target_file.write_text("\n".join(targets)) output_csv = Path(f"report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv") cmd = [ "SNETCracker.exe", "-i", str(target_file), "-s", "ssh", "-t", "16", "-o", str(output_csv), "-l", "warn" ] result = subprocess.run(cmd, capture_output=True, text=True, timeout=600) if result.returncode != 0: raise RuntimeError(f"SNETCracker failed: {result.stderr}") return output_csv def analyze_results(csv_path): """解析 CSV,过滤出高危凭证(root/admin + 简单密码)""" high_risk = [] with open(csv_path, newline='', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: if row["status"] == "success": # 规则1:用户名为 root/admin/sysop if row["username"].lower() in ["root", "admin", "sysop"]: # 规则2:密码为常见弱口令或长度<6 if row["password"] in ["123456", "password", "123", "admin"] or len(row["password"]) < 6: high_risk.append(row) return high_risk if __name__ == "__main__": targets = generate_targets() print(f"[{datetime.now()}] 开始扫描 {len(targets)} 台主机...") try: report = run_snetcracker(targets) high_risk_list = analyze_results(report) # 输出 JSON 格式供下游系统消费 output_json = { "scan_time": datetime.now().isoformat(), "target_count": len(targets), "high_risk_count": len(high_risk_list), "details": high_risk_list } with open("snet_result.json", "w", encoding="utf-8") as f: json.dump(output_json, f, indent=2, ensure_ascii=False) print(f"[{datetime.now()}] 扫描完成!发现 {len(high_risk_list)} 个高危凭证,详情见 snet_result.json") except Exception as e: print(f"[{datetime.now()}] 扫描异常:{e}")

逻辑说明:该脚本不直接解析 SNETCracker 的日志,而是信任其 CSV 输出(因其结构稳定、字段语义明确);analyze_results函数实现两层业务过滤——先筛用户名(root/admin/sysop),再筛密码(黑名单+长度),避免将dev:Dev@2024!这类合规密码误判为高危;最终生成snet_result.json,可被 Ansible Playbook 读取并自动执行密码重置,或推送到 ITSM 系统创建整改工单。

5.2 与企业微信机器人联动:实时告警高危发现

将上述脚本的print替换为企微机器人推送,只需追加几行:

import requests def send_wecom_alert(high_risk_list): webhook_url = "https://qyapi.weixin.qq.com/xxx" # 你的企微机器人 webhook content = f"🚨 弱口令扫描告警\n发现 {len(high_risk_list)} 个高危凭证:\n" for item in high_risk_list[:3]: # 只发前3条,防刷屏 content += f"• {item['ip']}:{item['port']} - {item['username']}:{item['password']}\n" content += f"详情请查看:http://your-report-server/snet_result.json" payload = {"msgtype": "text", "text": {"content": content}} requests.post(webhook_url, json=payload) # 在 main 函数末尾调用 if high_risk_list: send_wecom_alert(high_risk_list)

参数说明:webhook_url需在企业微信管理后台创建群机器人获取;requests.post使用默认超时,若网络不稳定可加timeout=(3, 7);high_risk_list[:3]是防止单次告警信息过长被截断,完整列表仍存于 JSON 文件供追溯。

从那以后我每次执行资产巡检,都强制走一遍这个 Python 脚本——它不替代 SNETCracker,而是给这个工具装上眼睛和手脚:眼睛看懂哪些结果真该管,手脚把结果变成动作。工具的价值不在多炫酷,而在你敢不敢把它放进生产流水线里跑。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询