ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PowerSploit 侦察系列:PowerView Get-DomainGPO 域组策略对象枚举实战指南

PowerSploit 侦察系列:PowerView Get-DomainGPO 域组策略对象枚举实战指南 渗透测试网络安全【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址https://gitcode.com/gh_mirrors/po/PowerSploit点击查看免费下载本指南以 PowerSploit 框架中 Recon 模块Recon/PowerView.ps1的Get-DomainGPO函数为主线系统讲解如何通过 LDAP 枚举 Active Directory 域内全部组策略对象GPO、按计算机/用户身份反查其生效的策略以及底层基于gplink与 OU/站点继承关系的解析原理。读完本文你将掌握Get-DomainGPO的全部参数、参数集、五种标准用法并能结合源码理解 PowerView 的 GPO 枚举算法直接用于域内信息收集与安全评估实战。函数定位域内 GPO 信息收集的入口Get-DomainGPO是 PowerSploit 的 Recon 模块Recon目录中 PowerView 侦察套件的一员其作者为 Will Schroederharmj0y采用 BSD 3-Clause 许可。函数实现在 Recon/PowerView.ps1通过Recon.psd1与Recon.psm1随模块导出。函数的核心职责是返回域内所有 GPO 或指定的单个 GPO 对象。其工作方式在官方文档与源码注释中描述一致使用Get-DomainSearcher构建一个目录搜索器System.DirectoryServices.DirectorySearcher对象根据定位目标Identity与过滤参数组装自定义 LDAP 过滤器在活动目录中搜索所有匹配条件的对象。从 docs/Recon/index.md 的模块索引可以看到Get-DomainGPO是 PowerView 中一组 GPO 相关函数的入口函数说明Get-DomainGPO返回域内所有 GPO 或指定 GPO 对象Get-DomainGPOLocalGroup返回域内通过“受限制的组”Restricted Groups或组策略首选项GPP修改本地组成员关系的 GPO及其用户成员映射Get-DomainGPOUserLocalGroupMapping通过 GPO 关联枚举特定域用户/组在哪些机器上是特定本地组成员Get-DomainGPOComputerLocalGroupMapping输入计算机或 GPO对象通过 GPO 关联确定该机器上指定本地组的用户/组成员本文聚焦第一个函数——它也是后三个函数进行 GPO 关联分析的底层数据来源。语法与参数集Get-DomainGPO依据[CmdletBinding(DefaultParameterSetName None)]声明源码默认参数集为None另有两个互斥参数集ComputerIdentity与UserIdentity。None默认参数集Get-DomainGPO [[-Identity] String[]] [-Domain String] [-LDAPFilter String] [-Properties String[]] [-SearchBase String] [-Server String] [-SearchScope String] [-ResultPageSize Int32] [-ServerTimeLimit Int32] [-SecurityMasks String] [-Tombstone] [-FindOne] [-Credential PSCredential] [-Raw]ComputerIdentity 参数集Get-DomainGPO [[-Identity] String[]] [-ComputerIdentity String] [-Domain String] [-LDAPFilter String] [-Properties String[]] [-SearchBase String] [-Server String] [-SearchScope String] [-ResultPageSize Int32] [-ServerTimeLimit Int32] [-SecurityMasks String] [-Tombstone] [-FindOne] [-Credential PSCredential] [-Raw]UserIdentity 参数集Get-DomainGPO [[-Identity] String[]] [-UserIdentity String] [-Domain String] [-LDAPFilter String] [-Properties String[]] [-SearchBase String] [-Server String] [-SearchScope String] [-ResultPageSize Int32] [-ServerTimeLimit Int32] [-SecurityMasks String] [-Tombstone] [-FindOne] [-Credential PSCredential] [-Raw]参数详解以下参数说明完整继承自原文档并结合 Recon/PowerView.ps1 中的声明别名、校验规则、默认值做了补充。-IdentityGPO 的显示名称display name如Test GPO、可分辨名称 DistinguishedName如CN{F260B76D-55C8-46C5-BEF1-9016DD98E272},CNPolicies,CNSystem,DCtestlab,DClocal、GUID如10ec320d-3111-4ef4-8faf-8f14f4adc789或 GPO 名称如{F260B76D-55C8-46C5-BEF1-9016DD98E272}。支持通配符源码中会对(与)做转义处理后再拼入过滤器。Type: String[] Parameter Sets: (All) Aliases: DistinguishedName, SamAccountName, Name Required: False Position: 1 Default value: None Accept pipeline input: True (ByPropertyName, ByValue) Accept wildcard characters: False-ComputerIdentity返回应用到指定计算机身份计算机名、DNS 名、DistinguishedName 等上的所有 GPO 对象。Type: String Parameter Sets: ComputerIdentity Aliases: ComputerName Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-UserIdentity返回应用到指定用户身份用户名、SID、DistinguishedName 等上的所有 GPO 对象。Type: String Parameter Sets: UserIdentity Aliases: UserName Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-Domain指定查询使用的域默认为当前域。Type: String Parameter Sets: (All) Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-LDAPFilter指定用于过滤 Active Directory 对象的 LDAP 查询字符串。Type: String Parameter Sets: (All) Aliases: Filter Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-Properties指定从服务器检索的输出对象属性。Type: String[] Parameter Sets: (All) Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-SearchBase要搜索的 LDAP 源例如LDAP://OUsecret,DCtestlab,DClocal适用于 OU 定向查询。注意当SearchBase以GC://全局编录开头时源码会额外计算gpcfilesyspath属性见下文“输出对象”一节。Type: String Parameter Sets: (All) Aliases: ADSPath Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-Server指定要绑定的 Active Directory 服务器域控制器。Type: String Parameter Sets: (All) Aliases: DomainController Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-SearchScope指定搜索范围取值受[ValidateSet(Base, OneLevel, Subtree)]约束默认Subtree。Type: String Parameter Sets: (All) Required: False Position: Named Default value: Subtree Accept pipeline input: False Accept wildcard characters: False-ResultPageSize设置 LDAP 搜索器对象的 PageSize。源码中声明为[ValidateRange(1, 10000)]默认 200。Type: Int32 Parameter Sets: (All) Required: False Position: Named Default value: 200 Accept pipeline input: False Accept wildcard characters: False-ServerTimeLimit指定服务器端搜索花费的最大时间。文档说明默认 120 秒源码声明同样带[ValidateRange(1, 10000)]秒。Type: Int32 Parameter Sets: (All) Required: False Position: Named Default value: 0 Accept pipeline input: False Accept wildcard characters: False-SecurityMasks指定检查目录对象安全信息的选项取值受[ValidateSet(Dacl, Group, None, Owner, Sacl)]约束即Dacl、Group、None、Owner、Sacl之一。Type: String Parameter Sets: (All) Required: False Position: Named Default value: None Accept pipeline input: False Accept wildcard characters: False-TombstoneSwitch 开关。指定搜索器同时返回已删除/已墓碑化tombstoned的对象。Type: SwitchParameter Parameter Sets: (All) Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False-FindOne只返回一条结果对象。别名ReturnOne。Type: SwitchParameter Parameter Sets: (All) Aliases: ReturnOne Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False-Credential用于连接目标域的备用凭据类型为[Management.Automation.PSCredential]对象。默认值为[Management.Automation.PSCredential]::Empty。Type: PSCredential Parameter Sets: (All) Required: False Position: Named Default value: [Management.Automation.PSCredential]::Empty Accept pipeline input: False Accept wildcard characters: False-RawSwitch 开关。返回原始结果而不是将字段翻译成自定义 PSObject。Type: SwitchParameter Parameter Sets: (All) Required: False Position: Named Default value: False Accept pipeline input: False Accept wildcard characters: False实战示例以下示例完整继承自原文档并补充了输出说明与使用提示。示例 1枚举某域的全部 GPOGet-DomainGPO -Domain testlab.local返回testlab.local域中所有 GPO 对象。这是最常用、最基础的用法——不指定任何身份时源码会直接以((objectCategorygroupPolicyContainer))作为过滤器执行FindAll()见“源码原理”一节。示例 2枚举某台计算机上生效的全部 GPOGet-DomainGPO -ComputerName windows1.testlab.local-ComputerName是-ComputerIdentity的别名。返回应用到windows1.testlab.local这台机器的所有 GPO。注意此处返回的是链接到该计算机所属 OU、站点与域的 GPO 全集含继承链而非仅 OU 直连项。示例 3通过管道按名称/GUID 查询指定 GPO{F260B76D-55C8-46C5-BEF1-9016DD98E272},Test GPO | Get-DomainGPO返回名称为{F260B76D-55C8-46C5-BEF1-9016DD98E272}、显示名称为Test GPO的 GPO 对象。-Identity参数同时支持ValueFromPipeline与ValueFromPipelineByPropertyName也可直接写成Get-DomainGPO -Identity {F260B76D-55C8-46C5-BEF1-9016DD98E272},Test GPO。示例 4结合 LDAP 过滤器与属性裁剪Get-DomainGPO -LDAPFilter (!primarygroupid513) -Properties samaccountname,lastlogon使用附加 LDAP 过滤器(!primarygroupid513)并只返回samaccountname、lastlogon两个属性。-Properties可有效减少网络与内存开销适合大规模域内的快速信息收集。示例 5使用备用凭据枚举$SecPassword ConvertTo-SecureString Password123! -AsPlainText -Force $Cred New-Object System.Management.Automation.PSCredential(TESTLAB\dfm.a, $SecPassword) Get-DomainGPO -Credential $Cred以TESTLAB\dfm.a的凭据连接目标域并枚举全部 GPO。注意ConvertTo-SecureString -AsPlainText表示明文口令以 SecureString 形式传入实际使用中应避免在脚本中硬编码口令。源码原理剖析BEGIN构建搜索器函数在BEGIN块中将所有显式传入的参数Domain、Properties、SearchBase、Server、SearchScope、ResultPageSize、ServerTimeLimit、SecurityMasks、Tombstone、Credential收集进$SearcherArguments哈希表再调用Get-DomainSearcher SearcherArguments得到$GPOSearcher源码。Get-DomainSearcher定义于 Recon/PowerView.ps1内部还会依赖Get-Domain确定目标域。分支一默认枚举路径Identity / LDAPFilter当未指定-ComputerIdentity与-UserIdentity时源码函数进入标准的 LDAP 枚举路径Identity 解析对每个传入的 Identity 依次尝试匹配源码以LDAP://或^CN.*开头 → 视为 DistinguishedName构建(distinguishedname$IdentityInstance)过滤条件若未显式指定-Domain/-SearchBase还会从 DN 中提取DC部分重建域搜索器匹配{.*}模式GPO 名称→ 构建(name$IdentityInstance)可成功解析为 GUID → 将 GUID 字节序反转后构建(objectguid$GuidByteString)LDAP 中objectGuid按字节数组存储故需ToByteArray()后反转并转义以上均不匹配 → 回退为(displayname$IdentityInstance)。多个 Identity 会被聚合成(|$IdentityFilter)形式。LDAPFilter 拼接若提供了-LDAPFilter直接追加到过滤器之后。执行查询最终过滤器为((objectCategorygroupPolicyContainer)$Filter)使用FindOne()配合-FindOne或FindAll()执行并妥善dispose()结果与搜索器。分支二按计算机/用户身份反查 GPO当指定-ComputerIdentity或-UserIdentity时源码函数实现了一个完整的“GPO 生效链路解析”算法定位目标对象先用Get-DomainComputer或Get-DomainUser配合-FindOne拿到目标对象的distinguishedname计算机还会取dnshostname用于站点查询。提取 OU 链从 DN 中解析出所有OU段构造该对象所属的 OU 路径列表$ObjectOUs。OU 级 GPO 链接解析对每个 OU 调用Get-DomainOU读取其gplink属性将gplink按][分割取LDAP开头的条目再用;分割出 GPO 的 DN 与“强制生效”标志位Enforced值为2表示强制。同时读取gpoptions属性若某 OU 的gpoptions -eq 1说明该 OU禁用了 GPO 继承后续外层 OU 的普通 GPO 将不再计入但标记为Enforced2的强制 GPO 仍然保留——这正是源码对“阻止继承 强制策略”语义的精确复刻。站点级 GPO 链接解析对计算机目标通过Get-NetComputerSiteName源码查询机器所在站点再经Get-DomainSite读取站点对象的gplink提取站点级链接的 GPO DN。域级 GPO 链接解析以(objectclassdomain)(distinguishedname$ObjectDomainDN)过滤查询域对象Get-DomainObject读取域对象的gplink加入域级链接的 GPO DN。回查 GPO 详情将收集到的每个 GPO DN 作为SearchBase以(objectCategorygroupPolicyContainer)过滤调用Get-DomainObject得到最终的 GPO 对象列表。从源码结构看这一分支正是 PowerView 用于还原“OU/站点/域 → GPO”三层链接关系的核心实现也是Get-DomainGPOLocalGroup、Get-DomainGPOUserLocalGroupMapping等函数进行组策略关联分析的基石。输出对象与 LDAP 属性翻译Get-DomainGPO默认输出类型为PowerView.GPO自定义 PSObject启用-Raw时输出类型为PowerView.GPO.Raw原始DirectoryServices.SearchResult。字段翻译由Convert-LDAPProperty源码完成其关键转换逻辑包括objectguid→ 转换为可读 GUID 字符串objectsid/sidhistory→ 转换为SecurityIdentifier的 SID 字符串ntsecuritydescriptor→ 解析出Owner、Group、DiscretionaryAcl、SystemAcl等安全描述符组件lastlogon、lastlogontimestamp、pwdlastset等 → 转换为[datetime]accountexpires→ 超出DateTime.MaxValue时输出NEVER单值属性直接取值多值属性保留数组。特别地当-SearchBase以GC://开头时源码还会依据 GPO 的 DN 反推域并计算gpcfilesyspath形如\\域\SysVol\域\Policies\GPO名便于进一步访问 GPO 在 SYSVOL 上的文件系统内容。依赖关系与模块加载原文档列出的必需依赖为Get-DomainSearcher、Get-DomainComputer、Get-DomainUser、Get-DomainOU、Get-NetComputerSiteName、Get-DomainSite、Get-DomainObject、Convert-LDAPProperty它们均定义于 Recon/PowerView.ps1并通过 Recon/Recon.psd1 的FileList与FunctionsToExport随 Recon 模块一起加载。PowerView 的测试脚本 Tests/Recon.tests.ps1 会在测试开始前直接Import-Module导入Recon\PowerView.ps1以便对其中各个辅助函数进行单元测试——这也说明Get-DomainGPO及其依赖函数均可脱离完整模块独立加载使用。使用前提与注意事项运行环境Get-DomainGPO为 PowerShell 脚本须运行在能访问目标 Active Directory 的 Windows 主机上域内主机或配置了正确凭据/服务器参数的机器PowerView 属于后渗透框架组件请仅在获得授权的渗透测试、红队演练或域安全审计环境中使用。目标可达性默认绑定当前域跨域查询需指定-Domain与-Server跨林查询可利用GC://开头的-SearchBase走全局编录。性能控制大规模域内建议用-Properties裁剪返回字段并用-ResultPageSize/-ServerTimeLimit控制分页与服务端耗时。继承语义通过-ComputerIdentity/-UserIdentity返回的是完整的 OU→站点→域链接 GPO 集合并已按“阻止继承”与“强制”标志做了过滤理解这一点有助于准确解读机器上真正生效的策略范围。赞分享渗透测试网络安全【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址https://gitcode.com/gh_mirrors/po/PowerSploit点击查看免费下载相关推荐PowerSploit 域渗透侦察使用 PowerView 的 Get-ForestTrust 枚举林信任关系PowerSploit 域渗透侦察使用 PowerView 的 Get ForestTrust 枚举林信任关系 导读 Get ForestTrust 是 Po渗透测试网络安全PowerSploit 内网侦察实战用 PowerView 的 Get-DomainGPOLocalGroup 枚举 GPO 本地组成员PowerSploit 内网侦察实战用 PowerView 的 Get DomainGPOLocalGroup 枚举 GPO 本地组成员 导读 Get Dom渗透测试网络安全PowerSploit 中的 Get-DomainUser基于 PowerView 的 Active Directory 用户对象侦察实战指南PowerSploit 中的 Get DomainUser基于 PowerView 的 Active Directory 用户对象侦察实战指南 本篇技术指南以渗透测试网络安全创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进