fix(Test-WeakADPasswords): add comprehensive DCSync diagnostic dump
When Get-ADReplAccount or Test-PasswordQuality throws, the catch block now dumps the full exception chain (type, message, HResult, source, target site, stack trace, inner exceptions) along with runtime context (Elysium version, PS version, DSInternals version, DC, domain, account). Output goes to console and a timestamped diagnostic file under Reports/ for offline analysis.
This commit is contained in:
@@ -631,16 +631,62 @@ function Test-WeakADPasswords {
|
|||||||
$testResults = $accounts | Test-PasswordQuality -WeakPasswordHashesSortedFile $resolvedHashFile.Path
|
$testResults = $accounts | Test-PasswordQuality -WeakPasswordHashesSortedFile $resolvedHashFile.Path
|
||||||
Write-Verbose "Password quality test completed."
|
Write-Verbose "Password quality test completed."
|
||||||
} catch {
|
} catch {
|
||||||
$message = $_.Exception.Message
|
$ex = $_.Exception
|
||||||
|
$diagLines = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$diagLines.Add('========================================')
|
||||||
|
$diagLines.Add('ELYSLUM DCSYNC DIAGNOSTIC DUMP')
|
||||||
|
$diagLines.Add('========================================')
|
||||||
|
$diagLines.Add("Timestamp : $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')")
|
||||||
|
$diagLines.Add("Script Ver : $ElysiumVersion")
|
||||||
|
$diagLines.Add("PS Version : $($PSVersionTable.PSVersion)")
|
||||||
|
$diagLines.Add("PS Edition : $($PSVersionTable.PSEdition)")
|
||||||
|
$diagLines.Add("DSInternals : $((Get-Module -Name DSInternals).Version)")
|
||||||
|
$diagLines.Add("DC : $($selectedDomain['DC'])")
|
||||||
|
$diagLines.Add("Domain : $($selectedDomain.Name)")
|
||||||
|
$diagLines.Add("Account : $($credential.UserName)")
|
||||||
|
$diagLines.Add("DomainDN : $($domainInfo.DistinguishedName)")
|
||||||
|
$diagLines.Add('')
|
||||||
|
$diagLines.Add('--- EXCEPTION CHAIN ---')
|
||||||
|
$depth = 0
|
||||||
|
$currentEx = $ex
|
||||||
|
while ($null -ne $currentEx) {
|
||||||
|
$diagLines.Add("Exception $depth : $($currentEx.GetType().FullName)")
|
||||||
|
$diagLines.Add(" Message : $($currentEx.Message)")
|
||||||
|
$diagLines.Add(" HResult : 0x$($currentEx.HResult.ToString('X8'))")
|
||||||
|
$diagLines.Add(" Source : $($currentEx.Source)")
|
||||||
|
if ($currentEx.TargetSite) {
|
||||||
|
$diagLines.Add(" TargetSite : $($currentEx.TargetSite)")
|
||||||
|
}
|
||||||
|
if ($currentEx.StackTrace) {
|
||||||
|
$diagLines.Add(" StackTrace :`n$($currentEx.StackTrace -replace '^', ' ')")
|
||||||
|
}
|
||||||
|
$diagLines.Add('')
|
||||||
|
$currentEx = $currentEx.InnerException
|
||||||
|
$depth++
|
||||||
|
}
|
||||||
|
$diagLines.Add('--- END DIAGNOSTIC DUMP ---')
|
||||||
|
|
||||||
|
$diagText = $diagLines -join "`r`n"
|
||||||
|
Write-Host $diagText -ForegroundColor Red
|
||||||
|
|
||||||
|
$diagPath = Join-Path -Path $reportPathBase -ChildPath "dcsync-diag-$timestamp.txt"
|
||||||
|
try {
|
||||||
|
New-Item -ItemType Directory -Path $reportPathBase -Force | Out-Null
|
||||||
|
[System.IO.File]::WriteAllText($diagPath, $diagText, [System.Text.Encoding]::UTF8)
|
||||||
|
Write-Host ("Diagnostic dump written to: {0}" -f $diagPath)
|
||||||
|
} catch {
|
||||||
|
Write-Warning ("Could not write diagnostic dump to disk: {0}" -f $_.Exception.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Still emit the concise error for the operator
|
||||||
|
$message = $ex.Message
|
||||||
if ($message -match 'Access is denied') {
|
if ($message -match 'Access is denied') {
|
||||||
Write-Error ("Access denied while reading replication data from '{0}' using '{1}'. Ensure this account has Replicating Directory Changes, Replicating Directory Changes All, and Replicating Directory Changes In Filtered Set on the domain." -f $selectedDomain["DC"], $credential.UserName)
|
Write-Error ("Access denied while reading replication data from '{0}' using '{1}'. Ensure this account has Replicating Directory Changes, Replicating Directory Changes All, and Replicating Directory Changes In Filtered Set on the domain." -f $selectedDomain["DC"], $credential.UserName)
|
||||||
return
|
} elseif ($message -match 'rejected the client credentials|unknown user name|bad password|logon failure') {
|
||||||
}
|
|
||||||
if ($message -match 'rejected the client credentials|unknown user name|bad password|logon failure') {
|
|
||||||
Write-Error ("Credentials for '{0}' were rejected by '{1}'. Re-run and provide valid domain credentials." -f $credential.UserName, $selectedDomain["DC"])
|
Write-Error ("Credentials for '{0}' were rejected by '{1}'. Re-run and provide valid domain credentials." -f $credential.UserName, $selectedDomain["DC"])
|
||||||
return
|
} else {
|
||||||
}
|
|
||||||
Write-Error ("An error occurred while testing passwords: {0}" -f $message)
|
Write-Error ("An error occurred while testing passwords: {0}" -f $message)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} finally {
|
} finally {
|
||||||
if ($resolvedHashFile -and $resolvedHashFile.IsTemporary -and (Test-Path -LiteralPath $resolvedHashFile.Path)) {
|
if ($resolvedHashFile -and $resolvedHashFile.IsTemporary -and (Test-Path -LiteralPath $resolvedHashFile.Path)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user