diff --git a/rdp_login_success_script.ps1 b/rdp_login_success_script.ps1 new file mode 100644 index 0000000..eba88a6 --- /dev/null +++ b/rdp_login_success_script.ps1 @@ -0,0 +1,179 @@ +# 服务器登录监控脚本 - 完整版(监控所有RDP相关登录类型) +# 监控远程桌面登录并通过钉钉机器人推送通知(支持加签) + +param ( + [string]$DingTalkWebhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=d28bd09159097d9cc5793a183990927ce637bd8addafb5e4586e2687ca317039", + [string]$DingTalkSecret = "SECd4bf3fb7703bd2826896deefa68d579e9945a67058ee9047ac5f8757ae800729" +) + +# 钉钉消息发送函数(支持加签) +function Send-DingTalkMessage { + param( + [string]$消息内容 + ) + + try { + # 计算签名 + $timestamp = [DateTimeOffset]::Now.ToUnixTimeMilliseconds() + $stringToSign = "$timestamp`n$DingTalkSecret" + + $hmacsha = New-Object System.Security.Cryptography.HMACSHA256 + $hmacsha.key = [Text.Encoding]::UTF8.GetBytes($DingTalkSecret) + $signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)) + $signatureBase64 = [Convert]::ToBase64String($signature) + $encodedSignature = [System.Web.HttpUtility]::UrlEncode($signatureBase64) + + # 完整的请求URL + $fullUrl = "$DingTalkWebhookUrl×tamp=$timestamp&sign=$encodedSignature" + + $body = @{ + msgtype = "text" + text = @{ + content = $消息内容 + } + } | ConvertTo-Json -Depth 10 + + $response = Invoke-RestMethod -Uri $fullUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8" + Write-Host "✓ 钉钉消息发送成功: $($response.errmsg)" -ForegroundColor Green + } catch { + Write-Error "✗ 钉钉消息发送失败: $_" + } +} + +# 登录类型说明 +$登录类型说明 = @{ + "2" = "交互式登录(本地控制台)" + "3" = "网络登录(含NLA身份验证)" + "4" = "批处理(计划任务)" + "5" = "服务登录" + "7" = "会话解锁" + "8" = "网络明文(如IIS基本认证)" + "9" = "新凭证(RunAs)" + "10" = "远程交互(RDP无NLA)" + "11" = "缓存交互(域凭据缓存)" +} + +# 程序启动信息 +Write-Host "========================================" -ForegroundColor Cyan +Write-Host " 服务器登录监控服务已启动" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "服务器名称: $env:COMPUTERNAME" -ForegroundColor Yellow +Write-Host "启动时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow +Write-Host "监控类型: 所有远程桌面相关登录(类型3、7、10)" -ForegroundColor Yellow +Write-Host "检查间隔: 5秒" -ForegroundColor Yellow +Write-Host "========================================" -ForegroundColor Cyan + +# 记录上次检查的时间 +$上次检查时间 = (Get-Date).AddHours(-1) +# 记录已发送过的登录事件,避免重复通知 +$已通知事件 = @{} + +# 主循环 +while ($true) { + try { + # 获取新的登录事件(Event ID 4624) + $事件列表 = Get-WinEvent -FilterHashtable @{ + LogName = 'Security' + ID = 4624 + StartTime = $上次检查时间 + } -ErrorAction SilentlyContinue + + foreach ($事件 in $事件列表) { + # 解析事件XML + $事件Xml = [xml]$事件.ToXml() + + # 获取登录类型 + $登录类型 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "LogonType"}).'#text' + + # 监控所有可能的远程桌面相关登录类型:3(NLA验证)、7(解锁)、10(传统RDP) + if ($登录类型 -eq "3" -or $登录类型 -eq "7" -or $登录类型 -eq "10") { + # 获取登录信息 + $用户名 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetUserName"}).'#text' + $域名 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetDomainName"}).'#text' + $来源IP = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "IpAddress"}).'#text' + $登录时间 = $事件.TimeCreated + $记录ID = $事件.RecordId + $登录GUID = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "LogonGuid"}).'#text' + + # 过滤本地IP和无效IP + $有效IP = $来源IP -and $来源IP -ne "127.0.0.1" -and $来源IP -ne "::1" -and $来源IP -ne "-" + + if ($有效IP) { + # 生成唯一标识,避免重复通知 + $事件标识 = "$记录ID-$来源IP-$用户名" + + if (-not $已通知事件.ContainsKey($事件标识)) { + # 清理过旧的记录,避免内存溢出 + if ($已通知事件.Count -gt 1000) { + $已通知事件.Clear() + } + + # 处理空域名 + if ([string]::IsNullOrEmpty($域名) -or $域名 -eq "-") { + $域名 = $env:COMPUTERNAME + } + + # 获取登录类型说明 + $类型说明 = if ($登录类型说明.ContainsKey($登录类型)) { + $登录类型说明[$登录类型] + } else { + "未知类型($登录类型)" + } + + # 添加额外说明 + $额外说明 = "" + if ($登录类型 -eq "3") { + $额外说明 = "(使用NLA验证的RDP连接)" + } elseif ($登录类型 -eq "7") { + $额外说明 = "(远程会话解锁)" + } elseif ($登录类型 -eq "10") { + $额外说明 = "(传统RDP连接)" + } + + # 构建钉钉消息 + $消息内容 = @" +【服务器登录告警】 +━━━━━━━━━━━━━━━━━━━━━━ +🏢 服务器:$env:COMPUTERNAME +📅 时间:$($登录时间.ToString('yyyy-MM-dd HH:mm:ss')) +👤 用户:$域名\$用户名 +🔑 登录类型:$类型说明 $额外说明 +🌐 来源IP:$来源IP +📝 记录ID:$记录ID +━━━━━━━━━━━━━━━━━━━━━━ +"@ + + # 显示日志 + Write-Host "`n[$(Get-Date -Format 'HH:mm:ss')] 检测到新的远程登录" -ForegroundColor Yellow + Write-Host " 用户: $域名\$用户名" -ForegroundColor White + Write-Host " 类型: $类型说明 $额外说明" -ForegroundColor Cyan + Write-Host " 来源IP: $来源IP" -ForegroundColor White + Write-Host " 时间: $($登录时间.ToString('HH:mm:ss'))" -ForegroundColor White + + # 发送钉钉通知 + Send-DingTalkMessage -消息内容 $消息内容 + + # 记录已通知 + $已通知事件[$事件标识] = $true + } + } + } + } + + # 更新上次检查时间 + $上次检查时间 = Get-Date + + # 显示运行状态(每5分钟显示一次) + if (((Get-Date).Minute % 5) -eq 0 -and (Get-Date).Second -lt 5) { + Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 监控运行中,已监控到 $($已通知事件.Count) 次登录" -ForegroundColor Gray + } + + # 等待5秒后继续检查 + Start-Sleep -Seconds 5 + + } catch { + Write-Error "监控过程发生错误: $_" + Write-Host "等待10秒后重试..." -ForegroundColor Red + Start-Sleep -Seconds 10 + } +} \ No newline at end of file