diff --git a/Active Directory/SIDHistory/Get-ADObjectWithSIDHistory.ps1 b/Active Directory/SIDHistory/Get-ADObjectWithSIDHistory.ps1 new file mode 100644 index 0000000..5160bf0 --- /dev/null +++ b/Active Directory/SIDHistory/Get-ADObjectWithSIDHistory.ps1 @@ -0,0 +1,76 @@ +function Get-ADObjectWithSIDHistory { + <# + .SYNOPSIS + Get all Active Directory objects that have SID history. + + .DESCRIPTION + This function gets all Active Directory objects that have SID history. It can optionally be filtered to only get + user, computer, or group objects. + + .EXAMPLE + Get-AllAdSidHistory + + This example gets all Active Directory objects that have SID history. + + .EXAMPLE + Get-AllAdSidHistory -Type User + + This example gets all Active Directory user objects that have SID history. + + .EXAMPLE + Get-AllAdSidHistory -Type Computer + + This example gets all Active Directory computer objects that have SID history. + + .EXAMPLE + Get-AllAdSidHistory -Type Group + + This example gets all Active Directory group objects that have SID history. + + .EXAMPLE + Get-AllAdSidHistory -Type All + + This example gets all Active Directory objects that have SID history, regardless of type. + + .NOTES + Author: Sam Erde, Sentinel Technologies, Inc. + Version: 0.1.0 + Modified: 2025-01-10 + #> + [CmdletBinding()] + [OutputType('Microsoft.ActiveDirectory.Management.ADObject[]')] + param ( + # Type of objects to get. Default is 'All'. + [Parameter()] + [ValidateSet('All', 'User', 'Computer', 'Group')] + [string] + $Type = 'All' + ) + + begin { + if (-not (Get-Module -Name ActiveDirectory)) { + Write-Verbose -Message 'Importing ActiveDirectory module.' + Import-Module ActiveDirectory + Write-Verbose -Message '------------------------------' + Write-Verbose -Message "Beginning ${MyInvocation.InvocationName}..." + } + + $BaseFilter = 'SIDHistory -like "*"' + switch ($Type) { + 'User' { $Filter = "$BaseFilter -and objectClass -eq 'user'" } + 'Computer' { $Filter = "$BaseFilter -and objectClass -eq 'computer'" } + 'Group' { $Filter = "$BaseFilter -and objectClass -eq 'group'" } + 'All' { $Filter = $BaseFilter } + } + } # end begin + + process { + # Get all ActiveDirectory objects that have SID history. + [Microsoft.ActiveDirectory.Management.ADObject[]]$ADObjectList = Get-ADObject -Filter $Filter -Properties SIDHistory | Select-Object * -ExpandProperty SIDHistory + } # end process + + end { + $ADObjectList + } # end end + +} # end function diff --git a/Active Directory/Get-AllADSIDHistoryDetail.ps1 b/Active Directory/SIDHistory/Get-AllADSIDHistoryDetail.ps1 similarity index 100% rename from Active Directory/Get-AllADSIDHistoryDetail.ps1 rename to Active Directory/SIDHistory/Get-AllADSIDHistoryDetail.ps1 diff --git a/Active Directory/Get-AllADSIDHistorySourceDomain.ps1 b/Active Directory/SIDHistory/Get-AllADSIDHistorySourceDomain.ps1 similarity index 100% rename from Active Directory/Get-AllADSIDHistorySourceDomain.ps1 rename to Active Directory/SIDHistory/Get-AllADSIDHistorySourceDomain.ps1 diff --git a/Active Directory/SIDHistory/Get-SIDHistorySourceDomainList.ps1 b/Active Directory/SIDHistory/Get-SIDHistorySourceDomainList.ps1 new file mode 100644 index 0000000..dcda541 --- /dev/null +++ b/Active Directory/SIDHistory/Get-SIDHistorySourceDomainList.ps1 @@ -0,0 +1,70 @@ +function Get-ADObjectWithSIDHistory { + <# + .SYNOPSIS + Get a list of source domain SIDs from all Active Directory objects that have SID history. + + .DESCRIPTION + This function gets all Active Directory objects that have SID history and returns a list of unique source domain SIDs. + + .NOTES + Author: Sam Erde, Sentinel Technologies, Inc. + Version: 0.1.0 + Modified: 2025-01-10 + #> + [CmdletBinding()] + [OutputType('Microsoft.ActiveDirectory.Management.ADObject[]')] + param ( + <# + # Type of objects to get. Default is 'All'. + [Parameter()] + [ValidateSet('All', 'User', 'Computer', 'Group')] + [string] + $Type = 'All' + #> + ) + + begin { + if (-not (Get-Module -Name ActiveDirectory)) { + Write-Verbose -Message 'Importing ActiveDirectory module.' + Import-Module ActiveDirectory + Write-Verbose -Message '------------------------------' + Write-Verbose -Message "Beginning ${MyInvocation.InvocationName}..." + } + + <# Build the filter for the Get-ADObject cmdlet. + $BaseFilter = 'SIDHistory -like "*"' + switch ($Type) { + 'User' { $Filter = "$BaseFilter -and objectClass -eq 'user'" } + 'Computer' { $Filter = "$BaseFilter -and objectClass -eq 'computer'" } + 'Group' { $Filter = "$BaseFilter -and objectClass -eq 'group'" } + 'All' { $Filter = $BaseFilter } + } + #> + $SIDHistorySourceDomainSIDList = [ordered]@{} + } # end begin + + process { + # Get all ActiveDirectory objects that have SID history. + [Microsoft.ActiveDirectory.Management.ADObject[]]$ADObjectList = Get-ADObject -Filter $Filter -Properties SIDHistory | Select-Object * -ExpandProperty SIDHistory + + foreach ($ADObject in $ADObjectList) { + + foreach ($SIDHistoryEntry in $ADObject.SIDHistory) { + # Extract the source domain SID from the SIDHistory attribute. + $SourceDomainSID = $SIDHistoryEntry.Substring(0, $SIDHistoryEntry.LastIndexOf('-')) + + # Add the source domain SID to the list if it doesn't already exist. + if (-not $SIDHistorySourceDomainSIDList.ContainsKey($SourceDomainSID)) { + $SIDHistorySourceDomainSIDList.Add($SourceDomainSID, $SourceDomainSID) + } + } # end foreach SIDHistoryEntry + + } # end foreach ADObject + } # end process + + end { + # Update to return the hash table after resolving source domain SIDs. + $SIDHistorySourceDomainSIDList.Keys + } # end end + +} # end function diff --git a/Active Directory/SIDHistory/Get-TrustedDomainSIDMapping.ps1 b/Active Directory/SIDHistory/Get-TrustedDomainSIDMapping.ps1 new file mode 100644 index 0000000..4004ff0 --- /dev/null +++ b/Active Directory/SIDHistory/Get-TrustedDomainSIDMapping.ps1 @@ -0,0 +1,108 @@ +function Get-TrustedDomainSIDMapping { + <# + .SYNOPSIS + Get the SID and DNSRoot name of trusted domains and forests. + + .DESCRIPTION + This function retrieves the SID and DNSRoot name of trusted domains and forests in the current Active Directory forest. + + .PARAMETER ManualEntry + If specified, the user may manually provide a SID and DNS name to add to the list of domains. + + .EXAMPLE + $SIDMappingTable = Get-TrustedDomainSIDMapping -ManualEntry 'S-1-5-21-1234567890-1234567890-1234567890', 'example.com' -Verbose + + This example retrieves the SIDs and DNSRoot names of trusted domains and forests in the current Active Directory forest and adds a manual entry to the results. + + .NOTES + Author: Sam Erde, Sentinel Technologies, Inc. + Version: 0.0.1 + Modified: 2024-11-14 + + To-Do: + - Add support for trusted forests and external trusts. + - Add support for manually including a CSV file with trusted domain information. + - Add support for exporting a CSV file with trusted domain information. + - Add support for taking an array of trusted domain SIDs and DNS root names as input for ManualEntry. + #> + [CmdletBinding()] + param ( + # If specified, the user may manually provide a SID and DNS name to add to the list of trusted domains. + [Parameter(HelpMessage = 'Enter the SID and DNS name of a trusted domain in the format ''S-1-5-21-1234567890-1234567890-1234567890'', ''example.com''.')] + [array]$ManualEntry + ) + begin { + # Import the ActiveDirectory module if it is not already loaded. + if (-not (Get-Module -Name ActiveDirectory)) { + Write-Verbose -Message 'Importing ActiveDirectory module.' + Import-Module ActiveDirectory + Write-Verbose -Message '------------------------------' + Write-Verbose -Message 'Beginning to process trusts...' + } + # Create a dictionary to store domain SIDs with their corresponding DNS root names. + $DomainSIDMapping = [ordered] @{} + $CurrentDomain = (Get-ADDomain) + $DomainSIDMapping.Add( + $CurrentDomain.DomainSID.Value, + $CurrentDomain.DNSRoot + ) + # If the user provided a manual entry, add it to the dictionary. + if ($PSBoundParameters.ContainsKey('ManualEntry')) { + Write-Verbose -Message "Manually entered SID: $($ManualEntry[0])" + Write-Verbose -Message "Manually entered DNS root name: $($ManualEntry[1])" + $DomainSIDMapping.Add( + $ManualEntry[0], + $ManualEntry[1] + ) + } + $Trusts = Get-ADTrust -Filter * + } + process { + # Loop through all trusts and add the trusted domain SIDs and DNS root names to the dictionary. + foreach ($trust in $Trusts) { + # Need to see if checking SID and DNSRoot requires a different process for trusted forests vs trusted domains. + switch ($trust.TrustType) { + <# + "DomainTrust" { + Write-Verbose -Message "Processing domain trust: $($trust.Target)" + try { + Write-Verbose -Message "Processing trust: $($trust.Target)" + $TrustedDomain = Get-ADDomain -Identity $trust.Target + $DomainSIDMapping.Add( + $TrustedDomain.DomainSID.Value, + $TrustedDomain.DNSRoot + ) + } catch { + Write-Warning -Message "$_" + continue + } + } + "ForestTrust" { + Write-Verbose -Message "Processing forest trust: $($trust.Target)" + # ... (add code to handle external trusts here + } + "External" { + Write-Verbose -Message "Processing external trust: $($trust.Target)" + # ... (add code to handle external trusts here + } + #> + default { + try { + Write-Verbose -Message "Processing trust: $($trust.Target)" + $TrustedDomain = Get-ADDomain -Identity $trust.Target + $DomainSIDMapping.Add( + $TrustedDomain.DomainSID.Value, + $TrustedDomain.DNSRoot + ) + } catch { + Write-Warning -Message "$_" + continue + } + } + } # end switch ($trust.TrustType) + } # end foreach ($trust in $Trusts) + } # end process + end { + $DomainSIDMapping + } # end end +} # end function