Link to home
Start Free TrialLog in
Avatar of Rich Rumble
Rich RumbleFlag for United States of America

asked on

Powershell script, specify domain

We've modified this Script to include a "ping" function since we have an unstable network at this time and are working on that separately. The current script assumes we want info about a user in the current domain, but we'd like to specify the domain, perhaps from a list like that found from issuing a "(Get-ADForest).domains" in PowerShell. Our PowerShell version is mostly 2.0, the windows 7 sp1 default. Commandlets or other scripting techniques should reflect this constraint. If possible I'd like it to also accept command line arg's beyond the username, like the domain then username.
.\FindUserBadPwdAttempts.ps1 domain_x user_x
or perhaps
.\FindUserBadPwdAttempts.ps1 domain_x\user_x
------------------------------------------------------------
if no args... (pseudo code)
Else
{
  $ADdomain = Read-Host "Pick a domain: 1='$domain_a,' 2='$domain_b', 3='$domain_c'"
#something to that effect
------------------------------------------------------------
I can't seem to make it work, so I rolled back to this working script. Anyone want to take a stab at helping add the domain specification piece?

Thanks!
-rich
# FindUserBadPwdAttempts.ps1 
# PowerShell Version 1 script to assist in troubleshooting accounts 
# experiencing bad password attempts. It can also be used to investigate 
# how accounts get locked out in Active Directory. The script finds 
# the values of the sAMAccountName, pwdLastSet, lockoutTime, lastLogon, 
# logonCount, badPwdCount, and badPasswordTime attributes for a specified 
# user. The last 4 attributes are not replicated, so a different value is 
# saved on every domain controller in the domain. A separate line of output 
# is generated for each domain controller. The script prompts for either 
# the distingished name or the sAMAccountName of an account. 
 
# Author: Richard L. Mueller 
# Version 1.0 - October 6, 2015 
 
# Check for parameter identifying the object. 
If ($Args.Count -eq 1) 
{ 
    $UserName = $Args[0] 
} 
Else 
{ 
    $UserName = Read-Host "Enter user sAMAccountName or distinguished name" 
} 
 
# Setup the DirectorySearcher object. 
$Searcher = New-Object System.DirectoryServices.DirectorySearcher 
$Searcher.PageSize = 200 
$Searcher.SearchScope = "subtree" 
$Domain = New-Object System.DirectoryServices.DirectoryEntry 
$BaseDN = $Domain.distinguishedName 
 
If ($UserName -Like "*,*") 
{ 
    $Searcher.Filter = "(distinguishedName=$UserName)"  #don't need this line for our needs
} 
Else 
{ 
    $Searcher.Filter = "(sAMAccountName=$UserName)" 
} 
 
# Check for existence of the user object on any DC. 
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$BaseDN" 
$Check = $Searcher.FindOne() 
If (-Not $Check) 
{ 
    Write-Host "Error: User $UserName not found" -foregroundcolor red 
    Break 
} 
 
# Specify the attribute values to retrieve. 
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null 
$Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null 
$Searcher.PropertiesToLoad.Add("badPwdCount") > $Null 
$Searcher.PropertiesToLoad.Add("badPasswordTime") > $Null 
$Searcher.PropertiesToLoad.Add("lockoutTime") > $Null 
$Searcher.PropertiesToLoad.Add("logonCount") > $Null 
$Searcher.PropertiesToLoad.Add("lastLogon") > $Null 
$Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null 
 
$D = [system.directoryservices.activedirectory.Domain]::GetCurrentDomain() 
$PDC= $D.PdcRoleOwner 
 
# Output a heading line. 
"sAMAccountName, pwdLastSet, lockoutTime, DC, lastLogon, logonCount, badPwdCount, badPasswordTime" 
 
# Query every domain controller in the domain. 
ForEach ($DC In $D.DomainControllers) 
{ 
    $ping = get-wmiobject -Query "select * from win32_pingstatus where Address='$DC'"
    # Display Results
    if ($ping.statuscode -eq 0) {
        #"'$DC' responded in: {0}ms" -f $ping.responsetime
        $Server = $DC.Name 
        $Result = $Null 
        # Identify the DC with the PDC Emulator role. 
        If ($Server -eq $PDC) {$ServerName = "$Server (PDCe)"} 
        Else {$ServerName = $Server} 
        # Specify the DC and domain in the Base of the query. 
        $Base = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$Server/$BaseDN" 
        $Searcher.SearchRoot = $Base 
        $Result = $Searcher.FindOne() 
        If ($Result) 
        { 
            # Retrieve the values. 
            $DN = $Result.Properties.Item("distinguishedName") 
            $NTName = $Result.Properties.Item("sAMAccountName") 
            $BadCount = $Result.Properties.Item("badPwdCount") 
            $LogonCount = $Result.Properties.Item("logonCount") 
            $Time = $Result.Properties.Item("badPasswordTime") 
            $Last = $Result.Properties.Item("lastLogon") 
            $Pwd = $Result.Properties.Item("pwdLastSet") 
            $Lock = $Result.Properties.Item("lockoutTime") 
            # Convert LargeInteger values into datetime values in the UTC zone. 
            If ($Time.Count -eq 0) {$BadTime = "Never"} 
            Else 
            { 
                If ($Time.Item(0) -eq 0) {$BadTime = "Never"} 
                Else {$BadTime = ([DateTime]$Time.Item(0)).AddYears(1600).ToUniversalTime()} 
            } 
            If ($Last.Count -eq 0) {$LastLogon = "Never"} 
            Else 
            { 
                If ($Last.Item(0) -eq 0) {$LastLogon = "Never"} 
                Else {$LastLogon = ([DateTime]$Last.Item(0)).AddYears(1600).ToUniversalTime()} 
            } 
            If ($Pwd.Count -eq 0) {$PwdLastSet = "Never"} 
            Else 
            { 
                If ($Pwd.Item(0) -eq 0) {$PwdLastSet = "Never"} 
                Else {$PwdLastSet = ([DateTime]$Pwd.Item(0)).AddYears(1600).ToUniversalTime()} 
            } 
            If ($Lock.Count -eq 0) {$Lockout = "Never"} 
            Else 
            { 
                If ($Lock.Item(0) -eq 0) {$Lockout = "Never"} 
                Else {$Lockout = ([DateTime]$Lock.Item(0)).AddYears(1600).ToUniversalTime()} 
            } 
            # Output in comma delimited format. 
            "$NTName,$PwdLastSet,$Lockout,$ServerName,$LastLogon,$LogonCount,$BadCount,$BadTime" 
        } 
        Else 
        { 
            Write-Host "ERROR: Failed to connect to DC $Server" -foregroundcolor red -backgroundcolor black 
            ",,,$ServerName,,,," 
        } 
    }
    else {
    "'$DC' did not respond"
    }
} 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of J0rtIT
J0rtIT
Flag of Venezuela, Bolivarian Republic of image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Rich Rumble

ASKER

Very close :) It's not actually searching any specified domains other than the current account's default. The $BaseDN variable needs to change... (or something) my attempts are not working... See code below, I also changed your $domain varible to $ADdomain, I thought there may have been a conflict with what is in the script later on, but I again am not a scripter. Are lines 47-54 of my script below needed?
(cmd line is now -addomin instead of -domain)

# FindUserBadPwdAttempts.ps1
# PowerShell Version 1 script to assist in troubleshooting accounts
# experiencing bad password attempts. It can also be used to investigate
# how accounts get locked out in Active Directory. The script finds
# the values of the sAMAccountName, pwdLastSet, lockoutTime, lastLogon,
# logonCount, badPwdCount, and badPasswordTime attributes for a specified
# user. The last 4 attributes are not replicated, so a different value is
# saved on every domain controller in the domain. A separate line of output
# is generated for each domain controller. The script prompts for either
# the distingished name or the sAMAccountName of an account.

# Author: Richard L. Mueller
# Version 1.0 - October 6, 2015
[CmdletBinding()]
param(
    [Parameter(Position=0,Mandatory=$false)]$Username,
    [Parameter(Position=1,Mandatory=$false)]$ADdomain="xxx.domain_x.com"
)

begin{

    $IsUsernameWithBar= $Username -match "\\"

    if($IsUsernameWithBar){
        $array= $Username.split('\')
        $Username=$array[1]
        $ADdomain=$array[0]
    }
    #else{ #get defaults}

    if([string]::IsNullOrEmpty($Username)){
        $UserName = Read-Host "Enter user sAMAccountName or distinguished name"
    }

}
process{

    # Setup the DirectorySearcher object.
    $Searcher = New-Object System.DirectoryServices.DirectorySearcher
    $Searcher.PageSize = 200
    $Searcher.SearchScope = "subtree"
    $Domain = New-Object System.DirectoryServices.DirectoryEntry
    $BaseDN = "'$ADdomain',DC=domain_x,DC=com"   #        <--------------------------------
   #$BaseDN = $Domain.distinguishedName
   # Write Host = $BaseDN

    If ($UserName -Like "*,*")
    {
        $Searcher.Filter = "(distinguishedName=$UserName)"  #don't need this line for our needs
    }
    Else
    {
        $Searcher.Filter = "(sAMAccountName=$UserName)"
    }

    # Check for existence of the user object on any DC.
    $Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$BaseDN"
    $Check = $Searcher.FindOne()
    If (-Not $Check)
    {
        Write-Host "Error: User $UserName not found" -foregroundcolor red
        Break
    }

    # Specify the attribute values to retrieve.
    $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
    $Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null
    $Searcher.PropertiesToLoad.Add("badPwdCount") > $Null
    $Searcher.PropertiesToLoad.Add("badPasswordTime") > $Null
    $Searcher.PropertiesToLoad.Add("lockoutTime") > $Null
    $Searcher.PropertiesToLoad.Add("logonCount") > $Null
    $Searcher.PropertiesToLoad.Add("lastLogon") > $Null
    $Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null

    $D = [system.directoryservices.activedirectory.Domain]::GetCurrentDomain()
    $PDC= $D.PdcRoleOwner

    # Output a heading line.
    "sAMAccountName, pwdLastSet, lockoutTime, DC, lastLogon, logonCount, badPwdCount, badPasswordTime"

    # Query every domain controller in the domain.
    ForEach ($DC In $D.DomainControllers)
    {
        $ping = get-wmiobject -Query "select * from win32_pingstatus where Address='$DC'"
        # Display Results
        if ($ping.statuscode -eq 0) {
            #"'$DC' responded in: {0}ms" -f $ping.responsetime
            $Server = $DC.Name
            $Result = $Null
            # Identify the DC with the PDC Emulator role.
            If ($Server -eq $PDC) {$ServerName = "$Server (PDCe)"}
            Else {$ServerName = $Server}
            # Specify the DC and domain in the Base of the query.
            $Base = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$Server/$BaseDN"
            $Searcher.SearchRoot = $Base
            $Result = $Searcher.FindOne()
            If ($Result)
            {
                # Retrieve the values.
                $DN = $Result.Properties.Item("distinguishedName")
                $NTName = $Result.Properties.Item("sAMAccountName")
                $BadCount = $Result.Properties.Item("badPwdCount")
                $LogonCount = $Result.Properties.Item("logonCount")
                $Time = $Result.Properties.Item("badPasswordTime")
                $Last = $Result.Properties.Item("lastLogon")
                $Pwd = $Result.Properties.Item("pwdLastSet")
                $Lock = $Result.Properties.Item("lockoutTime")
                # Convert LargeInteger values into datetime values in the UTC zone.
                If ($Time.Count -eq 0) {$BadTime = "Never"}
                Else
                {
                    If ($Time.Item(0) -eq 0) {$BadTime = "Never"}
                    Else {$BadTime = ([DateTime]$Time.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Last.Count -eq 0) {$LastLogon = "Never"}
                Else
                {
                    If ($Last.Item(0) -eq 0) {$LastLogon = "Never"}
                    Else {$LastLogon = ([DateTime]$Last.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Pwd.Count -eq 0) {$PwdLastSet = "Never"}
                Else
                {
                    If ($Pwd.Item(0) -eq 0) {$PwdLastSet = "Never"}
                    Else {$PwdLastSet = ([DateTime]$Pwd.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Lock.Count -eq 0) {$Lockout = "Never"}
                Else
                {
                    If ($Lock.Item(0) -eq 0) {$Lockout = "Never"}
                    Else {$Lockout = ([DateTime]$Lock.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                # Output in comma delimited format.
                "$NTName,$PwdLastSet,$Lockout,$ServerName,$LastLogon,$LogonCount,$BadCount,$BadTime"
            }
            Else
            {
                Write-Host "ERROR: Failed to connect to DC $Server" -foregroundcolor red -backgroundcolor black
                ",,,$ServerName,,,,"
            }
        }
        else {
        "'$DC' did not respond"
        }
    }
}

Open in new window

Fixed it! Forgot the "dc=" in front of the $ADdomain...

$BaseDN = "'$ADdomain',DC=domain_x,DC=com"
vs
$BaseDN = "DC=$ADdomain,DC=domain_x,DC=com"

Thanks!
Thanks for the help, finally figured out something for myself while I was at it!
Had to make even more changes, turns out line 75 of the above script still overrode the specified, I've managed to work it out, I'm sure it's not the best way, but it's working!

# FindUserBadPwdAttempts.ps1
# PowerShell Version 1 script to assist in troubleshooting accounts
# experiencing bad password attempts. It can also be used to investigate
# how accounts get locked out in Active Directory. The script finds
# the values of the sAMAccountName, pwdLastSet, lockoutTime, lastLogon,
# logonCount, badPwdCount, and badPasswordTime attributes for a specified
# user. The last 4 attributes are not replicated, so a different value is
# saved on every domain controller in the domain. A separate line of output
# is generated for each domain controller. The script prompts for either
# the distingished name or the sAMAccountName of an account.

# Author: Richard L. Mueller
# Version 1.0 - October 6, 2015
[CmdletBinding()]
param(
    [Parameter(Position=0,Mandatory=$false)]$Username
)

begin{

    $IsUsernameWithBar= $Username -match "\\"

    if($IsUsernameWithBar){
        $array= $Username.split('\')
        $Username=$array[1]
        $ADdomain=$array[0]
    }
       	$ADdomain = $ADdomain
    	$ADdomainDot= $ADdomain.psobject.copy()

}
process{

    # Setup the DirectorySearcher object.
    $Searcher = New-Object System.DirectoryServices.DirectorySearcher
    $Searcher.PageSize = 200
    $Searcher.SearchScope = "subtree"
    $Domain = New-Object System.DirectoryServices.DirectoryEntry
    $BaseDN = "DC=$ADdomain,DC=domain_x,DC=COM"
    $BaseDNdot = "$ADdomainDot.domain_x.COM"
    $Searcher.Filter = "(sAMAccountName=$UserName)"
 
    # Check for existence of the user object on any DC.
    $Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$BaseDN"
    $Check = $Searcher.FindOne()
    If (-Not $Check)
    {
        Write-Host "Error: User $UserName not found" -foregroundcolor red
        Break
    }

    # Specify the attribute values to retrieve.
    $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
    $Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null
    $Searcher.PropertiesToLoad.Add("badPwdCount") > $Null
    $Searcher.PropertiesToLoad.Add("badPasswordTime") > $Null
    $Searcher.PropertiesToLoad.Add("lockoutTime") > $Null
    $Searcher.PropertiesToLoad.Add("logonCount") > $Null
    $Searcher.PropertiesToLoad.Add("lastLogon") > $Null
    $Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null

    $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain", $BaseDNdot)
    $D = [system.directoryservices.activedirectory.Domain]::GetDomain($DomainContext)
    $PDC= $D.PdcRoleOwner

    # Output a heading line.
    "SamAccountName, PwdLastSet, LockoutTime, DC, DC IP, LastLogon, LogonCount, BadPwdCount, BadPasswordTime"

    # Query every domain controller in the domain.
    ForEach ($DC In $D.DomainControllers)
    {
        $ping = get-wmiobject -Query "select * from win32_pingstatus where Address='$DC'"
        # Display Results
        if ($ping.statuscode -eq 0) {
            #"'$DC' responded in: {0}ms" -f $ping.responsetime
            $Server = $DC.Name
            $IPAddress = $DC.IPAddress
            $Result = $Null
            # Identify the DC with the PDC Emulator role.
            If ($Server -eq $PDC) {$ServerName = "$Server (PDCe)"}
            Else {$ServerName = $Server}
            # Specify the DC and domain in the Base of the query.
            $Base = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$Server/$BaseDN"
            $Searcher.SearchRoot = $Base
            $Result = $Searcher.FindOne()
            If ($Result)
            {
                # Retrieve the values.
                $DN = $Result.Properties.Item("distinguishedName")
                $NTName = $Result.Properties.Item("sAMAccountName")
                $BadCount = $Result.Properties.Item("badPwdCount")
                $LogonCount = $Result.Properties.Item("logonCount")
                $Time = $Result.Properties.Item("badPasswordTime")
                $Last = $Result.Properties.Item("lastLogon")
                $Pwd = $Result.Properties.Item("pwdLastSet")
                $Lock = $Result.Properties.Item("lockoutTime")
                # Convert LargeInteger values into datetime values in the UTC zone.
                If ($Time.Count -eq 0) {$BadTime = "Never"}
                Else
                {
                    If ($Time.Item(0) -eq 0) {$BadTime = "Never"}
                    Else {$BadTime = ([DateTime]$Time.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Last.Count -eq 0) {$LastLogon = "Never"}
                Else
                {
                    If ($Last.Item(0) -eq 0) {$LastLogon = "Never"}
                    Else {$LastLogon = ([DateTime]$Last.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Pwd.Count -eq 0) {$PwdLastSet = "Never"}
                Else
                {
                    If ($Pwd.Item(0) -eq 0) {$PwdLastSet = "Never"}
                    Else {$PwdLastSet = ([DateTime]$Pwd.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                If ($Lock.Count -eq 0) {$Lockout = "Never"}
                Else
                {
                    If ($Lock.Item(0) -eq 0) {$Lockout = "Never"}
                    Else {$Lockout = ([DateTime]$Lock.Item(0)).AddYears(1600).ToUniversalTime()}
                }
                # Output in comma delimited format.
                "$NTName, $PwdLastSet, $Lockout, $ServerName, $IPAddress, $LastLogon, $LogonCount, $BadCount, $BadTime"
            }
            Else
            {
                Write-Host "ERROR: Failed to connect to DC $Server" -foregroundcolor red -backgroundcolor black
                ", , , $ServerName, $IPAddress, , ,"
            }
        }
        else {
        ", , , $DC, Ping Failed, , ,"
        }
    }
}

Open in new window