吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 79|回复: 4
上一主题 下一主题
收起左侧

[会员申请] 申请会员ID:tenriver

[复制链接]
跳转到指定楼层
楼主
吾爱游客  发表于 2026-8-13 21:53 回帖奖励 |自己
1、申 请 I D :tenriver
2、个人邮箱:tenriver@qq.com
3、原创技术文章:

从零开发 RDP 暴力破解防护工具:Win7 兼容约束下的技术选型与踩坑实录

一、项目背景与设计目标

公司内网有 Windows Server 2008 R2 / Win7 老机器,常年被 RDP 暴力破解扫端口(3389 每天几万次 4625 事件)。市面安全软件要么只支持 Win10+,要么是闭源商业产品,要么很大不好用,试用几个没有一个满意的。抱着顺便学习Rust的想法,借助AI写了一个单文件、绿色、免安装的 RDP 暴力破解防护工具。

产品硬性指标(这也是后面所有技术决策的"枷锁"):

  • 必须支持 Windows 7 / Server 2008 R2 及以上(内网老系统)
  • 单文件绿色部署,不写注册表、不装驱动、不依赖运行时
  • GUI 内存占用要小(老机器内存紧张)
  • 停止防护 = 完全卸载(不留任何系统残留)

围绕这四条,展开讲设计思路、技术选型和踩过的坑。

二、核心设计思路

1. 双窗口滑动封禁(快攻 + 慢攻)

暴力破解有两个典型节奏:单 IP 短时间内猛攻(10 分钟内 3 次),和慢速试探(24 小时内累计 10 次)。单一阈值要么误封要么漏封。实现上对每个 IP 维护两个独立滑动窗口

struct FailureRecord {
    attempts: Vec<Instant>,      // 快攻窗口(分钟级)时间戳
    slow_attempts: Vec<Instant>, // 慢攻窗口(小时级)时间戳
    cumulative_count: usize,     // 绝对累计次数(不清零)
    blocked_sent: bool,          // 是否已触发封禁
}

每次 4625 事件到达,向两个窗口各推一个时间戳,并按各自窗口长度 retain 过期条目;任一窗口达到阈值即触发封禁。

关键细节:窗口基于事件真实时间而不是处理时间。回放历史事件时,把事件时间回推成 Instant 再入窗,这样重启后补扫的历史攻击能正确参与窗口判断,不会因"处理延迟"而误算。

2. 动态封禁时长(打击反复试探)

被封过一次的 IP 再次攻击,封禁时长应递增,否则攻击者可以等解封再继续。公式:

非永久封禁时长 = 基础时长 + (封禁次数 - 1) × 动态增长时长
fn dynamic_ban_minutes(cfg: &Config, prev_ban_count: u32) -> u64 {
    if cfg.ban_type == "permanent" {
        0u64  // 0 表示永久
    } else {
        cfg.ban_duration_minutes
            .saturating_add((prev_ban_count as u64).saturating_mul(cfg.ban_growth_minutes))
    }
}

封禁次数存在数据库独立 key 里(bancount_<ip>),过期解封后不清零,保证反复攻击时次数持续累计、时长持续增长。

3. 停止 = 绿色卸载

这是"绿色软件"的核心理念:点"停止防护"时,程序主动删除自己添加的所有防火墙规则、清空当前封禁记录(但保留历史统计)。重新开启从零开始,不留任何系统痕迹。因此必须精确记录"哪些规则是我加的"——统一规则名前缀 RDPGuard_Batch / RDPGuard_AllowRDP,停止时按前缀批量清理。

三、Win7 兼容下的技术选型

1. 锁定 rustc 1.77.2

现代 Rust 编译出的 exe 在 Win7 上启动崩溃,因为新版本 std 导入了 Win8+ 才有的 API。排查时用 dumpbin /imports 对比,发现新 toolchain 引入了一堆 Win8+ 符号。方案:锁死 toolchain 版本,并在构建脚本里明确注释"Build with rustc 1.77.2 (no Win8+ API imports)",同时 CRT 静态链接,让 2008 R2 无需安装 VC++ 运行库。

2. GUI 选型:Sciter,而不是 Electron / Tauri / WebView2

这是本软件最关键也最有争议的选型:

方案 Win7/2008R2 体积 内存
Electron ✅ 但超大 150MB+ 100MB+
Tauri/WebView2 ❌ WebView2 不支持 Win7 - -
Sciter ✅ 原生 Win7 支持 exe 仅 ~11MB GUI ~15MB

Sciter 引擎(4~8MB)直接内嵌进 exe,运行时自动释放,单文件部署。代价是它是老旧的 TIScript 脚本引擎,和标准 JavaScript 有大量语义差异——这也是下文踩坑的重头戏。

3. 外部工具全部 API 化

早期实现用 sc.exeauditpolnetshtaskkill 子进程管服务/审核策略/防火墙,后来全部换成 Windows API(SCM API、Audit API、INetFwPolicy2 COM、TerminateProcess),理由后面讲。

四、开发中踩过的坑(重点)

坑 1:TIScript 的 String 是"类型对象",不是函数

GUI 事件列表渲染时偶发崩溃,错误:

[Sciter] Error: Wrong type - Type([type String]), expected instance of function

排查很久(加了分段断点日志定位),最终定位到 HTML 转义函数:

function escHtml(s) {
    return (s == null ? "" : String(s))   // ← 这一行
        .replace(/&/g, "&") ...;
}

本版 TIScript 中 String 是"类型对象"typeof String 返回 "Type"),String(x)原始字符串/数字正常,但对 slice()/substring() 等字符串方法的返回值(String 类型对象,typeof 仍显示 "string"!)会直接抛类型错误。修复:一律用 "" + s 拼接代替 String(s)

function escHtml(s) {
    return (s == null ? "" : "" + s)   // 对原始值/数字/String 对象都安全
        .replace(/&/g, "&") ...;
}

这个坑隐蔽在:只在列表第一次有数据时才触发(转义函数首次被真实数据调用),空列表时走"暂无记录"分支永远不执行——所以"之前一直好好的,突然就崩了"。

坑 2:typeof 返回值不是 JS 语义

typeof 数字 返回 "integer" / "float"不是 "number"。写 typeof x == "number" 判断数字恒为 false,导致封禁次数永远显示 0。修复:判断数字用 x || 0 或同时判断 "integer"/"float"

坑 3:全局函数名会被引擎内置遮蔽

esc 这个函数名在 TIScript 全局环境里是只读字符串数组(应该是内置的某个东西),function esc(s) 声明被遮蔽,调用时抛类型错误。改名 escHtml 才绕开。教训:旧版脚本引擎的全局命名空间不干净,自定义函数名要避开常见短名

坑 4:子进程调用依赖本地化输出

早期用 auditpol /get /r 解析审核策略,输出是 CSV 且按系统语言本地化(中文系统 GBK 编码 + 中文字段名),解析脆弱;sc query 输出也依赖本地化。干脆全部换成 API:审核策略用 AuditQuerySystemPolicy/AuditSetSystemPolicy,服务管理用 SCM API,防火墙用 INetFwPolicy2 COM,强杀进程用 TerminateProcess不再 spawn 任何外部控制台工具,彻底摆脱本地化和 PATH 依赖。

坑 5:Windows 防火墙 COM 会往 IP 后面追加子网掩码

通过 COM 写 RemoteAddresses = "1.2.3.4" 封禁 IP,再读回来可能变成 "1.2.3.4/255.255.255.255",导致精确匹配失败、解封失效。修复:解析时统一剥离 / 及之后的掩码部分。

坑 6:滑窗清理导致动态封禁永远不生效

cleanup_expired_bans 每分钟把过期的 active 记录从数据库删除,之后该 IP 再次触发封禁走"新封禁"分支,prev_ban_count 取到 0,动态公式被跳过——解封时间永远等于基础时长。修复:新封禁分支也走同一个公式(首次封禁 prev=0,结果不变),保证次数累计生效。

五、核心代码节选

1. 双窗口判定(简化)

// 快攻/慢攻判定核心
record.attempts.push(event_instant);
record.attempts.retain(|t| t.elapsed() <= check_window);      // 快攻窗口
record.slow_attempts.push(event_instant);
record.slow_attempts.retain(|t| t.elapsed() <= slow_window);  // 慢攻窗口

if !record.blocked_sent && record.attempts.len() >= fast_threshold {
    trigger_ban(ip, record.cumulative_count);  // 快攻命中
} else if !record.blocked_sent && record.slow_attempts.len() >= slow_threshold {
    trigger_ban(ip, record.cumulative_count);  // 慢攻命中
}

2. 防火墙批规则管理(封禁 IP 集中写入一条规则)

Windows 防火墙单条规则的地址字符串有长度上限(约 8000 字符),封禁 IP 多了会静默失败。方案:一条批规则装 ~500 个 IP,超长自动溢出到下一条编号规则

fn block_ip(&self, ip: &str, port: u16) {
    let rules = self.read_all_batch_rules(&policy)?;  // 读取真实状态,不信任缓存
    match rules.last() {
        Some((_, name, ips)) => {
            let joined = ips.join(",");
            if joined.len() + 1 + ip.len() <= MAX_REMOTE_LEN {
                set_remote_addresses(name, &format!("{},{}", joined, ip));
            } else {
                create_block_rule(&batch_rule_name(idx + 1), ip, port);  // 溢出新建
            }
        }
        None => create_block_rule(RULE_NAME, ip, port),
    }
}

3. 崩溃防护:刷新链永不中断

Sciter 里定时刷新链一旦抛异常就会永久停止self.timer 不再执行),表现为"按钮点击后列表不再刷新"。所有在刷新链上的代码必须 try/catch,并且先注册下一次定时、再执行刷新

function scheduleRefresh() {
    self.timer(1000, scheduleRefresh);   // 先注册,异常也杀不掉链
    try { refreshAll(); } catch (e) {}
}

六、总结

这个项目的核心价值不在于"实现了功能",而在于在一堆老旧约束(Win7 兼容、单文件、小体积、绿色卸载)下被迫做出的技术取舍:锁 rustc 版本保兼容、选老引擎 Sciter 换体积、把子进程全部 API 化换健壮性。每个坑背后都是对"为什么这样做"的真实思考——这些恰恰是读文档读不来的经验。若能通过会员申请将把软件首发在吾爱,欢迎交流。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
594046245 发表于 2026-8-14 16:50
防火墙设置IP访问白名单。如果IP经常变,加个程序,使用cmd动态增加白名单IP地址。是不是也很安全?
3#
Hmily 发表于 2026-8-14 18:22
抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。

ps:申请规则即将增加禁止ai文章投稿。
4#
吾爱游客  发表于 2026-8-14 21:20 |自己
594046245 发表于 2026-8-14 16:50
防火墙设置IP访问白名单。如果IP经常变,加个程序,使用cmd动态增加白名单IP地址。是不是也很安全?

哪有工具来得方便,何况你用手机、家庭宽带远程访问,哪来的固定IP
5#
吾爱游客  发表于 2026-8-14 21:25 |自己
Hmily 发表于 2026-8-14 18:22
抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。

ps: ...

生活离不开AI了,这篇文章的确是AI写的,公司内网应该是公司内,人工审核不细致,但这些坑也是实打实的,决非AI胡编乱造

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-8-17 05:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表