news 2026/9/23 5:35:38

PowerSploit Recon 模块 Find-DomainUserEvent 实战:跨域控制器批量追踪域用户登录事件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PowerSploit Recon 模块 Find-DomainUserEvent 实战:跨域控制器批量追踪域用户登录事件
  • 渗透测试
  • 网络安全

【免费下载链接】PowerSploit

PowerSploit - A PowerShell Post-Exploitation Framework

项目地址:https://gitcode.com/gh_mirrors/po/PowerSploit
点击查看免费下载

导读

本文围绕 PowerSploit 的 Recon(侦察)模块中用于定位用户登录活动的核心函数Find-DomainUserEvent展开,讲解如何在一台(或整个域的)域控制器上,按用户身份、组成员、特权标记、IP 地址、LogonGuid 等多种条件批量检索 Windows 安全日志中的登录事件(Event ID 4624)与显式凭据登录事件(Event ID 4648)。读完本文,你将掌握该函数的完整参数体系、四种典型调用方式,以及它与底层Get-DomainUserEventGet-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的实现逻辑非常清晰,源码中可分为三个相互衔接的阶段:

  1. 确定目标用户集合(BEGIN 阶段前半部分):根据用户指定的筛选条件,调用Get-DomainUserGet-DomainGroupMember得到目标用户名的列表;
  2. 确定目标主机集合(BEGIN 阶段后半部分):如果未显式给出-ComputerName,则通过Get-DomainController枚举指定域(默认当前域)的全部域控制器;
  3. 逐主机采集并过滤事件(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 中的参数声明):

参数类型默认值作用
-ComputerNameString[]None显式指定要检索事件的主机(别名dnshostnameHostNamename),支持管道输入
-DomainString当前域指定要查询域控制器的域
-FilterHashtableNonePowerView.LogonEvent 属性的过滤哈希表,支持op/operator/operation子句
-StartTimeDateTime[DateTime]::Now.AddDays(-1)事件采集起始时间
-EndTimeDateTime[DateTime]::Now事件采集结束时间
-MaxEventsInt325000每台主机最多返回的事件数(1–1000000)
-UserIdentityString[]None要搜索的一个或多个用户身份
-UserDomainString当前域查询目标用户时使用的域
-UserLDAPFilterStringNone用于搜索目标用户的 LDAP 查询字符串
-UserSearchBaseStringNone搜索目标用户的 LDAP 源,如LDAP://OU=secret,DC=testlab,DC=local,适合 OU 查询
-UserGroupIdentityString[]Domain Admins查询目标用户的组身份(别名GroupNameGroup);设置了其他用户条件时被忽略
-UserAdminCountSwitchFalse搜索(adminCount=1)的用户(即曾经/当前拥有特权的账户,别名AdminCount
-CheckAccessSwitchFalse源码中为占位参数(文档标注{{Fill CheckAccess Description}}),未参与过滤逻辑
-ServerStringNone要绑定的 AD 服务器(域控制器),别名DomainController
-SearchScopeStringSubtree计算机搜索范围,Base/OneLevel/Subtree
-ResultPageSizeInt32200LDAP 搜索器 PageSize(1–10000)
-ServerTimeLimitInt32无(不传则使用 LDAP 默认,文档描述为 120 秒)LDAP 服务器端搜索时间上限(1–10000 秒)
-TombstoneSwitchFalse搜索器同时返回已删除/墓碑对象
-CredentialPSCredential[PSCredential]::Empty连接目标计算机的备用凭据
-StopOnSuccessSwitchFalse找到目标用户后立即停止搜索
-DelayInt320主机枚举之间的延迟秒数(1–10000),传入后强制串行枚举
-JitterDouble0.3应用于-Delay的抖动系数(0.0–1.0),实际休眠时间为随机区间(1-Jitter)*Delay(1+Jitter)*Delay
-ThreadsInt3220用户搜索使用的线程数(1–100)

需要特别说明-Filter的语义(Recon/PowerView.ps1):

  • 过滤键是PowerView.LogonEvent输出对象的属性名(如IpAddressLogonGuidTargetLogonId),值是用于-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支持管道按值/按属性名输入(别名dnshostnameHostNamename),因此可以把主机名直接通过管道传入。-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匹配指定 GUIDTargetLogonId匹配10238128op&,对应源码中$Operator = 'and'的分支,Recon/PowerView.ps1);
  • 传入-Delay 1后,PROCESS 阶段会放弃多线程,改为逐台 DC 串行枚举,并在每次枚举前Start-Sleep随机间隔(Recon/PowerView.ps1),用于降低探测行为的特征与网络噪音。-Delay-StopOnSuccess任一被指定都会进入串行分支。

输出对象结构

函数的输出类型声明为PowerView.LogonEventPowerView.ExplicitCredentialLogonEvent(Recon/PowerView.ps1),分别对应 4624 与 4648 事件的解析结果。

4624 事件(PowerView.LogonEvent)包含字段:ComputerNameTimeCreatedEventIdSubjectUserSid/Name/DomainName/LogonIdTargetUserSid/Name/DomainName/LogonIdLogonTypeLogonProcessNameAuthenticationPackageNameWorkstationNameLogonGuidTransmittedServicesLmPackageNameKeyLengthProcessIdProcessNameIpAddressIpPortImpersonationLevelRestrictedAdminModeTargetOutboundUserName/DomainNameVirtualAccountTargetLinkedLogonIdElevatedToken(Recon/PowerView.ps1)。

4648 事件(PowerView.ExplicitCredentialLogonEvent)包含字段:ComputerNameTimeCreatedEventIdSubjectUserSid/Name/DomainName/LogonIdLogonGuidTargetUserName/DomainNameTargetLogonGuidTargetServerNameTargetInfoProcessIdProcessNameIpAddressIpPort(Recon/PowerView.ps1)。

从源码结构可以推断,LogonTypeIpAddressLogonGuidTargetLogonIdTargetUserNameProcessName等字段都是-Filter的合法键,其中LogonGuidTargetLogonId的组合可把 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

项目地址:https://gitcode.com/gh_mirrors/po/PowerSploit
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 5:35:34

用什么擦地最干净踩坑实录

3个擦地工具实测:解决报错堆栈与性能优化痛点 凌晨三点,生产环境突然报警。你抓起键盘,打开监控面板,满屏红色的异常日志像瀑布一样刷下来。 java.lang.NullPointerException 、 StackOverflowError…

作者头像 李华
网站建设 2026/9/23 5:35:19

3步搞定CAD制图软件性能优化,源码级解析避坑指南

3步搞定CAD制图软件性能优化,源码级解析避坑指南 官方文档动辄几百页,翻来覆去还是没抓到性能优化的核心痛点?别急,今天直接扒开 cad制图软件 的底层逻辑,用实战代码带你从源码层面解决卡顿和内存泄漏问题。我们不做理论空谈,直接上硬核干货。 项目目标与痛点拆解 很多工程师抱怨 CAD…

作者头像 李华
网站建设 2026/9/23 5:35:09

3步搞定马甲是什么源码解析 拒绝文档迷路

3步搞定马甲是什么源码解析 拒绝文档迷路 官方文档那一堆术语看得人头晕,想搞懂“马甲是什么”背后的实现逻辑,翻半天源码还是一头雾水。别急,今天直接上干货,带你从源码解析入手,把“马甲”这个概念拆得明明白白,不用死磕长文档,半小时就能在本地跑通一个最小可行案例。 项目目标…

作者头像 李华
网站建设 2026/9/23 5:35:03

5步搞定最终幻想勇气启示录幻影战争入门到精通避坑

5步搞定最终幻想勇气启示录幻影战争入门到精通避坑 官方文档太长抓不住重点,是不是让你在看《最终幻想勇气启示录 幻影战争》(FFBE幻影)的攻略或数据整理时,感觉像在看天书?很多老玩家想从新手坑走向高端局,甚至想自己写个脚本自动化处理角色数据,但一查资料,要么全是碎片化截图,要么就是那种几百页的PDF…

作者头像 李华
网站建设 2026/9/23 5:34:54

攻克ca959高频面试题:市政公用工程从业者必看的学时与证书避坑指南

攻克ca959高频面试题:市政公用工程从业者必看的学时与证书避坑指南 刚把网上搜来的《市政公用工程注册建造师继续教育学时计算表》复制到Excel里,结果公式全报#REF!,对着屏幕抓耳挠腮,不知道哪里配错了参数?这种“复制来的代码跑不通不知道怎么调”的绝望感,其实和我们在准备ca959高频面试题时遇…

作者头像 李华
网站建设 2026/9/23 5:34:52

在线视频中文字幕处理 3 个坑点助你从入门到精通

在线视频中文字幕处理 3 个坑点助你从入门到精通 报错一堆看不懂 StackTrace,盯着屏幕上的红色字体发呆,这种绝望感谁懂?很多刚接触媒体处理的朋友,一遇到“在线视频中文字幕”解析失败,第一反应就是改配置、换版本,结果越改越乱。其实,这不仅是代码问题,更是你对底层数据流理解的缺失。想从入门到精…

作者头像 李华