
只要通过 RDP 远程桌面协议连接 Windows 设备,就会在系统「事件日志」中留下诸多操作痕迹。安全审计真正的难点在于:如何把远程交互会话从本地控制台登录中剥离出来,再将散落在各处的「事件」串连成一条完整的时间线。
本文梳理了 RDP 连接的关键事件 ID、筛选规则和一整套简单好用的事件关联逻辑,并补充了客户端侧的痕迹排查技巧。整个流程共分为 7 步:定位事件源 → 拉取历史日志 → 关联会话 → 捕获失败与异常事件 → 补齐客户端痕迹 → 日志集中留存 → 输出审计结论。
查看 Windows 远程桌面连接历史
第 1 步:定位事件源
目标: 搞清楚有哪些 Windows 日志记录了身份认证事件,哪些专门承载 RDP 会话与连接上下文。
1按Windows + R打开「运行」对话框,输入eventvwr.msc并回车,打开「事件查看器」。
2分别展开下列路径:
- 「Windows 日志」>「安全」
- 「应用程序和服务日志」>「Microsoft」>「Windows」>「TerminalServices-LocalSessionManager」>「Operational」
- 「应用程序和服务日志」>「Microsoft」>「Windows」>「TerminalServices-RemoteConnectionManager」>「Operational」
3按场景筛选并记录以下核心事件 ID:
| 阶段 | 事件来源 | 关键事件 ID |
|---|---|---|
| 身份验证 | 安全日志 | 4624登录成功、4625登录失败、4634注销、4647用户主动注销 |
| RDP 连接(登录前的连接握手) | RemoteConnectionManager | 1149用户通过远程桌面完成预认证 |
| RDP 会话活动(登录后的会话生命周期) | LocalSessionManager | 21登录、22Shell 启动,桌面真正可用、23注销、24断开连接、25重连 |
第 2 步:使用 PowerShell 批量拉取日志
目标:从多个日志批量导出 RDP 相关事件,用于后续分析或归档。
1右键点击「开始」菜单,选择「终端管理员」,以管理员权限打开 Windows 终端。
2按Ctrl + Shift + 1快捷键,切换到 PowerShell 窗口。
3粘贴下列脚本并回车:
- 把最近 7 天的登录成功/失败事件带上
LogonType和源 IP 一并导出:
# 导出最近 7 天的安全日志(4624 成功、4625 失败),提取登录类型、用户名、来源 IP
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4624,4625
StartTime = (Get-Date).AddDays(-7)
} | ForEach-Object {
$xml = [xml]$_.ToXml()
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
EventID = $_.Id
LogonType = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text'
User = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
IpAddress = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
}
} | Export-Csv C:\Logs\SecurityEvents.csv -NoTypeInformation -Encoding UTF8
先手动创建C:\Logs\目录或换个位置;如需拉取更长时间范围,就把AddDays(-7)中的参数改为对应天数;事件量对应了 CSV 大小。
- 导出本地会话管理器(Local Session Manager, LSM)的完整操作日志:
# 导出 LSM 操作日志,包含会话启动、断开、注销等事件
Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" |
Export-Csv C:\Logs\LSM_Events.csv -NoTypeInformation -Encoding UTF8
第 3 步:关联事件,还原会话时间线
目标:通过匹配用户名、来源 IP 和时间戳等,拼接出完整的会话起止记录。
3.1 方法论
- 匹配
1149事件(RCM 预认证)与4624事件(LogonType = ID,即远程交互式登录)。关联字段为:用户名 + 时间戳(误差 ± 1 分钟)。
| LogonType ID | 含义 | 类型 |
|---|---|---|
2 | 本地控制台登录(直接坐在机器前登录) | 本地登录 |
7 | 解锁屏幕(含 RDP 会话建立时的伴生解锁事件) | 本地登录 |
3 | NLA 模式下的 RDP 远程登录(Windows 默认配置) | RDP 登录 |
10 | 标准 RDP 远程登录(未开启 NLA 时) | RDP 登录 |
在配置 Windows 11 远程桌面连接时,系统通常会默认启用「使用网络级别身份验证」,即 NLA 模式。
- 补充 LSM 的
22事件,确认桌面 Shell 已启动、远程桌面会话真正进入可用状态。 - 以 LSM 的
23事件(注销)或24事件(断开连接但未注销)标定会话结束时间。 - 会话时长 = 结束时间 –
1149事件的时间戳,就能得到完整的会话时长。
之所以这么拼接操作是因为:
- 安全日志中的
4624事件包含了用户名和来源 IP,但无法区分登录渠道; 1149事件明确标识了 RDP 连接请求,但却发生在认证流程完成前。
两者交叉验证,才能准确定位 RDP 会话并获取完整的来源信息,具体如何组合,需要你自由发挥,可以将 CSV 导入到 Excel 进行综合分析。
3.2 具体示例
例如,只需要简单识别出哪个用户、在哪个时间、从哪个 IP,远程登录了这台机器,会话时长是多少,就可以组合出以下 PowerShell 脚本:

#Requires -RunAsAdministrator
# RDP Login Audit | 需管理员权限运行
# 用法:.\RDP_Simple.ps1 [-DaysBack 30] [-OutputPath "D:\Audit\rdp.csv"]
param(
[int] $DaysBack = 7,
[string] $OutputPath = "C:\Logs\RDP_Simple.csv"
)
$OutputDir = Split-Path $OutputPath
if (-not (Test-Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir | Out-Null }
# 1. 登录事件:LogonType 3(NLA 模式)和 10(标准 RDP),排除本机 IP
$logins = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4624
StartTime = (Get-Date).AddDays(-$DaysBack)
} -ErrorAction SilentlyContinue | ForEach-Object {
$xml = [xml]$_.ToXml()
$ns = $xml.Event.EventData.Data
$lt = ($ns | Where-Object Name -eq 'LogonType').'#text'
$ip = ($ns | Where-Object Name -eq 'IpAddress').'#text'
if ($lt -in @('3', '10') -and $ip -and $ip -notmatch '^(::1|127\.|-)') {
[PSCustomObject]@{
LoginTime = $_.TimeCreated
UserName = ($ns | Where-Object Name -eq 'TargetUserName').'#text'
SourceIP = $ip
LogonType = $lt
LogonID = ($ns | Where-Object Name -eq 'TargetLogonId').'#text'
}
}
} | Where-Object { $_.UserName -and $_.UserName -ne '-' }
# 2. 去重:同用户同 IP 5 秒内只保留第一条(每次连接会触发多条重复事件)
$script:lastEvent = $null
$deduped = $logins | Sort-Object LoginTime | ForEach-Object {
$cur = $_
if (-not $script:lastEvent -or
$cur.UserName -ne $script:lastEvent.UserName -or
$cur.SourceIP -ne $script:lastEvent.SourceIP -or
($cur.LoginTime - $script:lastEvent.LoginTime).TotalSeconds -gt 5) {
$script:lastEvent = $cur
$cur
}
}
# 3. 登出事件:4634 系统注销/4647 用户主动注销
$logoffs = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4634, 4647
StartTime = (Get-Date).AddDays(-$DaysBack)
} -ErrorAction SilentlyContinue | ForEach-Object {
$xml = [xml]$_.ToXml()
$ns = $xml.Event.EventData.Data
[PSCustomObject]@{
LogoffTime = $_.TimeCreated
LogonID = ($ns | Where-Object Name -eq 'TargetLogonId').'#text'
}
} | Where-Object { $_.LogonID }
# 4. 用 LogonID 关联登出,计算时长
$result = foreach ($login in $deduped) {
$logoff = $logoffs |
Where-Object {
$_.LogonID -eq $login.LogonID -and
$_.LogoffTime -gt $login.LoginTime
} |
Sort-Object LogoffTime |
Select-Object -First 1
$duration = if ($logoff) {
$span = $logoff.LogoffTime - $login.LoginTime
'{0:D2}:{1:D2}:{2:D2}' -f [int]$span.TotalHours, $span.Minutes, $span.Seconds
} else { '进行中' }
[PSCustomObject]@{
登录时间 = $login.LoginTime
用户名 = $login.UserName
来源IP = $login.SourceIP
登录类型 = if ($login.LogonType -eq '10') { 'RDP 直连' } else { 'RDP (NLA)' }
会话时长 = $duration
}
}
# 5. 导出并预览最近 10 条
$result | Sort-Object 登录时间 |
Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "✅ 完成,共 $($result.Count) 条记录 → $OutputPath" -ForegroundColor Green
$result | Sort-Object 登录时间 -Descending | Select-Object -First 10 | Format-Table -AutoSize
第 4 步:捕获失败事件与异常行为
目标:识别暴力破解(枚举密码反复尝试登录)、撞库(用同一密码横扫多个账户)或越权使用等异常行为。
1按Windows + R打开「运行」对话框,输入eventvwr.msc并回车,打开「事件查看器」。
2展开「Windows 日志」>「安全」。
3在右侧「操作」面板中点击「筛选当前日志…」。
4在「事件 ID」中填入4625,点击「确定」。
5在筛选结果的「常规」或「详细信息」选项卡中,重点关注以下字段:
TargetUserName | 被攻击的目标账户 |
|---|---|
IpAddress | 攻击来源 IP |
Status/SubStatus | 失败原因码,例如0xC000006A表示密码错误,0xC0000234表示账户被锁定 |

第 5 步:补齐客户端侧痕迹
目标:当服务器端日志缺失时,从发起端工作站反查连接目标。
5.1 查找注册表 MRU 记录
1按Windows + R快捷键打开「运行」对话框,执行regedit打开注册表编辑器。
2导航到以下路径:
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default
3右侧会以MRU0、MRU1、MRU2等条目,列出最近连接过的 RDP 服务器名或 IP 地址。

该注册表项仅在使用原生mstsc.exe客户端连接时,才会生成记录。如果用户从未发起过 RDP 连接,或使用第三方远程桌面工具,此处可能为空。
5.2 查找跳转列表文件
「跳转列表」(Jump List)缓存文件本质上是:某个程序最近打开过的文件、目标、连接记录:
1按 Windows + E 快捷键打开「文件资源管理器」,在地址栏访问:
%AppData%\Microsoft\Windows\Recent\AutomaticDestinations\
2按「修改日期」排序,重点关注体积较大或近期改动过的文件。

<hash>.automaticDestinations-ms文件可以通过 JumpListExplorer 等工具深度解析出:最近连接的服务器、访问时间使用的应用(比如mstsc.exe)。即便不解析,文件的存在性与修改时间戳本身也是审计依据。
5.3 查找保存的 .rdp 连接文件
1在「文件资源管理器」中进入以下路径:
C:\Users\<username>\Documents\
2搜索扩展名为.rdp的文件,并记录文件名与修改日期。
.rdp文件属于可选痕迹,只在用户主动保存连接配置时才会生成。找不到不代表没用过 远程桌面。
优化运维与安全审计
第 6 步:日志大小与长期保存
目标:构建持续可见性能力,防止日志滚动覆盖关键审计事件。
6.1 调大日志存储上限
1打开「事件查看器」,进入「Windows 日志」。
2右键点击「安全」,选择「属性」。
3把「最大日志大小」调整为更大的值。
4选择「按需要覆盖事件」或「日志满时将其存档,不覆盖事件」,确认并保存。
安全日志没有放之四海皆准的推荐容量,通常按「预期日均事件量 × 期望保留周期」反推出所需容量。高活跃服务器建议 1GB 起步。
6.2 手动导出日志备份
在「事件查看器」中依次对以下 3 项日志执行「右键」>「将所有事件另存为」操作,保存到可靠位置,并在文件名中添加导出日期:
- 「Windows 日志」>「安全」
- 「应用程序和服务日志」>「Microsoft」>「Windows」>「TerminalServices-LocalSessionManager」>「Operational」
- 「应用程序和服务日志」>「Microsoft」>「Windows」>「TerminalServices-RemoteConnectionManager」>「Operational」
第 7 步:输出结论,把数据变成运维动作
目标:让审计结果真正落地,而不是躺在 CSV 里吃灰。
- 针对重复性失败登录、未知来源 IP 访问、日志覆盖断档等问题,建立运维工单跟进。
- 将完整的会话时间线附入事件复盘报告和服务评审材料。
- 定期复核会话记录覆盖范围与访问例外清单。
RDP 连接历史审计最佳实践
下表汇总了日常审计中可以落地的经验:
| 做法 | 目的 | 实际价值 |
|---|---|---|
| 同时采集安全日志、LSM、RCM 三类日志 | 扩大审计覆盖面 | 排查效率更高,判断依据更充分 |
按LogonType = ID与事件 ID 组合筛选 | 精准分类事件 | 清晰区分 RDP 登录与本地控制台登录 |
| 关联预认证事件与认证完成事件 | 准确来源归因 | 实现用户身份与访问 IP 的一一映射 |
| 统一导出为 CSV 或 JSON 格式 | 标准化数据源 | 支持重复审计与业务复盘场景 |
| 集中转发并长期留存日志 | 提升数据可靠性 | 可随时调取完整的历史会话时间线 |
常见问题解答
如何快速区分到底是 RDP 还是本地控制台登录?
查看安全日志4624事件中的LogonType字段即可快速判定:10代表标准 RDP 远程交互登录,3代表 NLA 模式下的 RDP 登录,7为解锁屏幕,2为本地控制台登录。只要筛选出LogonType等于3和10的记录,就能得到所有 RDP 登录事件。
登录失败事件 4625 里常见的 Status 报错码怎么解读?
常见的Status/SubStatus状态码含义如下:
0xC000006A:密码错误0xC0000064:用户名不存在0xC0000234:账户被锁定0xC000006F:非允许登录时段0xC0000193:账户已过期
若短时间内同一 IP 触发大量0xC000006A错误,基本可判定为暴力破解尝试。0064多为撞用户名(字典扫描),006A多为密码爆破(已命中用户)。












最新评论
提供snap包没意见,但是移除deb,还把deb改成虚包指向snap,实在是让人作呕
为什么关机关电源后,开机时打开电源就开机了。对电脑有损伤吗?
有多亮,是blingbling的吗🤣
这个网站眼前一亮