The PowerView PowerUsage Series #5
This is the fifth post in my âPowerView PowerUsageâ series, and follows the same Scenario/Solution/Explanation pattern as the previous entries. The original post contains a constantly updated list of the entire series.
The Scenario
You discovered on an engagement that most user workstations contain the userâs Active Directory samaccount name, e.g. John Smithâs (jsmith@domain.local) machine is named something like jsmith-workstation.domain.local. You want to find all user->workstation mappings, exported as a CSV.
The Solution
Get-DomainUser -Properties samaccountname | % {
$a=(Get-DomainComputer "*$($_.samaccountname)*" -Properties dnshostname | `
select -expand dnshostname) -join '|';
if($a){[pscustomobject]@{'UserName'=$_.samaccountname;'ComputerName'=$a}}
} | Export-Csv -NoTypeInformation user_workstations.csv
The Explanation
To start off, we enumerate all user samaccountnames in the environment, using the -Properties parameter of Get-DomainUser to again âoptimize to the left.â This signals the target domain controller to only return the samaccountname data back to the requestor, reducing the amount of exchange traffic, and causing the entire exchange to be faster than if ALL user data fields were returned (the default.)
We then iterate over each returned result with % (shortcut for ForEach-Object), and query all computers with a wildcard search for the resulting user samaccountname. This is done with Get-DomainComputer, embedding the current samaccountname in a wildcard search with â*$($_.samaccountname)*â, and using -Properties again to just return the dnshostname of the returned systems.
Then we pipe that to select (alias for Select-Object), indicating that we want to expand the given dnshostname field. This returns a flat list/array of one or more string representations of the system dnshostnames, which we then join together to create a pipe-separated string. This is because there may be multiple results (e.g. jsmith-laptop.domain.local and jsmith-workstation.domain.local), so we want to make sure we donât lose any results. These results are all saved to the variable $a.
The if ($a) {âĤ} check is to ensure that we only process search results that returned non-null values. For each valid result that was returned, we create a custom output object of âUserNameâ and âComputerNameâ fields. Finally, we output everything to a .csv file with Export-CSV, specifying the -NoTypeInformation flag so PS object type information isnât output to the file. Note that we could also pipe this to ConvertTo-Csv -NoTypeInformation to display the CSV to a screen if weâre executing these actions over some type of RAT.
Originally published at harmj0y.