Windows 10 远程桌面(RDP)防暴力破解脚本
0x01 设置5次失败后锁定账户30分钟
secpol.msc
# 导航到: 安全设置 > 账户策略 > 账户锁定策略
0x02 脚本如下
<#
.DESCRIPTION
此脚本分析Windows安全日志中的RDP登录失败事件(ID 4625),
统计每个IP的失败次数,对达到阈值的IP自动创建防火墙阻止规则。.VERSION
1.2
#># 设置正确的编码环境(UTF-8)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8# 配置参数
$config = @{LogName = "Security"EventID = 4625TimeRangeDays = 1BlockThreshold = 5MaxEvents = 5000Whitelist = @("192.168.1.100", "10.0.0.1", "127.0.0.1") # 信任IP列表RulePrefix = "AutoBlockRDP" # 防火墙规则前缀LogFile = "D:\SecurityScripts\Logs\RDP_Protection.log" # 日志文件路径
}# 创建日志目录
if (-not (Test-Path (Split-Path $config.LogFile -Parent))) {New-Item -ItemType Directory -Path (Split-Path $config.LogFile -Parent) -Force | Out-Null
}# 记录日志函数
function Write-Log {param([string]$Message,[ValidateSet("INFO","WARNING","ERROR")][string]$Level = "INFO")$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"$logEntry = "[$timestamp][$Level] $Message"Add-Content -Path $config.LogFile -Value $logEntry -Encoding UTF8if ($Level -eq "ERROR") { Write-Error $Message }elseif ($Level -eq "WARNING") { Write-Warning $Message }else { Write-Output $Message }
}# 主程序
try {# 1. 收集日志数据$startTime = (Get-Date).AddDays(-$config.TimeRangeDays)$endTime = Get-DateWrite-Log "开始分析RDP登录失败日志 ($startTime 至 $endTime)"$filter = @{LogName = $config.LogNameID = $config.EventIDStartTime = $startTimeEndTime = $endTime}$events = Get-WinEvent -FilterHashtable $filter -MaxEvents $config.MaxEvents -Oldest -ErrorAction Stop# 2. 统计IP失败次数$ipFailCount = @{}$totalEvents = 0foreach ($event in $events) {$totalEvents++if ($event.Message -match "(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::\d{1,5})?") {$ip = $matches.IPif ($config.Whitelist -notcontains $ip) {$ipFailCount[$ip] = ($ipFailCount[$ip] + 1)}}}Write-Log "共分析 $totalEvents 条日志记录,发现 $($ipFailCount.Count) 个唯一IP地址"# 3. 处理恶意IP$blockedIPs = 0$skippedIPs = 0foreach ($ip in $ipFailCount.Keys) {$failCount = $ipFailCount[$ip]if ($failCount -ge $config.BlockThreshold) {$ruleName = "$($config.RulePrefix)_$ip"# 检查是否已存在规则if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {try {New-NetFirewallRule -DisplayName $ruleName `-Direction Inbound `-Action Block `-RemoteAddress $ip `-Description "自动阻止于 $(Get-Date -Format 'yyyy-MM-dd'), 失败次数: $failCount" `-ErrorAction StopWrite-Log "已创建防火墙规则阻止IP: $ip (失败次数: $failCount)"$blockedIPs++}catch {Write-Log "创建防火墙规则失败 ($ip): $_" -Level "ERROR"}}else {Write-Log "IP $ip 已在阻止列表中 (失败次数: $failCount)"$skippedIPs++}}else {Write-Log "IP $ip 未达阻止阈值 (失败次数: $failCount)"}}# 4. 生成报告$report = @"
===== RDP防护报告 =====
分析时间范围: $($startTime.ToString('yyyy-MM-dd HH:mm')) 至 $($endTime.ToString('yyyy-MM-dd HH:mm'))
分析日志条目: $totalEvents
检测到的唯一IP: $($ipFailCount.Count)
达到阈值的IP: $($ipFailCount.Values.Where({$_ -ge $config.BlockThreshold}).Count)
新增阻止的IP: $blockedIPs
已有规则的IP: $skippedIPs
"@Write-Log $report# 5. 清理旧规则(可选)# Get-NetFirewallRule | Where { $_.DisplayName -like "$($config.RulePrefix)*" -and $_.CreationTime -lt (Get-Date).AddDays(-30) } | Remove-NetFirewallRule}
catch {Write-Log "脚本执行出错: $_" -Level "ERROR"exit 1
}exit 0
0x03 使用PowerShell执行脚本:
.\RDP_Protection.ps1
0x04 设置定时任务
# 创建任务触发器(每15分钟运行一次)
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `-RepetitionInterval (New-TimeSpan -Minutes 15) `-RepetitionDuration ([TimeSpan]::MaxValue)# 创建任务动作
$action = New-ScheduledTaskAction `-Execute "powershell.exe" `-Argument "-ExecutionPolicy Bypass -File `"C:\SecurityScripts\BlockFailedRDP.ps1`""# 注册计划任务
Register-ScheduledTask `-TaskName "RDP防护" `-Trigger $trigger `-Action $action `-RunLevel Highest `-User "SYSTEM" # 使用系统账户运行,最安全# 查看任务是否添加成功
PS C:\Windows\system32> Get-ScheduledTask -TaskName "RDP防护"TaskPath TaskName State
-------- -------- -----
\ RDP防护 Ready
0x05 如果提示系统禁止运行脚本:
# 以管理员身份打开PowerShell
Set-ExecutionPolicy RemoteSigned -Scope Process -Force# 测试运行(不会实际修改防火墙)
cd C:\SecurityScripts
.\BlockFailedRDP.ps1 -WhatIf
如果遇到中文乱码,使用PowerShell命令转换编码,或者用vscode转码。
# 将文件转换为UTF-8 with BOM编码
$content = Get-Content -Path "D:\SecurityScripts\BlockFailedRDP.ps1" -Raw
Set-Content -Path "D:\SecurityScripts\BlockFailedRDP.ps1" -Value $content -Encoding UTF8
其他几种检查方法:
# 1. 检查脚本错误
$Error[0] | Format-List * -Force# 2. 测试事件日志访问
Get-WinEvent -LogName Security -MaxEvents 1 -ErrorAction Stop# 3. 检查防火墙模块
Get-Module -Name NetSecurity -ListAvailable# 4. 查看最近的4625事件
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} -MaxEvents 5 | Select-Object TimeCreated, Message# 备份规则:定期导出防火墙配置
Export-NetFirewallRule -Path "C:\FirewallBackup\firewall-rules.xml"# 查看所有脚本创建的规则
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Block IP *"
} | Format-Table DisplayName, Enabled, Direction, Action# 启用RDP网络级认证(NLA),设置为1
(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication").UserAuthenticationSet-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 1# 修改默认RDP端口,修改注册表
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "PortNumber" -Value 3390
# 重启生效
Restart-Service TermService -Force# 限制RDP访问IP, 创建防火墙规则只允许特定IP访问
New-NetFirewallRule -DisplayName "允许特定IP访问RDP" `-Direction Inbound `-Protocol TCP `-LocalPort 3389,3390 `-RemoteAddress 192.168.1.0/24,123.45.67.89 `-Action Allow
0x99 几种安全措施,根据实际情况选择:
安全措施 | 作用 | 实施方法 |
---|---|---|
修改端口 | 减少扫描攻击 | 注册表 + 防火墙 |
NLA | 防止未授权连接 | 远程桌面设置 |
IP 白名单 | 限制访问来源 | 防火墙/安全组 |
MFA | 防止暴力破解 | 微软 Authenticator |
VPN/RD Gateway | 加密通信 | 企业级部署 |
通过以上方法,可大幅降低 RDP 被攻击的风险。对于企业用户,建议结合 RD Gateway(需要Win服务器) + MFA(需微软账户) + IP 白名单 提供最高级别的保护。
呦,发现github有现成的了
https://gist.github.com/example/secure-rdp-script