- 渗透测试
- 网络安全
【免费下载链接】PowerSploit
PowerSploit - A PowerShell Post-Exploitation Framework
导读
本文围绕 PowerSploit 的 Recon(侦察)模块中用于定位用户登录活动的核心函数Find-DomainUserEvent展开,讲解如何在一台(或整个域的)域控制器上,按用户身份、组成员、特权标记、IP 地址、LogonGuid 等多种条件批量检索 Windows 安全日志中的登录事件(Event ID 4624)与显式凭据登录事件(Event ID 4648)。读完本文,你将掌握该函数的完整参数体系、四种典型调用方式,以及它与底层Get-DomainUserEvent、Get-DomainController的协作原理,可直接用于红队侦察、横向移动目标筛选与域内安全审计场景。
函数定位与适用场景
Find-DomainUserEvent定义于 Recon/PowerView.ps1,由 Lee Christensen(@tifkin_)、Justin Warner(@sixdub)与 Will Schroeder(@harmj0y)编写,采用 BSD 3-Clause 许可,是 PowerView(PowerSploit Recon 模块)中面向"人"的侦察工具。它的职责一句话概括:在当前域(或指定远程域)中,为指定用户找到登录事件。
它的典型应用场景包括:
- 红队/渗透测试中确认目标域用户(如域管理员)最近在哪些主机上登录过,为横向移动选择目标主机;
- 追踪某个特定会话 GUID(LogonGuid)或登录 ID(TargetLogonId)对应的完整登录记录;
- 按来源 IP 段筛选登录事件,定位来自特定工作站/攻击源的认证活动;
- 蓝队场景下快速核对高权限账户(adminCount=1)在过去一段时间内的登录行为。
官方文档 docs/Recon/Find-DomainUserEvent.md 给出了它的完整语法与说明,Recon 模块的模块清单 Recon/Recon.psd1 将其作为导出函数提供给使用者,因此在导入 Recon 模块后即可直接调用。
核心工作流程:从域控制器到登录事件的三段式管线
Find-DomainUserEvent的实现逻辑非常清晰,源码中可分为三个相互衔接的阶段:
- 确定目标用户集合(BEGIN 阶段前半部分):根据用户指定的筛选条件,调用
Get-DomainUser或Get-DomainGroupMember得到目标用户名的列表; - 确定目标主机集合(BEGIN 阶段后半部分):如果未显式给出
-ComputerName,则通过Get-DomainController枚举指定域(默认当前域)的全部域控制器; - 逐主机采集并过滤事件(PROCESS 阶段):对每台目标主机调用
Get-DomainUserEvent拉取安全日志事件,再按用户名列表或-Filter哈希表进行匹配,最后按并发或串行策略输出。
其中第 3 步的采集动作封装在$HostEnumBlock脚本块中(Recon/PowerView.ps1),该脚本块会先用Test-Connection -Count 1 -Quiet做一次 ICMP 连通性探测,主机在线才继续采集,避免对不可达主机产生无谓的远程调用开销。
底层真正读日志的函数是Get-DomainUserEvent(Recon/PowerView.ps1),它不依赖其他函数,直接通过Get-WinEvent以 XML XPath 过滤器读取 Security 日志:
- Event ID 4624:账户登录事件(Account Logon),同时用
TimeCreated限定在-StartTime与-EndTime之间,并排除TargetUserName = 'ANONYMOUS LOGON'; - Event ID 4648:使用显式凭据登录事件(Logon with explicit credential);
- 通过
<Suppress>子句排除噪音:LogonType 为 0/5(系统账户/服务账户)、匿名登录以及TargetUserSID = 'S-1-5-18'(LocalSystem)的事件; - 解析 4624 事件时还会跳过以
$结尾的计算机账户登录($Properties[5].Value.EndsWith('$')),并在 4648 事件上要求进程名为taskhost\.exe才输出,用于聚焦真正由用户发起的显式凭据使用。
Get-DomainUserEvent的完整参数见 Recon/PowerView.ps1:-ComputerName(默认本机)、-StartTime(默认[DateTime]::Now.AddDays(-1))、-EndTime(默认[DateTime]::Now)、-MaxEvents(默认 5000,允许范围 1–1000000)、-Credential(默认空凭据)。
完整参数说明
Find-DomainUserEvent支持两套参数集:Domain(默认)与ComputerName。Domain 参数集在未指定主机时自动枚举域控制器;ComputerName 参数集则显式指定要查询的主机,并支持通过管道传入主机名。下表汇总了全部参数及其默认值与含义(默认值均来自源码 Recon/PowerView.ps1 中的参数声明):
| 参数 | 类型 | 默认值 | 作用 |
|---|---|---|---|
-ComputerName | String[] | None | 显式指定要检索事件的主机(别名dnshostname、HostName、name),支持管道输入 |
-Domain | String | 当前域 | 指定要查询域控制器的域 |
-Filter | Hashtable | None | PowerView.LogonEvent 属性的过滤哈希表,支持op/operator/operation子句 |
-StartTime | DateTime | [DateTime]::Now.AddDays(-1) | 事件采集起始时间 |
-EndTime | DateTime | [DateTime]::Now | 事件采集结束时间 |
-MaxEvents | Int32 | 5000 | 每台主机最多返回的事件数(1–1000000) |
-UserIdentity | String[] | None | 要搜索的一个或多个用户身份 |
-UserDomain | String | 当前域 | 查询目标用户时使用的域 |
-UserLDAPFilter | String | None | 用于搜索目标用户的 LDAP 查询字符串 |
-UserSearchBase | String | None | 搜索目标用户的 LDAP 源,如LDAP://OU=secret,DC=testlab,DC=local,适合 OU 查询 |
-UserGroupIdentity | String[] | Domain Admins | 查询目标用户的组身份(别名GroupName、Group);设置了其他用户条件时被忽略 |
-UserAdminCount | Switch | False | 搜索(adminCount=1)的用户(即曾经/当前拥有特权的账户,别名AdminCount) |
-CheckAccess | Switch | False | 源码中为占位参数(文档标注{{Fill CheckAccess Description}}),未参与过滤逻辑 |
-Server | String | None | 要绑定的 AD 服务器(域控制器),别名DomainController |
-SearchScope | String | Subtree | 计算机搜索范围,Base/OneLevel/Subtree |
-ResultPageSize | Int32 | 200 | LDAP 搜索器 PageSize(1–10000) |
-ServerTimeLimit | Int32 | 无(不传则使用 LDAP 默认,文档描述为 120 秒) | LDAP 服务器端搜索时间上限(1–10000 秒) |
-Tombstone | Switch | False | 搜索器同时返回已删除/墓碑对象 |
-Credential | PSCredential | [PSCredential]::Empty | 连接目标计算机的备用凭据 |
-StopOnSuccess | Switch | False | 找到目标用户后立即停止搜索 |
-Delay | Int32 | 0 | 主机枚举之间的延迟秒数(1–10000),传入后强制串行枚举 |
-Jitter | Double | 0.3 | 应用于-Delay的抖动系数(0.0–1.0),实际休眠时间为随机区间(1-Jitter)*Delay到(1+Jitter)*Delay |
-Threads | Int32 | 20 | 用户搜索使用的线程数(1–100) |
需要特别说明-Filter的语义(Recon/PowerView.ps1):
- 过滤键是
PowerView.LogonEvent输出对象的属性名(如IpAddress、LogonGuid、TargetLogonId),值是用于-match的正则表达式字符串; - 特殊键
op(或operator/operation)决定多条件组合逻辑:值为&或and时表示"所有条件都必须匹配",否则(包括默认情况)按or处理,即至少一个条件匹配即输出; - 注意源码中
or分支会对每个匹配的键各输出一次事件对象,因此同一事件在命中多个条件时可能重复出现,实际使用时若需去重可结合Sort-Object -Unique。
实战示例详解
官方文档提供了四个示例,下面逐一展开并补充说明。
示例 1:默认扫描域内所有 DC 上的域管理员登录
Find-DomainUserEvent未指定任何参数时,函数默认:目标用户 =Domain Admins组的全部成员(通过Get-DomainGroupMember -Identity 'Domain Admins' -Recurse递归展开,见 Recon/PowerView.ps1);目标主机 = 当前域全部域控制器的 DNS 主机名(通过Get-DomainController -LDAP获取,见 Recon/PowerView.ps1);时间范围 = 过去 24 小时。由于未传-Delay与-StopOnSuccess,会以 20 线程并发枚举所有 DC(Recon/PowerView.ps1),并输出PowerView.LogonEvent对象。
示例 2:指定 DC + 指定用户 + 备用凭据
$cred = Get-Credential dev\administrator Find-DomainUserEvent -ComputerName 'secondary.dev.testlab.local' -UserIdentity 'john'这里通过-ComputerName明确只查secondary.dev.testlab.local这一台主机,-UserIdentity 'john'让函数改用Get-DomainUser搜索名为john的用户(因为显式传了-UserIdentity,-UserGroupIdentity的默认值Domain Admins会被忽略,见 Recon/PowerView.ps1 的分支逻辑),-Credential则携带dev\administrator的凭据访问目标主机。-UserIdentity支持字符串数组,可一次传入多个用户。
示例 3:按来源 IP 过滤(管道输入)
'primary.testlab.local | Find-DomainUserEvent -Filter @{'IpAddress'='192.168.52.200|192.168.52.201'}-ComputerName支持管道按值/按属性名输入(别名dnshostname、HostName、name),因此可以把主机名直接通过管道传入。-Filter中的IpAddress值是正则表达式192.168.52.200|192.168.52.201,即匹配来源 IP 为这两个地址之一的登录事件。由于未提供op键,多条件默认按or处理。注意正则中的|表示"或",若要字面匹配含点的 IP 建议转义点号,如192\.168\.52\.(200|201)。
示例 4:多条件 AND 组合 + 串行枚举
$cred = Get-Credential testlab\administrator Find-DomainUserEvent -Delay 1 -Filter @{'LogonGuid'='b8458aa9-b36e-eaa1-96e0-4551000fdb19'; 'TargetLogonId' = '10238128'; 'op'='&'}该示例同时演示了-Filter的 AND 语义与-Delay的副作用:
- 过滤器同时要求
LogonGuid匹配指定 GUID且TargetLogonId匹配10238128(op为&,对应源码中$Operator = 'and'的分支,Recon/PowerView.ps1); - 传入
-Delay 1后,PROCESS 阶段会放弃多线程,改为逐台 DC 串行枚举,并在每次枚举前Start-Sleep随机间隔(Recon/PowerView.ps1),用于降低探测行为的特征与网络噪音。-Delay与-StopOnSuccess任一被指定都会进入串行分支。
输出对象结构
函数的输出类型声明为PowerView.LogonEvent与PowerView.ExplicitCredentialLogonEvent(Recon/PowerView.ps1),分别对应 4624 与 4648 事件的解析结果。
4624 事件(PowerView.LogonEvent)包含字段:ComputerName、TimeCreated、EventId、SubjectUserSid/Name/DomainName/LogonId、TargetUserSid/Name/DomainName/LogonId、LogonType、LogonProcessName、AuthenticationPackageName、WorkstationName、LogonGuid、TransmittedServices、LmPackageName、KeyLength、ProcessId、ProcessName、IpAddress、IpPort、ImpersonationLevel、RestrictedAdminMode、TargetOutboundUserName/DomainName、VirtualAccount、TargetLinkedLogonId、ElevatedToken(Recon/PowerView.ps1)。
4648 事件(PowerView.ExplicitCredentialLogonEvent)包含字段:ComputerName、TimeCreated、EventId、SubjectUserSid/Name/DomainName/LogonId、LogonGuid、TargetUserName/DomainName、TargetLogonGuid、TargetServerName、TargetInfo、ProcessId、ProcessName、IpAddress、IpPort(Recon/PowerView.ps1)。
从源码结构可以推断,LogonType、IpAddress、LogonGuid、TargetLogonId、TargetUserName、ProcessName等字段都是-Filter的合法键,其中LogonGuid与TargetLogonId的组合可把 4624 与后续 4648 事件关联起来,还原一次完整的显式凭据使用链条——这也正是示例 4 的意图所在。
使用前提与注意事项
- 运行环境:函数基于
Get-WinEvent读取远程/本地 Security 日志,需要目标主机开启安全审计且当前(或-Credential提供的)账户具备读取安全日志的权限;Find-DomainUserEvent默认枚举域控制器,因此调用者通常需要域内具备相应权限的账户。 - 连通性依赖:
$HostEnumBlock使用 ICMP(Test-Connection)判断主机在线,若防火墙屏蔽 ICMP 可能导致在线主机被跳过。 - 性能权衡:默认 20 线程并发枚举适合大规模域;
-Delay/-StopOnSuccess会退化为串行,速度慢但更隐蔽;-MaxEvents限制每台主机返回的事件上限,避免日志量过大拖垮管道。 - 事件噪音抑制:4624/4648 解析时会跳过计算机账户(
$结尾)、匿名登录、LocalSystem(S-1-5-18)以及 LogonType 0/5 的事件,4648 还要求进程为taskhost.exe,解读结果时需留意这些内置过滤。 - 时间窗口:默认仅回溯 24 小时(
-StartTime = Now.AddDays(-1)),如需更长窗口请显式传入-StartTime,例如-StartTime ([DateTime]::Now.AddDays(-7))。
延伸阅读
- 模块内配套文档:Find-DomainUserEvent.md
- 底层事件采集实现:Recon/PowerView.ps1
- 高层编排实现:Recon/PowerView.ps1
- Recon 模块功能总览:Recon/README.md
- 同一 Recon 模块中,
Get-DomainUser(用户枚举)、Get-DomainGroupMember(组展开)、Get-DomainController(DC 枚举)与New-ThreadedFunction(并发执行)是Find-DomainUserEvent声明的必需依赖,可结合阅读以理解完整的调用链。
- 渗透测试
- 网络安全
【免费下载链接】PowerSploit
PowerSploit - A PowerShell Post-Exploitation Framework
相关推荐
RuView BFLD 深度解析:基于 802.11ac/ax 波束成形反馈的隐私门控 WiFi 感知层
RuView BFLD 深度解析:基于 802.11ac/ax 波束成形反馈的隐私门控 WiFi 感知层 BFLD(Beamforming Feedback L
渗透测试网络安全PowerSploit Recon 模块 Find-DomainProcess 实战指南:基于 WMI 的域内用户进程与特权进程定位
PowerSploit Recon 模块 Find DomainProcess 实战指南:基于 WMI 的域内用户进程与特权进程定位 本篇技术指南围绕 Powe
渗透测试网络安全PowerSploit Recon 模块 New-DomainUser 实战指南:用 PowerShell 创建域用户并接管域内身份
PowerSploit Recon 模块 New DomainUser 实战指南:用 PowerShell 创建域用户并接管域内身份 PowerSploit 是
渗透测试网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考