内网横移中的RDP威胁狩猎
在大量真实入侵事件中,远程桌面协议(RDP)几乎已经成为攻击者进行横向移动的“标配工具”。这个最初由微软设计、用于远程系统管理和运维的协议,在现实环境中却频繁被滥用,成为内网扩散和权限放大的关键通道。
从应急响应的角度来看,RDP 的危险之处并不在于它本身有多“恶意”,而在于它太正常了。正因为企业日常运维和远程办公高度依赖 RDP,攻击者的行为很容易隐藏在合法流量和正常操作之中。
为什么 RDP 会成为内网横移的首选
在一次典型的入侵中,攻击者往往并不会满足于最初控制的一台主机。真正的目标通常是更有价值的系统,比如文件服务器、数据库服务器,甚至是域控。
横向移动就是攻击者在已经拿下一台主机后,利用凭据、信任关系或系统配置,在同一信任域内不断扩展控制范围的过程。和“纵向提权”不同,横向移动更像是在内网中“悄悄换房间”。
RDP 在这个阶段非常好用,原因很简单:
- 它提供完整的图形界面,攻击者可以像真正的用户一样操作系统
- 不需要复杂的工具链,一个系统自带的 RDP 客户端就够了
- 合法运维行为天然为攻击行为提供了掩护
在多起应急响应案例中,都能看到:攻击者最终横向移动的“最后一公里”,往往就是 RDP。
常见的 RDP 横向移动手法
凭据窃取与复用
这是最常见、也是最有效的一种方式。在已经被控制的主机上,攻击者通常会想办法获取更多账号凭据,例如:
- 从 LSASS 内存中提取明文密码或哈希值
- 通过键盘记录截获用户输入
- 利用系统缓存的凭据或票据
在真实事件中,“Pass-the-Hash” 尤其常见。攻击者并不需要破解密码,只要拿到 NTLM 哈希,就可以直接通过 RDP 或其他远程协议完成认证。一旦这些凭据在多台机器上复用,横向移动就会变得异常顺畅。
RDP 会话劫持
相比新建连接,会话劫持更加隐蔽。
攻击者会先枚举系统中已有的 RDP 会话,然后通过提权操作获取 SYSTEM 权限,直接接管已有会话的令牌,并将会话重定向到自己的客户端。
这种方式最大的特点是:几乎不会产生新的登录事件,对日志分析和规则检测极不友好。在很多情况下,只有通过内存取证或异常行为分析才能发现蛛丝马迹。
利用 RDP 协议漏洞
历史上,RDP 也曾多次成为高危漏洞的重灾区。

最著名的例子是 BlueKeep(CVE-2019-0708),该漏洞允许攻击者在无需有效凭据的情况下直接远程执行代码。类似的漏洞(如 DejaBlue)也曾被用于在内网中快速横向传播。
在应急响应中,一旦发现老旧系统开启了 RDP 且未打补丁,往往需要优先评估是否存在“无凭据横向移动”的风险。
从事件日志入手定位 RDP 行为
在真实的应急响应过程中,事件日志往往是我们最先接触、也是最容易被攻击者“动手脚”的数据源之一。但即便如此,Windows 仍然会在多个位置记录 RDP 相关行为,只要理解这些日志之间的关联关系,就很难被完全清除干净。
一个非常重要的认知是:一次 RDP 行为,日志并不只存在于一台主机上。
- 发起 RDP 的源主机会留下网络与身份相关痕迹
- 被登录的目标主机会记录会话、登录和桌面初始化过程
这对于分析横向移动尤其关键,因为攻击者不可能同时完美清理所有系统。
内网横移 vs 外部入侵 差异
在内网横向移动场景中(比如攻击者从一台已控主机跳到另一台内网服务器),我们往往可以同时看到源主机和目标主机的日志,这为溯源提供了极大的便利。
而在外部攻击场景中,如果攻击者是从互联网直接连接暴露在公网的 RDP 服务器,那么我们通常只能看到目标系统的日志,因为源主机并不在我们的取证范围内。
理解这一点,有助于我们在事件分析阶段合理调整预期,不会“执着地去找不存在的日志”。
Terminal Services :识别 RDP 尝试的入口
在所有与 RDP 相关的日志中,有一个经常被忽视、但价值极高的日志源:
Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
这个日志有一个非常重要的特点:
无论 RDP 是否最终登录成功,只要发生连接尝试,就会被记录。
其中最核心的事件是:Event ID 1149
这个事件表示一次 RDP 连接尝试已经发生。需要特别注意的是,1149 并不等同于“成功登录”,它只能说明:有人尝试通过 RDP 与这台主机建立会话。

在应急响应中,我们通常把 1149 当作**“RDP 行为的存在性证据”**,而不是成功入侵的直接证明。
很多应急响应的初学者看到事件描述中的 “User authentication succeeded” 就会误判为成功登录,但实际上,这里指的是 NLA(Network Level Authentication)阶段通过,并不代表用户已经进入桌面。
安全日志中的关键证据:4624 登录事件
如果说 1149 是“敲门声”,那么 Windows Security 日志中的 4624,才是真正的“进门记录”。
Event ID 4624 – An account was successfully logged on
这是 Windows 中最重要的认证事件之一,包含了大量对溯源至关重要的信息,例如:
- 登录时间(UTC)
- 使用的账号
- 源 IP 地址
- 登录类型(Logon Type)
- 源工作站名称
在分析 RDP 横向移动时,Logon Type 是重中之重。
Logon Type 是理解 RDP 的核心
Windows 一共定义了多种登录类型,但在 RDP 场景下,真正需要重点关注的只有几种:
- Logon Type 2(Interactive):本地物理登录
- Logon Type 3(Network):网络级认证(几乎所有远程登录都会出现)
- Logon Type 5(Service):当 Windows 服务使用服务账户进行身份验证以运行后台进程时触发。
- Logon Type 7(Unlock):解锁已有会话
- Logon Type 10(RemoteInteractive):典型的 RDP 新会话登录
一个非常关键、但在实战中经常被忽略的细节是:
RDP 登录并不是只出现 Logon Type 10
在一次完整的 RDP 登录过程中,通常会先出现 Logon Type 3,随后才是 Logon Type 10 或 7。这意味着,如果只盯着 Type 10,很容易漏掉真实的攻击行为。
新建会话 vs 重连会话

这里有一个在实战中非常有价值的判断点。
- 如果攻击者使用一个从未在该系统登录过的账号通过 RDP 登录,通常会看到 Logon Type 10
- 如果攻击者使用的是已经存在的会话账号(比如管理员之前登录过),那么更可能看到的是 Logon Type 7(Unlock)
这在横向移动中非常常见。攻击者往往不会频繁新建会话,而是反复“接管”已有会话,以降低日志噪音。

因此,在日志中看到大量重复的 Logon Type 7,而不是 Type 10,本身就是一个值得警惕的信号。
会话生命周期日志:确认攻击者是否真正进入桌面
仅靠 4624 还不足以完全确认攻击者是否成功操作系统。接下来需要结合另一个日志源:
Microsoft-Windows-TerminalServices-LocalSessionManager/Operational
这个日志记录的是 RDP 会话从创建、初始化到断开的完整生命周期。

在应急响应中,我们重点关注几个事件:
- Event ID 21:RDP 会话登录成功
- Event ID 22:用户 Shell(如 Explorer)启动
- Event ID 25:会话重新连接成功
- Event ID 24 / 39 / 40:会话断开
当在同一个 Session ID 下,看到 21 和 22 连续出现时,基本可以确认:攻击者已经成功进入图形桌面,并具备完整操作能力这一步,对于判断攻击是否进入“实质性操作阶段”非常关键。
断开 ≠ 登出:攻击者维持访问的常见方式
很多人误以为关闭 RDP 窗口就等同于退出系统,但实际上这只是断开会话。在断开而非登出的情况下:
- 会话仍然存在于内存中
- 下次连接不会触发完整的登录流程
- 日志中往往只出现 Logon Type 7(Unlock)
攻击者非常喜欢这种方式,因为它能:
- 减少新登录事件
- 避免引起基于 Type 10 的告警
- 快速恢复访问
在日志中,如果看到频繁出现:
- Session disconnect(24 / 40)
- Session reconnect(25)
- 配合 Logon Type 7
那么就需要高度怀疑这是一个被反复利用的 RDP 会话。
从进程执行痕迹还原 RDP 行为
在很多真实的入侵事件中,攻击者都会尝试清理或篡改事件日志。这个时候,如果分析只停留在 Event Log 层面,结论往往是不完整的,甚至会被误导。
在应急响应中,一个非常重要的原则是:
日志用来“指方向”,执行痕迹用来“定事实”。
进程执行证据,恰好是验证 RDP 行为是否真实发生、是否被攻击者实际使用过的关键补充。
从两端入手:源主机与目标主机的角色差异
分析 RDP 的进程执行行为时,必须明确一个前提:
RDP 是一个“跨主机行为”,两端留下的痕迹完全不同。
- 源主机(发起 RDP 的机器)
攻击者主动操作,通常通过 GUI 启动远程桌面客户端 - 目标主机(被登录的机器)
系统被动接收连接,相关进程由系统自动拉起
这一差异,直接决定了我们在两端应该关注哪些取证点。
源主机的 mstsc.exe 是最直接的突破口

在内网横向移动场景中,攻击者通常已经控制了一台工作站或服务器,并以此作为跳板,去连接下一个目标。当攻击者在源主机上发起 RDP 时,几乎一定会执行一个进程:
mstsc.exe(Microsoft Remote Desktop Client)
这是 Windows 自带的远程桌面客户端,大多数情况下通过 GUI 启动。因此,在源主机上,我们重点关注的不是“系统级服务”,而是用户侧执行痕迹。输出框的下拉按钮会展示历史的连接记录。
UserAssist:确认攻击者是否真的“点过远程桌面”
在所有 GUI 执行证据中,UserAssist 的价值非常高。它记录在用户的 NTUSER.DAT 中,反映的是用户实际交互过的程序,这点对判断“人为操作”尤其重要。

C:\Users\用户名\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist
通过 UserAssist,我们通常可以获取到:
- 程序的名称(如 Microsoft.Windows.RemoteDesktop)
- 启动次数(Run Counter)
- 窗口处于前台的时间(Focus Time)
- 最近一次执行时间
在应急响应中,一旦在 UserAssist 中看到远程桌面客户端,并且时间点与可疑 RDP 登录行为吻合,基本可以确认:这不是系统行为,而是一次明确的人工操作。这对判断是否为横向移动,而非运维自动化行为,意义非常大。

建议:用RegistryExplorer来查看NTUSER.DAT文件,不要用系统自带的注册表工具(只能看到未解码的数据)。
BAM:从系统层面印证执行行为
为了避免单一证据点造成误判,我们通常会进一步查看 BAM(Background Activity Moderator)。
SYSTEM\bam\State\UserSettings\<USER-SID>
BAM 位于 SYSTEM 注册表中,记录的是进程在后台被执行的时间信息。在 BAM 中再次看到 mstsc.exe,且时间与 UserAssist 对齐时,这种“交叉验证”会让证据更充分。

这个截图是Windows11上的,实测很多Windows Server系统版本并没有BAM的记录。因为BAM本质上是:Windows 为“电源 / 资源调度”设计的后台程序活动记录机制。而且BAM 不是只要执行进程就记录。它更偏向记录:后台运行、长时间存活的进程。
目标主机视角:系统拉起的进程
和源主机不同,目标主机上的 RDP 相关进程,并不是由用户手动启动的,而是由系统在会话建立过程中自动拉起。因此,这里有一个非常重要的取证误区需要避免:
不要在目标主机上找 UserAssist 或 RecentDocs 里的 RDP 痕迹
你什么都找不到,这是正常的。在目标主机上,我们关注的是系统执行证据,其中最直观的就是 Prefetch。
目标主机上常见的 RDP 相关进程

在一次完整的 RDP 会话中,目标系统通常会执行以下进程:
- tstheme.exe:负责远程桌面会话的主题与界面
- rdpclip.exe:处理剪贴板重定向(复制 / 粘贴)
这两个进程的出现,往往意味着:攻击者已经进入图形桌面,并开始进行真实操作。
Prefetch:确认 RDP 会话的存在与时间范围
在开启 Prefetch 的系统上,这些进程通常都会留下 Prefetch 文件。通过解析 Prefetch,我们可以获取到:
- 进程是否被执行过
- 最近一次执行时间
- 执行次数

在时间线分析中,一个非常关键的点是:
- 源主机 mstsc.exe 的执行时间
- 目标主机 tstheme.exe / rdpclip.exe 的执行时间
这两者之间通常只相差几秒钟到几十秒,这个时间差正好对应 RDP 会话建立过程。

在应急响应中,这种跨主机、跨证据源的时间线对齐,是判断横向移动是否真实发生的“铁证”。
Prefetch 不存在怎么办?
需要注意的是,在很多 Windows Server 环境中,Prefetch 默认是关闭的。这并不意味着就无法分析。
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v EnablePrefetcher

在这种情况下,可以考虑:
- Shimcache
- Amcache
- 结合事件日志中的会话 ID 和登录行为
核心思想不是“非要某一种证据”,而是用多种弱证据拼出一个强结论。
在大量真实案例中,我们都遇到过类似情况:
- 日志被清空或不完整
- SIEM 中只有零散的认证事件
- 攻击者否认进行过横向移动
而进程执行证据,尤其是 UserAssist + Prefetch 的组合,往往能直接击穿这些不确定性。它回答的不是“有没有登录”,而是:攻击者是否真的在远程桌面前操作过这台机器。
注册表里的RDP历史痕迹
在应急响应中,注册表往往不是第一时间被关注的对象。很多应急人员更习惯先看日志、再看进程执行,但在不少真实案件中,真正补全攻击路径的,反而是注册表里那些看似不起眼的键值。
对于 RDP 横向移动来说,有一个注册表位置,几乎可以称得上是“低调但杀伤力极强”。
Terminal Server Client:RDP 连接的“使用记录”

当攻击者使用 Windows 自带的远程桌面客户端(mstsc.exe) 发起连接时,系统会在用户级注册表中留下连接历史。这些信息存放在:
NTUSER.DAT
└─ Software
└─ Microsoft
└─ Terminal Server Client
└─ Servers
这个位置有几个非常重要的特点:
- 位于 用户的 NTUSER.DAT 中,具备明确的用户归属
- 记录的是 曾经连接过的远程主机
- 不依赖事件日志是否开启
- 通常不会被攻击者主动清理
在“攻击者有意识清日志,但没想到清注册表”的场景中,这个位置经常成为关键突破口。
在 Servers 键下,会看到一组以 MRU 开头的值,这些值代表的是 Most Recently Used(最近使用) 列表:
- MRU0:最近一次 RDP 连接
- 数字越大,时间越早
每一个 MRU 值中,保存的都是攻击者通过 RDP 连接过的 主机名或 IP 地址。在横向移动分析中,可以直接看到攻击者“按顺序去过哪些机器”。
如果点开 Terminal Server Client 的上层键,会发现这里不仅记录了目标主机信息,还往往能看到:
- 使用的用户名
- 注册表键的最后写入时间(LastWrite Time)
这两个信息,在应急响应中非常关键。当能把 RDP 目标主机 + 用户账号 + 时间戳 放在一起时,很多原本模糊的行为,就会突然变得非常清晰。
为什么这个注册表证据如此重要?
从实战经验来看,这个位置的价值主要体现在三个方面:
第一,它天然具备“用户归因能力”。
相比系统级日志,NTUSER.DAT 明确对应某一个用户配置文件,几乎不存在“到底是谁干的”这种歧义。
第二,它反映的是“真实使用行为”。
只有通过 Windows 原生 RDP 客户端发起的连接,才会在这里留下记录。这意味着它更接近“人为操作”,而不是脚本或服务行为。
第三,它极难被完全抹除。
攻击者即便清理事件日志,也很少会逐个用户加载 NTUSER.DAT 并清空相关键值。这使得它在事后取证中存活率极高。
Bitmap Cache:从“行为证据”跃迁到“行为画面”
在大多数应急响应场景中,我们习惯用日志、进程、注册表去回答一个问题:攻击者有没有做过某件事?
而 Bitmap Cache 提供的,是一个更激进、也更直观的能力:攻击者当时在屏幕前“看到了什么、点了什么”。这在 Windows 取证体系中是极其罕见的。
Bitmap Cache 的本质:RDP 的性能优化产物
从技术原理上看,Bitmap Cache 并不是为了取证而设计的。

在 RDP 会话中,为了减少带宽占用、提升图形刷新效率,系统会将常用的界面元素拆分成小块(tile),并缓存在客户端本地。当这些界面再次出现时,就无需重新从远端传输。
这些缓存文件,默认存放在:
C:\Users\<Username>\AppData\Local\Microsoft\Terminal Server Client\Cache\
对于攻击者来说,这只是性能优化;对于应急响应人员来说,这是一次完整远程桌面操作留下的“视觉残留”。
在 Bitmap Cache 目录中,通常会看到类似:
- Cache0000.bin
- Cache0001.bin
- Cache0002.bin
这些编号并不是随机的,而是按 RDP 会话顺序递增的:
- 数字越大,通常代表越新的会话
- 最新一次横向移动,往往就藏在编号最大的文件中
在实战中,这一点非常重要,因为它让我们可以快速聚焦到最有价值的一次会话,而不是被历史缓存淹没。
从“碎片”到“画面”:专用拼图工具
https://github.com/ANSSI-FR/bmc-tools
Bitmap Cache 文件本身是不可读的,它们存储的是大量零散的图形块。单独看任何一个 tile,都几乎没有意义。这也是为什么 Bitmap Cache 长期被忽视——直到专门的解析和拼接工具出现。

通过 Bitmap Cache 解析工具,我们可以:
- 将缓存中的图形块导出为图片
- 自动生成拼接预览图(collage)
- 再进一步重建接近真实桌面的截图

虽然无法保证 100% 还原,但在多数场景下,80%~90% 的画面可读性已经足够用于取证和归因。
RDP爆破:横向移动最常见的起点
在很多真实事件中,RDP 横向移动并不是从“高端技巧”开始的。相反,它往往源于一种非常原始、甚至看起来有些“粗糙”的手段——暴力破解或密码喷洒。
但正是这种方式,在大量企业内网中依然屡试不爽。
暴力破解并不隐蔽但经常被忽略

从检测角度看,RDP 暴力破解其实并不难发现。在 Windows 安全日志中,它通常表现为:
- 大量 Event ID 4625(登录失败)
- 在极短时间内集中出现
- 源 IP 或源工作站高度一致
在一些案例中,几十甚至上百次失败登录,发生在一分钟之内,但却没有触发任何告警。这并不是因为攻击者多高明,而是因为内部网络默认被认为是“可信的”。
一个很有价值的细节:源主机名

在很多真实环境中,暴力破解的“源主机名”本身就是一个强烈信号。
- 明显不符合企业命名规范
- 出现渗透测试或攻击系统常见的名称
- 或者来自一台本不应该主动连接其他系统的终端
即便攻击者对 IP 做了隐藏,工作站名依然会在日志中留下痕迹。在应急响应中,这往往是确定“攻击起点”的重要线索。
典型的真实攻击场景
在多起实战案例中,攻击路径往往高度相似:
攻击者通过钓鱼邮件拿下一台普通员工的工作站。随后利用漏洞或配置问题完成本地提权。在系统中运行凭据抓取工具,获取曾经登录过该主机的高权限账号信息。使用这些凭据,通过 RDP 登录到其他服务器。在新的系统中重复上述过程,逐步逼近域控。最终的结果,往往是整个域环境被完全控制。
再举个常见的例子:如果员工通常在早上 9 点到下午 5 点之间通过 RDP 登录办公主机,那么凌晨 3 点、周末或节假日出现的 RDP 登录行为,就值得高度警惕。
再比如,如果一台人力资源部门hr的电脑,突然尝试通过 RDP 连接运维系统或服务器集群,这在正常业务场景下几乎说不通。攻击者正是利用了“RDP 本身是合法行为”这一点,刻意选择非工作时间、跨部门系统进行操作,以降低被人工或自动化监控发现的概率。
从应急响应的角度看,这类事件真正的“失控点”,并不在最后一步,而在最初那几次异常的 RDP 登录行为。
赞赏
微信赞赏
支付宝赞赏
目前为止有一条评论