|
| 1 | +# Requires -Version 7.0 |
| 2 | + |
| 3 | +<# |
| 4 | +.SYNOPSIS |
| 5 | + - Enumerates details of discovered Domain Controllers. |
| 6 | +
|
| 7 | +.DESCRIPTION |
| 8 | + This script performs detailed Active Directory reconnaissance against |
| 9 | + Domain Controllers listed in an input CSV file produced by MSADPT_start.ps1. |
| 10 | +
|
| 11 | + All Active Directory operations: |
| 12 | + - use explicit credentials |
| 13 | + - target an explicit Domain Controller |
| 14 | + - do NOT assume the host is domain joined |
| 15 | +
|
| 16 | + All output paths are explicitly supplied as parameters. |
| 17 | +
|
| 18 | +.PARAMETER InputDcCsvPath |
| 19 | + Path to the CSV file containing discovered Domain Controllers. |
| 20 | + Example: |
| 21 | + C:\temp\MSADPT_Output\MSADPT_DCs.csv |
| 22 | +
|
| 23 | +.PARAMETER OutputBaseDir |
| 24 | + Base directory where per-DC output folders and CSVs will be written. |
| 25 | +
|
| 26 | +.PARAMETER Credential |
| 27 | + Domain credential used for all Active Directory enumeration. |
| 28 | +
|
| 29 | +.PARAMETER DomainFQDN |
| 30 | + Target Active Directory domain (e.g. foo.bar). |
| 31 | +
|
| 32 | +.PARAMETER AdServer |
| 33 | + Domain Controller / ADWS-capable server to use for all AD queries |
| 34 | + (e.g. dc01.foo.bar). |
| 35 | +
|
| 36 | +.EXAMPLE |
| 37 | + .\MSADPT_enumerate_dc2.ps1 ` |
| 38 | + -InputDcCsvPath "C:\temp\MSADPT_Output\MSADPT_DCs.csv" ` |
| 39 | + -OutputBaseDir "C:\temp\MSADPT_Output\DC_Enumeration" ` |
| 40 | + -Credential (Get-Credential) ` |
| 41 | + -DomainFQDN "foo.bar" ` |
| 42 | + -AdServer "dc01.foo.bar" |
| 43 | +#> |
| 44 | + |
| 45 | +param( |
| 46 | + [Parameter(Mandatory)] |
| 47 | + [ValidateScript({ |
| 48 | + if (-not (Test-Path $_)) { |
| 49 | + throw "Input file '$_' does not exist." |
| 50 | + } |
| 51 | + $true |
| 52 | + })] |
| 53 | + [string]$InputDcCsvPath, |
| 54 | + |
| 55 | + [Parameter(Mandatory)] |
| 56 | + [string]$OutputBaseDir, |
| 57 | + |
| 58 | + [Parameter(Mandatory)] |
| 59 | + [PSCredential]$Credential, |
| 60 | + |
| 61 | + [Parameter(Mandatory)] |
| 62 | + [string]$DomainFQDN, |
| 63 | + |
| 64 | + [Parameter(Mandatory)] |
| 65 | + [string]$AdServer |
| 66 | +) |
| 67 | + |
| 68 | +# --------------------------------------------------------------------- |
| 69 | +# Import helper module (same folder as script) |
| 70 | +# --------------------------------------------------------------------- |
| 71 | +$helpersModulePath = Join-Path $PSScriptRoot 'MSADPT.Helpers.psm1' |
| 72 | + |
| 73 | +if (-not (Test-Path -LiteralPath $helpersModulePath)) { |
| 74 | + Write-Error "Required helper module not found at '$helpersModulePath'. Aborting." |
| 75 | + exit 1 |
| 76 | +} |
| 77 | + |
| 78 | +Import-Module $helpersModulePath -Force -ErrorAction Stop |
| 79 | + |
| 80 | +Write-MSADPTLog -Message "MSADPT_enumerate_dc.ps1 starting." -Level 'INFO' |
| 81 | +Write-MSADPTLog -Message "DomainFQDN : $DomainFQDN" |
| 82 | +Write-MSADPTLog -Message "AdServer : $AdServer" |
| 83 | +Write-MSADPTLog -Message "Input CSV : $InputDcCsvPath" |
| 84 | +Write-MSADPTLog -Message "Output Dir : $OutputBaseDir" |
| 85 | + |
| 86 | +# --------------------------------------------------------------------- |
| 87 | +# Pre-flight: AD connectivity check |
| 88 | +# --------------------------------------------------------------------- |
| 89 | +$rootDSE = Test-MSADPTADConnectivity -Credential $Credential -AdServer $AdServer |
| 90 | +if (-not $rootDSE) { |
| 91 | + Write-MSADPTLog -Message "Active Directory connectivity pre-flight failed. Aborting." -Level 'ERROR' |
| 92 | + exit 1 |
| 93 | +} |
| 94 | + |
| 95 | +# --------------------------------------------------------------------- |
| 96 | +# Ensure output directory exists |
| 97 | +# --------------------------------------------------------------------- |
| 98 | +if (-not (Test-Path -LiteralPath $OutputBaseDir)) { |
| 99 | + New-Item -Path $OutputBaseDir -ItemType Directory -Force | Out-Null |
| 100 | +} |
| 101 | + |
| 102 | +# --------------------------------------------------------------------- |
| 103 | +# Import DC list |
| 104 | +# --------------------------------------------------------------------- |
| 105 | +$DCs = Import-Csv -Path $InputDcCsvPath |
| 106 | +if (-not $DCs) { |
| 107 | + Write-MSADPTLog -Message "No Domain Controllers found in input CSV. Exiting." -Level 'WARNING' |
| 108 | + exit 0 |
| 109 | +} |
| 110 | + |
| 111 | +# --------------------------------------------------------------------- |
| 112 | +# Iterate each Domain Controller |
| 113 | +# --------------------------------------------------------------------- |
| 114 | +foreach ($DC in $DCs) { |
| 115 | + |
| 116 | + $DCName = $DC.Name |
| 117 | + $DCIp = $DC.IPv4Address |
| 118 | + |
| 119 | + Write-MSADPTLog -Message "--------------------------------------------------------" |
| 120 | + Write-MSADPTLog -Message "Processing Domain Controller: $DCName ($DCIp)" |
| 121 | + Write-MSADPTLog -Message "--------------------------------------------------------" |
| 122 | + |
| 123 | + $CurrentDCOutputDir = Join-Path $OutputBaseDir $DCName |
| 124 | + if (-not (Test-Path $CurrentDCOutputDir)) { |
| 125 | + New-Item -Path $CurrentDCOutputDir -ItemType Directory -Force | Out-Null |
| 126 | + } |
| 127 | + |
| 128 | + $DCErrors = @() |
| 129 | + |
| 130 | + # ----------------------------------------------------------------- |
| 131 | + # 1. Connectivity Checks |
| 132 | + # ----------------------------------------------------------------- |
| 133 | + if (Prompt-User -PromptText "Perform connectivity checks for ${DCName}?") { |
| 134 | + |
| 135 | + Write-MSADPTLog -Message "Performing connectivity checks to $DCName ($DCIp)." |
| 136 | + |
| 137 | + if (-not (Test-Connection -ComputerName $DCIp -Count 1 -Quiet)) { |
| 138 | + Write-MSADPTLog -Message "Ping failed to $DCIp." -Level 'WARNING' |
| 139 | + $DCErrors += "Ping failed" |
| 140 | + } |
| 141 | + |
| 142 | + foreach ($port in 445,389,9389,135) { |
| 143 | + $result = Test-NetConnection -ComputerName $DCIp -Port $port -InformationLevel Quiet |
| 144 | + if ($result) { |
| 145 | + Write-MSADPTLog -Message "Port $port reachable on $DCIp." |
| 146 | + } else { |
| 147 | + Write-MSADPTLog -Message "Port $port NOT reachable on $DCIp." -Level 'WARNING' |
| 148 | + $DCErrors += "Port $port unreachable" |
| 149 | + } |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + # ----------------------------------------------------------------- |
| 154 | + # 2. Basic DC Information |
| 155 | + # ----------------------------------------------------------------- |
| 156 | + if (Prompt-User -PromptText "Retrieve detailed DC information for ${DCName}?") { |
| 157 | + try { |
| 158 | + $DCInfo = Get-ADDomainController ` |
| 159 | + -Identity $DCName ` |
| 160 | + -Server $AdServer ` |
| 161 | + -Credential $Credential ` |
| 162 | + -ErrorAction Stop |
| 163 | + |
| 164 | + $DCInfo | |
| 165 | + Select-Object Name, HostName, IPv4Address, OperatingSystem, Site, IsGlobalCatalog, IsReadOnly | |
| 166 | + Export-Csv -Path (Join-Path $CurrentDCOutputDir "MSADPT_DC_Details_$DCName.csv") -NoTypeInformation -Force |
| 167 | + |
| 168 | + Write-MSADPTLog -Message "DC details saved for $DCName." |
| 169 | + } |
| 170 | + catch { |
| 171 | + Write-MSADPTLog -Message "Failed retrieving DC info for ${DCName}: $($_.Exception.Message)" -Level 'ERROR' |
| 172 | + $DCErrors += "DC info failed" |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + # ----------------------------------------------------------------- |
| 177 | + # Final DC summary |
| 178 | + # ----------------------------------------------------------------- |
| 179 | + if ($DCErrors.Count -gt 0) { |
| 180 | + Write-MSADPTLog -Message "Finished $DCName with $($DCErrors.Count) warning/error(s)." -Level 'WARNING' |
| 181 | + $DCErrors | ForEach-Object { |
| 182 | + Write-MSADPTLog -Message " - $_" -Level 'WARNING' |
| 183 | + } |
| 184 | + } |
| 185 | + else { |
| 186 | + Write-MSADPTLog -Message "Finished $DCName successfully." |
| 187 | + } |
| 188 | +} |
| 189 | + |
| 190 | +Write-MSADPTLog -Message "MSADPT_enumerate_dc.ps1 completed." -Level 'INFO' |
0 commit comments