横向移动检测
横向移动(Lateral Movement)是攻击链中从初始落脚点扩展到其他主机的关键阶段
检测横向移动 = 确定攻击范围的核心手段; 错过任何一台被控主机都意味着清除不彻底
本章逐一分析每种横向移动技术的原理、事件日志和检测命令
交叉参考: 03-事件日志分析 | 28-AD持久化-Golden-Silver-Ticket
一、横向移动全景概览
1.1 技术分类
| 技术 |
协议/机制 |
典型工具 |
落地方式 |
| PsExec |
SMB + Service |
Sysinternals PsExec, Impacket |
服务二进制 |
| WMI |
DCOM/WMI |
wmic, Impacket wmiexec |
进程创建 |
| WinRM |
HTTP(5985)/HTTPS(5986) |
Enter-PSSession, evil-winrm |
PS Remoting |
| DCOM |
DCOM |
MMC20.Application |
进程创建 |
| SMB |
SMB(445) |
net use, copy |
文件传输 |
| RDP |
RDP(3389) |
mstsc, SharpRDP |
交互式会话 |
| Scheduled Task |
RPC |
schtasks /create /s |
计划任务 |
| Pass-the-Hash |
NTLM认证 |
mimikatz, Impacket |
各种 |
| Pass-the-Ticket |
Kerberos |
mimikatz, Rubeus |
各种 |
| SCM |
RPC + Service |
sc.exe \remote |
服务创建 |
1.2 通用检测思路
源主机(Source): 搜索远程连接发起痕迹
4648 (Explicit Credential Logon) — 使用非当前用户凭据的登录
网络连接到目标主机的445/135/5985/3389端口
目标主机(Destination): 搜索远程登录到达痕迹
4624 (Logon Success) — 关注Logon Type 3/10
4672 (Special Privileges) — 管理员登录
新创建的服务(7045)、计划任务(4698)
网络层: 搜索内网横向流量异常(正常工作站间不应有SMB/WMI通信)
二、PsExec 检测
2.1 PsExec原理
通过SMB(445端口)连接目标主机的 ADMIN$ 或 IPC$ 共享
上传服务可执行文件到 C:\Windows\ (如 PSEXESVC.exe)
通过Service Control Manager (SCM)远程创建并启动服务
服务建立命名管道(Named Pipe)进行I/O通信
执行完毕后删除服务和文件(但日志保留)
Impacket的psexec.py行为类似,但服务名和文件名随机化
2.2 目标主机事件日志
Event ID 7045 — 服务安装 ★关键
1 2 3 4 5 6 7 8 9
| Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045} | Select-Object TimeCreated, @{N='ServiceName';E={$_.Properties[0].Value}}, @{N='ImagePath';E={$_.Properties[1].Value}}, @{N='ServiceType';E={$_.Properties[2].Value}}, @{N='StartType';E={$_.Properties[3].Value}}, @{N='AccountName';E={$_.Properties[4].Value}} | Format-List
|
PsExec特征:
官方PsExec: 服务名 PSEXESVC, ImagePath %SystemRoot%\PSEXESVC.exe
Impacket: 服务名随机(8字符), ImagePath为随机.exe或cmd.exe /c ...
Cobalt Strike: 服务名随机(7-8字符), ImagePath通常是rundll32.exe或管道命令
1 2 3 4 5 6 7 8 9
| Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045} | Where-Object { $imagePath = $_.Properties[1].Value $imagePath -match 'cmd\.exe|powershell|rundll32|PSEXESVC|%COMSPEC%' -or $_.Properties[0].Value.Length -le 8 } | Select-Object TimeCreated, @{N='ServiceName';E={$_.Properties[0].Value}}, @{N='ImagePath';E={$_.Properties[1].Value}} | Format-List
|
Event ID 4624 — 登录成功 (Type 3)
PsExec使用Network Logon (Type 3)
1 2 3 4 5 6 7 8 9 10
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[8].Value -eq 3 } | Select-Object TimeCreated, @{N='TargetUser';E={$_.Properties[5].Value}}, @{N='SourceIP';E={$_.Properties[18].Value}}, @{N='LogonProcess';E={$_.Properties[9].Value}}, @{N='AuthPackage';E={$_.Properties[10].Value}} | Where-Object { $_.SourceIP -ne '-' -and $_.SourceIP -ne '::1' } | Sort-Object TimeCreated -Descending | Select-Object -First 50
|
Event ID 5145 — 共享对象访问
可检测到对 ADMIN$ 和 IPC$ 共享的访问
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5145} | Where-Object { $_.Properties[8].Value -match 'ADMIN\$|IPC\$' } | Select-Object TimeCreated, @{N='Account';E={$_.Properties[1].Value}}, @{N='SourceIP';E={$_.Properties[5].Value}}, @{N='ShareName';E={$_.Properties[8].Value}}, @{N='RelativePath';E={$_.Properties[9].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
Named Pipe检测 (Sysmon ID 17/18)
PsExec使用 \PSEXESVC 管道; Cobalt Strike使用自定义管道
1 2 3 4 5 6 7
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=17,18} | Select-Object TimeCreated, Id, @{N='Image';E={$_.Properties[4].Value}}, @{N='PipeName';E={$_.Properties[5].Value}} | Where-Object { $_.PipeName -match 'PSEXE|msagent_|postex_|status_|msse-|\\\\pipe\\\\[a-f0-9]{7,8}' } | Format-List
|
2.3 源主机检测
1 2 3 4 5 6 7 8 9
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4648} | Select-Object TimeCreated, @{N='SubjectUser';E={$_.Properties[1].Value}}, @{N='TargetUser';E={$_.Properties[5].Value}}, @{N='TargetServer';E={$_.Properties[8].Value}}, @{N='ProcessName';E={$_.Properties[11].Value}} | Where-Object { $_.ProcessName -match 'PsExec|cmd|powershell' } | Format-List
|
三、WMI (Windows Management Instrumentation) 检测
3.1 WMI横向移动原理
通过DCOM(135端口+动态端口)连接目标主机的WMI服务
调用 Win32_Process.Create() 在目标主机上创建进程
常见工具: wmic /node:target process call create "cmd.exe /c ...", Impacket wmiexec.py
特点: 不安装服务、不留可执行文件,但进程的父进程是 WmiPrvSE.exe
3.2 检测事件
目标主机 — 进程创建
1 2 3 4 5 6 7 8 9 10
|
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1} | Where-Object { $_.Properties[20].Value -match 'WmiPrvSE\.exe' } | Select-Object TimeCreated, @{N='Image';E={$_.Properties[4].Value}}, @{N='CommandLine';E={$_.Properties[10].Value}}, @{N='User';E={$_.Properties[12].Value}}, @{N='ParentImage';E={$_.Properties[20].Value}} | Format-List
|
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688} | Where-Object { $_.Properties[13].Value -match 'WmiPrvSE\.exe' } | Select-Object TimeCreated, @{N='NewProcess';E={$_.Properties[5].Value}}, @{N='CommandLine';E={$_.Properties[8].Value}}, @{N='ParentProcess';E={$_.Properties[13].Value}} | Format-List
|
WMI-Activity Operational日志
1 2 3 4
| Get-WinEvent -LogName 'Microsoft-Windows-WMI-Activity/Operational' -ErrorAction SilentlyContinue | Where-Object { $_.Id -eq 5857 -or $_.Id -eq 5858 -or $_.Id -eq 5859 -or $_.Id -eq 5860 -or $_.Id -eq 5861 } | Select-Object TimeCreated, Id, Message -First 30 | Format-List
|
Event ID 5857: WMI provider加载
Event ID 5858: WMI查询错误(攻击失败时)
Event ID 5861: WMI永久事件订阅(持久化!)
登录事件
WMI远程执行产生 4624 Type 3 + 4648
1 2 3 4 5 6 7 8 9 10 11 12
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[8].Value -eq 3 -and $_.Properties[18].Value -ne '-' -and $_.Properties[18].Value -ne '::1' } | Select-Object TimeCreated, @{N='User';E={"$($_.Properties[6].Value)\$($_.Properties[5].Value)"}}, @{N='SourceIP';E={$_.Properties[18].Value}}, @{N='LogonProcess';E={$_.Properties[9].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
3.3 wmic命令行检测
1 2 3 4 5 6 7
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688} | Where-Object { $_.Properties[8].Value -match 'wmic.*\/node:' } | Select-Object TimeCreated, @{N='User';E={$_.Properties[1].Value}}, @{N='CommandLine';E={$_.Properties[8].Value}} | Format-List
|
四、WinRM / PowerShell Remoting 检测
4.1 WinRM原理
基于HTTP(5985)/HTTPS(5986)的远程管理协议
PowerShell Remoting默认使用WinRM
命令: Enter-PSSession, Invoke-Command -ComputerName, New-PSSession
攻击工具: evil-winrm, Cobalt Strike的winrm命令
目标主机进程: wsmprovhost.exe (WinRM Provider Host)
4.2 目标主机检测
登录事件
1 2 3 4 5 6 7 8 9 10 11 12 13
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[8].Value -eq 3 -and $_.Properties[18].Value -ne '-' } | Select-Object TimeCreated, @{N='User';E={$_.Properties[5].Value}}, @{N='SourceIP';E={$_.Properties[18].Value}}, @{N='LogonProcess';E={$_.Properties[9].Value}}, @{N='AuthPackage';E={$_.Properties[10].Value}} | Where-Object { $_.SourceIP -match '^\d+\.\d+' } | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
WSMan / WinRM日志
1 2 3 4 5 6 7 8
| Get-WinEvent -LogName 'Microsoft-Windows-WinRM/Operational' -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message -First 30 | Format-List
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-WinRM/Operational'; Id=6,169} -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | Format-List
|
PowerShell 4104日志
远程执行的PS命令会被记录在目标主机的4104日志中
详见 10-PowerShell日志与脚本分析
1 2 3 4 5 6
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; Id=4104} | Where-Object { $_.Properties[4].Value -eq '' } | Select-Object TimeCreated, @{N='ScriptBlock';E={$_.Properties[2].Value.Substring(0, [Math]::Min(300, $_.Properties[2].Value.Length))}} | Sort-Object TimeCreated -Descending | Select-Object -First 20
|
wsmprovhost.exe进程创建
1 2 3 4 5 6 7 8 9 10 11
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1} | Where-Object { $_.Properties[4].Value -match 'wsmprovhost\.exe' -or $_.Properties[20].Value -match 'wsmprovhost\.exe' } | Select-Object TimeCreated, @{N='Image';E={$_.Properties[4].Value}}, @{N='CommandLine';E={$_.Properties[10].Value}}, @{N='ParentImage';E={$_.Properties[20].Value}} | Format-List
|
4.3 源主机检测
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; Id=4104} | Where-Object { $_.Properties[2].Value -match 'Enter-PSSession|Invoke-Command.*-ComputerName|New-PSSession|evil-winrm' } | Select-Object TimeCreated, @{N='Script';E={$_.Properties[2].Value.Substring(0, [Math]::Min(300, $_.Properties[2].Value.Length))}} | Format-List
|
5.1 DCOM横向移动原理
利用可远程调用的COM对象执行命令
常见被滥用的COM对象:
MMC20.Application — ExecuteShellCommand() 方法
ShellBrowserWindow — Document.Application.ShellExecute()
ShellWindows — 类似ShellBrowserWindow
Excel.Application — DDEInitiate() 或VBA宏执行
网络通信: TCP 135 (RPC Endpoint Mapper) + 动态高端口
5.2 检测方法
1 2 3 4 5 6 7 8 9 10 11
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1} | Where-Object { $_.Properties[20].Value -match 'mmc\.exe|svchost\.exe' -and $_.Properties[4].Value -match 'cmd\.exe|powershell|mshta' } | Select-Object TimeCreated, @{N='Image';E={$_.Properties[4].Value}}, @{N='CommandLine';E={$_.Properties[10].Value}}, @{N='ParentImage';E={$_.Properties[20].Value}} | Format-List
|
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; Id=4104} | Where-Object { $_.Properties[2].Value -match 'MMC20\.Application|ShellBrowserWindow|ShellWindows|ExecuteShellCommand|Document\.Application\.ShellExecute' } | Select-Object TimeCreated, @{N='Script';E={$_.Properties[2].Value.Substring(0, [Math]::Min(500, $_.Properties[2].Value.Length))}} | Format-List
|
1 2 3 4 5
|
Get-WinEvent -LogName 'System' | Where-Object { $_.ProviderName -eq 'Microsoft-Windows-DistributedCOM' } | Select-Object TimeCreated, Id, Message -First 20 | Format-List
|
六、SMB文件共享访问检测
6.1 SMB在横向移动中的角色
SMB(445端口)是几乎所有Windows横向移动的基础通道
文件传输: 通过 ADMIN$, C$, IPC$ 共享传输payload
直接作为攻击手段: EternalBlue (MS17-010)
6.2 关键事件
Event ID 5140 — 网络共享访问
1 2 3 4 5 6 7
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5140} | Select-Object TimeCreated, @{N='Account';E={"$($_.Properties[2].Value)\$($_.Properties[1].Value)"}}, @{N='SourceIP';E={$_.Properties[5].Value}}, @{N='ShareName';E={$_.Properties[7].Value}} | Where-Object { $_.ShareName -match 'ADMIN\$|C\$|IPC\$' } | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
Event ID 5145 — 详细共享对象访问
比5140更详细,记录具体访问的文件路径
1 2 3 4 5 6 7 8 9 10 11 12 13
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5145} | Where-Object { $_.Properties[9].Value -match '\.(exe|dll|bat|ps1|vbs|hta)$' -and $_.Properties[10].Value -match 'WriteData|AppendData' } | Select-Object TimeCreated, @{N='Account';E={$_.Properties[1].Value}}, @{N='SourceIP';E={$_.Properties[5].Value}}, @{N='ShareName';E={$_.Properties[8].Value}}, @{N='FilePath';E={$_.Properties[9].Value}}, @{N='AccessMask';E={$_.Properties[10].Value}} | Format-List
|
SMB会话枚举
1 2 3 4 5 6 7 8
| Get-SmbSession | Select-Object ClientComputerName, ClientUserName, NumOpens, SecondsExists
Get-SmbConnection | Select-Object ServerName, ShareName, UserName, Credential
Get-SmbShare | Select-Object Name, Path, Description
|
七、Pass-the-Hash (PtH) 检测
7.1 PtH原理
攻击者获取用户的NTLM哈希后,直接使用哈希进行NTLM认证,无需明文密码
工具: mimikatz sekurlsa::pth, Impacket, CrackMapExec
PtH利用的是NTLM协议的设计——认证只需哈希,不需密码原文
7.2 检测方法
4624 NTLM登录异常
PtH产生的4624事件特征:
Logon Type: 3 (Network) 或 9 (NewCredentials)
Authentication Package: NTLM (而非Kerberos)
Logon Process: NtLmSsp (而非Kerberos)
在域环境中,正常的域用户登录应使用Kerberos; 使用NTLM的域用户网络登录需要调查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[8].Value -eq 3 -and $_.Properties[10].Value -eq 'NTLM' -and $_.Properties[14].Value -eq 'NTLM V2' -and $_.Properties[18].Value -ne '-' -and $_.Properties[18].Value -ne '127.0.0.1' } | Select-Object TimeCreated, @{N='User';E={"$($_.Properties[6].Value)\$($_.Properties[5].Value)"}}, @{N='SourceIP';E={$_.Properties[18].Value}}, @{N='WorkstationName';E={$_.Properties[11].Value}}, @{N='LogonProcess';E={$_.Properties[9].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 50
|
4625 登录失败 + NTLM
PtH尝试使用错误哈希会产生大量4625
1 2 3 4 5 6 7
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} | Where-Object { $_.Properties[10].Value -eq 'NTLM' } | Select-Object TimeCreated, @{N='TargetUser';E={$_.Properties[5].Value}}, @{N='SourceIP';E={$_.Properties[19].Value}}, @{N='FailReason';E={$_.Properties[8].Value}} | Group-Object SourceIP | Sort-Object Count -Descending
|
Event ID 4776 — NTLM凭据验证
记录在域控制器上
1 2 3 4 5 6 7
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4776} | Select-Object TimeCreated, @{N='User';E={$_.Properties[1].Value}}, @{N='Workstation';E={$_.Properties[2].Value}}, @{N='Status';E={$_.Properties[3].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 50
|
7.3 PtH加固
启用 “Restricted Admin Mode” for RDP
配置 “Credential Guard” (Windows 10 Enterprise+)
配置 “Protected Users” 安全组 (禁止NTLM)
GPO: “Network security: Restrict NTLM” 策略
最小权限: 域管理员账户不应登录普通工作站
八、Pass-the-Ticket (PtT) / Kerberos攻击检测
8.1 Kerberos攻击概述
Pass-the-Ticket: 窃取TGT/TGS票据并注入其他会话
Golden Ticket: 伪造TGT(需要krbtgt哈希) → 28-AD持久化-Golden-Silver-Ticket
Silver Ticket: 伪造TGS(需要服务账户哈希)
Kerberoasting: 请求服务票据后离线破解服务账户密码
AS-REP Roasting: 针对不要求预认证的账户
8.2 关键事件ID
Event ID 4768 — TGT请求 (AS-REQ)
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4768} | Select-Object TimeCreated, @{N='User';E={$_.Properties[0].Value}}, @{N='SourceIP';E={$_.Properties[9].Value}}, @{N='EncryptionType';E={$_.Properties[5].Value}}, @{N='Status';E={$_.Properties[4].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 50
|
异常指标:
加密类型为RC4 (0x17) 在默认AES环境中 → 可能是Golden Ticket (旧版工具)
源IP与账户通常登录的工作站不匹配
非工作时间的TGT请求
Event ID 4769 — TGS请求 (TGS-REQ)
1 2 3 4 5 6 7 8 9
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4769} | Select-Object TimeCreated, @{N='User';E={$_.Properties[0].Value}}, @{N='ServiceName';E={$_.Properties[2].Value}}, @{N='SourceIP';E={$_.Properties[6].Value}}, @{N='EncryptionType';E={$_.Properties[5].Value}}, @{N='TicketOptions';E={$_.Properties[4].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 100
|
1 2 3 4 5 6
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4769} | Group-Object { $_.Properties[0].Value } | Where-Object { $_.Count -gt 10 } | Sort-Object Count -Descending | Select-Object Name, Count
|
加密类型为RC4 (0x17) 的TGS请求在AES环境中是Kerberoasting的强指标
Event ID 4771 — Kerberos预认证失败
1 2 3 4 5 6 7 8 9 10 11 12
|
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true } | Select-Object SamAccountName, Enabled
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4771} | Select-Object TimeCreated, @{N='User';E={$_.Properties[0].Value}}, @{N='SourceIP';E={$_.Properties[6].Value}}, @{N='FailCode';E={$_.Properties[4].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
九、Remote Scheduled Task 检测
9.1 原理
攻击者通过 schtasks /create /s <target> 在远程主机创建计划任务
或使用 at \\target (旧版)
通过RPC (TCP 135 + 动态端口)通信
9.2 检测
Event ID 4698 — 计划任务创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4698} | Select-Object TimeCreated, @{N='User';E={$_.Properties[1].Value}}, @{N='TaskName';E={$_.Properties[4].Value}}, @{N='TaskContent';E={$_.Properties[5].Value}} | ForEach-Object { Write-Host "=== Task: $($_.TaskName) at $($_.TimeCreated) by $($_.User) ===" -ForegroundColor Cyan try { $xml = [xml]$_.TaskContent $exec = $xml.Task.Actions.Exec Write-Host " Command: $($exec.Command) $($exec.Arguments)" } catch { Write-Host " Raw: $($_.TaskContent.Substring(0, 300))" } Write-Host "" }
|
Microsoft-Windows-TaskScheduler/Operational
1 2 3 4
| Get-WinEvent -LogName 'Microsoft-Windows-TaskScheduler/Operational' -ErrorAction SilentlyContinue | Where-Object { $_.Id -eq 106 -or $_.Id -eq 140 -or $_.Id -eq 141 } | Select-Object TimeCreated, Id, Message -First 30
|
当前计划任务审查
1 2 3 4 5 6
| Get-ScheduledTask | Where-Object { $_.TaskPath -notmatch '^\\Microsoft' } | Select-Object TaskName, TaskPath, State, @{N='Action';E={$_.Actions.Execute + ' ' + $_.Actions.Arguments}}, @{N='UserId';E={$_.Principal.UserId}} | Format-List
|
十、RDP (Remote Desktop) 检测
10.1 RDP事件
Event ID 4624 Type 10 — RemoteInteractive
1 2 3 4 5 6
| Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} | Where-Object { $_.Properties[8].Value -eq 10 } | Select-Object TimeCreated, @{N='User';E={"$($_.Properties[6].Value)\$($_.Properties[5].Value)"}}, @{N='SourceIP';E={$_.Properties[18].Value}} | Sort-Object TimeCreated -Descending | Select-Object -First 30
|
TerminalServices日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational'; Id=1149 } -ErrorAction SilentlyContinue | Select-Object TimeCreated, Message | Format-List
Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'; Id=21,24,25 } -ErrorAction SilentlyContinue | Select-Object TimeCreated, Id, Message | Format-List
|
RDP位图缓存
路径: C:\Users\<user>\AppData\Local\Microsoft\Terminal Server Client\Cache\
包含RDP会话的屏幕截图碎片(位图瓦片),可用bmc-tools重建
1 2 3
| Get-ChildItem "C:\Users\*\AppData\Local\Microsoft\Terminal Server Client\Cache\*" -Recurse -ErrorAction SilentlyContinue | Select-Object FullName, LastWriteTime, Length
|
10.2 RDP Hijacking (会话劫持)
攻击者用SYSTEM权限可连接到其他用户的RDP会话而无需密码:
1 2
| :: 需要SYSTEM权限 tscon <SessionID> /dest:console
|
检测: Event ID 4778 (Session Reconnect) + 40 (Session Disconnected from) 的异常组合
十一、综合检测脚本
11.1 横向移动一键排查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| $outputDir = "C:\IR\LateralMovement_$(Get-Date -Format yyyyMMdd_HHmmss)" New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
Write-Host "[*] Checking PsExec (7045 Service Install)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045} -ErrorAction SilentlyContinue | Select-Object TimeCreated, @{N='ServiceName';E={$_.Properties[0].Value}}, @{N='ImagePath';E={$_.Properties[1].Value}}, @{N='Account';E={$_.Properties[4].Value}} | Export-Csv "$outputDir\service_installs.csv" -NoTypeInformation
Write-Host "[*] Checking Network Logons (4624 Type 3)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} -ErrorAction SilentlyContinue | Where-Object { $_.Properties[8].Value -eq 3 -and $_.Properties[18].Value -ne '-' } | Select-Object TimeCreated, @{N='User';E={"$($_.Properties[6].Value)\$($_.Properties[5].Value)"}}, @{N='SourceIP';E={$_.Properties[18].Value}}, @{N='AuthPackage';E={$_.Properties[10].Value}} | Export-Csv "$outputDir\network_logons.csv" -NoTypeInformation
Write-Host "[*] Checking Explicit Credential Usage (4648)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4648} -ErrorAction SilentlyContinue | Select-Object TimeCreated, @{N='SubjectUser';E={$_.Properties[1].Value}}, @{N='TargetUser';E={$_.Properties[5].Value}}, @{N='TargetServer';E={$_.Properties[8].Value}}, @{N='ProcessName';E={$_.Properties[11].Value}} | Export-Csv "$outputDir\explicit_creds.csv" -NoTypeInformation
Write-Host "[*] Checking Scheduled Task Creation (4698)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4698} -ErrorAction SilentlyContinue | Select-Object TimeCreated, @{N='User';E={$_.Properties[1].Value}}, @{N='TaskName';E={$_.Properties[4].Value}} | Export-Csv "$outputDir\scheduled_tasks.csv" -NoTypeInformation
Write-Host "[*] Checking RDP Logons (4624 Type 10)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624} -ErrorAction SilentlyContinue | Where-Object { $_.Properties[8].Value -eq 10 } | Select-Object TimeCreated, @{N='User';E={"$($_.Properties[6].Value)\$($_.Properties[5].Value)"}}, @{N='SourceIP';E={$_.Properties[18].Value}} | Export-Csv "$outputDir\rdp_logons.csv" -NoTypeInformation
Write-Host "[*] Checking Admin Share Access (5140)..." -ForegroundColor Cyan Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5140} -ErrorAction SilentlyContinue | Where-Object { $_.Properties[7].Value -match 'ADMIN\$|C\$|IPC\$' } | Select-Object TimeCreated, @{N='Account';E={$_.Properties[1].Value}}, @{N='SourceIP';E={$_.Properties[5].Value}}, @{N='ShareName';E={$_.Properties[7].Value}} | Export-Csv "$outputDir\admin_shares.csv" -NoTypeInformation
Write-Host "[+] Lateral movement triage complete: $outputDir" -ForegroundColor Green
|
11.2 源IP统计与关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $allCSVs = Get-ChildItem "$outputDir\*.csv" $allIPs = @{} foreach ($csv in $allCSVs) { $data = Import-Csv $csv.FullName foreach ($row in $data) { $ip = $row.SourceIP if ($ip -and $ip -ne '-' -and $ip -ne '::1' -and $ip -ne '127.0.0.1') { if (-not $allIPs.ContainsKey($ip)) { $allIPs[$ip] = @() } $allIPs[$ip] += "$($csv.BaseName): $($row.TimeCreated)" } } } Write-Host "`n=== Source IP Summary ===" -ForegroundColor Yellow $allIPs.GetEnumerator() | Sort-Object { $_.Value.Count } -Descending | ForEach-Object { Write-Host "$($_.Key) — $($_.Value.Count) events" -ForegroundColor $(if($_.Value.Count -gt 10){'Red'}else{'White'}) }
|
十二、加固建议
启用所有相关审计策略(Logon/Logoff, Object Access, Detailed Tracking)
部署Sysmon并配置Named Pipe、Network Connection、Process Creation监控
实施分层管理(Tiered Administration):
Tier 0 (域控) 账户不登录Tier 1/2
Tier 1 (服务器) 账户不登录Tier 2 (工作站)
配置Windows Firewall限制工作站间的SMB/WMI/WinRM通信
启用Credential Guard防止凭据窃取
将特权账户加入Protected Users组
配置LAPS(Local Administrator Password Solution)确保每台机器本地管理员密码唯一
考虑禁用NTLM(仅允许Kerberos)或至少启用NTLM审计