├── README.md ├── Get-DomainKerberosPolicy ├── LICENSE ├── Get-PSADForestKRBTGTInfo ├── Discover-PSMSExchangeServers ├── Find-PSServiceAccounts ├── Discover-PSMSSQLServers ├── Get-PSADForestInfo └── Discover-PSInterestingServices /README.md: -------------------------------------------------------------------------------- 1 | PowerShell 2 | ========== 3 | 4 | PowerShell Scripts I find useful 5 | -------------------------------------------------------------------------------- /Get-DomainKerberosPolicy: -------------------------------------------------------------------------------- 1 | Function Get-KerberosPolicy 2 | { 3 | # NOTE: This script REQUIRES the GroupPolicy module installed. 4 | Import-Module GroupPolicy 5 | 6 | [string]$PDCHostName = (Get-ADDomainController -Discover -Service PrimaryDC).HostName 7 | [xml]$DefaultDomainPolicyXML = Get-GPO -Name "Default Domain Policy" -Server $PDCHostName | Get-GPOReport -ReportType XML # -Path c:\temp\DDP.xml 8 | $NameSpaceManager = New-Object System.XML.XmlNamespaceManager($DefaultDomainPolicyXML.NameTable) 9 | $NameSpaceManager.AddNamespace('root','http://www.microsoft.com/GroupPolicy/Settings') 10 | $GPOsettings = [array]$DefaultDomainPolicyXML.SelectNodes('//root:Extension',$NameSpaceManager) 11 | $KerberosPolicySettings = $GPOsettings.Account |?{$_.type -match "Kerberos"} 12 | 13 | $KerberosPolicySettingsMaxRenewAge = $KerberosPolicySettings.MaxRenewAge 14 | $KerberosPolicySettingsMaxTicketAge = $KerberosPolicySettings.MaxTicketAge 15 | 16 | return $KerberosPolicySettings 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, PyroTek3 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /Get-PSADForestKRBTGTInfo: -------------------------------------------------------------------------------- 1 | function Get-PSADForestKRBTGTInfo 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This function discovers all of the KRBTGT accounts in the forest and returns the account info. 7 | 8 | Get-PSADForestKRBTGTInfo 9 | Author: Sean Metcalf, Twitter: @PyroTek3 10 | License: BSD 3-Clause 11 | Required Dependencies: None 12 | Optional Dependencies: None 13 | 14 | Last Updated: 11/10/2014 15 | Version: 1.0 16 | 17 | .DESCRIPTION 18 | This function discovers all of the KRBTGT accounts in the forest using ADSI and returns the account info, specifically the last password change. 19 | 20 | Currently, the script performs the following actions: 21 | * Queries a Global Catalog in the Active Directory root domain for all KRBTGT accounts in the forest by querying the Global Catalog for SPN info. 22 | * Provides information about all of the KRBTGT accounts in the forest, specifically the last password change. 23 | 24 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 25 | 26 | .EXAMPLE 27 | Get-PSADForestKRBTGTInfo 28 | Perform KRBTGT account SPN discovery via AD and returns the results in a custom PowerShell object. 29 | 30 | .NOTES 31 | This function discovers all of the KRBTGT accounts in the forest and returns the account info. 32 | 33 | .LINK 34 | Blog: http://www.ADSecurity.org 35 | Github repo: https://github.com/PyroTek3/PowerShell-AD-Recon 36 | 37 | 38 | #> 39 | 40 | Param 41 | ( 42 | ) 43 | 44 | Write-Verbose "Get current Active Directory domain... " 45 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 46 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 47 | $ADForestInfoRootDomainDN = "DC=" + $ADForestInfoRootDomain -Replace("\.",',DC=') 48 | 49 | $ADDomainInfoLGCDN = 'GC://' + $ADForestInfoRootDomainDN 50 | 51 | Write-Verbose "Discovering service account SPNs in the AD Forest $ADForestInfoRootDomainDN " 52 | $root = [ADSI]$ADDomainInfoLGCDN 53 | $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"(serviceprincipalname=kadmin/changepw)") 54 | $ADSearcher.PageSize = 5000 55 | $AllADKRBTGTAccountSPNs = $ADSearcher.FindAll() 56 | 57 | $AllADKRBTGTAccountSPNsCount = $AllADKRBTGTAccountSPNs.Count 58 | 59 | Write-Output "Processing $AllADKRBTGTAccountSPNsCount service accounts (user accounts) with SPNs discovered in AD Forest $ADForestInfoRootDomainDN `r " 60 | 61 | $AllKRBTGTAccountReport = $Null 62 | ForEach ($AllADKRBTGTAccountSPNsItem in $AllADKRBTGTAccountSPNs) 63 | { 64 | $KRBTGTAccountsItemDomain = $Null 65 | [array]$AllADKRBTGTAccountSPNsItemDNArray = ($AllADKRBTGTAccountSPNsItem.Properties.distinguishedname) -Split(",DC=") 66 | [int]$DomainNameFECount = 0 67 | ForEach ($AllADKRBTGTAccountSPNsItemDNArrayItem in $AllADKRBTGTAccountSPNsItemDNArray) 68 | { 69 | IF ($DomainNameFECount -gt 0) 70 | { [string]$KRBTGTAccountsItemDomain += $AllADKRBTGTAccountSPNsItemDNArrayItem + "." } 71 | $DomainNameFECount++ 72 | } 73 | $KRBTGTAccountsItemDomain = $KRBTGTAccountsItemDomain.Substring(0,$KRBTGTAccountsItemDomain.Length-1) 74 | 75 | [string]$KRBTGTAccountsItemSAMAccountName = $AllADKRBTGTAccountSPNsItem.properties.samaccountname 76 | [string]$KRBTGTAccountsItemdescription = $AllADKRBTGTAccountSPNsItem.properties.description 77 | [string]$KRBTGTAccountsItempwdlastset = $AllADKRBTGTAccountSPNsItem.properties.pwdlastset 78 | [string]$KRBTGTAccountsItemPasswordLastSetDate = [datetime]::FromFileTimeUTC($KRBTGTAccountsItempwdlastset) 79 | [string]$KRBTGTAccountsItemlastlogon = $AllADKRBTGTAccountSPNsItem.properties.lastlogon 80 | [string]$KRBTGTAccountsItemLastLogonDate = [datetime]::FromFileTimeUTC($KRBTGTAccountsItemlastlogon) 81 | 82 | $KRBTGTAccountReport = New-Object -TypeName System.Object 83 | $KRBTGTAccountReport | Add-Member -MemberType NoteProperty -Name Domain -Value $KRBTGTAccountsItemDomain 84 | $KRBTGTAccountReport | Add-Member -MemberType NoteProperty -Name UserID -Value $KRBTGTAccountsItemSAMAccountName 85 | $KRBTGTAccountReport | Add-Member -MemberType NoteProperty -Name Description -Value $KRBTGTAccountsItemdescription 86 | $KRBTGTAccountReport | Add-Member -MemberType NoteProperty -Name PasswordLastSet -Value $KRBTGTAccountsItemPasswordLastSetDate 87 | $KRBTGTAccountReport | Add-Member -MemberType NoteProperty -Name LastLogon -Value $KRBTGTAccountsItemLastLogonDate 88 | 89 | [array]$AllKRBTGTAccountReport += $KRBTGTAccountReport 90 | 91 | } 92 | 93 | 94 | # $AllKRBTGTAccountReport | sort PasswordLastSet 95 | 96 | return $AllKRBTGTAccountReport 97 | } 98 | -------------------------------------------------------------------------------- /Discover-PSMSExchangeServers: -------------------------------------------------------------------------------- 1 | function Discover-PSMSExchangeServers 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This script is used to discover Microsoft Exchange servers without port scanning. 7 | Exchange discovery in the Active Directory Forest is performed by querying an Active Directory Gloabl Catalog via LDAP. 8 | 9 | PowerSploit Function: Discover-PSMSExchangeServers 10 | Author: Sean Metcalf, Twitter: @PyroTek3 11 | License: BSD 3-Clause 12 | Required Dependencies: None 13 | Optional Dependencies: None 14 | 15 | Version: 1.6 16 | 17 | .DESCRIPTION 18 | This script is used to discover Microsoft Exchange servers in the Active Directory Forest. 19 | 20 | Currently, the script performs the following actions: 21 | * Queries a Global Catalog in the Active Directory root domain for all Microsoft Exchange SPNs in the forest 22 | 23 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 24 | 25 | .EXAMPLE 26 | Discover-PSMSExchangeServers 27 | Perform Microsoft Exchange Server discovery via AD and displays the results in a table. 28 | 29 | .NOTES 30 | This script is used to discover Microsoft Exchange servers in the Active Directory Forest and can also provide additional computer information such as OS and last bootup time. 31 | 32 | .LINK 33 | Blog: http://www.ADSecurity.org 34 | Github repo: https://github.com/PyroTek3/PowerShell-AD-Recon 35 | 36 | #> 37 | Param 38 | ( 39 | 40 | ) 41 | 42 | Write-Verbose "Get current Active Directory domain... " 43 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 44 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 45 | $ADForestInfoRootDomainArray = $ADForestInfoRootDomain -Split("\.") 46 | $ADForestInfoRootDomainDN = $Null 47 | ForEach($ADForestInfoRootDomainArrayItem in $ADForestInfoRootDomainArray) 48 | { 49 | $ADForestInfoRootDomainDN += "DC=" + $ADForestInfoRootDomainArrayItem + "," 50 | } 51 | $ADForestInfoRootDomainDN = $ADForestInfoRootDomainDN.Substring(0,$ADForestInfoRootDomainDN.Length-1) 52 | 53 | $ADDomainInfoLGCDN = 'GC://' + $ADForestInfoRootDomainDN 54 | 55 | Write-Verbose "Discovering Microsoft Exchange Servers in the AD Forest $ADForestInfoRootDomainDN " 56 | $root = [ADSI]$ADDomainInfoLGCDN 57 | $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"(|(serviceprincipalname=exchangeRFR*)(serviceprincipalname=exchangeRFR*))") 58 | $ADSearcher.PageSize = 1000 59 | $AllADExchangeServerSPNs = $ADSearcher.FindAll() 60 | 61 | $AllADExchangeServerSPNs = $AllADExchangeServerSPNs | sort-object Path -unique 62 | 63 | $AllADExchangeServerSPNsCount = $AllADExchangeServerSPNs.Count 64 | 65 | Write-Output "Processing $AllADExchangeServerSPNsCount (user and computer) accounts with MS Exchange SPNs discovered in AD Forest $ADForestInfoRootDomainDN `r " 66 | 67 | $AllMSExchangeSPNs = $NULL 68 | $ALLExchangeServerReport = @() 69 | $AllMSExchangeSPNHashTable =@{} 70 | ForEach ($AllADExchangeServerSPNsItem in $AllADExchangeServerSPNs) 71 | { 72 | $AllADExchangeServerSPNsItemDomainName = $NULL 73 | [array]$AllADExchangeServerSPNsItemArray = $AllADExchangeServerSPNsItem.Path -Split(",DC=") 74 | [int]$DomainNameFECount = 0 75 | ForEach ($AllADExchangeServerSPNsItemArrayItem in $AllADExchangeServerSPNsItemArray) 76 | { 77 | IF ($DomainNameFECount -gt 0) 78 | { [string]$AllADExchangeServerSPNsItemDomainName += $AllADExchangeServerSPNsItemArrayItem + "." } 79 | $DomainNameFECount++ 80 | } 81 | $AllADExchangeServerSPNsItemDomainName = $AllADExchangeServerSPNsItemDomainName.Substring(0,$AllADExchangeServerSPNsItemDomainName.Length-1) 82 | 83 | ForEach ($ADSIExchangeServersItemSPN in $AllADExchangeServerSPNsItem.properties.serviceprincipalname) 84 | { 85 | IF ($ADSIExchangeServersItemSPN -like "exchange*") 86 | { 87 | $ADSIExchangeServersItemSPNArray1 = $ADSIExchangeServersItemSPN -Split("/") 88 | $ADSIExchangeServersItemSPNArray2 = $ADSIExchangeServersItemSPNArray1 -Split(":") 89 | [string]$ADSIExchangeServersItemSPNServerFQDN = $ADSIExchangeServersItemSPNArray2[1] 90 | IF ($ADSIExchangeServersItemSPNServerFQDN -notlike "*$AllADExchangeServerSPNsItemDomainName*" ) 91 | { $ADSIExchangeServersItemSPNServerFQDN = $ADSIExchangeServersItemSPNServerFQDN + "." + $AllADExchangeServerSPNsItemDomainName } 92 | 93 | $AllMSExchangeSPNsItemServerName = $ADSIExchangeServersItemSPNServerFQDN -Replace(("."+ $AllADExchangeServerSPNsItemDomainName),"") 94 | 95 | $ADSIExchangeServersItemSPNServerFQDNArray = $ADSIExchangeServersItemSPNServerFQDN -Split('\.') 96 | $ExchangeServerDomainDN = $NULL 97 | [int]$FQDNArrayFECount = 0 98 | ForEach ($ADSIExchangeServersItemSPNServerFQDNArrayItem in $ADSIExchangeServersItemSPNServerFQDNArray) 99 | { 100 | IF ($FQDNArrayFECount -ge 1) 101 | { 102 | [string]$ExchangeServerDomainName += $ADSIExchangeServersItemSPNServerFQDNArrayItem + "." 103 | [string]$ExchangeServerDomainDN += "DC=" + $ADSIExchangeServersItemSPNServerFQDNArrayItem + "," 104 | } 105 | $FQDNArrayFECount++ 106 | } 107 | 108 | $ExchangeServerDomainName = $ExchangeServerDomainName.Substring(0,$ExchangeServerDomainName.Length-1) 109 | $ExchangeServerDomainDN = $ExchangeServerDomainDN.Substring(0,$ExchangeServerDomainDN.Length-1) 110 | $ExchangeServerDomainLDAPDN = "LDAP://$ExchangeServerDomainDN" 111 | 112 | $ExchangeServerReport = New-Object -TypeName System.Object 113 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name Domain -Value $AllADExchangeServerSPNsItemDomainName 114 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name ServerName -Value $ADSIExchangeServersItemSPNServerFQDN 115 | 116 | TRY 117 | { 118 | $ADComputerSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 119 | $ADComputerSearch.SearchRoot = $ExchangeServerDomainLDAPDN 120 | $ADComputerSearch.PageSize = 500 121 | $ADComputerSearch.Filter = "(&(objectCategory=Computer)(name=$AllMSExchangeSPNsItemServerName))" 122 | $ADComputerSearchInfo = $ADComputerSearch.FindAll() 123 | 124 | [string]$ComputerADInfoLastLogonTimestamp = ($ADComputerSearchInfo[0].properties.lastlogontimestamp) 125 | TRY { [datetime]$ComputerADInfoLLT = [datetime]::FromFileTime($ComputerADInfoLastLogonTimestamp) } 126 | CATCH { } 127 | 128 | $ComputerADInfo.Values 129 | 130 | #$Name = $Result.Properties.Item("sAMAccOUntnAme") 131 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name OperatingSystem -Value ($ADComputerSearchInfo[0].properties.operatingsystem) 132 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name OSServicePack -Value ($ADComputerSearchInfo[0].properties.operatingsystemservicepack) 133 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name LastBootup -Value $ComputerADInfoLLT 134 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name OSVersion -Value ($ADComputerSearchInfo[0].properties.operatingsystemversion) 135 | $ExchangeServerReport | Add-Member -MemberType NoteProperty -Name Description -Value ($ADComputerSearchInfo[0].properties.description) 136 | } 137 | CATCH { } 138 | 139 | 140 | [array]$ALLExchangeServerReport += $ExchangeServerReport 141 | 142 | } 143 | } 144 | } 145 | 146 | $ALLExchangeServerReport = $ALLExchangeServerReport | sort-object ServerName -Unique 147 | 148 | return $ALLExchangeServerReport 149 | 150 | } 151 | 152 | -------------------------------------------------------------------------------- /Find-PSServiceAccounts: -------------------------------------------------------------------------------- 1 | function Find-PSServiceAccounts 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This function discovers all user accounts configured with a ServicePrincipalName in the Active Directory domain or forest. 7 | 8 | Find-PSServiceAccounts 9 | Author: Sean Metcalf, Twitter: @PyroTek3 10 | License: BSD 3-Clause 11 | Required Dependencies: None 12 | Optional Dependencies: None 13 | Last Updated: 1/16/2015 14 | Version: 1.1 15 | 16 | .DESCRIPTION 17 | This function discovers all user accounts configured with a ServicePrincipalName in the Active Directory domain or forest. 18 | 19 | Currently, the script performs the following actions: 20 | * Forest Mode: Queries a Global Catalog in the Active Directory root domain for all user accounts configured with a ServicePrincipalName in the forest by querying the Global Catalog for SPN info. 21 | * Domain Mode: Queries a DC in the current Active Directory domain for all user accounts configured with a ServicePrincipalName in the forest by querying the DCfor SPN info. 22 | * Identifies the ServicePrincipalNames associated with the account and reports on the SPN types and server names. 23 | * Provides password last set date & last logon date for service accounts 24 | 25 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 26 | 27 | .EXAMPLE 28 | Find-PSServiceAccounts 29 | Perform current AD domain user account SPN discovery via AD and returns the results in a custom PowerShell object. 30 | 31 | .EXAMPLE 32 | Find-PSServiceAccounts -Forest 33 | Perform current AD forest user account SPN discovery via AD and returns the results in a custom PowerShell object. 34 | 35 | .EXAMPLE 36 | Find-PSServiceAccounts -Domain "ad.domain.com" 37 | Perform user account SPN discovery for the Active Directory domain "ad.domain.com" via AD and returns the results in a custom PowerShell object. 38 | 39 | .EXAMPLE 40 | Find-PSServiceAccounts -Domain "ad.domain.com" -DumpSPNs 41 | Perform user account SPN discovery for the Active Directory domain "ad.domain.com" via AD and returns the list of discovered SPN FQDNs (de-duplicated). 42 | 43 | 44 | .NOTES 45 | This function discovers all user accounts configured with a ServicePrincipalName in the Active Directory domain or forest. 46 | 47 | .LINK 48 | Blog: http://www.ADSecurity.org 49 | Github repo: https://github.com/PyroTek3/PowerShell-AD-Recon 50 | #> 51 | 52 | Param 53 | ( 54 | [ValidateSet("Domain", "Forest")] 55 | [string]$Scope = "Domain", 56 | 57 | [string]$DomainName, 58 | 59 | [switch]$DumpSPNs, 60 | [switch]$GetTGS 61 | 62 | ) 63 | 64 | Write-Verbose "Get current Active Directory domain... " 65 | 66 | 67 | IF ($Scope -eq "Domain") 68 | { 69 | IF (!($DomainName)) 70 | { 71 | $ADDomainInfo = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 72 | $ADDomainName = $ADDomainInfo.Name 73 | } 74 | $ADDomainDN = "DC=" + $ADDomainName -Replace("\.",',DC=') 75 | $ADDomainLDAPDN = 'LDAP://' + $ADDomainDN 76 | Write-Output "Discovering service account SPNs in the AD Domain $ADDomainName " 77 | } 78 | 79 | IF ( ($Scope -eq "Forest") -AND (!($DomainName)) ) 80 | { 81 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 82 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 83 | $ADForestInfoRootDomainDN = "DC=" + $ADForestInfoRootDomain -Replace("\.",',DC=') 84 | $ADDomainLDAPDN = 'GC://' + $ADForestInfoRootDomainDN 85 | Write-Output "Discovering service account SPNs in the AD Forest $ADForestInfoRootDomain " 86 | } 87 | 88 | $root = [ADSI]$ADDomainLDAPDN 89 | $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"(&(objectcategory=user)(serviceprincipalname=*))") 90 | $ADSearcher.PageSize = 5000 91 | $AllServiceAccounts = $ADSearcher.FindAll() 92 | # $AllServiceAccountsCount = $AllServiceAccounts.Count 93 | # Write-Output "Processing $AllServiceAccountsCount service accounts (user accounts) with SPNs discovered in AD ($ADDomainLDAPDN) `r " 94 | 95 | $AllServiceAccountsReport = $Null 96 | $AllServiceAccountsSPNs = @() 97 | ForEach ($AllServiceAccountsItem in $AllServiceAccounts) 98 | { 99 | $AllServiceAccountsItemSPNTypes = @() 100 | $AllServiceAccountsItemSPNServerNames = @() 101 | $AllServiceAccountsItemSPNs = @() 102 | 103 | ForEach ($AllServiceAccountsItemSPN in $AllServiceAccountsItem.properties.serviceprincipalname) 104 | { 105 | $AllServiceAccountsItemDomainName = $NULL 106 | [array]$AllServiceAccountsItemmDNArray = $AllServiceAccountsItem.Path -Split(",DC=") 107 | [int]$DomainNameFECount = 0 108 | ForEach ($AllServiceAccountsItemmDNArrayItem in $AllServiceAccountsItemmDNArray) 109 | { 110 | IF ($DomainNameFECount -gt 0) 111 | { [string]$AllServiceAccountsItemDomainName += $AllServiceAccountsItemmDNArrayItem + "." } 112 | $DomainNameFECount++ 113 | } 114 | $AllServiceAccountsItemDomainName = $AllServiceAccountsItemDomainName.Substring(0,$AllServiceAccountsItemDomainName.Length-1) 115 | 116 | $AllServiceAccountsItemSPNArray1 = $AllServiceAccountsItemSPN -Split("/") 117 | $AllServiceAccountsItemSPNArray2 = $AllServiceAccountsItemSPNArray1 -Split(":") 118 | 119 | [string]$AllServiceAccountsItemSPNType = $AllServiceAccountsItemSPNArray1[0] 120 | [string]$AllServiceAccountsItemSPNServer = $AllServiceAccountsItemSPNArray2[1] 121 | IF ($AllServiceAccountsItemSPNServer -notlike "*$AllServiceAccountsItemDomainName*" ) 122 | { 123 | $AllServiceAccountsItemSPNServerName = $AllServiceAccountsItemSPNServer 124 | $AllServiceAccountsItemSPNServerFQDN = $NULL 125 | } 126 | ELSE 127 | { 128 | $AllServiceAccountsItemSPNServerName = $AllServiceAccountsItemSPNServer -Replace(("."+ $AllServiceAccountsItemDomainName),"") 129 | $AllServiceAccountsItemSPNServerFQDN = $AllServiceAccountsItemSPNServer 130 | [array]$AllServiceAccountsSPNs += $AllServiceAccountsItemSPN 131 | } 132 | 133 | #[string]$AllMSSQLSPNsItemServerInstancePort = $ADSISQLServersItemSPNArray2[2] 134 | 135 | [array]$AllServiceAccountsItemSPNTypes += $AllServiceAccountsItemSPNType 136 | [array]$AllServiceAccountsItemSPNServerNames += $AllServiceAccountsItemSPNServerFQDN 137 | [array]$AllServiceAccountsItemSPNs += $AllServiceAccountsItemSPN 138 | 139 | } 140 | 141 | [array]$AllServiceAccountsItemSPNTypes = $AllServiceAccountsItemSPNTypes | sort-object | get-unique 142 | [array]$AllServiceAccountsItemSPNServerNames = $AllServiceAccountsItemSPNServerNames | sort-object | get-unique 143 | [array]$AllServiceAccountsItemSPNs = $AllServiceAccountsItemSPNs | sort-object | get-unique 144 | 145 | $AllServiceAccountsItemDN = $Null 146 | [array]$AllServiceAccountsItemDNArray = ($AllServiceAccountsItem.Properties.distinguishedname) -Split(",DC=") 147 | [int]$DomainNameFECount = 0 148 | ForEach ($AllServiceAccountsItemDNArrayItem in $AllServiceAccountsItemDNArray) 149 | { 150 | IF ($DomainNameFECount -gt 0) 151 | { [string]$AllServiceAccountsItemDN += $AllServiceAccountsItemDNArrayItem + "." } 152 | $DomainNameFECount++ 153 | } 154 | $AllServiceAccountsItemDN = $AllServiceAccountsItemDN.Substring(0,$AllServiceAccountsItemDN.Length-1) 155 | 156 | [string]$ServiceAccountsItemSAMAccountName = $AllServiceAccountsItem.properties.samaccountname 157 | [string]$ServiceAccountsItemdescription = $AllServiceAccountsItem.properties.description 158 | [string]$ServiceAccountsItempwdlastset = $AllServiceAccountsItem.properties.pwdlastset 159 | [string]$ServiceAccountsItemPasswordLastSetDate = [datetime]::FromFileTimeUTC($ServiceAccountsItempwdlastset) 160 | [string]$ServiceAccountsItemlastlogon = $AllServiceAccountsItem.properties.lastlogon 161 | [string]$ServiceAccountsItemLastLogonDate = [datetime]::FromFileTimeUTC($ServiceAccountsItemlastlogon) 162 | 163 | $ServiceAccountsReport = New-Object PSObject -Property @{ 164 | Domain = $AllServiceAccountsItemDomainName 165 | UserID = $ServiceAccountsItemSAMAccountName 166 | Description = $ServiceAccountsItemdescription 167 | PasswordLastSet = $ServiceAccountsItemPasswordLastSetDate 168 | LastLogon = $ServiceAccountsItemLastLogonDate 169 | SPNServers = $AllServiceAccountsItemSPNServerNames 170 | SPNTypes = $AllServiceAccountsItemSPNTypes 171 | ServicePrincipalNames = $AllServiceAccountsItemSPNs 172 | } 173 | 174 | [array]$AllServiceAccountsReport += $ServiceAccountsReport 175 | } 176 | 177 | $AllServiceAccountsReport = $AllServiceAccountsReport | Select-Object Domain,UserID,PasswordLastSet,LastLogon,Description,SPNServers,SPNTypes,ServicePrincipalNames 178 | 179 | If ($DumpSPNs -eq $True) 180 | { 181 | [array]$AllServiceAccountsSPNs = $AllServiceAccountsSPNs | sort-object | Get-Unique 182 | return $AllServiceAccountsSPNs 183 | 184 | IF ($GetTGS) 185 | { 186 | ForEach ($AllServiceAccountsSPNsItem in $AllServiceAccountsSPNs) 187 | { 188 | Add-Type -AssemblyName System.IdentityModel 189 | New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "$AllServiceAccountsSPNsItem" 190 | } 191 | } 192 | } 193 | 194 | ELSE 195 | { return $AllServiceAccountsReport } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /Discover-PSMSSQLServers: -------------------------------------------------------------------------------- 1 | function Discover-PSMSSQLServers 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This script is used to discover Microsoft SQL servers without port scanning. 7 | SQL discovery in the Active Directory Forest is performed by querying an Active Directory Gloabl Catalog via ADSI. 8 | 9 | Discover-PSMSSQLServers 10 | Author: Sean Metcalf, Twitter: @PyroTek3 11 | License: BSD 3-Clause 12 | Required Dependencies: None 13 | Optional Dependencies: None 14 | 15 | Last Updated: 2/04/2015 16 | Version: 2.3 17 | 18 | .DESCRIPTION 19 | This script is used to discover Microsoft SQL servers in the Active Directory Forest. 20 | 21 | Currently, the script performs the following actions: 22 | * Queries a Global Catalog in the Active Directory root domain for all Microsoft SQL SPNs in the forest 23 | * Displays the Microsoft SQL server FQDNs ports and instances 24 | * Identifies any service accounts associated with the SQL instance and includes the account info 25 | 26 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 27 | 28 | .EXAMPLE 29 | Discover-PSMSSQLServers 30 | Perform Microsoft SQL Server discovery via AD and returns the results in a custom PowerShell object. 31 | 32 | .NOTES 33 | This script is used to discover Microsoft SQL servers in the Active Directory Forest and can also provide additional computer information such as OS and last bootup time. 34 | 35 | .LINK 36 | Blog: http://www.ADSecurity.org 37 | Github repo: https://github.com/PyroTek3/PowerShell-AD-Recon 38 | 39 | 40 | #> 41 | 42 | Param 43 | ( 44 | 45 | ) 46 | 47 | Write-Verbose "Get current Active Directory domain... " 48 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 49 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 50 | $ADForestInfoRootDomainDN = "DC=" + $ADForestInfoRootDomain -Replace("\.",',DC=') 51 | 52 | $ADDomainInfoLGCDN = 'GC://' + $ADForestInfoRootDomainDN 53 | 54 | Write-Verbose "Discovering Microsoft SQL Servers in the AD Forest $ADForestInfoRootDomainDN " 55 | $root = [ADSI]$ADDomainInfoLGCDN 56 | $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"(serviceprincipalname=mssql*)") 57 | $ADSearcher.PageSize = 50000 58 | $AllADSQLServerSPNs = $ADSearcher.FindAll() 59 | 60 | $AllADSQLServerSPNsCount = $AllADSQLServerSPNs.Count 61 | 62 | Write-Output "Processing $AllADSQLServerSPNsCount (user and computer) accounts with MS SQL SPNs discovered in AD Forest $ADForestInfoRootDomainDN `r " 63 | 64 | $AllMSSQLSPNs = $NULL 65 | $AllMSSQLSPNHashTable =@{} 66 | $AllMSSQLServiceAccountHashTable =@{} 67 | ForEach ($AllADSQLServerSPNsItem in $AllADSQLServerSPNs) 68 | { 69 | $AllADSQLServerSPNsItemDomainName = $NULL 70 | [array]$AllADSQLServerSPNsItemArray = $AllADSQLServerSPNsItem.Path -Split(",DC=") 71 | [int]$DomainNameFECount = 0 72 | ForEach ($AllADSQLServerSPNsItemArrayItem in $AllADSQLServerSPNsItemArray) 73 | { 74 | IF ($DomainNameFECount -gt 0) 75 | { [string]$AllADSQLServerSPNsItemDomainName += $AllADSQLServerSPNsItemArrayItem + "." } 76 | $DomainNameFECount++ 77 | } 78 | $AllADSQLServerSPNsItemDomainName = $AllADSQLServerSPNsItemDomainName.Substring(0,$AllADSQLServerSPNsItemDomainName.Length-1) 79 | 80 | ForEach ($ADSISQLServersItemSPN in $AllADSQLServerSPNsItem.properties.serviceprincipalname) 81 | { 82 | IF ( ($ADSISQLServersItemSPN -like "MSSQL*") -AND ($ADSISQLServersItemSPN -like "*:*") ) 83 | { 84 | IF (($AllADSQLServerSPNsItem.properties.objectcategory -like "CN=Person*") -AND ($ADSISQLServersItemSPNServerFQDN) ) 85 | { 86 | $AllMSSQLServiceAccountHashTable.Set_Item($ADSISQLServersItemSPNServerFQDN,$AllADSQLServerSPNsItem.properties.distinguishedname) 87 | } 88 | $ADSISQLServersItemSPNArray1 = $ADSISQLServersItemSPN -Split("/") 89 | $ADSISQLServersItemSPNArray2 = $ADSISQLServersItemSPNArray1 -Split(":") 90 | [string]$ADSISQLServersItemSPNServerFQDN = $ADSISQLServersItemSPNArray2[1] 91 | IF ($ADSISQLServersItemSPNServerFQDN -notlike "*$AllADSQLServerSPNsItemDomainName*" ) 92 | { $ADSISQLServersItemSPNServerFQDN = $ADSISQLServersItemSPNServerFQDN + "." + $AllADSQLServerSPNsItemDomainName } 93 | [string]$AllMSSQLSPNsItemServerInstancePort = $ADSISQLServersItemSPNArray2[2] 94 | 95 | $AllMSSQLSPNsItemServerName = $ADSISQLServersItemSPNServerFQDN -Replace(("."+ $AllADSQLServerSPNsItemDomainName),"") 96 | 97 | $AllMSSQLSPNHashTableData = $AllMSSQLSPNHashTable.Get_Item($ADSISQLServersItemSPNServerFQDN) 98 | IF ( ($AllMSSQLSPNHashTableData) -AND ($AllMSSQLSPNHashTableData -notlike "*$AllMSSQLSPNsItemServerInstancePort*") ) 99 | { 100 | $AllMSSQLSPNHashTableDataUpdate = $AllMSSQLSPNHashTableData + ";" + $AllMSSQLSPNsItemServerInstancePort 101 | $AllMSSQLSPNHashTable.Set_Item($ADSISQLServersItemSPNServerFQDN,$AllMSSQLSPNHashTableDataUpdate) 102 | } 103 | ELSE 104 | { $AllMSSQLSPNHashTable.Set_Item($ADSISQLServersItemSPNServerFQDN,$AllMSSQLSPNsItemServerInstancePort) } 105 | } 106 | } 107 | } 108 | 109 | ### 110 | Write-Verbose "Loop through the discovered MS SQL SPNs and build the report " 111 | ### 112 | $ALLSQLServerReport = @() 113 | #$AllMSSQLServerFQDNs = $NULL 114 | ForEach ($AllMSSQLSPNsItem in $AllMSSQLSPNHashTable.GetEnumerator()) 115 | { 116 | $AllMSSQLSPNsItemServerDomainName = $NULL 117 | $AllMSSQLSPNsItemServerDomainDN = $NULL 118 | $AllMSSQLSPNsItemServiceAccountDN = $NULL 119 | $AllMSSQLSPNsItemServiceAccountDomainDN = $NULL 120 | 121 | $AllMSSQLSPNsItemServerFQDN = $AllMSSQLSPNsItem.Name 122 | #[array]$AllMSSQLServerFQDNs += $AllMSSQLSPNsItemServerFQDN 123 | $AllMSSQLSPNsItemInstancePortArray = ($AllMSSQLSPNsItem.Value) -Split(';') 124 | 125 | $AllMSSQLSPNsItemServerFQDNArray = $AllMSSQLSPNsItemServerFQDN -Split('\.') 126 | [int]$FQDNArrayFECount = 0 127 | ForEach ($AllMSSQLSPNsItemServerFQDNArrayItem in $AllMSSQLSPNsItemServerFQDNArray) 128 | { 129 | IF ($FQDNArrayFECount -ge 1) 130 | { 131 | [string]$AllMSSQLSPNsItemServerDomainName += $AllMSSQLSPNsItemServerFQDNArrayItem + "." 132 | [string]$AllMSSQLSPNsItemServerDomainDN += "DC=" + $AllMSSQLSPNsItemServerFQDNArrayItem + "," 133 | } 134 | $FQDNArrayFECount++ 135 | } 136 | 137 | $AllMSSQLSPNsItemServerDomainName = $AllMSSQLSPNsItemServerDomainName.Substring(0,$AllMSSQLSPNsItemServerDomainName.Length-1) 138 | $AllMSSQLSPNsItemServerDomainDN = $AllMSSQLSPNsItemServerDomainDN.Substring(0,$AllMSSQLSPNsItemServerDomainDN.Length-1) 139 | $AllMSSQLSPNsItemServerDomainLDAPDN = "LDAP://$AllMSSQLSPNsItemServerDomainDN" 140 | 141 | $AllMSSQLSPNsItemServerName = $AllMSSQLSPNsItemServerFQDN -Replace(("."+$AllMSSQLSPNsItemServerDomainName),"") 142 | 143 | $AllMSSQLSPNsItemServiceAccountDN = $AllMSSQLServiceAccountHashTable.Get_Item($AllMSSQLSPNsItemServerFQDN) 144 | IF ($AllMSSQLSPNsItemServiceAccountDN) 145 | { 146 | $ADServiceAccountSearchInfo = @() 147 | $AllMSSQLSPNsItemServiceAccountDNArray = $AllMSSQLSPNsItemServiceAccountDN -Split(",") 148 | ForEach ($AllMSSQLSPNsItemServiceAccountDNArrayItem in $AllMSSQLSPNsItemServiceAccountDNArray) 149 | { 150 | IF ($AllMSSQLSPNsItemServiceAccountDNArrayItem -like 'DC=*') 151 | { [string]$AllMSSQLSPNsItemServiceAccountDomainDN += "$AllMSSQLSPNsItemServiceAccountDNArrayItem," } 152 | 153 | } 154 | $AllMSSQLSPNsItemServiceAccountDomainDN = $AllMSSQLSPNsItemServiceAccountDomainDN.Substring(0,$AllMSSQLSPNsItemServiceAccountDomainDN.Length-1) 155 | 156 | $AllMSSQLSPNsItemServiceAccountDomainLDAPDN = "LDAP://$AllMSSQLSPNsItemServiceAccountDomainDN" 157 | 158 | $ADServiceAccountSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 159 | $ADServiceAccountSearch.SearchRoot = $AllMSSQLSPNsItemServiceAccountDomainLDAPDN 160 | $ADServiceAccountSearch.PageSize = 50000 161 | $ADServiceAccountSearch.Filter = "distinguishedname=$AllMSSQLSPNsItemServiceAccountDN" 162 | $ADServiceAccountSearchInfo = $ADServiceAccountSearch.FindAll() 163 | 164 | IF ($ADServiceAccountSearchInfo) 165 | { 166 | [string]$ADServiceAccountSAMAccountName = $ADServiceAccountInfo[0].Properties.samaccountname 167 | [string]$ADServiceAccountdescription = $ADServiceAccountSearchInfo[0].Properties.description 168 | [string]$ADServiceAccountpwdlastset = $ADServiceAccountSearchInfo[0].Properties.pwdlastset 169 | [string]$ADServiceAccountPasswordLastSetDate = [datetime]::FromFileTimeUTC($ADServiceAccountpwdlastset) 170 | [string]$ADServiceAccountlastlogon = $ADServiceAccountSearchInfo[0].Properties.lastlogon 171 | [string]$ADServiceAccountLastLogonDate = [datetime]::FromFileTimeUTC($ADServiceAccountlastlogon) 172 | 173 | $ADServiceAccountadmincount = $ADServiceAccountSearchInfo[0].Properties.admincount 174 | 175 | [string]$ADServiceAccountDistinguishedName = $ADServiceAccountSearchInfo[0].Properties.distinguishedname 176 | } 177 | $ADServiceAccountLDAPDN = "LDAP://"+$ADServiceAccountDistinguishedName 178 | $ADServiceAccountInfo = ([adsi] $ADServiceAccountLDAPDN) 179 | 180 | } 181 | ForEach ($AllMSSQLSPNsItemInstancePortArrayItem in $AllMSSQLSPNsItemInstancePortArray) 182 | { 183 | $AllMSSQLSPNsItemServerPort = $NULL 184 | $AllMSSQLSPNsItemServerInstance = $NULL 185 | 186 | $SQLServerReport = New-Object -TypeName System.Object 187 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name Domain -Value $AllMSSQLSPNsItemServerDomainName 188 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name ServerName -Value $AllMSSQLSPNsItemServerFQDN 189 | 190 | IF ($AllMSSQLSPNsItemInstancePortArrayItem -match "^[\d\.]+$") 191 | { [int]$AllMSSQLSPNsItemServerPort = $AllMSSQLSPNsItemInstancePortArrayItem } 192 | IF ($AllMSSQLSPNsItemInstancePortArrayItem -NOTmatch "^[\d\.]+$") 193 | { [string]$AllMSSQLSPNsItemServerInstance = $AllMSSQLSPNsItemInstancePortArrayItem } 194 | 195 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name Port -Value $AllMSSQLSPNsItemServerPort 196 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name Instance -Value $AllMSSQLSPNsItemServerInstance 197 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name ServiceAccountDN -Value $AllMSSQLSPNsItemServiceAccountDN 198 | 199 | TRY 200 | { 201 | $ADComputerSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 202 | $ADComputerSearch.SearchRoot = $AllMSSQLSPNsItemServerDomainLDAPDN 203 | $ADComputerSearch.PageSize = 50000 204 | $ADComputerSearch.Filter = "(&(objectCategory=Computer)(name=$AllMSSQLSPNsItemServerName))" 205 | $ADComputerSearchInfo = $ADComputerSearch.FindAll() 206 | 207 | [string]$ComputerADInfoLastLogonTimestamp = ($ADComputerSearchInfo[0].properties.lastlogontimestamp) 208 | TRY { [datetime]$ComputerADInfoLLT = [datetime]::FromFileTime($ComputerADInfoLastLogonTimestamp) } 209 | CATCH { } 210 | 211 | #$ComputerADInfo.Values 212 | 213 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name OperatingSystem -Value ($ADComputerSearchInfo[0].properties.operatingsystem) 214 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name OSServicePack -Value ($ADComputerSearchInfo[0].properties.operatingsystemservicepack) 215 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name LastBootup -Value $ComputerADInfoLLT 216 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name OSVersion -Value ($ADComputerSearchInfo[0].properties.operatingsystemversion) 217 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name Description -Value ($ADComputerSearchInfo[0].properties.description) 218 | } 219 | CATCH { } 220 | 221 | IF ($AllMSSQLSPNsItemServiceAccountDN) 222 | { 223 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name SrvAcctUserID -Value $ADServiceAccountSAMAccountName 224 | $SQLServerReport | Add-Member -MemberType NoteProperty -Name SrvAcctDescription -Value $ADServiceAccountdescription 225 | #$SQLServerReport | Add-Member -MemberType NoteProperty -Name SrvAcctPasswordLastSet -Value $ADServiceAccountPasswordLastSetDate 226 | #$SQLServerReport | Add-Member -MemberType NoteProperty -Name SAadmincount -Value $ADServiceAccountadmincount 227 | } 228 | 229 | [array]$ALLSQLServerReport += $SQLServerReport 230 | } 231 | } 232 | 233 | # Find all SQL service account that may be a domain-level admin in the domain 234 | # $ALLSQLServerReport | Where {$_.SAadmincount -eq 1} | select ServerName,SrvAcctUserID,SrvAcctPasswordLastSet,SrvAcctDescription | sort SrvAcctUserID -unique | format-table -auto 235 | return $ALLSQLServerReport 236 | 237 | } 238 | 239 | -------------------------------------------------------------------------------- /Get-PSADForestInfo: -------------------------------------------------------------------------------- 1 | function Get-PSADForestInfo 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This script is used to gather information on the Active Directory environment. 7 | 8 | PowerSploit Function: Get-PSADForestInfo 9 | Author: Sean Metcalf, Twitter: @PyroTek3 10 | License: BSD 3-Clause 11 | Required Dependencies: None 12 | Optional Dependencies: None 13 | 14 | Version: 0.31 15 | 16 | .DESCRIPTION 17 | This script is used to gather information on the Active Directory environment using system .Net calls and built-in PowerShell functionality. 18 | 19 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 20 | 21 | Currently, the script performs the following actions: 22 | * Identifies the current AD forest and lists Forest Mode & Forest FSMOs. 23 | * Enumerates all domain details (including child domains). 24 | * Domain details (for all domains including forest root) include: 25 | - Netbios Name 26 | - Domain SID 27 | - Domain Mode 28 | - Domain krbtgt Last Password Set Date 29 | - Domain FSMOs 30 | - Domain Password Policy 31 | - Domain Trusts 32 | - Child Domains 33 | * Identifies AD & Exchange schema versions 34 | * Enumerates AD Sites and provides Forest Subnet data 35 | 36 | .EXAMPLE 37 | Get-PSADForestInfo 38 | This script is used to gather information on the Active Directory environment. 39 | 40 | .NOTES 41 | This script is used to gather information on the Active Directory environment. 42 | 43 | .LINK 44 | 45 | #> 46 | Param 47 | ( 48 | 49 | ) 50 | 51 | # Get RootDSE Info 52 | $rootDSE = [adsi]"LDAP://rootDSE" 53 | $rootDSEconfigurationNamingContext = $rootDSE.configurationNamingContext 54 | $rootDSEcurrentTime = $rootDSE.currentTime ## Convert 55 | $rootDSEdefaultNamingContext = $rootDSE.defaultNamingContext 56 | $rootDSEdnsHostName = $rootDSE.dnsHostName 57 | $rootDSEdomainControllerFunctionality = $rootDSE.domainControllerFunctionality 58 | $rootDSEdomainFunctionality = $rootDSE.domainFunctionality ## Convert 59 | $rootDSEdsServiceName = $rootDSE.dsServiceName 60 | $rootDSEforestFunctionality = $rootDSE.forestFunctionality ## Convert 61 | $rootDSEhighestCommittedUSN = $rootDSE.highestCommittedUSN 62 | $rootDSEisGlobalCatalogReady = $rootDSE.isGlobalCatalogReady 63 | $rootDSEisSynchronized = $rootDSE.isSynchronized 64 | $rootDSEldapServiceName = $rootDSE.ldapServiceName 65 | $rootDSEnamingContexts = $rootDSE.namingContexts 66 | $rootDSErootDomainNamingContext = $rootDSE.rootDomainNamingContext 67 | $rootDSEschemaNamingContext = $rootDSE.schemaNamingContext 68 | $rootDSEserverName = $rootDSE.serverName 69 | $rootDSEsubschemaSubentry = $rootDSE.subschemaSubentry 70 | $rootDSEsupportedCapabilities = $rootDSE.supportedCapabilities 71 | $rootDSEsupportedControl = $rootDSE.supportedControl 72 | $rootDSEsupportedLDAPPolicies = $rootDSE.supportedLDAPPolicies 73 | $rootDSEsupportedLDAPVersion = $rootDSE.supportedLDAPVersion 74 | $rootDSEsupportedSASLMechanisms = $rootDSE.supportedSASLMechanisms 75 | 76 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 77 | $ADForestInfoName = $ADForestInfo.Name 78 | $ADForestInfoSites = $ADForestInfo.Sites 79 | $ADForestInfoGlobalCatalogs = $ADForestInfo.GlobalCatalogs 80 | $ADForestInfoApplicationPartitions = $ADForestInfo.ApplicationPartitions 81 | $ADForestInfoForestMode = $ADForestInfo.ForestMode 82 | $ADForestInfoSchema = $ADForestInfo.Schema 83 | $ADForestInfoSchemaRoleOwner = $ADForestInfo.SchemaRoleOwner 84 | $ADForestInfoNamingRoleOwner = $ADForestInfo.NamingRoleOwner 85 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 86 | 87 | $ADDomainInfo = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 88 | $ADDomainInfoName = $ADDomainInfo.Name 89 | $ADDomainInfoForest = $ADDomainInfo.Forest 90 | $ADDomainInfoDomainControllers = $ADDomainInfo.DomainControllers 91 | $ADDomainInfoChildren = $ADDomainInfo.Children 92 | $ADDomainInfoDomainMode = $ADDomainInfo.DomainMode 93 | $ADDomainInfoParent = $ADDomainInfo.Parent 94 | $ADDomainInfoPdcRoleOwner = $ADDomainInfo.PdcRoleOwner 95 | $ADDomainInfoRidRoleOwner = $ADDomainInfo.RidRoleOwner 96 | $ADDomainInfoInfrastructureRoleOwner = $ADDomainInfo.InfrastructureRoleOwner 97 | 98 | $LocalSiteInfo = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite() 99 | 100 | $ADForestDomains = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).domains 101 | $ADForestPartitionsContainer = "CN=Partitions," + $rootDSEconfigurationNamingContext 102 | 103 | <# 104 | ####################################### 105 | # IN PROGRESS - AD Instantiation Date # 106 | ####################################### 107 | #$ADForestInstatiationDate = Get-ADObject -SearchBase (Get-ADForest).PartitionsContainer ` 108 | #-LDAPFilter "(&(objectClass=crossRef)(systemFlags=3))" ` 109 | #-Property dnsRoot, nETBIOSName, whenCreated | Sort-Object whenCreated | Format-Table dnsRoot, nETBIOSName, whenCreated -AutoSize 110 | 111 | $ADSISearcherFID = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 112 | $ADSISearcherFID.SearchRoot = "LDAP://CN=$ADForestPartitionsContainer" 113 | $ADSISearcherFID.PageSize = 500 114 | $ADSISearcherFID.Filter = "(&(objectClass=crossRef)(systemFlags=3))" 115 | $ADForestInstatiationDateResults = $ADSISearcherFID.FindOne() 116 | 117 | Write-Output "AD Forest Instatiation Date: $ADForestInstatiationDate" 118 | 119 | #> 120 | 121 | # Set Report Variables 122 | $ADForestInfoReport = New-Object -TypeName System.Object 123 | 124 | 125 | $ADSISearcher = New-Object System.DirectoryServices.DirectorySearcher 126 | $ADSISearcher.SearchScope = "subtree" 127 | $ADSISearcher.PropertiesToLoad.Add("nETBIOSName") > $Null 128 | $ADSISearcher.SearchRoot = "LDAP://$ADForestPartitionsContainer" 129 | 130 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestName -Value $ADForestInfoName 131 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestMode -Value $ADForestInfoForestMode 132 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestFSMOSchema -Value $ADForestInfoSchemaRoleOwner 133 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestFSMODomNaming -Value $ADForestInfoNamingRoleOwner 134 | 135 | # Get AD and Exchange Schema version 136 | Write-Verbose "Create Schema Version hashtable `r " 137 | $SchemaVersionTable = 138 | @{ 139 | "13" = "Windows 2000 Schema" ; 140 | "30" = "Windows 2003 Schema"; 141 | "31" = "Windows 2003 R2 Schema" ; 142 | "39" = "Windows 2008 BETA Schema" ; 143 | "44" = "Windows 2008 Schema" ; 144 | "47" = "Windows 2008 R2 Schema" ; 145 | "51" = "Windows Server 8 Developer Preview Schema" ; 146 | "52" = "Windows Server 8 BETA Schema" ; 147 | "56" = "Windows Server 2012 Schema" ; 148 | "69" = "Windows Server 2012 R2 Schema" ; 149 | 150 | "4397" = "Exchange 2000 RTM Schema" ; 151 | "4406" = "Exchange 2000 SP3 Schema" ; 152 | "6870" = "Exchange 2003 RTM Schema" ; 153 | "6936" = "Exchange 2003 SP3 Schema" ; 154 | "10637" = "Exchange 2007 RTM Schema" ; 155 | "11116" = "Exchange 2007 RTM Schema" ; 156 | "14622" = "Exchange 2007 SP2 & Exchange 2010 RTM Schema" ; 157 | "14625" = "Exchange 2007 SP3 Schema" ; 158 | "14726" = "Exchange 2010 SP1 Schema" ; 159 | "14732" = "Exchange 2010 SP2 Schema" ; 160 | "14734" = "Exchange 2010 SP3 Schema" ; 161 | "15137" = "Exchange 2013 RTM Schema" ; 162 | "15254" = "Exchange 2013 CU1 Schema" ; 163 | "15281" = "Exchange 2013 CU2 Schema" ; 164 | "15283" = "Exchange 2013 CU3 Schema" ; 165 | "15292" = "Exchange 2013 SP1/CU4 Schema" ; 166 | "15300" = "Exchange 2013 CU5 Schema" ; 167 | "15303" = "Exchange 2013 CU6 Schema" 168 | } 169 | 170 | Write-Verbose "Get Exchange Forest Prep Version" 171 | $RootDSE= ([ADSI]"").distinguishedName 172 | $RootDSEExchangerangeUpper = ([ADSI]"LDAP://CN=ms-Exch-Schema-Version-Pt,CN=Schema,CN=Configuration,$RootDSE").rangeUpper 173 | $RootDSEExchangeobjectVersion =([ADSI]"LDAP://cn=,cn=Microsoft Exchange,cn=Services,cn=Configuration,$RootDSE").objectVersion 174 | $ExchangeSchemaVersionName = $SchemaVersionTable.Get_Item("$RootDSEExchangerangeUpper") 175 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ExchangeSchemaVersionNum -Value $RootDSEExchangerangeUpper 176 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ExchangeSchemaVersion -Value $ExchangeSchemaVersionName 177 | 178 | Write-Verbose "Get AD Forest Prep Version" 179 | $RootDSE= ([ADSI]"").distinguishedName 180 | $RootDSEADObjectVersion =([ADSI]"LDAP://$rootDSEschemaNamingContext").objectVersion 181 | $ADSchemaVersionName = $SchemaVersionTable.Get_Item("$RootDSEADObjectVersion") 182 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ADSchemaVersionNum -Value $RootDSEADObjectVersion 183 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ADSchemaVersion -Value $ADSchemaVersionName 184 | 185 | # Get Tombstone Setting 186 | Write-Verbose "Get Tombstone Setting `r" 187 | $RootDSE= ([ADSI]"").distinguishedName 188 | $RootDSEADTombstoneLifetime =([ADSI]"LDAP://CN=Directory Service,CN=Windows NT,CN=Services,$rootDSEconfigurationNamingContext") 189 | $TombstoneLifetime = $RootDSEADTombstoneLifetime.tombstoneLifetime 190 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name TombstoneLifetime -Value $TombstoneLifetime 191 | 192 | # Get AD Site List 193 | Write-Verbose "Get AD Site List `r" 194 | $ADSites = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites 195 | [int]$ADSitesCount = $ADSites.Count 196 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestSites -Value $ADSitesCount 197 | 198 | Write-Verbose "Processing AD Site & Subnet data " 199 | $ADSitesItemSubnets = $Null 200 | ForEach ($ADSitesItem in $ADSites) 201 | { 202 | [array]$ADSitesItemSubnetArray = $ADSitesItem.Subnets 203 | ForEach ($ADSitesItemSubnetArrayItem in $ADSitesItemSubnetArray) 204 | { [array]$ADForestSiteSubnets += $ADSitesItemSubnetArrayItem.Name } 205 | } 206 | 207 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestSubnets -Value $ADForestSiteSubnets 208 | 209 | $ADSISearcher = New-Object System.DirectoryServices.DirectorySearcher 210 | $ADSISearcher.SearchScope = "subtree" 211 | $ADSISearcher.PropertiesToLoad.Add("nETBIOSName") > $Null 212 | $ADSISearcher.SearchRoot = "LDAP://$ADForestPartitionsContainer" 213 | 214 | [array]$ALLADForestDomainControllers = $Null 215 | $ALLADDomainInfoReport = @() 216 | ForEach ($ADForestDomainsItem in $ADForestDomains) 217 | { 218 | $DomainChildrenList = $Null 219 | [array]$ALLADForestDomainControllers += $ADForestDomainsItem.DomainControllers 220 | 221 | $ADForestDomainsItemName = $ADForestDomainsItem.Name 222 | 223 | $DomainDetail = [ADSI]"LDAP://$ADForestDomainsItemName" 224 | $DomainDetailmaxPwdAgeValue = $DomainDetail.maxPwdAge.Value 225 | $DomainDetailminPwdAgeValue = $DomainDetail.minPwdAge.Value 226 | $DomainDetailmaxPwdAgeInt64 = $DomainDetail.ConvertLargeIntegerToInt64($DomainDetailmaxPwdAgeValue) 227 | $DomainDetailminPwdAgeInt64 = $DomainDetail.ConvertLargeIntegerToInt64($DomainDetailminPwdAgeValue) 228 | 229 | $MaxPwdAge = -$DomainDetailmaxPwdAgeInt64/(600000000 * 1440) 230 | $MinPwdAge = -$DomainDetailminPwdAgeInt64/(600000000 * 1440) 231 | 232 | $DomainDetailminPwdLength = $DomainDetail.minPwdLength 233 | $DomainDetailpwdHistoryLength = $DomainDetail.pwdHistoryLength 234 | $DomainDetaildistinguishedName = $DomainDetail.distinguishedName 235 | #$DomainDetailrIDManagerReference = $DomainDetail.rIDManagerReference 236 | 237 | $DomainDetailSID = (New-Object System.Security.Principal.SecurityIdentifier($DomainDetail.objectSid[0], 0)).Value 238 | 239 | $ADForestDomainsDN = "DC=" + $ADForestDomainsItem.Name -Replace("\.",',DC=') 240 | $ADSISearcher.Filter = "(nCName=$ADForestDomainsDN)" 241 | $ADForestDomainsItemNetBIOSName = ($ADSISearcher.FindOne()).Properties.Item("nETBIOSName") 242 | 243 | ## Find Trust Objects 244 | $ADTDOSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 245 | $ADTDOSearch.SearchRoot = "LDAP://$ADForestDomainsDN" 246 | $ADTDOSearch.PageSize = 500 247 | $ADTDOSearch.Filter = "(ObjectClass=trustedDomain)" 248 | $ADTrustArray = $ADTDOSearch.FindAll() 249 | 250 | $AllADDomainTrusts = $Null 251 | ForEach ($ADTrustArrayItem in $ADTrustArray) 252 | { [string]$AllADDomainTrusts = $ADTrustArrayItem.Properties.name } 253 | 254 | $ADUserKRBSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 255 | $ADUserKRBSearch.SearchRoot = "LDAP://$ADForestDomainsDN" 256 | $ADUserKRBSearch.PageSize = 500 257 | $ADUserKRBSearch.Filter = "(&(objectCategory=User)(name=krbtgt))" 258 | $KRBADInfo = $ADUserKRBSearch.FindAll() 259 | 260 | [string]$KRBADInfopwdlastsetInt8 = $KRBADInfo.Properties.pwdlastset 261 | $KRBADInfopwdlastset = [DateTime]::FromFileTimeutc($KRBADInfopwdlastsetInt8) 262 | 263 | ForEach ($ADForestDomainsItemChildrenItem in $ADForestDomainsItemChildren) 264 | { 265 | [string]$DomainChildrenList += $ADForestDomainsItemChildrenItem.Name 266 | Write-Output " * $ADForestDomainsItemChildrenItemName" 267 | } 268 | 269 | $ADDomainInfoReport = New-Object -TypeName System.Object 270 | 271 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name ForestName -Value $ADForestDomainsItemForest 272 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainName -Value $ADForestDomainsItem.Name 273 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name NetbiosName -Value $ADForestDomainsItemNetBIOSName 274 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainSID -Value $DomainDetailSID 275 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainMode -Value $ADForestDomainsItemDomainMode 276 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainFSMOPDC -Value $ADForestDomainsItem.PdcRoleOwner 277 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainFSMORID -Value $ADForestDomainsItem.RidRoleOwner 278 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainFSMOInfra -Value $ADForestDomainsItem.InfrastructureRoleOwner 279 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainChildren -Value $ADForestDomainsItem.Children 280 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainTrusts -Value $ADTrustArray 281 | 282 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainMaxPwdAge -Value $MaxPwdAge 283 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainMinPwdAge -Value $MinPwdAge 284 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainPwdHistory -Value $DomainDetailpwdHistoryLength 285 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainMinPwdLen -Value $DomainDetailminPwdLength 286 | $ADDomainInfoReport | Add-Member -MemberType NoteProperty -Name DomainkrbtgtPwdLastSet -Value $KRBADInfopwdlastset 287 | 288 | [array]$ALLADDomainInfoReport += $ADDomainInfoReport 289 | } 290 | 291 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestDomainDetail -Value $ALLADDomainInfoReport 292 | 293 | $ADForestInfoReport | Add-Member -MemberType NoteProperty -Name ForestDCs -Value $ALLADForestDomainControllers.Count 294 | 295 | 296 | return $ADForestInfoReport 297 | 298 | } 299 | -------------------------------------------------------------------------------- /Discover-PSInterestingServices: -------------------------------------------------------------------------------- 1 | function Discover-PSInterestingServices 2 | { 3 | 4 | <# 5 | .SYNOPSIS 6 | This script is used to discover network servers with interesting services without port scanning. 7 | Service discovery in the Active Directory Forest is performed by querying an Active Directory Gloabl Catalog via LDAP. 8 | The script can also provide additional computer information such as OS and last bootup time. 9 | 10 | PowerSploit Function: Discover-PSInterestingServices 11 | Author: Sean Metcalf, Twitter: @PyroTek3 12 | License: BSD 3-Clause 13 | Required Dependencies: None 14 | Optional Dependencies: None 15 | 16 | Version: 1.5 17 | 18 | .DESCRIPTION 19 | This script is used to discover network servers with interesting services without port scanning. 20 | Service discovery in the Active Directory Forest is performed by querying an Active Directory Gloabl Catalog via ADSI. 21 | 22 | REQUIRES: Active Directory user authentication. Standard user access is fine - admin access is not necessary. 23 | 24 | Currently, the script performs the following actions: 25 | * Queries a Global Catalog in the Active Directory root domain for all SPNs in the forest 26 | * Identifies interesting services running on computers (if a port is identified in the SPN, it is shown in the report as SPN.port) 27 | 28 | A description of SPN Service Types can be found here: 29 | http://adsecurity.org/?page_id=183 30 | 31 | 32 | .PARAMETER StandardSPNServiceFilter 33 | Array of Strings: Standard list of SPN Services Reported: ("ADAM","AGPM","bo","CESREMOTE","Dfs","DNS","Exchange","FIMService","ftp","http","IMAP","ipp","iSCSITarget","kadmin","ldap","MS","sql","nfs","secshd","sip","SMTP","SoftGrid","TERMSRV","Virtual","vmrc","vnc","vpn","vssrvc","WSMAN","xmpp") 34 | It is best to remove from this list if needed. Use the OptionalSPNServiceFilter parameter for adding SPN Services to the report. 35 | 36 | .PARAMETER OptionalSPNServiceFilter 37 | Array of Strings: Provide additonal SPN service types desired in the report. 38 | Multiple values are acceptable. 39 | 40 | .EXAMPLE 41 | Discover-PSInterestingServices 42 | Perform discovery on servers running interesting services via ADSI returning results in a custom PowerShell object. 43 | Discovers the following SPNs: ("ADAM","AGPM","bo","CESREMOTE","Dfs","DNS","Exchange","FIMService","ftp","http","IMAP","ipp","iSCSITarget","kadmin","ldap","MS","sql","nfs","secshd","sip","SMTP","SoftGrid","TERMSRV","Virtual","vmrc","vnc","vpn","vssrvc","WSMAN","xmpp") 44 | 45 | Discover-PSInterestingServices -GetAllForestSPNs 46 | Perform discovery of ALL SPN typs in Active Directory in order to discover servers running interesting services via ADSI returning results in a custom PowerShell object. 47 | 48 | Discover-PSInterestingServices -OptionalSPNServiceFilter ("Microsoft Virtual Console Service","Dfsr") 49 | Perform discovery on servers running interesting services (adding Hyper-V hosts and domain DFS servers) via ADSI returning results in a custom PowerShell object. 50 | 51 | .NOTES 52 | This script is used to discover computers with interesting services without port scanning. 53 | 54 | .LINK 55 | Blog: http://www.ADSecurity.org 56 | Github repo: https://github.com/PyroTek3/PowerShell-AD-Recon 57 | 58 | #> 59 | 60 | 61 | Param 62 | ( 63 | [switch] $GetAllForestSPNs, 64 | [String[]] $StandardSPNServiceFilter = ("ADAM","AGPM","bo","CESREMOTE","Dfs","DNS","Exchange","FIMService","ftp","http","IMAP","ipp","iSCSITarget","kadmin","ldap","MS","sql","nfs","secshd","sip","SMTP","SoftGrid","TERMSRV","Virtual","vmrc","vnc","vpn","vssrvc","WSMAN","xmpp"), 65 | [String[]] $OptionalSPNServiceFilter 66 | ) 67 | 68 | IF ($OptionalSPNServiceFilter) 69 | { [array]$SPNServiceFilter = $StandardSPNServiceFilter + $OptionalSPNServiceFilter } 70 | ELSE 71 | { [array]$SPNServiceFilter = $StandardSPNServiceFilter } 72 | 73 | Write-verbose "Build SPN searcher based on Standard and Optional " 74 | [string]$ADSearcherSPNTypes = "(|" 75 | ForEach ($SPNServiceFilterItem in $SPNServiceFilter) 76 | { [string]$ADSearcherSPNTypes += "(serviceprincipalname=*$SPNServiceFilterItem*)" } 77 | [string]$ADSearcherSPNTypes += " )" 78 | 79 | Write-Verbose "Get current Active Directory domain... " 80 | $ADForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() 81 | $ADForestInfoRootDomain = $ADForestInfo.RootDomain 82 | $ADForestInfoRootDomainArray = $ADForestInfoRootDomain -Split("\.") 83 | $ADForestInfoRootDomainDN = "DC=" + $ADForestInfoRootDomain -Replace("\.",',DC=') 84 | 85 | $ADDomainInfoLGCDN = 'GC://' + $ADForestInfoRootDomainDN 86 | 87 | Write-Verbose "Discovering Interesting Services in the AD Forest $ADForestInfoRootDomainDN " 88 | $root = [ADSI]$ADDomainInfoLGCDN 89 | 90 | IF ($GetAllForestSPNs -eq $True) 91 | { $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"(serviceprincipalname=*)") } 92 | ELSE 93 | { $ADSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,"$ADSearcherSPNTypes") } 94 | 95 | $ADSearcher.PageSize = 1000 96 | $AllForestSPNs = $ADSearcher.FindAll() 97 | 98 | #$AllForestSPNsCount = $AllForestSPNs.Count 99 | 100 | $AllInterestingSPNs = $NULL 101 | $AllSPNs = $NULL 102 | $AllSPNTypes = $NULL 103 | $AllInterestingSPNHashTable =@{} 104 | $AllInterestingSPNReverseHashTable =@{} 105 | ForEach ($AllForestSPNsItem in $AllForestSPNs) 106 | { 107 | $AllForestSPNsItemPath = $AllForestSPNsItem.Path 108 | Write-Verbose "Reviewing SPN for $AllForestSPNsItemPath " 109 | $AllForestSPNsItemDomainName = $NULL 110 | [array]$AllForestSPNsItemArray = $AllForestSPNsItem.Path -Split(",DC=") 111 | [int]$DomainNameFECount = 0 112 | ForEach ($AllForestSPNsItemArrayItem in $AllForestSPNsItemArray) 113 | { 114 | IF ($DomainNameFECount -gt 0) 115 | { [string]$AllForestSPNsItemDomainName += $AllForestSPNsItemArrayItem + "." } 116 | $DomainNameFECount++ 117 | } 118 | $AllForestSPNsItemDomainName = $AllForestSPNsItemDomainName.Substring(0,$AllForestSPNsItemDomainName.Length-1) 119 | 120 | ForEach ($FSPNItemSPNItem in $AllForestSPNsItem.properties.serviceprincipalname) 121 | { 122 | Write-Verbose "Reviewing SPN Data: $FSPNItemSPNItem " 123 | [string]$FSPNItemSPNItemSPNType = ( $FSPNItemSPNItem -Split("/") )[0] 124 | [array]$AllSPNTypes += ( $FSPNItemSPNItem -Split("/") )[0] 125 | 126 | IF ( ($FSPNItemSPNItemSPNType -like "*kadmin*") -AND ($AllForestSPNsItem -like "*krbtgt*") ) 127 | { 128 | $AllInterestingSPNHashTable.Set_Item("krbtgt ($AllForestSPNsItemDomainName)",$FSPNItemSPNItem) 129 | $AllInterestingSPNReverseHashTableData = $AllInterestingSPNReverseHashTable.Get_Item($FSPNItemSPNItem) 130 | IF ($AllInterestingSPNReverseHashTableData) 131 | { 132 | $AllInterestingSPNReverseHashTableDataUpdate = $AllInterestingSPNReverseHashTableData + ";" + "krbtgt ($AllForestSPNsItemDomainName)" 133 | $AllInterestingSPNReverseHashTable.Set_Item($FSPNItemSPNItem,$AllInterestingSPNReverseHashTableDataUpdate) 134 | } 135 | IF (!$AllInterestingSPNReverseHashTableData) 136 | { $AllInterestingSPNReverseHashTable.Set_Item($FSPNItemSPNItem,"krbtgt ($AllForestSPNsItemDomainName)") } 137 | } 138 | ELSE 139 | { 140 | $FSPNItemSPNItemServerFQDN = ( ( ( $FSPNItemSPNItem -Split("/") )[1] )-Split(":") )[0] 141 | IF ($FSPNItemSPNItemServerFQDN -notlike "*$AllForestSPNsItemDomainName*" ) 142 | { $FSPNItemSPNItemServerFQDN = $FSPNItemSPNItemServerFQDN + "." + $AllForestSPNsItemDomainName } 143 | [string]$FSPNItemSPNItemServerPort = ( ( ( $FSPNItemSPNItem -Split("/") )[1] )-Split(":") )[1] 144 | 145 | $AllInterestingSPNReverseHashTableData = $AllInterestingSPNReverseHashTable.Get_Item($FSPNItemSPNItemSPNType) 146 | IF ( ($AllInterestingSPNReverseHashTableData) -AND ($AllInterestingSPNReverseHashTableData -notlike "*$FSPNItemSPNItemServerFQDN*") ) 147 | { 148 | $AllInterestingSPNReverseHashTableDataUpdate = $AllInterestingSPNReverseHashTableData + ";" + $FSPNItemSPNItemServerFQDN 149 | $AllInterestingSPNReverseHashTable.Set_Item($FSPNItemSPNItemSPNType,$AllInterestingSPNReverseHashTableDataUpdate) 150 | } 151 | IF (!$AllInterestingSPNReverseHashTableData) 152 | { $AllInterestingSPNReverseHashTable.Set_Item($FSPNItemSPNItemSPNType,$FSPNItemSPNItemServerFQDN) } 153 | 154 | IF ( ($FSPNItemSPNItemServerPort) -AND ($FSPNItemSPNItemServerPort -match "^[\d\.]+$") ) 155 | { $FSPNItemSPNItemSPNType = $FSPNItemSPNItemSPNType + "." + $FSPNItemSPNItemServerPort } 156 | 157 | ForEach ($SPNServiceFilterItem in $SPNServiceFilter) 158 | { 159 | IF ($FSPNItemSPNItemSPNType -like "*$SPNServiceFilterItem*") 160 | { 161 | Write-Verbose "SPNServiceFilterItem is $SPNServiceFilterItem " 162 | $AllInterestingSPNsData = $AllInterestingSPNHashTable.Get_Item($FSPNItemSPNItemServerFQDN) 163 | IF ( ($AllInterestingSPNsData) -AND ($AllInterestingSPNsData -notlike "*$SPNServiceFilterItem*") ) 164 | { 165 | $AllInterestingSPNsDataUpdate = $AllInterestingSPNsData + ";" + $FSPNItemSPNItemSPNType 166 | $AllInterestingSPNHashTable.Set_Item($FSPNItemSPNItemServerFQDN,$AllInterestingSPNsDataUpdate) 167 | Write-Verbose "Updating AllInterestingSPNHashTable with $FSPNItemSPNItemServerFQDN : $AllInterestingSPNsDataUpdate " 168 | } 169 | IF (!$AllInterestingSPNsData) 170 | { 171 | $AllInterestingSPNHashTable.Set_Item($FSPNItemSPNItemServerFQDN,$FSPNItemSPNItemSPNType) 172 | Write-Verbose "Updating AllInterestingSPNHashTable with new data $FSPNItemSPNItemServerFQDN : $FSPNItemSPNItemSPNType " 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | 180 | 181 | $ALLIntServerServicesReport = @() 182 | 183 | ForEach ($AllInterestingSPNHashTableItem in $AllInterestingSPNHashTable.GetEnumerator() ) 184 | { 185 | $AllServerInterstingSPNServiceList = $NULL 186 | $AllInterestingSPNHashTableItemServerDomainName = $NULL 187 | $AllInterestingSPNHashTableItemServerDomainDN = $NULL 188 | 189 | $AllInterestingSPNHashTableItemServerFQDN = $AllInterestingSPNHashTableItem.Name 190 | [array]$AllServerInterstingSPNArray = ($AllInterestingSPNHashTableItem.Value) -split(";") 191 | [array]$AllServerInterstingSPNArraySorted = $AllServerInterstingSPNArray | sort-Object 192 | 193 | ForEach ($AllServerInterstingSPNArraySortedItem in $AllServerInterstingSPNArraySorted) 194 | { [string]$AllServerInterstingSPNServiceList += $AllServerInterstingSPNArraySortedItem + ";" } 195 | $AllServerInterstingSPNServiceList = $AllServerInterstingSPNServiceList.Substring(0,$AllServerInterstingSPNServiceList.Length-1) 196 | 197 | $AllInterestingSPNHashTableItemServerFQDNArray = $AllInterestingSPNHashTableItemServerFQDN -Split('\.') 198 | [int]$FQDNArrayFECount = 0 199 | ForEach ($AllInterestingSPNHashTableItemServerFQDNArrayItem in $AllInterestingSPNHashTableItemServerFQDNArray) 200 | { 201 | IF ($FQDNArrayFECount -ge 1) 202 | { 203 | [string]$AllInterestingSPNHashTableItemServerDomainName += $AllInterestingSPNHashTableItemServerFQDNArrayItem + "." 204 | [string]$AllInterestingSPNHashTableItemServerDomainDN += "DC=" + $AllInterestingSPNHashTableItemServerFQDNArrayItem + "," 205 | } 206 | $FQDNArrayFECount++ 207 | } 208 | 209 | $AllInterestingSPNHashTableItemServerDomainName = $AllInterestingSPNHashTableItemServerDomainName.Substring(0,$AllInterestingSPNHashTableItemServerDomainName.Length-1) 210 | $AllInterestingSPNHashTableItemServerDomainDN = $AllInterestingSPNHashTableItemServerDomainDN.Substring(0,$AllInterestingSPNHashTableItemServerDomainDN.Length-1) 211 | $AllInterestingSPNHashTableItemServerDomainLDAPDN = "LDAP://$AllInterestingSPNHashTableItemServerDomainDN" 212 | 213 | $AllInterestingSPNHashTableItemServerName = $AllInterestingSPNHashTableItemServerFQDN -Replace(("."+$AllInterestingSPNHashTableItemServerDomainName),"") 214 | 215 | IF ($AllInterestingSPNHashTableItemServerFQDN -like "*changepw*") 216 | { $AllInterestingSPNHashTableItemServerFQDN = $AllInterestingSPNHashTableItemServerDomainName + "\krbgt" } 217 | 218 | IF ($AllInterestingSPNHashTableItemServerFQDN -like "*_msdcs*") 219 | { 220 | $AllInterestingSPNHashTableItemServerFQDN = $AllInterestingSPNHashTableItemServerDomainName + "\DNSzone" 221 | $AllInterestingSPNHashTableItemServerName = $NULL 222 | } 223 | 224 | TRY 225 | { 226 | $ADComputerSearch = New-Object DirectoryServices.DirectorySearcher([ADSI]"") 227 | $ADComputerSearch.SearchRoot = $AllInterestingSPNHashTableItemServerDomainLDAPDN 228 | $ADComputerSearch.PageSize = 500 229 | $ADComputerSearch.Filter = "(&(objectCategory=Computer)(name=$AllInterestingSPNHashTableItemServerName))" 230 | $ComputerADInfo = $ADComputerSearch.FindAll() 231 | 232 | [string]$ComputerADInfoLastLogonTimestamp = ($ComputerADInfo[0].properties.lastlogontimestamp) 233 | TRY { [datetime]$ComputerADInfoLLT = [datetime]::FromFileTime($ComputerADInfoLastLogonTimestamp) } 234 | CATCH { $ComputerADInfoLLT = $Null } 235 | } 236 | CATCH 237 | { Write-Warning "Unable to gather property data for computer $AllInterestingSPNHashTableItemServerName " } 238 | 239 | $ComputerADInfoShortOS = $Null 240 | $ComputerADInfoShortOSArray = $ComputerADInfoOperatingSystem -split(" ") 241 | ForEach ($ComputerADInfoShortOSArrayItem in $ComputerADInfoShortOSArray ) 242 | { 243 | IF ($ComputerADInfoShortOSArrayItem -eq "Windows") 244 | { [string] $ComputerADInfoShortOS += "Win" } 245 | 246 | IF ($ComputerADInfoShortOSArrayItem -eq "Server") 247 | { } 248 | 249 | IF ($ComputerADInfoShortOSArrayItem -match "\d") 250 | { [string] $ComputerADInfoShortOS += $ComputerADInfoShortOSArrayItem } 251 | } 252 | 253 | $IntServerServicesReport = New-Object -TypeName System.Object 254 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name Domain -Value $AllInterestingSPNHashTableItemServerDomainName 255 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name ServerName -Value $AllInterestingSPNHashTableItemServerFQDN 256 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name SPNServices -Value $AllServerInterstingSPNServiceList 257 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name OperatingSystem -Value ($ComputerADInfo[0].properties.operatingsystem) 258 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name OSServicePack -Value ($ComputerADInfo[0].properties.operatingsystemservicepack) 259 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name LastBootup -Value $ComputerADInfoLLT 260 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name OSVersion -Value ($ComputerADInfo[0].properties.operatingsystemversion) 261 | $IntServerServicesReport | Add-Member -MemberType NoteProperty -Name Description -Value ($ComputerADInfo[0].properties.description) 262 | 263 | [array]$ALLIntServerServicesReport += $IntServerServicesReport 264 | } 265 | 266 | return $ALLIntServerServicesReport 267 | } 268 | --------------------------------------------------------------------------------